diff --git a/CMakeLists.txt b/CMakeLists.txt index c8ebb270d..85132055b 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -183,17 +183,16 @@ endif() if(MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Gd") - #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MD") - #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /O2") - #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Ob2") - #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W2") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3") + if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_AMD64_") else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_X86_") endif() - SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}) - SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}) + + set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}) + set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}) if(CMAKE_BUILD_TYPE STREQUAL "Release") else() @@ -216,28 +215,29 @@ endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWINPR_EXPORTS") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFREERDP_EXPORTS") + # Include files if(NOT IOS) -check_include_files(fcntl.h HAVE_FCNTL_H) -check_include_files(unistd.h HAVE_UNISTD_H) -check_include_files(stdint.h HAVE_STDINT_H) -check_include_files(inttypes.h HAVE_INTTYPES_H) -check_include_files(sys/modem.h HAVE_SYS_MODEM_H) -check_include_files(sys/filio.h HAVE_SYS_FILIO_H) -check_include_files(sys/strtio.h HAVE_SYS_STRTIO_H) -check_include_files(sys/select.h HAVE_SYS_SELECT_H) + check_include_files(fcntl.h HAVE_FCNTL_H) + check_include_files(unistd.h HAVE_UNISTD_H) + check_include_files(stdint.h HAVE_STDINT_H) + check_include_files(inttypes.h HAVE_INTTYPES_H) + check_include_files(sys/modem.h HAVE_SYS_MODEM_H) + check_include_files(sys/filio.h HAVE_SYS_FILIO_H) + check_include_files(sys/strtio.h HAVE_SYS_STRTIO_H) + check_include_files(sys/select.h HAVE_SYS_SELECT_H) else() -set(HAVE_FCNTL_H 1) -set(HAVE_UNISTD_H 1) -set(HAVE_STDINT_H 1) -set(HAVE_INTTYPES_H 1) -set(HAVE_SYS_FILIO_H 1) + set(HAVE_FCNTL_H 1) + set(HAVE_UNISTD_H 1) + set(HAVE_STDINT_H 1) + set(HAVE_INTTYPES_H 1) + set(HAVE_SYS_FILIO_H 1) endif() if(NOT IOS) -check_struct_has_member("struct tm" tm_gmtoff time.h HAVE_TM_GMTOFF) + check_struct_has_member("struct tm" tm_gmtoff time.h HAVE_TM_GMTOFF) else() -set(HAVE_TM_GMTOFF 1) + set(HAVE_TM_GMTOFF 1) endif() # Mac OS X @@ -315,10 +315,11 @@ if(NOT IOS AND NOT ANDROID) find_package(Threads REQUIRED) endif() -list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) -check_library_exists(pthread pthread_tryjoin_np "" HAVE_PTHREAD_GNU_EXT) -list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) - +if(NOT WIN32) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) + check_library_exists(pthread pthread_tryjoin_np "" HAVE_PTHREAD_GNU_EXT) + list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) +endif() if(UNIX OR CYGWIN) check_include_files(sys/eventfd.h HAVE_AIO_H) @@ -376,10 +377,6 @@ set(IPP_FEATURE_TYPE "OPTIONAL") set(IPP_FEATURE_PURPOSE "performance") set(IPP_FEATURE_DESCRIPTION "Intel Integrated Performance Primitives library") -set(NPP_FEATURE_TYPE "OPTIONAL") -set(NPP_FEATURE_PURPOSE "performance") -set(NPP_FEATURE_DESCRIPTION "NVIDIA Performance Primitives library") - set(JPEG_FEATURE_TYPE "OPTIONAL") set(JPEG_FEATURE_PURPOSE "codec") set(JPEG_FEATURE_DESCRIPTION "use JPEG library") @@ -433,9 +430,7 @@ endif() find_feature(X11 ${X11_FEATURE_TYPE} ${X11_FEATURE_PURPOSE} ${X11_FEATURE_DESCRIPTION}) find_feature(DirectFB ${DIRECTFB_FEATURE_TYPE} ${DIRECTFB_FEATURE_PURPOSE} ${DIRECTFB_FEATURE_DESCRIPTION}) if (${WITH_DIRECTFB}) - message(WARNING " -DIRECTFB is orphaned and not maintained see docs/README.directfb for details -") + message(WARNING "DIRECTFB is orphaned and not maintained see docs/README.directfb for details") endif() find_feature(ZLIB ${ZLIB_FEATURE_TYPE} ${ZLIB_FEATURE_PURPOSE} ${ZLIB_FEATURE_DESCRIPTION}) @@ -459,13 +454,6 @@ if(TARGET_ARCH MATCHES "x86|x64") # Intel Performance Primitives find_feature(IPP ${IPP_FEATURE_TYPE} ${IPP_FEATURE_PURPOSE} ${IPP_FEATURE_DESCRIPTION}) endif() - find_feature(NPP ${NPP_FEATURE_TYPE} ${NPP_FEATURE_PURPOSE} ${NPP_FEATURE_DESCRIPTION}) -endif() - -# Installation Paths -if(WIN32) - set(CMAKE_INSTALL_BINDIR ".") - set(CMAKE_INSTALL_LIBDIR ".") endif() # Path to put FreeRDP data diff --git a/channels/audin/client/CMakeLists.txt b/channels/audin/client/CMakeLists.txt index 2a370743c..e126eab0d 100644 --- a/channels/audin/client/CMakeLists.txt +++ b/channels/audin/client/CMakeLists.txt @@ -49,3 +49,7 @@ endif() if(WITH_OPENSLES) add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "opensles" "") endif() + +if(WITH_WINMM) + add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "winmm" "") +endif() diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c index b620126a7..18632b759 100644 --- a/channels/audin/client/audin_main.c +++ b/channels/audin/client/audin_main.c @@ -102,7 +102,7 @@ static int audin_process_version(IWTSVirtualChannelCallback* pChannelCallback, w out = Stream_New(NULL, 5); Stream_Write_UINT8(out, MSG_SNDIN_VERSION); Stream_Write_UINT32(out, Version); - error = callback->channel->Write(callback->channel, Stream_GetPosition(s), Stream_Buffer(s), NULL); + error = callback->channel->Write(callback->channel, (UINT32) Stream_GetPosition(s), Stream_Buffer(s), NULL); Stream_Free(out, TRUE); return error; @@ -183,7 +183,7 @@ static int audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, w audin_send_incoming_data_pdu(pChannelCallback); - cbSizeFormatsPacket = Stream_GetPosition(out); + cbSizeFormatsPacket = (UINT32) Stream_GetPosition(out); Stream_SetPosition(out, 0); Stream_Write_UINT8(out, MSG_SNDIN_FORMATS); /* Header (1 byte) */ @@ -240,7 +240,7 @@ static BOOL audin_receive_wave_data(BYTE* data, int size, void* user_data) out = Stream_New(NULL, size + 1); Stream_Write_UINT8(out, MSG_SNDIN_DATA); Stream_Write(out, data, size); - error = callback->channel->Write(callback->channel, Stream_GetPosition(out), Stream_Buffer(out), NULL); + error = callback->channel->Write(callback->channel, (UINT32) Stream_GetPosition(out), Stream_Buffer(out), NULL); Stream_Free(out, TRUE); return (error == 0 ? TRUE : FALSE); @@ -607,6 +607,15 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) } #endif +#if defined(WITH_WINMM) + if (!audin->device) + { + audin_set_subsystem(audin, "winmm"); + audin_set_device_name(audin, "default"); + audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args); + } +#endif + if (audin->device == NULL) { DEBUG_WARN("no sound device."); diff --git a/channels/audin/client/winmm/CMakeLists.txt b/channels/audin/client/winmm/CMakeLists.txt new file mode 100644 index 000000000..10db102ad --- /dev/null +++ b/channels/audin/client/winmm/CMakeLists.txt @@ -0,0 +1,41 @@ +# 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_client_subsystem("audin" "winmm" "") + +set(${MODULE_PREFIX}_SRCS + audin_winmm.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} winmm.lib) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + + +install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets) + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client/winmm") diff --git a/channels/audin/client/winmm/audin_winmm.c b/channels/audin/client/winmm/audin_winmm.c new file mode 100644 index 000000000..8881c04b0 --- /dev/null +++ b/channels/audin/client/winmm/audin_winmm.c @@ -0,0 +1,309 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Audio Input Redirection Virtual Channel - WinMM implementation + * + * Copyright 2013 Zhang Zhaolong + * + * 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 +#include + +#include "audin_main.h" + +typedef struct _AudinWinmmDevice +{ + IAudinDevice iface; + + char* device_name; + AudinReceive receive; + void* user_data; + HANDLE thread; + HANDLE stopEvent; + HWAVEIN hWaveIn; + PWAVEFORMATEX *ppwfx; + PWAVEFORMATEX pwfx_cur; + UINT32 ppwfx_size; + UINT32 cFormats; + UINT32 frames_per_packet; +} AudinWinmmDevice; + +static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance, + DWORD_PTR dwParam1, DWORD_PTR dwParam2) +{ + AudinWinmmDevice* winmm = (AudinWinmmDevice*) dwInstance; + PWAVEHDR pWaveHdr; + + switch(uMsg) + { + case WIM_CLOSE: + break; + + case WIM_DATA: + pWaveHdr = (WAVEHDR *)dwParam1; + if (WHDR_DONE == (WHDR_DONE & pWaveHdr->dwFlags)) + { + if (pWaveHdr->dwBytesRecorded + && !(WaitForSingleObject(winmm->stopEvent, 0) == WAIT_OBJECT_0)) + { + winmm->receive(pWaveHdr->lpData, pWaveHdr->dwBytesRecorded, winmm->user_data); + waveInAddBuffer(hWaveIn, pWaveHdr, sizeof(WAVEHDR)); + } + } + break; + + case WIM_OPEN: + break; + + default: + break; + } +} + +static DWORD audin_winmm_thread_func(void* arg) +{ + AudinWinmmDevice* winmm = (AudinWinmmDevice*) arg; + char *buffer; + int size, i; + WAVEHDR waveHdr[4]; + + if (!winmm->hWaveIn) + { + if (MMSYSERR_NOERROR != waveInOpen(&winmm->hWaveIn, WAVE_MAPPER, winmm->pwfx_cur, + (DWORD_PTR)waveInProc, (DWORD_PTR)winmm, CALLBACK_FUNCTION)) + { + return 0; + } + } + + size = (winmm->pwfx_cur->wBitsPerSample * winmm->pwfx_cur->nChannels * winmm->frames_per_packet + 7) / 8; + for (i = 0; i < 4; i++) + { + buffer = (char *) malloc(size); + waveHdr[i].dwBufferLength = size; + waveHdr[i].dwFlags = 0; + waveHdr[i].lpData = buffer; + if (MMSYSERR_NOERROR != waveInPrepareHeader(winmm->hWaveIn, &waveHdr[i], sizeof(waveHdr[i]))) + { + DEBUG_DVC("waveInPrepareHeader failed."); + } + if (MMSYSERR_NOERROR != waveInAddBuffer(winmm->hWaveIn, &waveHdr[i], sizeof(waveHdr[i]))) + { + DEBUG_DVC("waveInAddBuffer failed."); + } + } + waveInStart(winmm->hWaveIn); + + WaitForSingleObject(winmm->stopEvent, INFINITE); + + waveInStop(winmm->hWaveIn); + + for (i = 0; i < 4; i++) + { + if (MMSYSERR_NOERROR != waveInUnprepareHeader(winmm->hWaveIn, &waveHdr[i], sizeof(waveHdr[i]))) + { + DEBUG_DVC("waveInUnprepareHeader failed."); + } + free(waveHdr[i].lpData); + } + + waveInClose(winmm->hWaveIn); + winmm->hWaveIn = NULL; + + return 0; +} + +static void audin_winmm_free(IAudinDevice* device) +{ + AudinWinmmDevice* winmm = (AudinWinmmDevice*) device; + int i; + + for (i = 0; i < winmm->cFormats; i++) + { + free(winmm->ppwfx[i]); + } + + free(winmm->ppwfx); + free(winmm->device_name); + free(winmm); +} + +static void audin_winmm_close(IAudinDevice* device) +{ + AudinWinmmDevice* winmm = (AudinWinmmDevice*) device; + + DEBUG_DVC(""); + + SetEvent(winmm->stopEvent); + + WaitForSingleObject(winmm->thread, INFINITE); + + CloseHandle(winmm->thread); + CloseHandle(winmm->stopEvent); + + winmm->thread = NULL; + winmm->stopEvent = NULL; + winmm->receive = NULL; + winmm->user_data = NULL; +} + +static void audin_winmm_set_format(IAudinDevice* device, audinFormat* format, UINT32 FramesPerPacket) +{ + AudinWinmmDevice* winmm = (AudinWinmmDevice*) device; + int i; + + winmm->frames_per_packet = FramesPerPacket; + + for (i = 0; i < winmm->cFormats; i++) + { + if (winmm->ppwfx[i]->wFormatTag == format->wFormatTag + && winmm->ppwfx[i]->nChannels == format->nChannels + && winmm->ppwfx[i]->wBitsPerSample == format->wBitsPerSample) + { + winmm->pwfx_cur = winmm->ppwfx[i]; + break; + } + } +} + +static BOOL audin_winmm_format_supported(IAudinDevice* device, audinFormat* format) +{ + AudinWinmmDevice* winmm = (AudinWinmmDevice*) device; + PWAVEFORMATEX pwfx; + BYTE *data; + + pwfx = (PWAVEFORMATEX)malloc(sizeof(WAVEFORMATEX) + format->cbSize); + pwfx->cbSize = format->cbSize; + pwfx->wFormatTag = format->wFormatTag; + pwfx->nChannels = format->nChannels; + pwfx->nSamplesPerSec = format->nSamplesPerSec; + pwfx->nBlockAlign = format->nBlockAlign; + pwfx->wBitsPerSample = format->wBitsPerSample; + data = (BYTE *)pwfx + sizeof(WAVEFORMATEX); + + memcpy(data, format->data, format->cbSize); + + if (pwfx->wFormatTag == WAVE_FORMAT_PCM) + { + pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign; + if (MMSYSERR_NOERROR == waveInOpen(NULL, WAVE_MAPPER, pwfx, 0, 0, WAVE_FORMAT_QUERY)) + { + if (winmm->cFormats >= winmm->ppwfx_size) + { + winmm->ppwfx_size *= 2; + winmm->ppwfx = realloc(winmm->ppwfx, sizeof(PWAVEFORMATEX) * winmm->ppwfx_size); + } + winmm->ppwfx[winmm->cFormats++] = pwfx; + + return 1; + } + } + + free(pwfx); + return 0; +} + +static void audin_winmm_open(IAudinDevice* device, AudinReceive receive, void* user_data) +{ + AudinWinmmDevice* winmm = (AudinWinmmDevice*) device; + + DEBUG_DVC(""); + + winmm->receive = receive; + winmm->user_data = user_data; + + winmm->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + winmm->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) audin_winmm_thread_func, winmm, 0, NULL); +} + +static COMMAND_LINE_ARGUMENT_A audin_winmm_args[] = +{ + { "audio-dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "audio device name" }, + { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } +}; + +static void audin_winmm_parse_addin_args(AudinWinmmDevice* device, ADDIN_ARGV* args) +{ + int status; + DWORD flags; + COMMAND_LINE_ARGUMENT_A* arg; + AudinWinmmDevice* winmm = (AudinWinmmDevice*) device; + + flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON; + + status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, audin_winmm_args, flags, winmm, NULL, NULL); + + arg = audin_winmm_args; + + do + { + if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) + continue; + + CommandLineSwitchStart(arg) + + CommandLineSwitchCase(arg, "audio-dev") + { + winmm->device_name = _strdup(arg->Value); + } + + CommandLineSwitchEnd(arg) + } + while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); +} + +#ifdef STATIC_CHANNELS +#define freerdp_audin_client_subsystem_entry winmm_freerdp_audin_client_subsystem_entry +#endif + +int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) +{ + ADDIN_ARGV* args; + AudinWinmmDevice* winmm; + + winmm = (AudinWinmmDevice*) malloc(sizeof(AudinWinmmDevice)); + ZeroMemory(winmm, sizeof(AudinWinmmDevice)); + + winmm->iface.Open = audin_winmm_open; + winmm->iface.FormatSupported = audin_winmm_format_supported; + winmm->iface.SetFormat = audin_winmm_set_format; + winmm->iface.Close = audin_winmm_close; + winmm->iface.Free = audin_winmm_free; + + args = pEntryPoints->args; + + audin_winmm_parse_addin_args(winmm, args); + + if (!winmm->device_name) + winmm->device_name = _strdup("default"); + + winmm->ppwfx_size = 10; + winmm->ppwfx = malloc(sizeof(PWAVEFORMATEX) * winmm->ppwfx_size); + + pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) winmm); + + return 0; +} diff --git a/channels/audin/server/CMakeLists.txt b/channels/audin/server/CMakeLists.txt index a95da3909..e23d33192 100644 --- a/channels/audin/server/CMakeLists.txt +++ b/channels/audin/server/CMakeLists.txt @@ -29,6 +29,8 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MODULE freerdp MODULES freerdp-codec freerdp-utils) +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets) set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server") diff --git a/channels/audin/server/audin.c b/channels/audin/server/audin.c index defdf50e1..02c36ffa9 100644 --- a/channels/audin/server/audin.c +++ b/channels/audin/server/audin.c @@ -55,6 +55,8 @@ typedef struct _audin_server HANDLE thread; void* audin_channel; + DWORD SessionId; + FREERDP_DSP_CONTEXT* dsp_context; } audin_server; @@ -397,7 +399,20 @@ static BOOL audin_server_open(audin_server_context* context) if (!audin->thread) { - audin->audin_channel = WTSVirtualChannelManagerOpenEx(context->vcm, "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC); + PULONG pSessionId = NULL; + DWORD BytesReturned = 0; + + audin->SessionId = WTS_CURRENT_SESSION; + + if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, + WTSSessionId, (LPSTR*) pSessionId, &BytesReturned)) + { + audin->SessionId = (DWORD) *pSessionId; + WTSFreeMemory(pSessionId); + } + + audin->audin_channel = WTSVirtualChannelOpenEx(audin->SessionId, + "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC); if (!audin->audin_channel) return FALSE; @@ -438,12 +453,11 @@ static BOOL audin_server_close(audin_server_context* context) return TRUE; } -audin_server_context* audin_server_context_new(WTSVirtualChannelManager* vcm) +audin_server_context* audin_server_context_new(HANDLE vcm) { audin_server* audin; - audin = (audin_server*) malloc(sizeof(audin_server)); - ZeroMemory(audin, sizeof(audin_server)); + audin = (audin_server*) calloc(1, sizeof(audin_server)); audin->context.vcm = vcm; audin->context.selected_client_format = -1; diff --git a/channels/client/CMakeLists.txt b/channels/client/CMakeLists.txt index fc42466bb..21c04fc1f 100644 --- a/channels/client/CMakeLists.txt +++ b/channels/client/CMakeLists.txt @@ -22,13 +22,7 @@ set(${MODULE_PREFIX}_SRCS ${CMAKE_CURRENT_BINARY_DIR}/tables.c ${CMAKE_CURRENT_SOURCE_DIR}/tables.h ${CMAKE_CURRENT_SOURCE_DIR}/addin.c - ${CMAKE_CURRENT_SOURCE_DIR}/addin.h - ${CMAKE_CURRENT_SOURCE_DIR}/init.c - ${CMAKE_CURRENT_SOURCE_DIR}/init.h - ${CMAKE_CURRENT_SOURCE_DIR}/open.c - ${CMAKE_CURRENT_SOURCE_DIR}/open.h - ${CMAKE_CURRENT_SOURCE_DIR}/channels.c - ${CMAKE_CURRENT_SOURCE_DIR}/channels.h) + ${CMAKE_CURRENT_SOURCE_DIR}/addin.h) list(REMOVE_DUPLICATES CHANNEL_STATIC_CLIENT_ENTRIES) diff --git a/channels/client/init.c b/channels/client/init.c deleted file mode 100644 index f88867a6a..000000000 --- a/channels/client/init.c +++ /dev/null @@ -1,135 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Client Channels - * - * 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 "channels.h" - -#include "init.h" - -extern int g_open_handle_sequence; - -extern void* g_pInterface; -extern CHANNEL_INIT_DATA g_ChannelInitData; - -UINT32 FreeRDP_VirtualChannelInit(void** ppInitHandle, PCHANNEL_DEF pChannel, - int channelCount, UINT32 versionRequested, PCHANNEL_INIT_EVENT_FN pChannelInitEventProc) -{ - int index; - void* pInterface; - rdpChannel* channel; - rdpChannels* channels; - PCHANNEL_DEF pChannelDef; - CHANNEL_INIT_DATA* pChannelInitData; - CHANNEL_OPEN_DATA* pChannelOpenData; - CHANNEL_CLIENT_DATA* pChannelClientData; - - if (!ppInitHandle) - { - DEBUG_CHANNELS("error bad init handle"); - return CHANNEL_RC_BAD_INIT_HANDLE; - } - - channels = g_ChannelInitData.channels; - pInterface = g_pInterface; - - pChannelInitData = &(channels->initDataList[channels->initDataCount]); - *ppInitHandle = pChannelInitData; - channels->initDataCount++; - - pChannelInitData->channels = channels; - pChannelInitData->pInterface = pInterface; - - DEBUG_CHANNELS("enter"); - - if (!channels->can_call_init) - { - DEBUG_CHANNELS("error not in entry"); - return CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY; - } - - if (channels->openDataCount + channelCount >= CHANNEL_MAX_COUNT) - { - DEBUG_CHANNELS("error too many channels"); - return CHANNEL_RC_TOO_MANY_CHANNELS; - } - - if (!pChannel) - { - DEBUG_CHANNELS("error bad channel"); - return CHANNEL_RC_BAD_CHANNEL; - } - - if (channels->is_connected) - { - DEBUG_CHANNELS("error already connected"); - return CHANNEL_RC_ALREADY_CONNECTED; - } - - if (versionRequested != VIRTUAL_CHANNEL_VERSION_WIN2000) - { - DEBUG_CHANNELS("warning version"); - } - - for (index = 0; index < channelCount; index++) - { - pChannelDef = &pChannel[index]; - - if (freerdp_channels_find_channel_open_data_by_name(channels, pChannelDef->name) != 0) - { - DEBUG_CHANNELS("error channel already used"); - return CHANNEL_RC_BAD_CHANNEL; - } - } - - pChannelClientData = &channels->clientDataList[channels->clientDataCount]; - pChannelClientData->pChannelInitEventProc = pChannelInitEventProc; - pChannelClientData->pInitHandle = *ppInitHandle; - channels->clientDataCount++; - - for (index = 0; index < channelCount; index++) - { - pChannelDef = &pChannel[index]; - pChannelOpenData = &channels->openDataList[channels->openDataCount]; - - pChannelOpenData->OpenHandle = g_open_handle_sequence++; - - pChannelOpenData->flags = 1; /* init */ - strncpy(pChannelOpenData->name, pChannelDef->name, CHANNEL_NAME_LEN); - pChannelOpenData->options = pChannelDef->options; - - if (channels->settings->ChannelCount < CHANNEL_MAX_COUNT) - { - channel = channels->settings->ChannelDefArray + channels->settings->ChannelCount; - strncpy(channel->Name, pChannelDef->name, 7); - channel->options = pChannelDef->options; - channels->settings->ChannelCount++; - } - else - { - DEBUG_CHANNELS("warning more than %d channels", CHANNEL_MAX_COUNT); - } - - channels->openDataCount++; - } - - return CHANNEL_RC_OK; -} diff --git a/channels/client/open.c b/channels/client/open.c deleted file mode 100644 index 1233fb964..000000000 --- a/channels/client/open.c +++ /dev/null @@ -1,103 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Client Channels - * - * 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. - */ - -#include "open.h" - -UINT32 FreeRDP_VirtualChannelOpen(void* pInitHandle, UINT32* pOpenHandle, - char* pChannelName, PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc) -{ - void* pInterface; - rdpChannels* channels; - CHANNEL_INIT_DATA* pChannelInitData; - CHANNEL_OPEN_DATA* pChannelOpenData; - - DEBUG_CHANNELS("enter"); - - pChannelInitData = (CHANNEL_INIT_DATA*) pInitHandle; - channels = pChannelInitData->channels; - pInterface = pChannelInitData->pInterface; - - if (!pOpenHandle) - { - DEBUG_CHANNELS("error bad channel handle"); - return CHANNEL_RC_BAD_CHANNEL_HANDLE; - } - - if (!pChannelOpenEventProc) - { - DEBUG_CHANNELS("error bad proc"); - return CHANNEL_RC_BAD_PROC; - } - - if (!channels->is_connected) - { - DEBUG_CHANNELS("error not connected"); - return CHANNEL_RC_NOT_CONNECTED; - } - - pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, pChannelName); - - if (!pChannelOpenData) - { - DEBUG_CHANNELS("error channel name"); - return CHANNEL_RC_UNKNOWN_CHANNEL_NAME; - } - - if (pChannelOpenData->flags == 2) - { - DEBUG_CHANNELS("error channel already open"); - return CHANNEL_RC_ALREADY_OPEN; - } - - pChannelOpenData->flags = 2; /* open */ - pChannelOpenData->pInterface = pInterface; - pChannelOpenData->pChannelOpenEventProc = pChannelOpenEventProc; - *pOpenHandle = pChannelOpenData->OpenHandle; - - return CHANNEL_RC_OK; -} - -UINT32 FreeRDP_VirtualChannelClose(UINT32 openHandle) -{ - int index; - rdpChannels* channels; - CHANNEL_OPEN_DATA* pChannelOpenData; - - DEBUG_CHANNELS("enter"); - - channels = freerdp_channels_find_by_open_handle(openHandle, &index); - - if ((channels == NULL) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) - { - DEBUG_CHANNELS("error bad channels"); - return CHANNEL_RC_BAD_CHANNEL_HANDLE; - } - - pChannelOpenData = &channels->openDataList[index]; - - if (pChannelOpenData->flags != 2) - { - DEBUG_CHANNELS("error not open"); - return CHANNEL_RC_NOT_OPEN; - } - - pChannelOpenData->flags = 0; - - return CHANNEL_RC_OK; -} diff --git a/channels/cliprdr/client/cliprdr_format.c b/channels/cliprdr/client/cliprdr_format.c index e01cb656d..087635054 100644 --- a/channels/cliprdr/client/cliprdr_format.c +++ b/channels/cliprdr/client/cliprdr_format.c @@ -217,7 +217,7 @@ void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data if (context->custom) { - int index; + UINT32 index; int formatNameLength; CLIPRDR_FORMAT* formats; CLIPRDR_FORMAT_LIST formatList; diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c index 99a1b7b1f..77e4c9d8c 100644 --- a/channels/cliprdr/client/cliprdr_main.c +++ b/channels/cliprdr/client/cliprdr_main.c @@ -362,8 +362,8 @@ int cliprdr_client_capabilities(CliprdrClientContext* context, CLIPRDR_CAPABILIT int cliprdr_client_format_list(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList) { - int index; wStream* s; + UINT32 index; int length = 0; int formatNameSize; CLIPRDR_FORMAT* format; @@ -468,10 +468,9 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) { cliprdrPlugin* cliprdr; CliprdrClientContext* context; - CHANNEL_ENTRY_POINTS_EX* pEntryPointsEx; + CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx; - cliprdr = (cliprdrPlugin*) malloc(sizeof(cliprdrPlugin)); - ZeroMemory(cliprdr, sizeof(cliprdrPlugin)); + cliprdr = (cliprdrPlugin*) calloc(1, sizeof(cliprdrPlugin)); cliprdr->plugin.channel_def.options = CHANNEL_OPTION_INITIALIZED | @@ -486,13 +485,12 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) cliprdr->plugin.event_callback = cliprdr_process_event; cliprdr->plugin.terminate_callback = cliprdr_process_terminate; - pEntryPointsEx = (CHANNEL_ENTRY_POINTS_EX*) pEntryPoints; + pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints; - if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_EX)) && + if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) && (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER)) { - context = (CliprdrClientContext*) malloc(sizeof(CliprdrClientContext)); - ZeroMemory(context, sizeof(CliprdrClientContext)); + context = (CliprdrClientContext*) calloc(1, sizeof(CliprdrClientContext)); context->handle = (void*) cliprdr; diff --git a/channels/cliprdr/server/cliprdr_main.c b/channels/cliprdr/server/cliprdr_main.c index 3e81809f0..5375237d8 100644 --- a/channels/cliprdr/server/cliprdr_main.c +++ b/channels/cliprdr/server/cliprdr_main.c @@ -468,7 +468,7 @@ static void* cliprdr_server_thread(void* arg) static int cliprdr_server_start(CliprdrServerContext* context) { - context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "cliprdr", 0); + context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "cliprdr"); if (!context->priv->ChannelHandle) return -1; @@ -491,16 +491,14 @@ static int cliprdr_server_stop(CliprdrServerContext* context) return 0; } -CliprdrServerContext* cliprdr_server_context_new(WTSVirtualChannelManager* vcm) +CliprdrServerContext* cliprdr_server_context_new(HANDLE vcm) { CliprdrServerContext* context; - context = (CliprdrServerContext*) malloc(sizeof(CliprdrServerContext)); + context = (CliprdrServerContext*) calloc(1, sizeof(CliprdrServerContext)); if (context) { - ZeroMemory(context, sizeof(CliprdrServerContext)); - context->vcm = vcm; context->Start = cliprdr_server_start; diff --git a/channels/disp/client/disp_main.c b/channels/disp/client/disp_main.c index feb971550..343c9e3db 100644 --- a/channels/disp/client/disp_main.c +++ b/channels/disp/client/disp_main.c @@ -73,10 +73,10 @@ typedef struct _DISP_PLUGIN DISP_PLUGIN; int disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback, UINT32 NumMonitors, DISPLAY_CONTROL_MONITOR_LAYOUT* Monitors) { - int index; int status; wStream* s; UINT32 type; + UINT32 index; UINT32 length; DISP_PLUGIN* disp; UINT32 MonitorLayoutSize; @@ -155,7 +155,7 @@ int disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback Stream_SealLength(s); - status = callback->channel->Write(callback->channel, Stream_Length(s), Stream_Buffer(s), NULL); + status = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), Stream_Buffer(s), NULL); Stream_Free(s, TRUE); diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index 17492542b..03f0c7bea 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -356,7 +356,7 @@ static void drdynvc_process_receive(rdpSvcPlugin* plugin, wStream* s) static void drdynvc_process_connect(rdpSvcPlugin* plugin) { - int index; + UINT32 index; ADDIN_ARGV* args; rdpSettings* settings; drdynvcPlugin* drdynvc = (drdynvcPlugin*)plugin; @@ -411,7 +411,7 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) { drdynvcPlugin* _p; DrdynvcClientContext* context; - CHANNEL_ENTRY_POINTS_EX* pEntryPointsEx; + CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx; _p = (drdynvcPlugin*) malloc(sizeof(drdynvcPlugin)); ZeroMemory(_p, sizeof(drdynvcPlugin)); @@ -428,9 +428,9 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) _p->plugin.event_callback = drdynvc_process_event; _p->plugin.terminate_callback = drdynvc_process_terminate; - pEntryPointsEx = (CHANNEL_ENTRY_POINTS_EX*) pEntryPoints; + pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints; - if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_EX)) && + if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) && (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER)) { context = (DrdynvcClientContext*) malloc(sizeof(DrdynvcClientContext)); diff --git a/channels/drdynvc/client/dvcman.c b/channels/drdynvc/client/dvcman.c index 954247d02..71222d13e 100644 --- a/channels/drdynvc/client/dvcman.c +++ b/channels/drdynvc/client/dvcman.c @@ -413,13 +413,13 @@ int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelI IFCALL(context->OnChannelDisconnected, context, channel->channel_name, channel->pInterface); + free(channel->channel_name); + DEBUG_DVC("dvcman_close_channel: channel %d closed", ChannelId); ichannel = (IWTSVirtualChannel*) channel; ichannel->Close(ichannel); } - free(channel->channel_name); - return 0; } @@ -469,7 +469,7 @@ int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 C Stream_Write(channel->dvc_data, data, data_size); - if (Stream_GetPosition(channel->dvc_data) >= Stream_Capacity(channel->dvc_data)) + if (((size_t) Stream_GetPosition(channel->dvc_data)) >= Stream_Capacity(channel->dvc_data)) { error = channel->channel_callback->OnDataReceived(channel->channel_callback, Stream_Capacity(channel->dvc_data), Stream_Buffer(channel->dvc_data)); diff --git a/channels/drdynvc/server/drdynvc_main.c b/channels/drdynvc/server/drdynvc_main.c index 07da57e0c..b6436c6a5 100644 --- a/channels/drdynvc/server/drdynvc_main.c +++ b/channels/drdynvc/server/drdynvc_main.c @@ -86,7 +86,7 @@ static void* drdynvc_server_thread(void* arg) static int drdynvc_server_start(DrdynvcServerContext* context) { - context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpdr", 0); + context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "drdynvc"); if (!context->priv->ChannelHandle) return -1; @@ -109,27 +109,20 @@ static int drdynvc_server_stop(DrdynvcServerContext* context) return 0; } -DrdynvcServerContext* drdynvc_server_context_new(WTSVirtualChannelManager* vcm) +DrdynvcServerContext* drdynvc_server_context_new(HANDLE vcm) { DrdynvcServerContext* context; - context = (DrdynvcServerContext*) malloc(sizeof(DrdynvcServerContext)); + context = (DrdynvcServerContext*) calloc(1, 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)); - } + context->priv = (DrdynvcServerPrivate*) calloc(1, sizeof(DrdynvcServerPrivate)); } return context; diff --git a/channels/drive/client/drive_file.c b/channels/drive/client/drive_file.c index edab10a45..eb430fec6 100644 --- a/channels/drive/client/drive_file.c +++ b/channels/drive/client/drive_file.c @@ -64,7 +64,7 @@ static void drive_file_fix_path(char* path) int i; int length; - length = strlen(path); + length = (int) strlen(path); for (i = 0; i < length; i++) { @@ -177,9 +177,9 @@ static BOOL drive_file_init(DRIVE_FILE* file, UINT32 DesiredAccess, UINT32 Creat struct STAT st; BOOL exists; #ifdef WIN32 - const static int mode = _S_IREAD | _S_IWRITE ; + const static int mode = _S_IREAD | _S_IWRITE ; #else - const static int mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; + const static int mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; BOOL largeFile = FALSE; #endif int oflag = 0; @@ -265,8 +265,10 @@ static BOOL drive_file_init(DRIVE_FILE* file, UINT32 DesiredAccess, UINT32 Creat #ifndef WIN32 if (largeFile) { - oflag |= O_LARGEFILE; + oflag |= O_LARGEFILE; } +#else + oflag |= O_BINARY; #endif file->fd = OPEN(file->fullpath, oflag, mode); @@ -426,7 +428,7 @@ BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, w BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length, wStream* input) { char* s = NULL; - mode_t m; + mode_t m; UINT64 size; int status; char* fullpath; @@ -456,7 +458,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN tv[1].tv_sec = (LastWriteTime > 0 ? FILE_TIME_RDP_TO_SYSTEM(LastWriteTime) : st.st_mtime); tv[1].tv_usec = 0; #ifndef WIN32 -/* TODO on win32 */ + /* TODO on win32 */ #ifdef ANDROID utimes(file->fullpath, tv); #else @@ -474,15 +476,17 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN fchmod(file->fd, st.st_mode); } #endif - break; + break; case FileEndOfFileInformation: /* http://msdn.microsoft.com/en-us/library/cc232067.aspx */ case FileAllocationInformation: /* http://msdn.microsoft.com/en-us/library/cc232076.aspx */ +#ifndef _WIN32 Stream_Read_UINT64(input, size); if (ftruncate(file->fd, size) != 0) return FALSE; +#endif break; case FileDispositionInformation: @@ -509,10 +513,16 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN fullpath = drive_file_combine_fullpath(file->basepath, s); free(s); - /* TODO rename does not work on win32 */ - if (rename(file->fullpath, fullpath) == 0) +#ifdef _WIN32 + if (file->fd) + close(file->fd); +#endif + if (rename(file->fullpath, fullpath) == 0) { drive_file_set_fullpath(file, fullpath); +#ifdef _WIN32 + file->fd = OPEN(fullpath, O_RDWR | O_BINARY); +#endif } else { diff --git a/channels/drive/client/drive_file.h b/channels/drive/client/drive_file.h index 769a18def..28ac5780a 100644 --- a/channels/drive/client/drive_file.h +++ b/channels/drive/client/drive_file.h @@ -40,13 +40,13 @@ #endif #ifdef _WIN32 -#define STAT stat +#define STAT __stat64 #define OPEN _open #define close _close #define read _read #define write _write -#define LSEEK _lseek -#define FSTAT fstat +#define LSEEK _lseeki64 +#define FSTAT _fstat64 #define STATVFS statvfs #define mkdir(a,b) _mkdir(a) #define rmdir _rmdir diff --git a/channels/drive/client/drive_main.c b/channels/drive/client/drive_main.c index e81992764..1ad78fbb3 100644 --- a/channels/drive/client/drive_main.c +++ b/channels/drive/client/drive_main.c @@ -576,29 +576,29 @@ static void drive_process_irp(DRIVE_DEVICE* drive, IRP* irp) static void* drive_thread_func(void* arg) { - IRP* irp; - wMessage message; - DRIVE_DEVICE* drive = (DRIVE_DEVICE*) arg; + IRP* irp; + wMessage message; + DRIVE_DEVICE* drive = (DRIVE_DEVICE*) arg; - while (1) - { - if (!MessageQueue_Wait(drive->IrpQueue)) - break; + while (1) + { + if (!MessageQueue_Wait(drive->IrpQueue)) + break; - if (!MessageQueue_Peek(drive->IrpQueue, &message, TRUE)) - break; + if (!MessageQueue_Peek(drive->IrpQueue, &message, TRUE)) + break; - if (message.id == WMQ_QUIT) - break; + if (message.id == WMQ_QUIT) + break; - irp = (IRP*) message.wParam; + irp = (IRP*) message.wParam; - if (irp) - drive_process_irp(drive, irp); - } + if (irp) + drive_process_irp(drive, irp); + } - ExitThread(0); - return NULL; + ExitThread(0); + return NULL; } static void drive_irp_request(DEVICE* device, IRP* irp) @@ -650,7 +650,7 @@ void drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char* drive->device.IRPRequest = drive_irp_request; drive->device.Free = drive_free; - length = strlen(name); + length = (int) strlen(name); drive->device.data = Stream_New(NULL, length + 1); for (i = 0; i <= length; i++) @@ -712,13 +712,13 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) drive->Path = _strdup("/"); } - drive_register_drive_path(pEntryPoints, drive->Name, drive->Path); + drive_register_drive_path(pEntryPoints, drive->Name, drive->Path); #else sys_code_page = GetACP(); - /* Special case: path[0] == '*' -> export all drives */ + /* Special case: path[0] == '*' -> export all drives */ /* Special case: path[0] == '%' -> user home dir */ - if (strcmp(drive->Path, "%") == 0) + if (strcmp(drive->Path, "%") == 0) { _snprintf(buf, sizeof(buf), "%s\\", getenv("USERPROFILE")); drive_register_drive_path(pEntryPoints, drive->Name, _strdup(buf)); @@ -733,7 +733,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) for (dev = devlist, i = 0; *dev; dev += 4, i++) { if (*dev > 'B') - { + { /* Suppress disk drives A and B to avoid pesty messages */ len = _snprintf(buf, sizeof(buf) - 4, "%s", drive->Name); buf[len] = '_'; @@ -744,11 +744,11 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) } } } - else - { + else + { drive_register_drive_path(pEntryPoints, drive->Name, drive->Path); } #endif - - return 0; - } + + return 0; +} diff --git a/channels/rail/client/rail_main.c b/channels/rail/client/rail_main.c index 7dd557fec..a65e7d29c 100644 --- a/channels/rail/client/rail_main.c +++ b/channels/rail/client/rail_main.c @@ -505,7 +505,7 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) { railPlugin* rail; RailClientContext* context; - CHANNEL_ENTRY_POINTS_EX* pEntryPointsEx; + CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx; rail = (railPlugin*) malloc(sizeof(railPlugin)); ZeroMemory(rail, sizeof(railPlugin)); @@ -523,9 +523,9 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) rail->plugin.event_callback = rail_process_event; rail->plugin.terminate_callback = rail_process_terminate; - pEntryPointsEx = (CHANNEL_ENTRY_POINTS_EX*) pEntryPoints; + pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints; - if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_EX)) && + if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) && (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER)) { context = (RailClientContext*) malloc(sizeof(RailClientContext)); diff --git a/channels/rail/client/rail_orders.c b/channels/rail/client/rail_orders.c index d5d4126bb..3096f543b 100644 --- a/channels/rail/client/rail_orders.c +++ b/channels/rail/client/rail_orders.c @@ -35,7 +35,7 @@ void rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType) { UINT16 orderLength; - orderLength = Stream_GetPosition(s); + orderLength = (UINT16) Stream_GetPosition(s); Stream_SetPosition(s, 0); rail_write_pdu_header(s, orderType, orderLength); diff --git a/channels/rdpdr/client/devman.c b/channels/rdpdr/client/devman.c index 7ff21273f..8ecaf4dd1 100644 --- a/channels/rdpdr/client/devman.c +++ b/channels/rdpdr/client/devman.c @@ -67,6 +67,15 @@ void devman_free(DEVMAN* devman) free(devman); } +void devman_unregister_device(DEVMAN* devman, void* key) +{ + DEVICE* device; + + device = (DEVICE *)ListDictionary_Remove(devman->devices, key); + if (device) + devman_device_free(device); +} + static void devman_register_device(DEVMAN* devman, DEVICE* device) { void* key = NULL; diff --git a/channels/rdpdr/client/devman.h b/channels/rdpdr/client/devman.h index dd2126d91..9164052cd 100644 --- a/channels/rdpdr/client/devman.h +++ b/channels/rdpdr/client/devman.h @@ -23,6 +23,7 @@ #include "rdpdr_main.h" +void devman_unregister_device(DEVMAN* devman, void* key); BOOL devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device); DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id); diff --git a/channels/rdpdr/client/irp.c b/channels/rdpdr/client/irp.c index 12b9ef997..552221e60 100644 --- a/channels/rdpdr/client/irp.c +++ b/channels/rdpdr/client/irp.c @@ -45,7 +45,7 @@ static void irp_complete(IRP* irp) { int pos; - pos = Stream_GetPosition(irp->output); + pos = (int) Stream_GetPosition(irp->output); Stream_SetPosition(irp->output, 12); Stream_Write_UINT32(irp->output, irp->IoStatus); Stream_SetPosition(irp->output, pos); diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index af21f5a26..323dc8a1a 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -33,6 +33,15 @@ #include #include +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#endif + #ifdef HAVE_UNISTD_H #include #endif @@ -44,9 +53,435 @@ #include "rdpdr_main.h" +typedef struct _DEVICE_DRIVE_EXT DEVICE_DRIVE_EXT; + +struct _DEVICE_DRIVE_EXT +{ + DEVICE device; + char* path; +}; + +static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL userLoggedOn); + +static void rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 count, UINT32 ids[]) +{ + wStream* s; + int i; + + s = Stream_New(NULL, 256); + + Stream_Write_UINT16(s, RDPDR_CTYP_CORE); + Stream_Write_UINT16(s, PAKID_CORE_DEVICELIST_REMOVE); + Stream_Write_UINT32(s, count); + + for (i = 0; i < count; i++) + Stream_Write_UINT32(s, ids[i]); + + Stream_SealLength(s); + + rdpdr_send(rdpdr, s); +} + +#ifdef _WIN32 + +LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + rdpdrPlugin *rdpdr; + PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam; + + rdpdr = (rdpdrPlugin *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + + switch(Msg) + { + case WM_DEVICECHANGE: + switch (wParam) + { + case DBT_DEVICEARRIVAL: + if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME) + { + PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb; + DWORD unitmask = lpdbv->dbcv_unitmask; + int i; + char drive_path[4] = { 'c', ':', '/', '\0'}; + + for (i = 0; i < 26; i++) + { + if (unitmask & 0x01) + { + RDPDR_DRIVE* drive; + + drive_path[0] = 'A' + i; + + drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE)); + ZeroMemory(drive, sizeof(RDPDR_DRIVE)); + + drive->Type = RDPDR_DTYP_FILESYSTEM; + + drive->Path = _strdup(drive_path); + drive_path[1] = '\0'; + drive->Name = _strdup(drive_path); + devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive); + rdpdr_send_device_list_announce_request(rdpdr, TRUE); + } + unitmask = unitmask >> 1; + } + } + break; + + case DBT_DEVICEREMOVECOMPLETE: + if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME) + { + PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb; + DWORD unitmask = lpdbv->dbcv_unitmask; + int i, j, count; + char drive_name_upper, drive_name_lower; + + ULONG_PTR *keys; + DEVICE_DRIVE_EXT *device_ext; + UINT32 ids[1]; + + for (i = 0; i < 26; i++) + { + if (unitmask & 0x01) + { + drive_name_upper = 'A' + i; + drive_name_lower = 'a' + i; + + count = ListDictionary_GetKeys(rdpdr->devman->devices, &keys); + + for (j = 0; j < count; j++) + { + device_ext = (DEVICE_DRIVE_EXT *)ListDictionary_GetItemValue(rdpdr->devman->devices, (void *)keys[j]); + if (device_ext->path[0] == drive_name_upper || device_ext->path[0] == drive_name_lower) + { + devman_unregister_device(rdpdr->devman, (void *)keys[j]); + ids[0] = keys[j]; + rdpdr_send_device_list_remove_request(rdpdr, 1, ids); + break; + } + } + } + unitmask = unitmask >> 1; + } + } + break; + + default: + break; + } + break; + + default: + return DefWindowProc(hWnd, Msg, wParam, lParam); + } + return DefWindowProc(hWnd, Msg, wParam, lParam); +} + +static void* drive_hotplug_thread_func(void* arg) +{ + rdpdrPlugin *rdpdr; + WNDCLASSEX wnd_cls; + HWND hwnd; + MSG msg; + BOOL bRet; + DEV_BROADCAST_HANDLE NotificationFilter; + HDEVNOTIFY hDevNotify; + + rdpdr = (rdpdrPlugin *)arg; + + /* init windows class */ + wnd_cls.cbSize = sizeof(WNDCLASSEX); + wnd_cls.style = CS_HREDRAW | CS_VREDRAW; + wnd_cls.lpfnWndProc = hotplug_proc; + wnd_cls.cbClsExtra = 0; + wnd_cls.cbWndExtra = 0; + wnd_cls.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wnd_cls.hCursor = NULL; + wnd_cls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); + wnd_cls.lpszMenuName = NULL; + wnd_cls.lpszClassName = L"DRIVE_HOTPLUG"; + wnd_cls.hInstance = NULL; + wnd_cls.hIconSm = LoadIcon(NULL, IDI_APPLICATION); + RegisterClassEx(&wnd_cls); + + /* create window */ + hwnd = CreateWindowEx(0, L"DRIVE_HOTPLUG", NULL, + 0, 0, 0, 0, 0, + NULL, NULL, NULL, NULL); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)rdpdr); + + rdpdr->hotplug_wnd = hwnd; + /* register device interface to hwnd */ + NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE); + NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE; + hDevNotify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE); + + /* message loop */ + while ((bRet = GetMessage(&msg, 0, 0, 0)) != 0) + { + if (bRet == -1) + { + break; + } + else + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + UnregisterDeviceNotification(hDevNotify); + + return NULL; +} + +static void drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) +{ + if (rdpdr->hotplug_wnd) + PostMessage(rdpdr->hotplug_wnd, WM_QUIT, 0, 0); +} + +#else + +#define MAX_USB_DEVICES 100 + +typedef struct _hotplug_dev { + char* path; + BOOL to_add; +} hotplug_dev; + +static char* next_line(FILE* fd, size_t* len) +{ + size_t newsiz; + int c; + char* newbuf; + char* lrbuf; + int lrsiz; + + *len = 0; + lrsiz = 0; + lrbuf = NULL; + newbuf = NULL; + + for (;;) + { + c = fgetc(fd); + if (ferror(fd)) + return NULL; + + if (c == EOF) + { + if (*len == 0) + return NULL; + else + { + lrbuf[(*len)] = '\0'; + return lrbuf; + } + } + else + { + if (*len == lrsiz) + { + newsiz = lrsiz + 4096; + newbuf = realloc(lrbuf, newsiz); + if (newbuf == NULL) + return NULL; + lrbuf = newbuf; + lrsiz = newsiz; + } + lrbuf[(*len)] = c; + + if (c == '\n') + { + lrbuf[(*len)] = '\0'; + return lrbuf; + } + + (*len)++; + } + } +} + +static char* get_word(char* str, unsigned int* offset) +{ + char* p; + char* tmp; + int wlen; + + if (*offset >= strlen(str)) + return NULL; + + p = str + *offset; + tmp = p; + + while (*tmp != ' ' && *tmp != '\0') + tmp++; + + wlen = tmp - p; + *offset += wlen; + + /* in case there are more than one space between words */ + while (*(str + *offset) == ' ') + (*offset)++; + + return strndup(p, wlen); +} + +static void handle_hotplug(rdpdrPlugin* rdpdr) +{ + FILE *f; + size_t len; + char *line; + char *word; + unsigned int wlen; + + hotplug_dev dev_array[MAX_USB_DEVICES]; + int i, j; + int size = 0; + + int count; + DEVICE_DRIVE_EXT *device_ext; + ULONG_PTR *keys; + UINT32 ids[1]; + + f = fopen("/proc/mounts", "r"); + if (f == NULL) + { + return; + } + + while ((line = next_line(f, &len))) + { + wlen = 0; + while ((word = get_word(line, &wlen))) + { + /* copy hotpluged device mount point to the dev_array */ + if (strstr(word, "/mnt/") != NULL || strstr(word, "/media/") != NULL) + { + dev_array[size].path = strdup(word); + dev_array[size++].to_add = TRUE; + } + free(word); + } + free(line); + } + + fclose(f); + + /* delete removed devices */ + count = ListDictionary_GetKeys(rdpdr->devman->devices, &keys); + + for (j = 0; j < count; j++) + { + BOOL dev_found = FALSE; + + device_ext = (DEVICE_DRIVE_EXT *)ListDictionary_GetItemValue(rdpdr->devman->devices, (void *)keys[j]); + + /* not plugable device */ + if (strstr(device_ext->path, "/mnt/") == NULL && strstr(device_ext->path, "/media/") == NULL) + continue; + + for (i = 0; i < size; i++) + { + if (strstr(device_ext->path, dev_array[i].path) != NULL) + { + dev_found = TRUE; + dev_array[i].to_add = FALSE; + break; + } + } + + if (!dev_found) + { + devman_unregister_device(rdpdr->devman, (void *)keys[j]); + ids[0] = keys[j]; + rdpdr_send_device_list_remove_request(rdpdr, 1, ids); + } + } + + /* add new devices */ + for (i = 0; i < size; i++) + { + RDPDR_DRIVE* drive; + + if (dev_array[i].to_add) + { + char* name; + + drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE)); + ZeroMemory(drive, sizeof(RDPDR_DRIVE)); + + drive->Type = RDPDR_DTYP_FILESYSTEM; + + drive->Path = _strdup(dev_array[i].path); + name = strrchr(drive->Path, '/') + 1; + drive->Name = _strdup(name); + devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive); + } + + free(dev_array[i].path); + dev_array[i].path = NULL; + } + rdpdr_send_device_list_announce_request(rdpdr, TRUE); +} + +static void* drive_hotplug_thread_func(void* arg) +{ + rdpdrPlugin* rdpdr; + int mfd; + fd_set rfds; + struct timeval tv; + int rv; + + rdpdr = (rdpdrPlugin *)arg; + + rdpdr->stop_event = CreateEvent(NULL, TRUE, FALSE, NULL); + + mfd = open("/proc/mounts", O_RDONLY, 0); + if (mfd < 0) + { + fprintf(stderr, "ERROR: Unable to open /proc/mounts."); + return NULL; + } + + FD_ZERO(&rfds); + FD_SET(mfd, &rfds); + tv.tv_sec = 1; + tv.tv_usec = 0; + + while ((rv = select(mfd+1, NULL, NULL, &rfds, &tv)) >= 0) + { + if (WaitForSingleObject(rdpdr->stop_event, 0) == WAIT_OBJECT_0) + break; + + if (FD_ISSET(mfd, &rfds)) + { + /* file /proc/mounts changed, handle this */ + handle_hotplug(rdpdr); + } + + FD_ZERO(&rfds); + FD_SET(mfd, &rfds); + tv.tv_sec = 1; + tv.tv_usec = 0; + } + + return NULL; +} + +static void drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) +{ + if (rdpdr->stop_event) + SetEvent(rdpdr->stop_event); +} + +#endif + + static void rdpdr_process_connect(rdpdrPlugin* rdpdr) { - int index; + UINT32 index; RDPDR_DEVICE* device; rdpSettings* settings; @@ -58,6 +493,11 @@ static void rdpdr_process_connect(rdpdrPlugin* rdpdr) for (index = 0; index < settings->DeviceCount; index++) { device = settings->DeviceArray[index]; + if (strcmp(device->Name, "*") == 0) + { + rdpdr->hotplug_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)drive_hotplug_thread_func, rdpdr, 0, NULL); + continue; + } devman_load_device_service(rdpdr->devman, device); } } @@ -153,7 +593,7 @@ static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL use Stream_Write_UINT16(s, RDPDR_CTYP_CORE); Stream_Write_UINT16(s, PAKID_CORE_DEVICELIST_ANNOUNCE); - count_pos = Stream_GetPosition(s); + count_pos = (int) Stream_GetPosition(s); count = 0; Stream_Seek_UINT32(s); /* deviceCount */ @@ -175,7 +615,7 @@ static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL use if ((rdpdr->versionMinor == 0x0005) || (device->type == RDPDR_DTYP_SMARTCARD) || userLoggedOn) { - data_len = (device->data == NULL ? 0 : Stream_GetPosition(device->data)); + data_len = (int) (device->data == NULL ? 0 : Stream_GetPosition(device->data)); Stream_EnsureRemainingCapacity(s, 20 + data_len); Stream_Write_UINT32(s, device->type); /* deviceType */ @@ -207,7 +647,7 @@ static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL use if (pKeys) free(pKeys); - pos = Stream_GetPosition(s); + pos = (int) Stream_GetPosition(s); Stream_SetPosition(s, count_pos); Stream_Write_UINT32(s, count); Stream_SetPosition(s, pos); @@ -349,10 +789,14 @@ int rdpdr_send(rdpdrPlugin* rdpdr, wStream* s) rdpdrPlugin* plugin = (rdpdrPlugin*) rdpdr; if (!plugin) + { status = CHANNEL_RC_BAD_INIT_HANDLE; + } else + { status = plugin->channelEntryPoints.pVirtualChannelWrite(plugin->OpenHandle, - Stream_Buffer(s), Stream_GetPosition(s), s); + Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s); + } if (status != CHANNEL_RC_OK) { @@ -406,8 +850,8 @@ static void rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, } } -static void rdpdr_virtual_channel_open_event(UINT32 openHandle, UINT32 event, - void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) +static VOID VCAPITYPE rdpdr_virtual_channel_open_event(DWORD openHandle, UINT event, + LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { rdpdrPlugin* rdpdr; @@ -464,7 +908,7 @@ static void* rdpdr_virtual_channel_client_thread(void* arg) return NULL; } -static void rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, void* pData, UINT32 dataLength) +static void rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, LPVOID pData, UINT32 dataLength) { UINT32 status; @@ -493,6 +937,10 @@ static void rdpdr_virtual_channel_event_terminated(rdpdrPlugin* rdpdr) MessagePipe_Free(rdpdr->MsgPipe); CloseHandle(rdpdr->thread); + drive_hotplug_thread_terminate(rdpdr); + + WaitForSingleObject(rdpdr->hotplug_thread, INFINITE); + rdpdr->channelEntryPoints.pVirtualChannelClose(rdpdr->OpenHandle); if (rdpdr->data_in) @@ -511,7 +959,7 @@ static void rdpdr_virtual_channel_event_terminated(rdpdrPlugin* rdpdr) rdpdr_remove_init_handle_data(rdpdr->InitHandle); } -static void rdpdr_virtual_channel_init_event(void* pInitHandle, UINT32 event, void* pData, UINT32 dataLength) +static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength) { rdpdrPlugin* rdpdr; @@ -545,8 +993,10 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) { rdpdrPlugin* rdpdr; - rdpdr = (rdpdrPlugin*) malloc(sizeof(rdpdrPlugin)); - ZeroMemory(rdpdr, sizeof(rdpdrPlugin)); + rdpdr = (rdpdrPlugin*) calloc(1, sizeof(rdpdrPlugin)); + + if (!rdpdr) + return -1; rdpdr->channelDef.options = CHANNEL_OPTION_INITIALIZED | @@ -555,7 +1005,7 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) strcpy(rdpdr->channelDef.name, "rdpdr"); - CopyMemory(&(rdpdr->channelEntryPoints), pEntryPoints, pEntryPoints->cbSize); + CopyMemory(&(rdpdr->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP)); rdpdr->channelEntryPoints.pVirtualChannelInit(&rdpdr->InitHandle, &rdpdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, rdpdr_virtual_channel_init_event); diff --git a/channels/rdpdr/client/rdpdr_main.h b/channels/rdpdr/client/rdpdr_main.h index f0699fce9..a0d6dd8f6 100644 --- a/channels/rdpdr/client/rdpdr_main.h +++ b/channels/rdpdr/client/rdpdr_main.h @@ -38,12 +38,12 @@ typedef struct rdpdr_plugin rdpdrPlugin; struct rdpdr_plugin { CHANNEL_DEF channelDef; - CHANNEL_ENTRY_POINTS_EX channelEntryPoints; + CHANNEL_ENTRY_POINTS_FREERDP channelEntryPoints; HANDLE thread; wStream* data_in; void* InitHandle; - UINT32 OpenHandle; + DWORD OpenHandle; wMessagePipe* MsgPipe; DEVMAN* devman; @@ -52,6 +52,14 @@ struct rdpdr_plugin UINT16 versionMinor; UINT16 clientID; char computerName[256]; + + /* hotplug support */ + HANDLE hotplug_thread; +#ifdef _WIN32 + HWND hotplug_wnd; +#else + HANDLE stop_event; +#endif }; int rdpdr_send(rdpdrPlugin* rdpdr, wStream* s); diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c index 16c150eaa..f7bee4aea 100644 --- a/channels/rdpdr/server/rdpdr_main.c +++ b/channels/rdpdr/server/rdpdr_main.c @@ -630,7 +630,7 @@ static void* rdpdr_server_thread(void* arg) static int rdpdr_server_start(RdpdrServerContext* context) { - context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpdr", 0); + context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "rdpdr"); if (!context->priv->ChannelHandle) return -1; @@ -653,7 +653,7 @@ static int rdpdr_server_stop(RdpdrServerContext* context) return 0; } -RdpdrServerContext* rdpdr_server_context_new(WTSVirtualChannelManager* vcm) +RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm) { RdpdrServerContext* context; diff --git a/channels/rdpei/client/rdpei_main.c b/channels/rdpei/client/rdpei_main.c index 0bd813900..08ba4bca4 100644 --- a/channels/rdpei/client/rdpei_main.c +++ b/channels/rdpei/client/rdpei_main.c @@ -211,7 +211,7 @@ int rdpei_send_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s, UINT16 eventId, Stream_Write_UINT32(s, pduLength); /* pduLength (4 bytes) */ Stream_SetPosition(s, Stream_Length(s)); - status = callback->channel->Write(callback->channel, Stream_Length(s), Stream_Buffer(s), NULL); + status = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), Stream_Buffer(s), NULL); #ifdef WITH_DEBUG_RDPEI fprintf(stderr, "rdpei_send_pdu: eventId: %d (%s) length: %d status: %d\n", @@ -267,7 +267,7 @@ void rdpei_print_contact_flags(UINT32 contactFlags) int rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame) { - int index; + UINT32 index; int rectSize = 2; RDPINPUT_CONTACT_DATA* contact; @@ -284,7 +284,7 @@ int rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame) */ rdpei_write_8byte_unsigned(s, frame->frameOffset * 1000); /* frameOffset (EIGHT_BYTE_UNSIGNED_INTEGER) */ - Stream_EnsureRemainingCapacity(s, frame->contactCount * 64); + Stream_EnsureRemainingCapacity(s, (size_t) frame->contactCount * 64); for (index = 0; index < frame->contactCount; index++) { @@ -360,7 +360,7 @@ int rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, RDPINPUT_TOUCH_ * the time that has elapsed (in milliseconds) from when the oldest touch frame * was generated to when it was encoded for transmission by the client. */ - rdpei_write_4byte_unsigned(s, frame->frameOffset); /* encodeTime (FOUR_BYTE_UNSIGNED_INTEGER) */ + rdpei_write_4byte_unsigned(s, (UINT32) frame->frameOffset); /* encodeTime (FOUR_BYTE_UNSIGNED_INTEGER) */ rdpei_write_2byte_unsigned(s, 1); /* (frameCount) TWO_BYTE_UNSIGNED_INTEGER */ diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index 3c485cacd..3d4cc1900 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -55,12 +55,12 @@ struct rdpsnd_plugin { CHANNEL_DEF channelDef; - CHANNEL_ENTRY_POINTS_EX channelEntryPoints; + CHANNEL_ENTRY_POINTS_FREERDP channelEntryPoints; HANDLE thread; wStream* data_in; void* InitHandle; - UINT32 OpenHandle; + DWORD OpenHandle; wMessagePipe* MsgPipe; wLog* log; @@ -453,7 +453,7 @@ static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s) CopyMemory(Stream_Buffer(s), rdpsnd->waveData, 4); data = Stream_Buffer(s); - size = Stream_Capacity(s); + size = (int) Stream_Capacity(s); wave = (RDPSND_WAVE*) malloc(sizeof(RDPSND_WAVE)); @@ -866,10 +866,14 @@ int rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s) UINT32 status = 0; if (!rdpsnd) + { status = CHANNEL_RC_BAD_INIT_HANDLE; + } else + { status = rdpsnd->channelEntryPoints.pVirtualChannelWrite(rdpsnd->OpenHandle, - Stream_Buffer(s), Stream_GetPosition(s), s); + Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s); + } if (status != CHANNEL_RC_OK) { @@ -917,8 +921,8 @@ static void rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin, } } -static void rdpsnd_virtual_channel_open_event(UINT32 openHandle, UINT32 event, - void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) +static VOID VCAPITYPE rdpsnd_virtual_channel_open_event(DWORD openHandle, UINT event, + LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { rdpsndPlugin* plugin; @@ -975,7 +979,7 @@ static void* rdpsnd_virtual_channel_client_thread(void* arg) return NULL; } -static void rdpsnd_virtual_channel_event_connected(rdpsndPlugin* plugin, void* pData, UINT32 dataLength) +static void rdpsnd_virtual_channel_event_connected(rdpsndPlugin* plugin, LPVOID pData, UINT32 dataLength) { UINT32 status; @@ -1031,7 +1035,7 @@ static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd) rdpsnd_remove_init_handle_data(rdpsnd->InitHandle); } -static void rdpsnd_virtual_channel_init_event(void* pInitHandle, UINT32 event, void* pData, UINT32 dataLength) +static VOID VCAPITYPE rdpsnd_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength) { rdpsndPlugin* plugin; @@ -1086,7 +1090,7 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) strcpy(rdpsnd->channelDef.name, "rdpsnd"); - CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints, pEntryPoints->cbSize); + CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP)); rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client"); diff --git a/channels/rdpsnd/client/winmm/rdpsnd_winmm.c b/channels/rdpsnd/client/winmm/rdpsnd_winmm.c index b19f114ba..7c1e47cd0 100644 --- a/channels/rdpsnd/client/winmm/rdpsnd_winmm.c +++ b/channels/rdpsnd/client/winmm/rdpsnd_winmm.c @@ -95,7 +95,6 @@ static void rdpsnd_winmm_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* fo static void CALLBACK rdpsnd_winmm_callback_function(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { - MMRESULT mmResult; RDPSND_WAVE* wave; LPWAVEHDR lpWaveHdr; rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) dwInstance; diff --git a/channels/rdpsnd/server/CMakeLists.txt b/channels/rdpsnd/server/CMakeLists.txt index a5f784679..9cb5c1d6f 100644 --- a/channels/rdpsnd/server/CMakeLists.txt +++ b/channels/rdpsnd/server/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) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) diff --git a/channels/rdpsnd/server/rdpsnd_main.c b/channels/rdpsnd/server/rdpsnd_main.c index 4bc7107d5..91d5949b9 100644 --- a/channels/rdpsnd/server/rdpsnd_main.c +++ b/channels/rdpsnd/server/rdpsnd_main.c @@ -201,12 +201,7 @@ static void* rdpsnd_server_thread(void* arg) 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 + (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE) { if (!BytesReturned) break; @@ -488,7 +483,7 @@ static BOOL rdpsnd_server_close(RdpsndServerContext* context) static int rdpsnd_server_start(RdpsndServerContext* context) { - context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpsnd", 0); + context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "rdpsnd"); if (!context->priv->ChannelHandle) return -1; @@ -513,7 +508,7 @@ static int rdpsnd_server_stop(RdpsndServerContext* context) return 0; } -RdpsndServerContext* rdpsnd_server_context_new(WTSVirtualChannelManager* vcm) +RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm) { RdpsndServerContext* context; diff --git a/channels/server/channels.c b/channels/server/channels.c index 35da5afb2..1f470e6e9 100644 --- a/channels/server/channels.c +++ b/channels/server/channels.c @@ -67,840 +67,3 @@ void freerdp_channels_dummy() /** * end of ugly symbols import workaround */ - -#define CREATE_REQUEST_PDU 0x01 -#define DATA_FIRST_PDU 0x02 -#define DATA_PDU 0x03 -#define CLOSE_REQUEST_PDU 0x04 -#define CAPABILITY_REQUEST_PDU 0x05 - -typedef struct wts_data_item -{ - UINT16 channel_id; - BYTE* buffer; - UINT32 length; -} wts_data_item; - -static void wts_data_item_free(wts_data_item* item) -{ - free(item->buffer); - free(item); -} - -void* freerdp_channels_server_find_static_entry(const char* name, const char* entry) -{ - return NULL; -} - -static rdpPeerChannel* wts_get_dvc_channel_by_id(WTSVirtualChannelManager* vcm, UINT32 ChannelId) -{ - LIST_ITEM* item; - rdpPeerChannel* channel = NULL; - - for (item = vcm->dvc_channel_list->head; item; item = item->next) - { - channel = (rdpPeerChannel*) item->data; - - if (channel->channel_id == ChannelId) - break; - } - - return channel; -} - -static void wts_queue_receive_data(rdpPeerChannel* channel, const BYTE* buffer, UINT32 length) -{ - wts_data_item* item; - - item = (wts_data_item*) malloc(sizeof(wts_data_item)); - ZeroMemory(item, sizeof(wts_data_item)); - - item->length = length; - item->buffer = malloc(length); - CopyMemory(item->buffer, buffer, length); - - WaitForSingleObject(channel->mutex, INFINITE); - list_enqueue(channel->receive_queue, item); - ReleaseMutex(channel->mutex); - - SetEvent(channel->receive_event); -} - -static void wts_queue_send_item(rdpPeerChannel* channel, wts_data_item* item) -{ - WTSVirtualChannelManager* vcm; - - vcm = channel->vcm; - - item->channel_id = channel->channel_id; - - WaitForSingleObject(vcm->mutex, INFINITE); - list_enqueue(vcm->send_queue, item); - ReleaseMutex(vcm->mutex); - - SetEvent(vcm->send_event); -} - -static int wts_read_variable_uint(wStream* s, int cbLen, UINT32* val) -{ - switch (cbLen) - { - case 0: - if (Stream_GetRemainingLength(s) < 1) - return 0; - Stream_Read_UINT8(s, *val); - return 1; - - case 1: - if (Stream_GetRemainingLength(s) < 2) - return 0; - Stream_Read_UINT16(s, *val); - return 2; - - default: - if (Stream_GetRemainingLength(s) < 4) - return 0; - Stream_Read_UINT32(s, *val); - return 4; - } -} - -static void wts_read_drdynvc_capabilities_response(rdpPeerChannel* channel, UINT32 length) -{ - UINT16 Version; - - if (length < 3) - return; - - Stream_Seek_UINT8(channel->receive_data); /* Pad (1 byte) */ - Stream_Read_UINT16(channel->receive_data, Version); - - DEBUG_DVC("Version: %d", Version); - - channel->vcm->drdynvc_state = DRDYNVC_STATE_READY; -} - -static void wts_read_drdynvc_create_response(rdpPeerChannel* channel, wStream* s, UINT32 length) -{ - UINT32 CreationStatus; - - if (length < 4) - return; - - Stream_Read_UINT32(s, CreationStatus); - - if ((INT32) CreationStatus < 0) - { - DEBUG_DVC("ChannelId %d creation failed (%d)", channel->channel_id, (INT32) CreationStatus); - channel->dvc_open_state = DVC_OPEN_STATE_FAILED; - } - else - { - DEBUG_DVC("ChannelId %d creation succeeded", channel->channel_id); - channel->dvc_open_state = DVC_OPEN_STATE_SUCCEEDED; - } - - SetEvent(channel->receive_event); -} - -static void wts_read_drdynvc_data_first(rdpPeerChannel* channel, wStream* s, int cbLen, UINT32 length) -{ - int value; - - value = wts_read_variable_uint(s, cbLen, &channel->dvc_total_length); - - if (value == 0) - return; - - length -= value; - - if (length > channel->dvc_total_length) - return; - - Stream_SetPosition(channel->receive_data, 0); - Stream_EnsureRemainingCapacity(channel->receive_data, (int) channel->dvc_total_length); - Stream_Write(channel->receive_data, Stream_Pointer(s), length); -} - -static void wts_read_drdynvc_data(rdpPeerChannel* channel, wStream* s, UINT32 length) -{ - if (channel->dvc_total_length > 0) - { - if (Stream_GetPosition(channel->receive_data) + length > channel->dvc_total_length) - { - channel->dvc_total_length = 0; - fprintf(stderr, "wts_read_drdynvc_data: incorrect fragment data, discarded.\n"); - return; - } - - Stream_Write(channel->receive_data, Stream_Pointer(s), length); - - if (Stream_GetPosition(channel->receive_data) >= (int) channel->dvc_total_length) - { - wts_queue_receive_data(channel, Stream_Buffer(channel->receive_data), channel->dvc_total_length); - channel->dvc_total_length = 0; - } - } - else - { - wts_queue_receive_data(channel, Stream_Pointer(s), length); - } -} - -static void wts_read_drdynvc_close_response(rdpPeerChannel* channel) -{ - DEBUG_DVC("ChannelId %d close response", channel->channel_id); - channel->dvc_open_state = DVC_OPEN_STATE_CLOSED; -} - -static void wts_read_drdynvc_pdu(rdpPeerChannel* channel) -{ - UINT32 length; - int value; - int Cmd; - int Sp; - int cbChId; - UINT32 ChannelId; - rdpPeerChannel* dvc; - - length = Stream_GetPosition(channel->receive_data); - - if (length < 1) - return; - - Stream_SetPosition(channel->receive_data, 0); - Stream_Read_UINT8(channel->receive_data, value); - - length--; - Cmd = (value & 0xf0) >> 4; - Sp = (value & 0x0c) >> 2; - cbChId = (value & 0x03) >> 0; - - if (Cmd == CAPABILITY_REQUEST_PDU) - { - wts_read_drdynvc_capabilities_response(channel, length); - } - else if (channel->vcm->drdynvc_state == DRDYNVC_STATE_READY) - { - value = wts_read_variable_uint(channel->receive_data, cbChId, &ChannelId); - - if (value == 0) - return; - - length -= value; - - DEBUG_DVC("Cmd %d ChannelId %d length %d", Cmd, ChannelId, length); - dvc = wts_get_dvc_channel_by_id(channel->vcm, ChannelId); - - if (dvc) - { - switch (Cmd) - { - case CREATE_REQUEST_PDU: - wts_read_drdynvc_create_response(dvc, channel->receive_data, length); - break; - - case DATA_FIRST_PDU: - wts_read_drdynvc_data_first(dvc, channel->receive_data, Sp, length); - break; - - case DATA_PDU: - wts_read_drdynvc_data(dvc, channel->receive_data, length); - break; - - case CLOSE_REQUEST_PDU: - wts_read_drdynvc_close_response(dvc); - break; - - default: - fprintf(stderr, "wts_read_drdynvc_pdu: Cmd %d not recognized.\n", Cmd); - break; - } - } - else - { - DEBUG_DVC("ChannelId %d not exists.", ChannelId); - } - } - else - { - fprintf(stderr, "wts_read_drdynvc_pdu: received Cmd %d but channel is not ready.\n", Cmd); - } -} - -static int wts_write_variable_uint(wStream* stream, UINT32 val) -{ - int cb; - - if (val <= 0xFF) - { - cb = 0; - Stream_Write_UINT8(stream, val); - } - else if (val <= 0xFFFF) - { - cb = 1; - Stream_Write_UINT16(stream, val); - } - else - { - cb = 3; - Stream_Write_UINT32(stream, val); - } - - return cb; -} - -static void wts_write_drdynvc_header(wStream *s, BYTE Cmd, UINT32 ChannelId) -{ - BYTE* bm; - int cbChId; - - Stream_GetPointer(s, bm); - Stream_Seek_UINT8(s); - cbChId = wts_write_variable_uint(s, ChannelId); - *bm = ((Cmd & 0x0F) << 4) | cbChId; -} - -static void wts_write_drdynvc_create_request(wStream *s, UINT32 ChannelId, const char *ChannelName) -{ - UINT32 len; - - wts_write_drdynvc_header(s, CREATE_REQUEST_PDU, ChannelId); - len = strlen(ChannelName) + 1; - Stream_EnsureRemainingCapacity(s, (int) len); - Stream_Write(s, ChannelName, len); -} - -static void WTSProcessChannelData(rdpPeerChannel* channel, int channelId, BYTE* data, int size, int flags, int total_size) -{ - if (flags & CHANNEL_FLAG_FIRST) - { - Stream_SetPosition(channel->receive_data, 0); - } - - Stream_EnsureRemainingCapacity(channel->receive_data, size); - Stream_Write(channel->receive_data, data, size); - - if (flags & CHANNEL_FLAG_LAST) - { - if (Stream_GetPosition(channel->receive_data) != total_size) - { - fprintf(stderr, "WTSProcessChannelData: read error\n"); - } - if (channel == channel->vcm->drdynvc_channel) - { - wts_read_drdynvc_pdu(channel); - } - else - { - wts_queue_receive_data(channel, Stream_Buffer(channel->receive_data), Stream_GetPosition(channel->receive_data)); - } - Stream_SetPosition(channel->receive_data, 0); - } -} - -static int WTSReceiveChannelData(freerdp_peer* client, int channelId, BYTE* data, int size, int flags, int total_size) -{ - int i; - BOOL result = FALSE; - rdpPeerChannel* channel; - - for (i = 0; i < client->settings->ChannelCount; i++) - { - if (client->settings->ChannelDefArray[i].ChannelId == channelId) - break; - } - - if (i < client->settings->ChannelCount) - { - channel = (rdpPeerChannel*) client->settings->ChannelDefArray[i].handle; - - if (channel != NULL) - { - WTSProcessChannelData(channel, channelId, data, size, flags, total_size); - result = TRUE; - } - } - - return result; -} - -WTSVirtualChannelManager* WTSCreateVirtualChannelManager(freerdp_peer* client) -{ - WTSVirtualChannelManager* vcm; - - vcm = (WTSVirtualChannelManager*) malloc(sizeof(WTSVirtualChannelManager)); - - if (vcm) - { - ZeroMemory(vcm, sizeof(WTSVirtualChannelManager)); - - vcm->client = client; - vcm->send_event = CreateEvent(NULL, TRUE, FALSE, NULL); - vcm->send_queue = list_new(); - vcm->mutex = CreateMutex(NULL, FALSE, NULL); - vcm->dvc_channel_id_seq = 1; - vcm->dvc_channel_list = list_new(); - - client->ReceiveChannelData = WTSReceiveChannelData; - } - - return vcm; -} - -void WTSDestroyVirtualChannelManager(WTSVirtualChannelManager* vcm) -{ - wts_data_item* item; - rdpPeerChannel* channel; - - if (vcm != NULL) - { - while ((channel = (rdpPeerChannel*) list_dequeue(vcm->dvc_channel_list)) != NULL) - { - WTSVirtualChannelClose(channel); - } - - list_free(vcm->dvc_channel_list); - - if (vcm->drdynvc_channel != NULL) - { - WTSVirtualChannelClose(vcm->drdynvc_channel); - vcm->drdynvc_channel = NULL; - } - - CloseHandle(vcm->send_event); - - while ((item = (wts_data_item*) list_dequeue(vcm->send_queue)) != NULL) - { - wts_data_item_free(item); - } - - list_free(vcm->send_queue); - CloseHandle(vcm->mutex); - free(vcm); - } -} - -void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm, void** fds, int* fds_count) -{ - void* fd; - - fd = GetEventWaitObject(vcm->send_event); - - if (fd) - { - fds[*fds_count] = fd; - (*fds_count)++; - } - - if (vcm->drdynvc_channel) - { - fd = GetEventWaitObject(vcm->drdynvc_channel->receive_event); - - if (fd) - { - fds[*fds_count] = fd; - (*fds_count)++; - } - } -} - -BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm) -{ - BOOL result = TRUE; - wts_data_item* item; - rdpPeerChannel* channel; - UINT32 dynvc_caps; - - if (vcm->drdynvc_state == DRDYNVC_STATE_NONE && vcm->client->activated) - { - /* Initialize drdynvc channel once and only once. */ - vcm->drdynvc_state = DRDYNVC_STATE_INITIALIZED; - - channel = WTSVirtualChannelManagerOpenEx(vcm, "drdynvc", 0); - - if (channel) - { - vcm->drdynvc_channel = channel; - dynvc_caps = 0x00010050; /* DYNVC_CAPS_VERSION1 (4 bytes) */ - WTSVirtualChannelWrite(channel, (PCHAR) &dynvc_caps, sizeof(dynvc_caps), NULL); - } - } - - ResetEvent(vcm->send_event); - - WaitForSingleObject(vcm->mutex, INFINITE); - - while ((item = (wts_data_item*) list_dequeue(vcm->send_queue)) != NULL) - { - if (vcm->client->SendChannelData(vcm->client, item->channel_id, item->buffer, item->length) == FALSE) - { - result = FALSE; - } - - wts_data_item_free(item); - - if (result == FALSE) - break; - } - - ReleaseMutex(vcm->mutex); - - return result; -} - -HANDLE WTSVirtualChannelManagerGetEventHandle(WTSVirtualChannelManager* vcm) -{ - return vcm->send_event; -} - -HANDLE WTSVirtualChannelManagerOpenEx(WTSVirtualChannelManager* vcm, LPSTR pVirtualName, DWORD flags) -{ - int i; - int len; - wStream* s; - rdpPeerChannel* channel; - freerdp_peer* client = vcm->client; - - if ((flags & WTS_CHANNEL_OPTION_DYNAMIC) != 0) - { - for (i = 0; i < client->settings->ChannelCount; i++) - { - if (client->settings->ChannelDefArray[i].joined && - strncmp(client->settings->ChannelDefArray[i].Name, "drdynvc", 7) == 0) - { - break; - } - } - if (i >= client->settings->ChannelCount) - { - DEBUG_DVC("Dynamic virtual channel not registered."); - SetLastError(ERROR_NOT_FOUND); - return NULL; - } - - if (vcm->drdynvc_channel == NULL || vcm->drdynvc_state != DRDYNVC_STATE_READY) - { - DEBUG_DVC("Dynamic virtual channel not ready."); - SetLastError(ERROR_NOT_READY); - return NULL; - } - - channel = (rdpPeerChannel*) malloc(sizeof(rdpPeerChannel)); - ZeroMemory(channel, sizeof(rdpPeerChannel)); - - channel->vcm = vcm; - channel->client = client; - channel->channel_type = RDP_PEER_CHANNEL_TYPE_DVC; - channel->receive_data = Stream_New(NULL, client->settings->VirtualChannelChunkSize); - channel->receive_event = CreateEvent(NULL, TRUE, FALSE, NULL); - channel->receive_queue = list_new(); - channel->mutex = CreateMutex(NULL, FALSE, NULL); - - WaitForSingleObject(vcm->mutex, INFINITE); - channel->channel_id = vcm->dvc_channel_id_seq++; - list_enqueue(vcm->dvc_channel_list, channel); - ReleaseMutex(vcm->mutex); - - s = Stream_New(NULL, 64); - wts_write_drdynvc_create_request(s, channel->channel_id, pVirtualName); - 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)); - } - else - { - len = strlen(pVirtualName); - - if (len > 8) - { - SetLastError(ERROR_NOT_FOUND); - return NULL; - } - - for (i = 0; i < client->settings->ChannelCount; i++) - { - if (client->settings->ChannelDefArray[i].joined && - strncmp(client->settings->ChannelDefArray[i].Name, pVirtualName, len) == 0) - { - break; - } - } - - if (i >= client->settings->ChannelCount) - { - SetLastError(ERROR_NOT_FOUND); - return NULL; - } - - channel = (rdpPeerChannel*) client->settings->ChannelDefArray[i].handle; - - if (channel == NULL) - { - channel = (rdpPeerChannel*) malloc(sizeof(rdpPeerChannel)); - ZeroMemory(channel, sizeof(rdpPeerChannel)); - - channel->vcm = vcm; - channel->client = client; - channel->channel_id = client->settings->ChannelDefArray[i].ChannelId; - channel->index = i; - channel->channel_type = RDP_PEER_CHANNEL_TYPE_SVC; - channel->receive_data = Stream_New(NULL, client->settings->VirtualChannelChunkSize); - channel->receive_event = CreateEvent(NULL, TRUE, FALSE, NULL); - channel->receive_queue = list_new(); - channel->mutex = CreateMutex(NULL, FALSE, NULL); - - client->settings->ChannelDefArray[i].handle = channel; - } - } - - return channel; -} - -BOOL WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned) -{ - void* pfd; - BOOL bval; - void* fds[10]; - int fds_count = 0; - BOOL result = FALSE; - rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; - ZeroMemory(fds, sizeof(fds)); - - switch (WtsVirtualClass) - { - case WTSVirtualFileHandle: - - pfd = GetEventWaitObject(channel->receive_event); - - if (pfd) - { - fds[fds_count] = pfd; - (fds_count)++; - } - - *ppBuffer = malloc(sizeof(void*)); - CopyMemory(*ppBuffer, &fds[0], sizeof(void*)); - *pBytesReturned = sizeof(void*); - 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) - { - bval = TRUE; - result = TRUE; - } - else - { - switch (channel->dvc_open_state) - { - case DVC_OPEN_STATE_NONE: - bval = FALSE; - result = TRUE; - break; - - case DVC_OPEN_STATE_SUCCEEDED: - bval = TRUE; - result = TRUE; - break; - - default: - bval = FALSE; - result = FALSE; - break; - } - } - - *ppBuffer = malloc(sizeof(BOOL)); - CopyMemory(*ppBuffer, &bval, sizeof(BOOL)); - *pBytesReturned = sizeof(BOOL); - break; - - default: - break; - } - return result; -} - -VOID WTSFreeMemory(PVOID pMemory) -{ - free(pMemory); -} - -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) - { - ResetEvent(channel->receive_event); - *pBytesRead = 0; - return TRUE; - } - - *pBytesRead = item->length; - - if (item->length > BufferSize) - return FALSE; - - /* remove the first element (same as what we just peek) */ - WaitForSingleObject(channel->mutex, INFINITE); - list_dequeue(channel->receive_queue); - - if (list_size(channel->receive_queue) == 0) - ResetEvent(channel->receive_event); - - ReleaseMutex(channel->mutex); - - CopyMemory(Buffer, item->buffer, item->length); - wts_data_item_free(item); - - return TRUE; -} - -BOOL WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten) -{ - rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; - wts_data_item* item; - wStream* s; - int cbLen; - int cbChId; - int first; - UINT32 written; - - if (!channel) - return FALSE; - - if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC) - { - item = (wts_data_item*) malloc(sizeof(wts_data_item)); - ZeroMemory(item, sizeof(wts_data_item)); - - item->buffer = malloc(Length); - item->length = Length; - CopyMemory(item->buffer, Buffer, Length); - - wts_queue_send_item(channel, item); - } - else if (channel->vcm->drdynvc_channel == NULL || channel->vcm->drdynvc_state != DRDYNVC_STATE_READY) - { - DEBUG_DVC("drdynvc not ready"); - return FALSE; - } - else - { - first = TRUE; - - while (Length > 0) - { - item = (wts_data_item*) malloc(sizeof(wts_data_item)); - ZeroMemory(item, sizeof(wts_data_item)); - - s = Stream_New(NULL, channel->client->settings->VirtualChannelChunkSize); - item->buffer = Stream_Buffer(s); - - Stream_Seek_UINT8(s); - cbChId = wts_write_variable_uint(s, channel->channel_id); - - if (first && (Length > (UINT32) Stream_GetRemainingLength(s))) - { - cbLen = wts_write_variable_uint(s, Length); - item->buffer[0] = (DATA_FIRST_PDU << 4) | (cbLen << 2) | cbChId; - } - else - { - item->buffer[0] = (DATA_PDU << 4) | cbChId; - } - - first = FALSE; - written = Stream_GetRemainingLength(s); - - if (written > Length) - written = Length; - - Stream_Write(s, Buffer, written); - item->length = Stream_GetPosition(s); - Stream_Free(s, FALSE); - - Length -= written; - Buffer += written; - - wts_queue_send_item(channel->vcm->drdynvc_channel, item); - } - } - - if (pBytesWritten != NULL) - *pBytesWritten = Length; - - return TRUE; -} - -BOOL WTSVirtualChannelClose(HANDLE hChannelHandle) -{ - wStream* s; - wts_data_item* item; - WTSVirtualChannelManager* vcm; - rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; - - if (channel) - { - vcm = channel->vcm; - - if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC) - { - if (channel->index < channel->client->settings->ChannelCount) - channel->client->settings->ChannelDefArray[channel->index].handle = NULL; - } - else - { - WaitForSingleObject(vcm->mutex, INFINITE); - list_remove(vcm->dvc_channel_list, channel); - ReleaseMutex(vcm->mutex); - - if (channel->dvc_open_state == DVC_OPEN_STATE_SUCCEEDED) - { - s = Stream_New(NULL, 8); - wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channel_id); - WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL); - Stream_Free(s, TRUE); - } - } - - if (channel->receive_data) - Stream_Free(channel->receive_data, TRUE); - - if (channel->receive_event) - CloseHandle(channel->receive_event); - - if (channel->receive_queue) - { - while ((item = (wts_data_item*) list_dequeue(channel->receive_queue)) != NULL) - { - wts_data_item_free(item); - } - - list_free(channel->receive_queue); - } - - if (channel->mutex) - CloseHandle(channel->mutex); - - free(channel); - } - - return TRUE; -} - diff --git a/channels/server/channels.h b/channels/server/channels.h index d6fa95278..96a295da4 100644 --- a/channels/server/channels.h +++ b/channels/server/channels.h @@ -21,71 +21,6 @@ #ifndef __WTSVC_H #define __WTSVC_H -#include -#include -#include -#include -#include -#include - -#ifdef WITH_DEBUG_DVC -#define DEBUG_DVC(fmt, ...) DEBUG_CLASS(DVC, fmt, ## __VA_ARGS__) -#else -#define DEBUG_DVC(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) -#endif - -enum -{ - RDP_PEER_CHANNEL_TYPE_SVC = 0, - RDP_PEER_CHANNEL_TYPE_DVC = 1 -}; - -enum -{ - DRDYNVC_STATE_NONE = 0, - DRDYNVC_STATE_INITIALIZED = 1, - DRDYNVC_STATE_READY = 2 -}; - -enum -{ - DVC_OPEN_STATE_NONE = 0, - DVC_OPEN_STATE_SUCCEEDED = 1, - DVC_OPEN_STATE_FAILED = 2, - DVC_OPEN_STATE_CLOSED = 3 -}; - -typedef struct rdp_peer_channel rdpPeerChannel; - -struct rdp_peer_channel -{ - WTSVirtualChannelManager* vcm; - freerdp_peer* client; - UINT32 channel_id; - UINT16 channel_type; - UINT16 index; - - wStream* receive_data; - HANDLE receive_event; - LIST* receive_queue; - HANDLE mutex; - - BYTE dvc_open_state; - UINT32 dvc_total_length; -}; - -struct WTSVirtualChannelManager -{ - freerdp_peer* client; - HANDLE send_event; - LIST* send_queue; - HANDLE mutex; - - rdpPeerChannel* drdynvc_channel; - BYTE drdynvc_state; - UINT32 dvc_channel_id_seq; - LIST* dvc_channel_list; -}; #endif /* __WTSVC_H */ diff --git a/channels/smartcard/ChannelOptions.cmake b/channels/smartcard/ChannelOptions.cmake index ad8cc40fc..130516d34 100644 --- a/channels/smartcard/ChannelOptions.cmake +++ b/channels/smartcard/ChannelOptions.cmake @@ -15,4 +15,3 @@ define_channel_options(NAME "smartcard" TYPE "device" define_channel_client_options(${OPTION_CLIENT_DEFAULT}) define_channel_server_options(${OPTION_SERVER_DEFAULT}) - diff --git a/channels/smartcard/client/CMakeLists.txt b/channels/smartcard/client/CMakeLists.txt index 859ea9b67..9c927a9ed 100644 --- a/channels/smartcard/client/CMakeLists.txt +++ b/channels/smartcard/client/CMakeLists.txt @@ -40,6 +40,10 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PCSC_LIBRARIES}) +if(WIN32) + list(APPEND ${MODULE_PREFIX}_LIBS winscard) +endif() + target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets) diff --git a/channels/smartcard/client/smartcard_main.h b/channels/smartcard/client/smartcard_main.h index 320292be2..1ab4f7aeb 100644 --- a/channels/smartcard/client/smartcard_main.h +++ b/channels/smartcard/client/smartcard_main.h @@ -21,8 +21,6 @@ #ifndef FREERDP_CHANNEL_SMARTCARD_CLIENT_MAIN_H #define FREERDP_CHANNEL_SMARTCARD_CLIENT_MAIN_H -#include - #include #include #include diff --git a/channels/smartcard/client/smartcard_operations.c b/channels/smartcard/client/smartcard_operations.c index 81d0583d0..acb5a85b2 100644 --- a/channels/smartcard/client/smartcard_operations.c +++ b/channels/smartcard/client/smartcard_operations.c @@ -23,17 +23,37 @@ #include "config.h" #endif -#include #include #include #include -#include +#include +#ifdef _WIN32 +#include +#else +#include #define BOOL PCSC_BOOL #include -#include #include +#if !defined(__APPLE__) +#include +#else +/* On OS X reader.h isn't available so define it here */ +#endif +#define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag))) +#define SCARD_CLASS_SYSTEM 0x7fff /**< System-specific definitions */ +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0003) +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0005) +#ifdef UNICODE +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_W /**< Reader's display name. */ +#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_W /**< Reader's system name. */ +#else +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_A /**< Reader's display name. */ +#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_A /**< Reader's system name. */ +#define SCARD_CTL_CODE(code) (0x42000000 + (code)) +#endif #undef BOOL +#endif #include #include diff --git a/client/Android/.gitignore b/client/Android/.gitignore index 1eee223a1..31b2e3c80 100644 --- a/client/Android/.gitignore +++ b/client/Android/.gitignore @@ -8,3 +8,7 @@ libs/armeabi* AndroidManifest.xml local.properties !.project + +FreeRDPCore/project.properties +FreeRDPCore/src/com/freerdp/freerdpcore/utils/BuildConfiguration.java +aFreeRDP/project.properties diff --git a/client/Android/FreeRDPCore/.gitignore b/client/Android/FreeRDPCore/.gitignore new file mode 100644 index 000000000..2d8df2acd --- /dev/null +++ b/client/Android/FreeRDPCore/.gitignore @@ -0,0 +1,4 @@ +ant.properties +build.xml +jni/Android.mk +jni/Application.mk diff --git a/client/Android/FreeRDPCore/jni/android_freerdp.c b/client/Android/FreeRDPCore/jni/android_freerdp.c index e66325e2f..5f75ce40e 100644 --- a/client/Android/FreeRDPCore/jni/android_freerdp.c +++ b/client/Android/FreeRDPCore/jni/android_freerdp.c @@ -246,11 +246,6 @@ BOOL android_verify_changed_certificate(freerdp* instance, char* subject, char* return android_verify_certificate(instance, subject, issuer, new_fingerprint); } -int android_receive_channel_data(freerdp* instance, int channelId, UINT8* data, int size, int flags, int total_size) -{ - return freerdp_channels_data(instance, channelId, data, size, flags, total_size); -} - static void android_process_channel_event(rdpChannels* channels, freerdp* instance) { wMessage* event; @@ -635,8 +630,6 @@ JNIEXPORT jint JNICALL jni_freerdp_new(JNIEnv *env, jclass cls) instance->Authenticate = android_authenticate; instance->VerifyCertificate = android_verify_certificate; instance->VerifyChangedCertificate = android_verify_changed_certificate; - instance->ReceiveChannelData = android_receive_channel_data; - // create context instance->ContextSize = sizeof(androidContext); diff --git a/client/Android/aFreeRDP/.gitignore b/client/Android/aFreeRDP/.gitignore new file mode 100644 index 000000000..2d8df2acd --- /dev/null +++ b/client/Android/aFreeRDP/.gitignore @@ -0,0 +1,4 @@ +ant.properties +build.xml +jni/Android.mk +jni/Application.mk diff --git a/client/Mac/CMakeLists.txt b/client/Mac/CMakeLists.txt index 71d912e29..33c946ee2 100755 --- a/client/Mac/CMakeLists.txt +++ b/client/Mac/CMakeLists.txt @@ -8,9 +8,10 @@ set(MODULE_PREFIX "FREERDP_CLIENT_MAC_LIBRARY") find_library(FOUNDATION_LIBRARY Foundation) find_library(COCOA_LIBRARY Cocoa) find_library(APPKIT_LIBRARY AppKit) +find_library(IOKIT_LIBRARY IOKit) mark_as_advanced(COCOA_LIBRARY FOUNDATION_LIBRARY APPKIT_LIBRARY) -set(EXTRA_LIBS ${COCOA_LIBRARY} ${FOUNDATION_LIBRARY} ${APPKIT_LIBRARY}) +set(EXTRA_LIBS ${COCOA_LIBRARY} ${FOUNDATION_LIBRARY} ${APPKIT_LIBRARY} ${IOKIT_LIBRARY}) set(MACOSX_BUNDLE_INFO_STRING "${MODULE_OUTPUT_NAME}") set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.freerdp.mac") @@ -30,6 +31,7 @@ set(${MODULE_PREFIX}_OBJECTIVE_SOURCES mf_client.m MRDPCursor.m MRDPView.m + Keyboard.m PasswordDialog.m) list(APPEND ${MODULE_PREFIX}_SOURCES ${${MODULE_PREFIX}_OBJECTIVE_SOURCES}) @@ -39,6 +41,7 @@ set(${MODULE_PREFIX}_HEADERS mf_client.h MRDPCursor.h MRDPView.h + Keyboard.h PasswordDialog.h) set(${MODULE_PREFIX}_RESOURCES "en.lproj/InfoPlist.strings") diff --git a/channels/client/open.h b/client/Mac/Keyboard.h similarity index 58% rename from channels/client/open.h rename to client/Mac/Keyboard.h index 4bb525d53..cc6f85964 100644 --- a/channels/client/open.h +++ b/client/Mac/Keyboard.h @@ -1,8 +1,8 @@ /** * FreeRDP: A Remote Desktop Protocol Implementation - * Client Channels + * MacFreeRDP * - * Copyright 2013 Marc-Andre Moreau + * Copyright 2014 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. @@ -17,14 +17,11 @@ * limitations under the License. */ -#ifndef FREERDP_PRIVATE_CLIENT_CHANNELS_OPEN -#define FREERDP_PRIVATE_CLIENT_CHANNELS_OPEN +enum APPLE_KEYBOARD_TYPE +{ + APPLE_KEYBOARD_TYPE_ANSI, + APPLE_KEYBOARD_TYPE_ISO, + APPLE_KEYBOARD_TYPE_JIS +}; -#include "channels.h" - -UINT32 FreeRDP_VirtualChannelOpen(void* pInitHandle, UINT32* pOpenHandle, - char* pChannelName, PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc); - -UINT32 FreeRDP_VirtualChannelClose(UINT32 openHandle); - -#endif /* FREERDP_PRIVATE_CLIENT_CHANNELS_OPEN */ +enum APPLE_KEYBOARD_TYPE mac_detect_keyboard_type(); diff --git a/client/Mac/Keyboard.m b/client/Mac/Keyboard.m new file mode 100644 index 000000000..63cbfd4bc --- /dev/null +++ b/client/Mac/Keyboard.m @@ -0,0 +1,247 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * MacFreeRDP + * + * Copyright 2014 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. + */ + +#import "Keyboard.h" + +#include + +#include + +struct _APPLE_KEYBOARD_DESC +{ + uint32_t ProductId; + enum APPLE_KEYBOARD_TYPE Type; +}; +typedef struct _APPLE_KEYBOARD_DESC APPLE_KEYBOARD_DESC; + +/* VendorID: 0x05AC (Apple, Inc.) */ + +APPLE_KEYBOARD_DESC APPLE_KEYBOARDS[] = +{ + { 0x200, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x201, APPLE_KEYBOARD_TYPE_ANSI }, /* USB Keyboard [Alps or Logitech, M2452] */ + { 0x202, APPLE_KEYBOARD_TYPE_ANSI }, /* Keyboard [ALPS] */ + { 0x203, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x204, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x205, APPLE_KEYBOARD_TYPE_ANSI }, /* Extended Keyboard [Mitsumi] */ + { 0x206, APPLE_KEYBOARD_TYPE_ANSI }, /* Extended Keyboard [Mitsumi] */ + { 0x207, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x208, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x209, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x20A, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x20B, APPLE_KEYBOARD_TYPE_ANSI }, /* Pro Keyboard [Mitsumi, A1048/US layout] */ + { 0x20C, APPLE_KEYBOARD_TYPE_ANSI }, /* Extended Keyboard [Mitsumi] */ + { 0x20D, APPLE_KEYBOARD_TYPE_ANSI }, /* Pro Keyboard [Mitsumi, A1048/JIS layout] */ + { 0x20E, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */ + { 0x20F, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */ + { 0x210, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x211, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x212, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x213, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x214, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */ + { 0x215, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */ + { 0x216, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */ + { 0x217, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */ + { 0x218, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */ + { 0x219, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */ + { 0x21A, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */ + { 0x21B, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */ + { 0x21C, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */ + { 0x21D, APPLE_KEYBOARD_TYPE_ANSI }, /* Aluminum Mini Keyboard (ANSI) */ + { 0x21E, APPLE_KEYBOARD_TYPE_ISO }, /* Aluminum Mini Keyboard (ISO) */ + { 0x21F, APPLE_KEYBOARD_TYPE_JIS }, /* Aluminum Mini Keyboard (JIS) */ + { 0x220, APPLE_KEYBOARD_TYPE_ANSI }, /* Aluminum Keyboard (ANSI) */ + { 0x221, APPLE_KEYBOARD_TYPE_JIS }, /* Aluminum Keyboard (JIS) */ + { 0x222, APPLE_KEYBOARD_TYPE_JIS }, /* Aluminum Keyboard (JIS) */ + { 0x223, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */ + { 0x224, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */ + { 0x225, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */ + { 0x226, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x227, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x228, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x229, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (MacBook Pro) (ANSI) */ + { 0x22A, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (MacBook Pro) (ISO) */ + { 0x22B, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (MacBook Pro) (JIS) */ + { 0x22C, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x22D, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x22E, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x22F, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x230, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (MacBook Pro 4,1) (ANSI) */ + { 0x231, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (MacBook Pro 4,1) (ISO) */ + { 0x232, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (MacBook Pro 4,1) (JIS) */ + { 0x233, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x234, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x235, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x236, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */ + { 0x237, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */ + { 0x238, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */ + { 0x239, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x23A, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x23B, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x23C, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x23D, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x23E, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x23F, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */ + { 0x240, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */ + { 0x241, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */ + { 0x242, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */ + { 0x243, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */ + { 0x244, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */ + { 0x245, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */ + { 0x246, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */ + { 0x247, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */ + { 0x248, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x249, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x24A, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (MacBook Air) (ISO) */ + { 0x24B, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x24C, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x24D, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (MacBook Air) (ISO) */ + { 0x24E, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x24F, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x250, APPLE_KEYBOARD_TYPE_ISO }, /* Aluminium Keyboard (ISO) */ + { 0x251, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x252, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */ + { 0x253, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */ + { 0x254, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */ + { 0x255, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x256, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x257, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x258, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x259, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x25A, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x25B, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x25C, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x25D, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x25E, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x25F, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x260, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x261, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x262, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x263, APPLE_KEYBOARD_TYPE_ANSI }, /* Apple Internal Keyboard / Trackpad (MacBook Retina) */ + { 0x264, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x265, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x266, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x267, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x268, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x269, APPLE_KEYBOARD_TYPE_ANSI }, + { 0x26A, APPLE_KEYBOARD_TYPE_ANSI } +}; + +enum APPLE_KEYBOARD_TYPE mac_identify_keyboard_type(uint32_t vendorID, uint32_t productID) +{ + enum APPLE_KEYBOARD_TYPE type = APPLE_KEYBOARD_TYPE_ANSI; + + if (vendorID != 0x05AC) /* Apple, Inc. */ + return type; + + if ((productID < 0x200) || (productID > 0x26A)) + return type; + + type = APPLE_KEYBOARDS[productID - 0x200].Type; + + return type; +} + +enum APPLE_KEYBOARD_TYPE mac_detect_keyboard_type() +{ + CFSetRef deviceCFSetRef = NULL; + IOHIDDeviceRef inIOHIDDeviceRef = NULL; + IOHIDManagerRef tIOHIDManagerRef = NULL; + IOHIDDeviceRef* tIOHIDDeviceRefs = nil; + enum APPLE_KEYBOARD_TYPE type = APPLE_KEYBOARD_TYPE_ANSI; + + tIOHIDManagerRef = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + + if (!tIOHIDManagerRef) + return type; + + IOHIDManagerSetDeviceMatching(tIOHIDManagerRef, NULL); + + IOReturn tIOReturn = IOHIDManagerOpen(tIOHIDManagerRef, kIOHIDOptionsTypeNone); + + if (noErr != tIOReturn) + return type; + + deviceCFSetRef = IOHIDManagerCopyDevices(tIOHIDManagerRef); + + if (!deviceCFSetRef) + return type; + + CFIndex deviceIndex, deviceCount = CFSetGetCount(deviceCFSetRef); + + tIOHIDDeviceRefs = malloc(sizeof(IOHIDDeviceRef) * deviceCount); + + if (!tIOHIDDeviceRefs) + return type; + + CFSetGetValues(deviceCFSetRef, (const void**) tIOHIDDeviceRefs); + CFRelease(deviceCFSetRef); + deviceCFSetRef = NULL; + + for (deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++) + { + CFTypeRef tCFTypeRef; + uint32_t vendorID = 0; + uint32_t productID = 0; + uint32_t countryCode = 0; + enum APPLE_KEYBOARD_TYPE ltype; + + if (!tIOHIDDeviceRefs[deviceIndex]) + continue; + + inIOHIDDeviceRef = tIOHIDDeviceRefs[deviceIndex]; + + tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDVendorIDKey)); + + if (tCFTypeRef) + CFNumberGetValue((CFNumberRef) tCFTypeRef, kCFNumberSInt32Type, &vendorID); + + tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDProductIDKey)); + + if (tCFTypeRef) + CFNumberGetValue((CFNumberRef) tCFTypeRef, kCFNumberSInt32Type, &productID); + + tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDCountryCodeKey)); + + if (tCFTypeRef) + CFNumberGetValue((CFNumberRef) tCFTypeRef, kCFNumberSInt32Type, &countryCode); + + ltype = mac_identify_keyboard_type(vendorID, productID); + + if (ltype != APPLE_KEYBOARD_TYPE_ANSI) + { + type = ltype; + break; + } + } + + if (tIOHIDDeviceRefs) + free(tIOHIDDeviceRefs); + + if (deviceCFSetRef) + { + CFRelease(deviceCFSetRef); + deviceCFSetRef = NULL; + } + + if (tIOHIDManagerRef) + CFRelease(tIOHIDManagerRef); + + return type; +} diff --git a/client/Mac/MRDPView.h b/client/Mac/MRDPView.h index 6e4c3a4b8..70ef3130d 100755 --- a/client/Mac/MRDPView.h +++ b/client/Mac/MRDPView.h @@ -22,25 +22,9 @@ #import -/* - #import "freerdp/freerdp.h" -#import "freerdp/types.h" -#import "freerdp/channels/channels.h" -#import "freerdp/gdi/gdi.h" -#import "freerdp/graphics.h" -#import "freerdp/utils/event.h" -#import "freerdp/client/cliprdr.h" -#import "freerdp/client/file.h" -#import "freerdp/client/cmdline.h" -#import "freerdp/rail/rail.h" -#import "freerdp/rail.h" -#import "freerdp/utils/rail.h" - -#import "mf_interface.h" -*/ - #import "mfreerdp.h" #import "mf_client.h" +#import "Keyboard.h" @interface MRDPView : NSView { @@ -98,7 +82,7 @@ BOOL mac_pre_connect(freerdp* instance); BOOL mac_post_connect(freerdp* instance); BOOL mac_authenticate(freerdp* instance, char** username, char** password, char** domain); -int mac_receive_channel_data(freerdp* instance, int chan_id, BYTE* data, int size, int flags, int total_size); + DWORD mac_client_thread(void* param); #endif // MRDPVIEW_H diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m index da2992629..66b13a9d6 100644 --- a/client/Mac/MRDPView.m +++ b/client/Mac/MRDPView.m @@ -17,31 +17,6 @@ * limitations under the License. */ -/* - * TODO - * + provide a UI for configuring optional parameters, but keep cmd line args - * + audio redirection is delayed considerably - * + caps lock key needs to be sent in func flagsChanged() - * + libfreerdp-utils.1.0.dylib needs to be installed to /usr/local/lib - * - * - MRDPView implementation is incomplete - * - all variables should have consistent nameing scheme - camel case - * - all funcs same as above - * - PolygonSc seems to create a transparent rect - * - ensure mouse cursor changes are working ok after moving to NSTracking area - * - RAIL: - * - - * - - * - tool tips to be correctly positioned - * - dragging is slightly of - * - resize after dragging not working - * - dragging app from macbook to monitor gives exec/access err - * - unable to drag rect out of monitor boundaries - * - - * - - * - - */ - #include #include "mf_client.h" @@ -52,6 +27,8 @@ #include #include +#include +#include #include @@ -67,26 +44,20 @@ #import "freerdp/client/file.h" #import "freerdp/client/cmdline.h" -/****************************************** - Forward declarations - ******************************************/ - - void mf_Pointer_New(rdpContext* context, rdpPointer* pointer); void mf_Pointer_Free(rdpContext* context, rdpPointer* pointer); void mf_Pointer_Set(rdpContext* context, rdpPointer* pointer); void mf_Pointer_SetNull(rdpContext* context); void mf_Pointer_SetDefault(rdpContext* context); -// int rdp_connect(void); -void mac_set_bounds(rdpContext* context, rdpBounds* bounds); -void mac_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap); + void mac_begin_paint(rdpContext* context); void mac_end_paint(rdpContext* context); -void mac_save_state_info(freerdp* instance, rdpContext* context); +void mac_desktop_resize(rdpContext* context); + static void update_activity_cb(freerdp* instance); static void input_activity_cb(freerdp* instance); static void channel_activity_cb(freerdp* instance); -int invoke_draw_rect(rdpContext* context); + int process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data); int receive_channel_data(freerdp* instance, int chan_id, BYTE* data, int size, int flags, int total_size); @@ -99,7 +70,6 @@ void cliprdr_process_text(freerdp* instance, BYTE* data, int len); void cliprdr_send_supported_format_list(freerdp* instance); int register_channel_fds(int* fds, int count, freerdp* instance); - DWORD mac_client_thread(void* param); struct cursor @@ -140,10 +110,10 @@ struct rgba_data e.handle = (void*) self; PubSub_OnEmbedWindow(context->pubSub, context, &e); - NSScreen *screen = [[NSScreen screens] objectAtIndex:0]; + NSScreen* screen = [[NSScreen screens] objectAtIndex:0]; NSRect screenFrame = [screen frame]; - if(instance->settings->Fullscreen) + if (instance->settings->Fullscreen) { instance->settings->DesktopWidth = screenFrame.size.width; instance->settings->DesktopHeight = screenFrame.size.height; @@ -157,15 +127,108 @@ struct rgba_data return 0; } +DWORD mac_client_update_thread(void* param) +{ + int status; + wMessage message; + wMessageQueue* queue; + rdpContext* context = (rdpContext*) param; + + status = 1; + queue = freerdp_get_message_queue(context->instance, FREERDP_UPDATE_MESSAGE_QUEUE); + + while (MessageQueue_Wait(queue)) + { + while (MessageQueue_Peek(queue, &message, TRUE)) + { + status = freerdp_message_queue_process_message(context->instance, FREERDP_UPDATE_MESSAGE_QUEUE, &message); + + if (!status) + break; + } + + if (!status) + break; + } + + ExitThread(0); + return NULL; +} + +DWORD mac_client_input_thread(void* param) +{ + int status; + wMessage message; + wMessageQueue* queue; + rdpContext* context = (rdpContext*) param; + + status = 1; + queue = freerdp_get_message_queue(context->instance, FREERDP_INPUT_MESSAGE_QUEUE); + + while (MessageQueue_Wait(queue)) + { + while (MessageQueue_Peek(queue, &message, TRUE)) + { + status = freerdp_message_queue_process_message(context->instance, FREERDP_INPUT_MESSAGE_QUEUE, &message); + + if (!status) + break; + } + } + + ExitThread(0); + return NULL; +} + +DWORD mac_client_channels_thread(void* param) +{ + int status; + wMessage* event; + HANDLE channelsEvent; + rdpChannels* channels; + rdpContext* context = (rdpContext*) param; + + channels = context->channels; + channelsEvent = freerdp_channels_get_event_handle(context->instance); + + while (WaitForSingleObject(channelsEvent, INFINITE) == WAIT_OBJECT_0) + { + status = freerdp_channels_process_pending_messages(context->instance); + + if (!status) + break; + + event = freerdp_channels_pop_event(context->channels); + + if (event) + { + switch (GetMessageClass(event->id)) + { + case CliprdrChannel_Class: + process_cliprdr_event(context->instance, event); + break; + } + + freerdp_event_free(event); + } + } + + ExitThread(0); + return NULL; +} + DWORD mac_client_thread(void* param) { @autoreleasepool { int status; HANDLE events[4]; - HANDLE input_event; - HANDLE update_event; - HANDLE channels_event; + HANDLE inputEvent; + HANDLE inputThread; + HANDLE updateEvent; + HANDLE updateThread; + HANDLE channelsEvent; + HANDLE channelsThread; DWORD nCount; rdpContext* context = (rdpContext*) param; @@ -190,17 +253,29 @@ DWORD mac_client_thread(void* param) if (settings->AsyncUpdate) { - events[nCount++] = update_event = freerdp_get_message_queue_event_handle(instance, FREERDP_UPDATE_MESSAGE_QUEUE); + updateThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) mac_client_update_thread, context, 0, NULL); + } + else + { + events[nCount++] = updateEvent = freerdp_get_message_queue_event_handle(instance, FREERDP_UPDATE_MESSAGE_QUEUE); } if (settings->AsyncInput) { - events[nCount++] = input_event = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE); + inputThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) mac_client_input_thread, context, 0, NULL); + } + else + { + events[nCount++] = inputEvent = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE); } if (settings->AsyncChannels) { - events[nCount++] = channels_event = freerdp_channels_get_event_handle(instance); + channelsThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) mac_client_channels_thread, context, 0, NULL); + } + else + { + events[nCount++] = channelsEvent = freerdp_channels_get_event_handle(instance); } while (1) @@ -213,44 +288,58 @@ DWORD mac_client_thread(void* param) break; } - if (settings->AsyncUpdate) + if (!settings->AsyncUpdate) { - if (WaitForSingleObject(update_event, 0) == WAIT_OBJECT_0) + if (WaitForSingleObject(updateEvent, 0) == WAIT_OBJECT_0) { update_activity_cb(instance); } } - if (settings->AsyncInput) + if (!settings->AsyncInput) { - if (WaitForSingleObject(input_event, 0) == WAIT_OBJECT_0) + if (WaitForSingleObject(inputEvent, 0) == WAIT_OBJECT_0) { input_activity_cb(instance); } } - if (settings->AsyncChannels) + if (!settings->AsyncChannels) { - if (WaitForSingleObject(channels_event, 0) == WAIT_OBJECT_0) + if (WaitForSingleObject(channelsEvent, 0) == WAIT_OBJECT_0) { channel_activity_cb(instance); } } } + if (settings->AsyncUpdate) + { + wMessageQueue* updateQueue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE); + MessageQueue_PostQuit(updateQueue, 0); + WaitForSingleObject(updateThread, INFINITE); + CloseHandle(updateThread); + } + + if (settings->AsyncInput) + { + wMessageQueue* inputQueue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE); + MessageQueue_PostQuit(inputQueue, 0); + WaitForSingleObject(inputThread, INFINITE); + CloseHandle(inputThread); + } + + if (settings->AsyncChannels) + { + WaitForSingleObject(channelsThread, INFINITE); + CloseHandle(channelsThread); + } + ExitThread(0); return 0; } } -/************************************************************************ - methods we override - ************************************************************************/ - -/** ********************************************************************* - * create MRDPView with specified rectangle - ***********************************************************************/ - - (id)initWithFrame:(NSRect)frame { self = [super initWithFrame:frame]; @@ -263,12 +352,6 @@ DWORD mac_client_thread(void* param) return self; } -/** ********************************************************************* - * called when MRDPView has been successfully created from the NIB - ***********************************************************************/ - -//TODO - Expose this code as a public method, because awakeFromNib -// won't be called if the view is created dynamically - (void) viewDidLoad { [self initializeView]; @@ -298,35 +381,16 @@ DWORD mac_client_thread(void* param) [[self window] invalidateCursorRectsForView:self]; } - -// Set the current cursor - (void) resetCursorRects { [self addCursorRect:[self visibleRect] cursor:currentCursor]; } -/** ********************************************************************* - * become first responder so we can get keyboard and mouse events - ***********************************************************************/ - - (BOOL)acceptsFirstResponder { return YES; } -/** ********************************************************************* - * called when a mouse move event occurrs - * - * ideally we want to be called when the mouse moves over NSView client area, - * but in reality we get called any time the mouse moves anywhere on the screen; - * we could use NSTrackingArea class to handle this but this class is available - * on Mac OS X v10.5 and higher; since we want to be compatible with older - * versions, we do this manually. - * - * TODO: here is how it can be done using legacy methods - * http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/EventOverview/MouseTrackingEvents/MouseTrackingEvents.html#//apple_ref/doc/uid/10000060i-CH11-SW1 - ***********************************************************************/ - - (void) mouseMoved:(NSEvent *)event { [super mouseMoved:event]; @@ -341,10 +405,6 @@ DWORD mac_client_thread(void* param) mf_scale_mouse_event(context, instance->input, PTR_FLAGS_MOVE, x, y); } -/** ********************************************************************* - * called when left mouse button is pressed down - ***********************************************************************/ - - (void)mouseDown:(NSEvent *) event { [super mouseDown:event]; @@ -359,10 +419,6 @@ DWORD mac_client_thread(void* param) mf_scale_mouse_event(context, instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, x, y); } -/** ********************************************************************* - * called when left mouse button is released - ***********************************************************************/ - - (void) mouseUp:(NSEvent *) event { [super mouseUp:event]; @@ -377,10 +433,6 @@ DWORD mac_client_thread(void* param) mf_scale_mouse_event(context, instance->input, PTR_FLAGS_BUTTON1, x, y); } -/** ********************************************************************* - * called when right mouse button is pressed down - ***********************************************************************/ - - (void) rightMouseDown:(NSEvent *)event { [super rightMouseDown:event]; @@ -395,10 +447,6 @@ DWORD mac_client_thread(void* param) mf_scale_mouse_event(context, instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2, x, y); } -/** ********************************************************************* - * called when right mouse button is released - ***********************************************************************/ - - (void) rightMouseUp:(NSEvent *)event { [super rightMouseUp:event]; @@ -413,10 +461,6 @@ DWORD mac_client_thread(void* param) mf_scale_mouse_event(context, instance->input, PTR_FLAGS_BUTTON2, x, y); } -/** ********************************************************************* - * called when middle mouse button is pressed - ***********************************************************************/ - - (void) otherMouseDown:(NSEvent *)event { [super otherMouseDown:event]; @@ -431,10 +475,6 @@ DWORD mac_client_thread(void* param) mf_scale_mouse_event(context, instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3, x, y); } -/** ********************************************************************* - * called when middle mouse button is released - ***********************************************************************/ - - (void) otherMouseUp:(NSEvent *)event { [super otherMouseUp:event]; @@ -478,11 +518,6 @@ DWORD mac_client_thread(void* param) } } -/** ********************************************************************* - * called when mouse is moved with left button pressed - * note: invocation order is: mouseDown, mouseDragged, mouseUp - ***********************************************************************/ - - (void) mouseDragged:(NSEvent *)event { [super mouseDragged:event]; @@ -498,55 +533,121 @@ DWORD mac_client_thread(void* param) mf_scale_mouse_event(context, instance->input, PTR_FLAGS_MOVE, x, y); } -/** ********************************************************************* - * called when a key is pressed - ***********************************************************************/ +DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type) +{ + /** + * In 99% of cases, the given key code is truly keyboard independent. + * This function handles the remaining 1% of edge cases. + * + * Hungarian Keyboard: This is 'QWERTZ' and not 'QWERTY'. + * The '0' key is on the left of the '1' key, where '~' is on a US keyboard. + * A special 'i' letter key with acute is found on the right of the left shift key. + * On the hungarian keyboard, the 'i' key is at the left of the 'Y' key + * Some international keyboards have a corresponding key which would be at + * the left of the 'Z' key when using a QWERTY layout. + * + * The Apple Hungarian keyboard sends inverted key codes for the '0' and 'i' keys. + * When using the US keyboard layout, key codes are left as-is (inverted). + * When using the Hungarian keyboard layout, key codes are swapped (non-inverted). + * This means that when using the Hungarian keyboard layout with a US keyboard, + * the keys corresponding to '0' and 'i' will effectively be inverted. + * + * To fix the '0' and 'i' key inversion, we use the corresponding output character + * provided by OS X and check for a character to key code mismatch: for instance, + * when the output character is '0' for the key code corresponding to the 'i' key. + */ + +#if 0 + switch (keyChar) + { + case '0': + case 0x00A7: /* section sign */ + if (keyCode == APPLE_VK_ISO_Section) + keyCode = APPLE_VK_ANSI_Grave; + break; + + case 0x00ED: /* latin small letter i with acute */ + case 0x00CD: /* latin capital letter i with acute */ + if (keyCode == APPLE_VK_ANSI_Grave) + keyCode = APPLE_VK_ISO_Section; + break; + } +#endif + + /* Perform keycode correction for all ISO keyboards */ + + if (type == APPLE_KEYBOARD_TYPE_ISO) + { + if (keyCode == APPLE_VK_ANSI_Grave) + keyCode = APPLE_VK_ISO_Section; + else if (keyCode == APPLE_VK_ISO_Section) + keyCode = APPLE_VK_ANSI_Grave; + } + + return keyCode; +} - (void) keyDown:(NSEvent *) event { - int key; + DWORD keyCode; DWORD keyFlags; DWORD vkcode; DWORD scancode; + unichar keyChar; + NSString* characters; if (!is_connected) return; keyFlags = KBD_FLAGS_DOWN; - key = [event keyCode] + 8; + keyCode = [event keyCode]; - vkcode = GetVirtualKeyCodeFromKeycode(key, KEYCODE_TYPE_APPLE); + characters = [event charactersIgnoringModifiers]; + + if ([characters length] > 0) + { + keyChar = [characters characterAtIndex:0]; + keyCode = fixKeyCode(keyCode, keyChar, mfc->appleKeyboardType); + } + + vkcode = GetVirtualKeyCodeFromKeycode(keyCode + 8, KEYCODE_TYPE_APPLE); scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4); keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0; scancode &= 0xFF; vkcode &= 0xFF; - + #if 0 - fprintf(stderr, "keyDown: key: 0x%04X scancode: 0x%04X vkcode: 0x%04X keyFlags: %d name: %s\n", - key - 8, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode)); + fprintf(stderr, "keyDown: keyCode: 0x%04X scancode: 0x%04X vkcode: 0x%04X keyFlags: %d name: %s\n", + keyCode, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode)); #endif freerdp_input_send_keyboard_event(instance->input, keyFlags, scancode); } -/** ********************************************************************* - * called when a key is released - ***********************************************************************/ - - (void) keyUp:(NSEvent *) event { - int key; + DWORD keyCode; DWORD keyFlags; DWORD vkcode; DWORD scancode; + unichar keyChar; + NSString* characters; if (!is_connected) return; - key = [event keyCode] + 8; keyFlags = KBD_FLAGS_RELEASE; + keyCode = [event keyCode]; + + characters = [event charactersIgnoringModifiers]; + + if ([characters length] > 0) + { + keyChar = [characters characterAtIndex:0]; + keyCode = fixKeyCode(keyCode, keyChar, mfc->appleKeyboardType); + } - vkcode = GetVirtualKeyCodeFromKeycode(key, KEYCODE_TYPE_APPLE); + vkcode = GetVirtualKeyCodeFromKeycode(keyCode + 8, KEYCODE_TYPE_APPLE); scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4); keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0; scancode &= 0xFF; @@ -554,16 +655,12 @@ DWORD mac_client_thread(void* param) #if 0 fprintf(stderr, "keyUp: key: 0x%04X scancode: 0x%04X vkcode: 0x%04X keyFlags: %d name: %s\n", - key - 8, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode)); + keyCode, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode)); #endif freerdp_input_send_keyboard_event(instance->input, keyFlags, scancode); } -/** ********************************************************************* - * called when shift, control, alt and meta keys are pressed/released - ***********************************************************************/ - - (void) flagsChanged:(NSEvent*) event { int key; @@ -670,38 +767,34 @@ DWORD mac_client_thread(void* param) free(pixel_data); } -/** ********************************************************************* - * called when our view needs refreshing - ***********************************************************************/ - - (void) drawRect:(NSRect)rect { if (!context) return; - + if (self->bitmap_context) { CGContextRef cgContext = [[NSGraphicsContext currentContext] graphicsPort]; CGImageRef cgImage = CGBitmapContextCreateImage(self->bitmap_context); - + + CGContextSaveGState(cgContext); + CGContextClipToRect(cgContext, CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)); - CGContextDrawImage(cgContext, CGRectMake(0, - 0, [self bounds].size.width, [self bounds].size.height), cgImage); + CGContextDrawImage(cgContext, CGRectMake(0, 0, [self bounds].size.width, [self bounds].size.height), cgImage); + + CGContextRestoreGState(cgContext); + CGImageRelease(cgImage); } else { - // just clear the screen with black + /* Fill the screen with black */ [[NSColor blackColor] set]; NSRectFill([self bounds]); } } -/************************************************************************ - instance methods - ************************************************************************/ - - (void) onPasteboardTimerFired :(NSTimer*) timer { int i; @@ -729,30 +822,13 @@ DWORD mac_client_thread(void* param) mfc->client_width = width; } -/************************************************************************ - * * - * C functions * - * * - ***********************************************************************/ - -/** ********************************************************************* - * a callback given to freerdp_connect() to process the pre-connect operations. - * - * @param inst - pointer to a rdp_freerdp struct that contains the connection's parameters, and - * will be filled with the appropriate informations. - * - * @return true if successful. false otherwise. - ************************************************************************/ - BOOL mac_pre_connect(freerdp* instance) { rdpSettings* settings; - // setup callbacks instance->update->BeginPaint = mac_begin_paint; instance->update->EndPaint = mac_end_paint; - instance->update->SetBounds = mac_set_bounds; - //instance->update->BitmapUpdate = mac_bitmap_update; + instance->update->DesktopResize = mac_desktop_resize; settings = instance->settings; @@ -763,7 +839,6 @@ BOOL mac_pre_connect(freerdp* instance) return -1; } - settings->ColorDepth = 32; settings->SoftwareGdi = TRUE; settings->OsMajorType = OSMAJORTYPE_MACINTOSH; @@ -790,8 +865,8 @@ BOOL mac_pre_connect(freerdp* instance) settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE; settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE; settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE; - settings->OrderSupport[NEG_POLYGON_SC_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE; - settings->OrderSupport[NEG_POLYGON_CB_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE; + settings->OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE; + settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE; settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE; @@ -802,25 +877,16 @@ BOOL mac_pre_connect(freerdp* instance) return TRUE; } -/** ********************************************************************* - * a callback registered with freerdp_connect() to perform post-connection operations. - * we get called only if the connection was initialized properly, and will continue - * the initialization based on the newly created connection. - * - * @param inst - pointer to a rdp_freerdp struct - * - * @return true on success, false on failure - * - ************************************************************************/ - BOOL mac_post_connect(freerdp* instance) { + rdpGdi* gdi; UINT32 flags; + rdpSettings* settings; rdpPointer rdp_pointer; - mfContext *mfc = (mfContext*) instance->context; + mfContext* mfc = (mfContext*) instance->context; MRDPView* view = (MRDPView*) mfc->view; - + ZeroMemory(&rdp_pointer, sizeof(rdpPointer)); rdp_pointer.size = sizeof(rdpPointer); rdp_pointer.New = mf_Pointer_New; @@ -828,14 +894,21 @@ BOOL mac_post_connect(freerdp* instance) rdp_pointer.Set = mf_Pointer_Set; rdp_pointer.SetNull = mf_Pointer_SetNull; rdp_pointer.SetDefault = mf_Pointer_SetDefault; - - flags = CLRBUF_32BPP | CLRCONV_ALPHA; + + settings = instance->settings; + + flags = CLRCONV_ALPHA | CLRCONV_RGB555; + + if (settings->ColorDepth > 16) + flags |= CLRBUF_32BPP; + else + flags |= CLRBUF_16BPP; + gdi_init(instance, flags, NULL); - - rdpGdi* gdi = instance->context->gdi; - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - view->bitmap_context = CGBitmapContextCreate(gdi->primary_buffer, gdi->width, gdi->height, 8, gdi->width * 4, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst); - + gdi = instance->context->gdi; + + view->bitmap_context = mac_create_bitmap_context(instance->context); + pointer_cache_register_callbacks(instance->update); graphics_register_pointer(instance->context->graphics, &rdp_pointer); @@ -848,6 +921,8 @@ BOOL mac_post_connect(freerdp* instance) view->pasteboard_rd = [NSPasteboard generalPasteboard]; view->pasteboard_changecount = (int) [view->pasteboard_rd changeCount]; view->pasteboard_timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:mfc->view selector:@selector(onPasteboardTimerFired:) userInfo:nil repeats:YES]; + + mfc->appleKeyboardType = mac_detect_keyboard_type(); return TRUE; } @@ -880,14 +955,6 @@ BOOL mac_authenticate(freerdp* instance, char** username, char** password, char* return ok; } -/** ********************************************************************* - * create a new mouse cursor - * - * @param context our context state - * @param pointer information about the cursor to create - * - ************************************************************************/ - void mf_Pointer_New(rdpContext* context, rdpPointer* pointer) { NSRect rect; @@ -916,7 +983,7 @@ void mf_Pointer_New(rdpContext* context, rdpPointer* pointer) freerdp_alpha_cursor_convert(cursor_data, pointer->xorMaskData, pointer->andMaskData, pointer->width, pointer->height, pointer->xorBpp, context->gdi->clrconv); - + /* store cursor bitmap image in representation - required by NSImage */ bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &cursor_data pixelsWide:rect.size.width @@ -950,10 +1017,6 @@ void mf_Pointer_New(rdpContext* context, rdpPointer* pointer) [ma addObject:mrdpCursor]; } -/** ********************************************************************* - * release resources on specified cursor - ************************************************************************/ - void mf_Pointer_Free(rdpContext* context, rdpPointer* pointer) { mfContext* mfc = (mfContext*) context; @@ -974,10 +1037,6 @@ void mf_Pointer_Free(rdpContext* context, rdpPointer* pointer) } } -/** ********************************************************************* - * set specified cursor as the current cursor - ************************************************************************/ - void mf_Pointer_Set(rdpContext* context, rdpPointer* pointer) { mfContext* mfc = (mfContext*) context; @@ -997,19 +1056,11 @@ void mf_Pointer_Set(rdpContext* context, rdpPointer* pointer) NSLog(@"Cursor not found"); } -/** ********************************************************************* - * do not display any mouse cursor - ***********************************************************************/ - void mf_Pointer_SetNull(rdpContext* context) { } -/** ********************************************************************* - * display default mouse cursor - ***********************************************************************/ - void mf_Pointer_SetDefault(rdpContext* context) { mfContext* mfc = (mfContext*) context; @@ -1017,28 +1068,31 @@ void mf_Pointer_SetDefault(rdpContext* context) [view setCursor:[NSCursor arrowCursor]]; } -/** ********************************************************************* - * clip drawing surface so nothing is drawn outside specified bounds - ***********************************************************************/ - -void mac_set_bounds(rdpContext* context, rdpBounds* bounds) +CGContextRef mac_create_bitmap_context(rdpContext* context) { + CGContextRef bitmap_context; + rdpGdi* gdi = context->gdi; -} - -/** ********************************************************************* - * we don't do much over here - ***********************************************************************/ - -void mac_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap) -{ + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + if (gdi->dstBpp == 16) + { + bitmap_context = CGBitmapContextCreate(gdi->primary_buffer, + gdi->width, gdi->height, 5, gdi->width * 2, colorSpace, + kCGBitmapByteOrder16Little | kCGImageAlphaNoneSkipFirst); + } + else + { + bitmap_context = CGBitmapContextCreate(gdi->primary_buffer, + gdi->width, gdi->height, 8, gdi->width * 4, colorSpace, + kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst); + } + + CGColorSpaceRelease(colorSpace); + + return bitmap_context; } -/** ********************************************************************* - * we don't do much over here - ***********************************************************************/ - void mac_begin_paint(rdpContext* context) { rdpGdi* gdi = context->gdi; @@ -1049,10 +1103,6 @@ void mac_begin_paint(rdpContext* context) gdi->primary->hdc->hwnd->invalid->null = 1; } -/** ********************************************************************* - * RDP server wants us to draw new data in the view - ***********************************************************************/ - void mac_end_paint(rdpContext* context) { rdpGdi* gdi; @@ -1077,9 +1127,6 @@ void mac_end_paint(rdpContext* context) if (context->gdi->primary->hdc->hwnd->invalid->null) return; - - if (context->gdi->drawing != context->gdi->primary) - return; invalid = gdi->primary->hdc->hwnd->invalid; @@ -1110,17 +1157,36 @@ void mac_end_paint(rdpContext* context) gdi->primary->hdc->hwnd->ninvalid = 0; } - -/** ********************************************************************* - * called when update data is available - ***********************************************************************/ +void mac_desktop_resize(rdpContext* context) +{ + mfContext* mfc = (mfContext*) context; + MRDPView* view = (MRDPView*) mfc->view; + rdpSettings* settings = context->settings; + + /** + * TODO: Fix resizing race condition. We should probably implement a message to be + * put on the update message queue to be able to properly flush pending updates, + * resize, and then continue with post-resizing graphical updates. + */ + + CGContextRef old_context = view->bitmap_context; + view->bitmap_context = NULL; + CGContextRelease(old_context); + + mfc->width = settings->DesktopWidth; + mfc->height = settings->DesktopHeight; + + gdi_resize(context->gdi, mfc->width, mfc->height); + + view->bitmap_context = mac_create_bitmap_context(context); +} static void update_activity_cb(freerdp* instance) { int status; wMessage message; wMessageQueue* queue; - + status = 1; queue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE); @@ -1129,7 +1195,7 @@ static void update_activity_cb(freerdp* instance) while (MessageQueue_Peek(queue, &message, TRUE)) { status = freerdp_message_queue_process_message(instance, FREERDP_UPDATE_MESSAGE_QUEUE, &message); - + if (!status) break; } @@ -1140,10 +1206,6 @@ static void update_activity_cb(freerdp* instance) } } -/** ********************************************************************* - * called when input data is available - ***********************************************************************/ - static void input_activity_cb(freerdp* instance) { int status; @@ -1169,10 +1231,6 @@ static void input_activity_cb(freerdp* instance) } } -/** ********************************************************************* - * called when data is available on a virtual channel - ***********************************************************************/ - static void channel_activity_cb(freerdp* instance) { wMessage* event; @@ -1195,29 +1253,6 @@ static void channel_activity_cb(freerdp* instance) } } -/** ********************************************************************* - * called when channel data is available - ***********************************************************************/ - -int mac_receive_channel_data(freerdp* instance, int chan_id, BYTE* data, int size, int flags, int total_size) -{ - return freerdp_channels_data(instance, chan_id, data, size, flags, total_size); -} - -/** - * Used to load plugins based on the commandline parameters. - * This function is provided as a parameter to freerdp_parse_args(), that will call it - * each time a plugin name is found on the command line. - * This function just calls freerdp_channels_load_plugin() for the given plugin, and always returns 1. - * - * @param settings - * @param name - * @param plugin_data - * @param user_data - * - * @return 1 - */ - int process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data) { rdpChannels* channels = (rdpChannels*) user_data; @@ -1231,10 +1266,6 @@ int process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA * stuff related to clipboard redirection */ -/** - * remote system has requested clipboard data from local system - */ - void cliprdr_process_cb_data_request_event(freerdp* instance) { int len; diff --git a/client/Mac/cli/AppDelegate.m b/client/Mac/cli/AppDelegate.m index 351111b97..218f28178 100644 --- a/client/Mac/cli/AppDelegate.m +++ b/client/Mac/cli/AppDelegate.m @@ -71,35 +71,38 @@ void mac_set_view_size(rdpContext* context, MRDPView* view); - (int) ParseCommandLineArguments { int i; - int len; + int length; int status; char* cptr; - int argc; - char** argv = nil; NSArray* args = [[NSProcessInfo processInfo] arguments]; - argc = (int) [args count]; - argv = malloc(sizeof(char*) * argc); + context->argc = (int) [args count]; + context->argv = malloc(sizeof(char*) * context->argc); i = 0; for (NSString* str in args) { - len = (int) ([str length] + 1); - cptr = (char*) malloc(len); + /* filter out some arguments added by XCode */ + + if ([str isEqualToString:@"YES"]) + continue; + + if ([str isEqualToString:@"-NSDocumentRevisionsDebugMode"]) + continue; + + length = (int) ([str length] + 1); + cptr = (char*) malloc(length); strcpy(cptr, [str UTF8String]); - argv[i++] = cptr; + context->argv[i++] = cptr; } - status = freerdp_client_settings_parse_command_line(context->settings, argc, argv); - - if (context->argc && context->argv) - status = freerdp_client_settings_command_line_status_print(context->settings, status, context->argc, context->argv); - else - { - freerdp_client_print_command_line_help(argc, argv); - } + context->argc = i; + + status = freerdp_client_settings_parse_command_line(context->settings, context->argc, context->argv); + + status = freerdp_client_settings_command_line_status_print(context->settings, status, context->argc, context->argv); return status; } diff --git a/client/Mac/mf_client.m b/client/Mac/mf_client.m index 6bc679818..b9b16171f 100755 --- a/client/Mac/mf_client.m +++ b/client/Mac/mf_client.m @@ -93,17 +93,17 @@ int mfreerdp_client_new(freerdp* instance, rdpContext* context) context->instance->PreConnect = mac_pre_connect; context->instance->PostConnect = mac_post_connect; - context->instance->ReceiveChannelData = mac_receive_channel_data; context->instance->Authenticate = mac_authenticate; context->channels = freerdp_channels_new(); settings = instance->settings; + settings->AsyncTransport = TRUE; + settings->AsyncUpdate = TRUE; settings->AsyncInput = TRUE; settings->AsyncChannels = TRUE; - settings->AsyncTransport = TRUE; return 0; } @@ -136,7 +136,6 @@ void freerdp_client_mouse_event(rdpContext* cfc, DWORD flags, int x, int y) input->MouseEvent(input, flags, x, y); } - void mf_scale_mouse_event(void* context, rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) { mfContext* mfc = (mfContext*) context; diff --git a/client/Mac/mfreerdp.h b/client/Mac/mfreerdp.h index 52e7be122..fa1961951 100644 --- a/client/Mac/mfreerdp.h +++ b/client/Mac/mfreerdp.h @@ -20,6 +20,7 @@ typedef struct mf_context mfContext; #include #include "MRDPView.h" +#include "Keyboard.h" #include struct mf_context @@ -28,7 +29,7 @@ struct mf_context DEFINE_RDP_CLIENT_COMMON(); void* view; - BOOL view_ownership; // TRUE indicates that the window was created and should be freed by the API. + BOOL view_ownership; int width; int height; @@ -43,9 +44,10 @@ struct mf_context int client_width; int client_height; + HANDLE stopEvent; HANDLE keyboardThread; - HANDLE stopEvent; - + enum APPLE_KEYBOARD_TYPE appleKeyboardType; + HGDI_DC hdc; UINT16 srcBpp; UINT16 dstBpp; diff --git a/client/Windows/CMakeLists.txt b/client/Windows/CMakeLists.txt index 5bc2d5eef..1e5cab1d8 100644 --- a/client/Windows/CMakeLists.txt +++ b/client/Windows/CMakeLists.txt @@ -33,6 +33,8 @@ set(${MODULE_PREFIX}_SRCS wf_rail.h wf_interface.c wf_interface.h + wf_floatbar.c + wf_floatbar.h wfreerdp.rc resource.h) @@ -63,7 +65,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) if(WITH_CLIENT_INTERFACE) - install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries EXPORT WinPRTargets) + install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries EXPORT FreeRDPTargets) add_subdirectory(cli) else() install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client) diff --git a/client/Windows/resource.h b/client/Windows/resource.h index 5ee440fa5..89c1e79ba 100644 --- a/client/Windows/resource.h +++ b/client/Windows/resource.h @@ -1,2 +1,13 @@ -#define IDI_ICON1 101 +#define IDI_ICON1 101 +#define IDB_BACKGROUND 102 +#define IDB_MINIMIZE 103 +#define IDB_MINIMIZE_ACT 104 +#define IDB_LOCK 105 +#define IDB_LOCK_ACT 106 +#define IDB_UNLOCK 107 +#define IDB_UNLOCK_ACT 108 +#define IDB_CLOSE 109 +#define IDB_CLOSE_ACT 100 +#define IDB_RESTORE 111 +#define IDB_RESTORE_ACT 112 diff --git a/client/Windows/resource/bg.bmp b/client/Windows/resource/bg.bmp new file mode 100644 index 000000000..c97ef5d99 Binary files /dev/null and b/client/Windows/resource/bg.bmp differ diff --git a/client/Windows/resource/close.bmp b/client/Windows/resource/close.bmp new file mode 100644 index 000000000..8fce91657 Binary files /dev/null and b/client/Windows/resource/close.bmp differ diff --git a/client/Windows/resource/close_active.bmp b/client/Windows/resource/close_active.bmp new file mode 100644 index 000000000..2c58a3de6 Binary files /dev/null and b/client/Windows/resource/close_active.bmp differ diff --git a/client/Windows/resource/lock.bmp b/client/Windows/resource/lock.bmp new file mode 100644 index 000000000..91d7384d9 Binary files /dev/null and b/client/Windows/resource/lock.bmp differ diff --git a/client/Windows/resource/lock_active.bmp b/client/Windows/resource/lock_active.bmp new file mode 100644 index 000000000..78e2ed45e Binary files /dev/null and b/client/Windows/resource/lock_active.bmp differ diff --git a/client/Windows/resource/minimize.bmp b/client/Windows/resource/minimize.bmp new file mode 100644 index 000000000..f4c5f6c7a Binary files /dev/null and b/client/Windows/resource/minimize.bmp differ diff --git a/client/Windows/resource/minimize_active.bmp b/client/Windows/resource/minimize_active.bmp new file mode 100644 index 000000000..152fad298 Binary files /dev/null and b/client/Windows/resource/minimize_active.bmp differ diff --git a/client/Windows/resource/restore.bmp b/client/Windows/resource/restore.bmp new file mode 100644 index 000000000..d74eddf23 Binary files /dev/null and b/client/Windows/resource/restore.bmp differ diff --git a/client/Windows/resource/restore_active.bmp b/client/Windows/resource/restore_active.bmp new file mode 100644 index 000000000..f88bc4d9a Binary files /dev/null and b/client/Windows/resource/restore_active.bmp differ diff --git a/client/Windows/resource/unlock.bmp b/client/Windows/resource/unlock.bmp new file mode 100644 index 000000000..8359ae7cc Binary files /dev/null and b/client/Windows/resource/unlock.bmp differ diff --git a/client/Windows/resource/unlock_active.bmp b/client/Windows/resource/unlock_active.bmp new file mode 100644 index 000000000..59d730d6e Binary files /dev/null and b/client/Windows/resource/unlock_active.bmp differ diff --git a/client/Windows/wf_cliprdr.c b/client/Windows/wf_cliprdr.c index 031b53a1b..31045860f 100644 --- a/client/Windows/wf_cliprdr.c +++ b/client/Windows/wf_cliprdr.c @@ -283,7 +283,7 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM break; } - if (SetClipboardData(wParam, cliprdr->hmem) == NULL) + if (SetClipboardData((UINT) wParam, cliprdr->hmem) == NULL) { DEBUG_CLIPRDR("SetClipboardData failed with 0x%x", GetLastError()); cliprdr->hmem = GlobalFree(cliprdr->hmem); @@ -339,11 +339,10 @@ static int create_cliprdr_window(cliprdrContext *cliprdr) static void *cliprdr_thread_func(void *arg) { - cliprdrContext *cliprdr = (cliprdrContext *)arg; - BOOL mcode; - MSG msg; int ret; - HRESULT result; + MSG msg; + BOOL mcode; + cliprdrContext* cliprdr = (cliprdrContext*) arg; if ((ret = create_cliprdr_window(cliprdr)) != 0) { @@ -437,15 +436,15 @@ static void wf_cliprdr_process_cb_monitor_ready_event(wfContext *wfc, RDP_CB_MON cliprdr_send_format_list(wfc->cliprdr_context); } -static void wf_cliprdr_process_cb_data_request_event(wfContext *wfc, RDP_CB_DATA_REQUEST_EVENT *event) +static void wf_cliprdr_process_cb_data_request_event(wfContext* wfc, RDP_CB_DATA_REQUEST_EVENT* event) { - cliprdrContext *cliprdr = (cliprdrContext *)wfc->cliprdr_context; - RDP_CB_DATA_RESPONSE_EVENT *responce_event; HANDLE hClipdata; int size = 0; - char *buff = NULL; - char *globlemem = NULL; + char* buff = NULL; + char* globlemem = NULL; UINT32 local_format; + cliprdrContext* cliprdr = (cliprdrContext*) wfc->cliprdr_context; + RDP_CB_DATA_RESPONSE_EVENT* response_event; local_format = event->format; @@ -473,6 +472,7 @@ static void wf_cliprdr_process_cb_data_request_event(wfContext *wfc, RDP_CB_DATA } hClipdata = GetClipboardData(event->format); + if (!hClipdata) { DEBUG_CLIPRDR("GetClipboardData failed."); @@ -480,10 +480,10 @@ static void wf_cliprdr_process_cb_data_request_event(wfContext *wfc, RDP_CB_DATA return; } - globlemem = (char *)GlobalLock(hClipdata); - size = GlobalSize(hClipdata); + globlemem = (char*) GlobalLock(hClipdata); + size = (int) GlobalSize(hClipdata); - buff = (char *)malloc(size); + buff = (char*) malloc(size); memcpy(buff, globlemem, size); GlobalUnlock(hClipdata); @@ -491,15 +491,15 @@ static void wf_cliprdr_process_cb_data_request_event(wfContext *wfc, RDP_CB_DATA CloseClipboard(); } - responce_event = (RDP_CB_DATA_RESPONSE_EVENT *)freerdp_event_new(CliprdrChannel_Class, + response_event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_DataResponse, NULL, NULL); - responce_event->data = (BYTE *)buff; - responce_event->size = size; + response_event->data = (BYTE *)buff; + response_event->size = size; - freerdp_channels_send_event(cliprdr->channels, (wMessage *) responce_event); + freerdp_channels_send_event(cliprdr->channels, (wMessage*) response_event); - /* Note: don't free buff here. */ + /* Note: don't free buffer here. */ } static void wf_cliprdr_process_cb_format_list_event(wfContext *wfc, RDP_CB_FORMAT_LIST_EVENT *event) @@ -560,12 +560,12 @@ static void wf_cliprdr_process_cb_format_list_event(wfContext *wfc, RDP_CB_FORMA } else { - int k; + UINT32 k; for (k = 0; k < event->raw_format_data_size / 36; k++) { - formatMapping *map; int name_len; + formatMapping* map; map = &cliprdr->format_mappings[i++]; diff --git a/client/Windows/wf_event.c b/client/Windows/wf_event.c index cb2b952a9..1b8194794 100644 --- a/client/Windows/wf_event.c +++ b/client/Windows/wf_event.c @@ -34,8 +34,8 @@ static HWND g_focus_hWnd; -#define X_POS(lParam) (lParam & 0xFFFF) -#define Y_POS(lParam) ((lParam >> 16) & 0xFFFF) +#define X_POS(lParam) ((UINT16) (lParam & 0xFFFF)) +#define Y_POS(lParam) ((UINT16) ((lParam >> 16) & 0xFFFF)) BOOL wf_scale_blt(wfContext* wfc, HDC hdc, int x, int y, int w, int h, HDC hdcSrc, int x1, int y1, DWORD rop); void wf_scale_mouse_event(wfContext* wfc, rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); @@ -189,14 +189,13 @@ void wf_sizing(wfContext* wfc, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { HDC hdc; - LONG ptr; + LONG_PTR ptr; wfContext* wfc; int x, y, w, h; PAINTSTRUCT ps; rdpInput* input; BOOL processed; RECT windowRect; - RECT clientRect; MINMAXINFO* minmax; SCROLLINFO si; @@ -286,7 +285,7 @@ LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam break; case WM_LBUTTONDOWN: - wf_scale_mouse_event(wfc, input,PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, X_POS(lParam) - wfc->offset_x, Y_POS(lParam) - wfc->offset_y); + wf_scale_mouse_event(wfc, input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, X_POS(lParam) - wfc->offset_x, Y_POS(lParam) - wfc->offset_y); break; case WM_LBUTTONUP: diff --git a/client/Windows/wf_floatbar.c b/client/Windows/wf_floatbar.c new file mode 100644 index 000000000..b331dc5c0 --- /dev/null +++ b/client/Windows/wf_floatbar.c @@ -0,0 +1,466 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Windows Float Bar + * + * Copyright 2013 Zhang Zhaolong + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "wf_interface.h" +#include "wf_floatbar.h" +#include "wf_window.h" +#include "wf_gdi.h" +#include "resource.h" + +typedef struct _Button Button; + +/* TIMERs */ +#define TIMER_HIDE 1 +#define TIMER_ANIMAT_SHOW 2 +#define TIMER_ANIMAT_HIDE 3 + +/* Button Type */ +#define BUTTON_LOCKPIN 0 +#define BUTTON_MINIMIZE 1 +#define BUTTON_RESTORE 2 +#define BUTTON_CLOSE 3 +#define BTN_MAX 4 + +/* bmp size */ +#define BACKGROUND_W 581 +#define BACKGROUND_H 29 +#define LOCK_X 13 +#define MINIMIZE_X (BACKGROUND_W - 91) +#define CLOSE_X (BACKGROUND_W - 37) +#define RESTORE_X (BACKGROUND_W - 64) + +#define BUTTON_Y 2 +#define BUTTON_WIDTH 24 +#define BUTTON_HEIGHT 24 + +struct _Button { + FloatBar* floatbar; + int type; + int x, y, h, w; + int active; + HBITMAP bmp; + HBITMAP bmp_act; + + /* Lock Specified */ + HBITMAP locked_bmp; + HBITMAP locked_bmp_act; + HBITMAP unlocked_bmp; + HBITMAP unlocked_bmp_act; +}; + +struct _FloatBar { + HWND parent; + HWND hwnd; + RECT rect; + LONG width; + LONG height; + wfContext* wfc; + Button* buttons[BTN_MAX]; + BOOL shown; + BOOL locked; + HDC hdcmem; + HBITMAP background; +}; + +static int button_hit(Button* button) +{ + FloatBar* floatbar = button->floatbar; + + switch (button->type) + { + case BUTTON_LOCKPIN: + if (!floatbar->locked) + { + button->bmp = button->locked_bmp; + button->bmp_act = button->locked_bmp_act; + } + else + { + button->bmp = button->unlocked_bmp; + button->bmp_act = button->unlocked_bmp_act; + } + + floatbar->locked = ~floatbar->locked; + InvalidateRect(button->floatbar->hwnd, NULL, FALSE); + UpdateWindow(button->floatbar->hwnd); + break; + + case BUTTON_MINIMIZE: + ShowWindow(floatbar->parent, SW_MINIMIZE); + break; + + case BUTTON_RESTORE: + wf_toggle_fullscreen(floatbar->wfc); + break; + + case BUTTON_CLOSE: + SendMessage(floatbar->parent, WM_DESTROY, 0 , 0); + break; + + default: + return 0; + } + + return 0; +} + +static int button_paint(Button* button, HDC hdc) +{ + FloatBar* floatbar = button->floatbar; + + SelectObject(floatbar->hdcmem, button->active ? button->bmp_act : button->bmp); + StretchBlt(hdc, button->x, button->y, button->w, button->h, floatbar->hdcmem, 0, 0, button->w, button->h, SRCCOPY); + + return 0; +} + +static Button* floatbar_create_button(FloatBar* floatbar, int type, int resid, int resid_act, int x, int y, int h, int w) +{ + Button *button; + HDC hDC; + HDC hMemDC; + HBITMAP hBitmap; + HBITMAP hOldBitmap; + BITMAP bm; + + button = (Button *)malloc(sizeof(Button)); + + if (!button) + return NULL; + + button->floatbar = floatbar; + button->type = type; + button->x = x; + button->y = y; + button->w = w; + button->h = h; + button->active = FALSE; + + button->bmp = (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(resid), IMAGE_BITMAP, w, h, LR_DEFAULTCOLOR); + button->bmp_act = (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(resid_act), IMAGE_BITMAP, w, h, LR_DEFAULTCOLOR); + + return button; +} + +static Button* floatbar_create_lock_button(FloatBar* floatbar, + int unlock_resid, int unlock_resid_act, + int lock_resid, int lock_resid_act, + int x, int y, int h, int w) +{ + Button* button; + + button = floatbar_create_button(floatbar, BUTTON_LOCKPIN, unlock_resid, unlock_resid_act, x, y, h, w); + + if (!button) + return NULL; + + button->unlocked_bmp = button->bmp; + button->unlocked_bmp_act = button->bmp_act; + button->locked_bmp = (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(lock_resid), IMAGE_BITMAP, w, h, LR_DEFAULTCOLOR); + button->locked_bmp_act = (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(lock_resid_act), IMAGE_BITMAP, w, h, LR_DEFAULTCOLOR); + + return button; +} + +static Button* floatbar_get_button(FloatBar* floatbar, int x, int y) +{ + int i; + + if (y > BUTTON_Y && y < BUTTON_Y + BUTTON_HEIGHT) + for (i = 0; i < BTN_MAX; i++) + if (x > floatbar->buttons[i]->x && x < floatbar->buttons[i]->x + floatbar->buttons[i]->w) + return floatbar->buttons[i]; + + return NULL; +} + +static int floatbar_paint(FloatBar* floatbar, HDC hdc) +{ + int i; + + if (!floatbar->wfc->fullscreen) + return -1; + + /* paint background */ + SelectObject(floatbar->hdcmem, floatbar->background); + StretchBlt(hdc, 0, 0, BACKGROUND_W, BACKGROUND_H, floatbar->hdcmem, 0, 0, BACKGROUND_W, BACKGROUND_H, SRCCOPY); + + /* paint buttons */ + for (i = 0; i < BTN_MAX; i++) + button_paint(floatbar->buttons[i], hdc); + + return 0; +} + +static int floatbar_animation(FloatBar* floatbar, BOOL show) +{ + SetTimer(floatbar->hwnd, show ? TIMER_ANIMAT_SHOW : TIMER_ANIMAT_HIDE, 10, NULL); + floatbar->shown = show; + return 0; +} + +LRESULT CALLBACK floatbar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + static int dragging = FALSE; + static int lbtn_dwn = FALSE; + static int btn_dwn_x = 0; + static FloatBar* floatbar; + static TRACKMOUSEEVENT tme; + + PAINTSTRUCT ps; + Button* button; + HDC hdc; + int pos_x; + int pos_y; + + int xScreen = GetSystemMetrics(SM_CXSCREEN); + + switch(Msg) + { + case WM_CREATE: + floatbar = (FloatBar *)((CREATESTRUCT *)lParam)->lpCreateParams; + floatbar->hwnd = hWnd; + floatbar->parent = GetParent(hWnd); + + GetWindowRect(floatbar->hwnd, &floatbar->rect); + floatbar->width = floatbar->rect.right - floatbar->rect.left; + floatbar->height = floatbar->rect.bottom - floatbar->rect.top; + + hdc = GetDC(hWnd); + floatbar->hdcmem = CreateCompatibleDC(hdc); + ReleaseDC(hWnd, hdc); + + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = hWnd; + tme.dwHoverTime = HOVER_DEFAULT; + + SetTimer(hWnd, TIMER_HIDE, 3000, NULL); + break; + + case WM_PAINT: + hdc = BeginPaint(hWnd, &ps); + floatbar_paint(floatbar, hdc); + EndPaint(hWnd, &ps); + break; + + case WM_LBUTTONDOWN: + pos_x = lParam & 0xffff; + pos_y = (lParam >> 16) & 0xffff; + + button = floatbar_get_button(floatbar, pos_x, pos_y); + if (!button) + { + SetCapture(hWnd); + dragging = TRUE; + btn_dwn_x = lParam & 0xffff; + } + else + lbtn_dwn = TRUE; + + break; + + case WM_LBUTTONUP: + pos_x = lParam & 0xffff; + pos_y = (lParam >> 16) & 0xffff; + + ReleaseCapture(); + dragging = FALSE; + + if (lbtn_dwn) + { + button = floatbar_get_button(floatbar, pos_x, pos_y); + if (button) + button_hit(button); + lbtn_dwn = FALSE; + } + break; + + case WM_MOUSEMOVE: + KillTimer(hWnd, TIMER_HIDE); + pos_x = lParam & 0xffff; + pos_y = (lParam >> 16) & 0xffff; + + if (!floatbar->shown) + floatbar_animation(floatbar, TRUE); + + if (dragging) + { + floatbar->rect.left = floatbar->rect.left + (lParam & 0xffff) - btn_dwn_x; + + if (floatbar->rect.left < 0) + floatbar->rect.left = 0; + else if (floatbar->rect.left > xScreen - floatbar->width) + floatbar->rect.left = xScreen - floatbar->width; + + MoveWindow(hWnd, floatbar->rect.left, floatbar->rect.top, floatbar->width, floatbar->height, TRUE); + } + else + { + int i; + + for (i = 0; i < BTN_MAX; i++) + floatbar->buttons[i]->active = FALSE; + + button = floatbar_get_button(floatbar, pos_x, pos_y); + if (button) + button->active = TRUE; + + InvalidateRect(hWnd, NULL, FALSE); + UpdateWindow(hWnd); + } + + TrackMouseEvent(&tme); + break; + + case WM_CAPTURECHANGED: + dragging = FALSE; + break; + + case WM_MOUSELEAVE: + { + int i; + + for (i = 0; i < BTN_MAX; i++) + floatbar->buttons[i]->active = FALSE; + + InvalidateRect(hWnd, NULL, FALSE); + UpdateWindow(hWnd); + + SetTimer(hWnd, TIMER_HIDE, 3000, NULL); + break; + } + case WM_TIMER: + switch (wParam) + { + case TIMER_HIDE: + { + KillTimer(hWnd, TIMER_HIDE); + if (!floatbar->locked) + floatbar_animation(floatbar, FALSE); + break; + } + case TIMER_ANIMAT_SHOW: + { + static int y = 0; + + MoveWindow(floatbar->hwnd, floatbar->rect.left, (y++ - floatbar->height), floatbar->width, floatbar->height, TRUE); + if (y == floatbar->height) + { + y = 0; + KillTimer(hWnd, wParam); + } + break; + } + case TIMER_ANIMAT_HIDE: + { + static int y = 0; + + MoveWindow(floatbar->hwnd, floatbar->rect.left, -y++, floatbar->width, floatbar->height, TRUE); + if (y == floatbar->height) + { + y = 0; + KillTimer(hWnd, wParam); + } + break; + } + default: + break; + } + break; + + case WM_DESTROY: + DeleteDC(floatbar->hdcmem); + PostQuitMessage(0); + break; + + default: + return DefWindowProc(hWnd, Msg, wParam, lParam); + } + return 0; +} + +static FloatBar* floatbar_create(wfContext* wfc) +{ + FloatBar* floatbar; + + floatbar = (FloatBar *)malloc(sizeof(FloatBar)); + + if (!floatbar) + return NULL; + + floatbar->locked = FALSE; + floatbar->shown = TRUE; + floatbar->hwnd = NULL; + floatbar->parent = wfc->hwnd; + floatbar->wfc = wfc; + floatbar->hdcmem = NULL; + + floatbar->background = (HBITMAP)LoadImage(wfc->hInstance, MAKEINTRESOURCE(IDB_BACKGROUND), IMAGE_BITMAP, BACKGROUND_W, BACKGROUND_H, LR_DEFAULTCOLOR); + floatbar->buttons[0] = floatbar_create_button(floatbar, BUTTON_MINIMIZE, IDB_MINIMIZE, IDB_MINIMIZE_ACT, MINIMIZE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH); + floatbar->buttons[1] = floatbar_create_button(floatbar, BUTTON_RESTORE, IDB_RESTORE, IDB_RESTORE_ACT, RESTORE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH); + floatbar->buttons[2] = floatbar_create_button(floatbar, BUTTON_CLOSE, IDB_CLOSE, IDB_CLOSE_ACT, CLOSE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH); + floatbar->buttons[3] = floatbar_create_lock_button(floatbar, IDB_UNLOCK, IDB_UNLOCK_ACT, IDB_LOCK, IDB_LOCK_ACT, LOCK_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH); + + return floatbar; +} + +int floatbar_hide(FloatBar* floatbar) +{ + MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->height, floatbar->width, floatbar->height, TRUE); + return 0; +} + +int floatbar_show(FloatBar* floatbar) +{ + MoveWindow(floatbar->hwnd, floatbar->rect.left, floatbar->rect.top, floatbar->width, floatbar->height, TRUE); + return 0; +} + +void floatbar_window_create(wfContext *wfc) +{ + WNDCLASSEX wnd_cls; + HWND barWnd; + int x = (GetSystemMetrics(SM_CXSCREEN) - BACKGROUND_W) / 2; + + wnd_cls.cbSize = sizeof(WNDCLASSEX); + wnd_cls.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wnd_cls.lpfnWndProc = floatbar_proc; + wnd_cls.cbClsExtra = 0; + wnd_cls.cbWndExtra = 0; + wnd_cls.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wnd_cls.hCursor = LoadCursor(wfc->hInstance, IDC_ARROW); + wnd_cls.hbrBackground = NULL; + wnd_cls.lpszMenuName = NULL; + wnd_cls.lpszClassName = L"floatbar"; + wnd_cls.hInstance = wfc->hInstance; + wnd_cls.hIconSm = LoadIcon(NULL, IDI_APPLICATION); + + RegisterClassEx(&wnd_cls); + + wfc->floatbar = floatbar_create(wfc); + + barWnd = CreateWindowEx(WS_EX_TOPMOST, L"floatbar", L"floatbar", WS_CHILD, x, 0, BACKGROUND_W, BACKGROUND_H, wfc->hwnd, NULL, wfc->hInstance, wfc->floatbar); + if (barWnd == NULL) + return; + ShowWindow(barWnd, SW_SHOWNORMAL); +} diff --git a/channels/client/init.h b/client/Windows/wf_floatbar.h similarity index 60% rename from channels/client/init.h rename to client/Windows/wf_floatbar.h index a5dccc133..7b6f67dd0 100644 --- a/channels/client/init.h +++ b/client/Windows/wf_floatbar.h @@ -1,8 +1,8 @@ /** * FreeRDP: A Remote Desktop Protocol Implementation - * Client Channels + * Windows Float Bar * - * Copyright 2013 Marc-Andre Moreau + * Copyright 2013 Zhang Zhaolong * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,12 +17,14 @@ * limitations under the License. */ -#ifndef FREERDP_PRIVATE_CLIENT_CHANNELS_INIT -#define FREERDP_PRIVATE_CLIENT_CHANNELS_INIT +#ifndef __WF_FLOATBAR_H__ +#define __WF_FLOATBAR_H__ -#include "channels.h" +typedef struct _FloatBar FloatBar; +typedef struct wf_context wfContext; -UINT32 FreeRDP_VirtualChannelInit(void** ppInitHandle, PCHANNEL_DEF pChannel, - int channelCount, UINT32 versionRequested, PCHANNEL_INIT_EVENT_FN pChannelInitEventProc); +void floatbar_window_create(wfContext* wfc); +int floatbar_show(FloatBar* floatbar); +int floatbar_hide(FloatBar* floatbar); -#endif /* FREERDP_PRIVATE_CLIENT_CHANNELS_INIT */ +#endif diff --git a/client/Windows/wf_gdi.c b/client/Windows/wf_gdi.c index 16359d858..2a7daedc0 100644 --- a/client/Windows/wf_gdi.c +++ b/client/Windows/wf_gdi.c @@ -278,10 +278,7 @@ void wf_resize_window(wfContext* wfc) } } else if (!wfc->instance->settings->Decorations) - { - RECT rc_wnd; - RECT rc_client; - + { SetWindowLongPtr(wfc->hwnd, GWL_STYLE, WS_CHILD); /* Now resize to get full canvas size and room for caption and borders */ @@ -292,9 +289,6 @@ void wf_resize_window(wfContext* wfc) } else { - RECT rc_wnd; - RECT rc_client; - SetWindowLongPtr(wfc->hwnd, GWL_STYLE, WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX | WS_MAXIMIZEBOX); if (!wfc->client_height) @@ -328,6 +322,11 @@ void wf_toggle_fullscreen(wfContext* wfc) wfc->disablewindowtracking = TRUE; } + if (wfc->fullscreen) + floatbar_show(wfc->floatbar); + else + floatbar_hide(wfc->floatbar); + SetParent(wfc->hwnd, wfc->fullscreen ? NULL : wfc->hWndParent); wf_resize_window(wfc); ShowWindow(wfc->hwnd, SW_SHOW); @@ -521,12 +520,18 @@ void wf_gdi_polyline(wfContext* wfc, POLYLINE_ORDER* polyline) if (polyline->numPoints > 0) { + POINT temp; + + temp.x = polyline->xStart; + temp.y = polyline->yStart; pts = (POINT*) malloc(sizeof(POINT) * polyline->numPoints); for (i = 0; i < (int) polyline->numPoints; i++) { - pts[i].x = polyline->points[i].x; - pts[i].y = polyline->points[i].y; + temp.x += polyline->points[i].x; + temp.y += polyline->points[i].y; + pts[i].x = temp.x; + pts[i].y = temp.y; if (wfc->drawing == wfc->primary) wf_invalidate_region(wfc, pts[i].x, pts[i].y, pts[i].x + 1, pts[i].y + 1); diff --git a/client/Windows/wf_interface.c b/client/Windows/wf_interface.c index 6e1b341bd..6eca6cab9 100644 --- a/client/Windows/wf_interface.c +++ b/client/Windows/wf_interface.c @@ -59,8 +59,6 @@ #include "resource.h" -void wf_size_scrollbars(wfContext* wfc, int client_width, int client_height); - int wf_create_console(void) { if (!AllocConsole()) @@ -265,18 +263,16 @@ BOOL wf_pre_connect(freerdp* instance) { if (settings->UseMultimon) { - settings->DesktopWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN); - settings->DesktopHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN); + desktopWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN); + desktopHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN); } else { - settings->DesktopWidth = GetSystemMetrics(SM_CXSCREEN); - settings->DesktopHeight = GetSystemMetrics(SM_CYSCREEN); + desktopWidth = GetSystemMetrics(SM_CXSCREEN); + desktopHeight = GetSystemMetrics(SM_CYSCREEN); } } - desktopWidth = (desktopWidth + 3) & (~3); - if (desktopWidth != settings->DesktopWidth) { freerdp_set_param_uint32(settings, FreeRDP_DesktopWidth, desktopWidth); @@ -312,7 +308,7 @@ void wf_add_system_menu(wfContext* wfc) item_info.wID = SYSCOMMAND_ID_SMARTSIZING; item_info.fType = MFT_STRING; item_info.dwTypeData = _wcsdup(_T("Smart sizing")); - item_info.cch = _wcslen(_T("Smart sizing")); + item_info.cch = (UINT) _wcslen(_T("Smart sizing")); item_info.dwItemData = (ULONG_PTR) wfc; InsertMenuItem(hMenu, 6, TRUE, &item_info); @@ -448,6 +444,7 @@ BOOL wf_post_connect(freerdp* instance) freerdp_channels_post_connect(instance->context->channels, instance); wf_cliprdr_init(wfc, instance->context->channels); + floatbar_window_create(wfc); return TRUE; } @@ -829,14 +826,10 @@ int freerdp_client_load_settings_from_rdp_file(wfContext* wfc, char* filename) return 0; } -void wf_size_scrollbars(wfContext* wfc, int client_width, int client_height) +void wf_size_scrollbars(wfContext* wfc, UINT32 client_width, UINT32 client_height) { - BOOL rc; - - if (wfc->disablewindowtracking == TRUE) - { + if (wfc->disablewindowtracking) return; - } // prevent infinite message loop wfc->disablewindowtracking = TRUE; diff --git a/client/Windows/wf_interface.h b/client/Windows/wf_interface.h index f5e95cfb3..b9aa4056c 100644 --- a/client/Windows/wf_interface.h +++ b/client/Windows/wf_interface.h @@ -37,6 +37,7 @@ #include #include +#include "wf_floatbar.h" #include "wf_event.h" #ifdef __cplusplus @@ -132,6 +133,7 @@ struct wf_context int yCurrentScroll; // current vertical scroll value int yMaxScroll; // maximum vertical scroll value cliprdrContext *cliprdr_context; + FloatBar* floatbar; }; typedef struct wf_context wfContext; @@ -141,7 +143,7 @@ typedef struct wf_context wfContext; FREERDP_API int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints); FREERDP_API int freerdp_client_set_window_size(wfContext* wfc, int width, int height); - +FREERDP_API void wf_size_scrollbars(wfContext* wfc, UINT32 client_width, UINT32 client_height); #ifdef __cplusplus } diff --git a/client/Windows/wfreerdp.rc b/client/Windows/wfreerdp.rc index ef912b2d7..135f64104 100644 Binary files a/client/Windows/wfreerdp.rc and b/client/Windows/wfreerdp.rc differ diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 331cae176..4a92692f5 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -51,8 +51,6 @@ #include #endif -#define WITH_AUTORECONNECT - #include #include #include @@ -1122,11 +1120,6 @@ int xf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type) return 1; } -int xf_receive_channel_data(freerdp* instance, int channelId, BYTE* data, int size, int flags, int total_size) -{ - return freerdp_channels_data(instance, channelId, data, size, flags, total_size); -} - void xf_process_channel_event(rdpChannels* channels, freerdp* instance) { xfContext* xfc; @@ -1367,19 +1360,20 @@ void* xf_channels_thread(void* arg) return NULL; } -#ifdef WITH_AUTORECONNECT BOOL xf_auto_reconnect(freerdp* instance) { - xfContext* xfc = (xfContext*)instance->context; + xfContext* xfc = (xfContext*) instance->context; UINT32 num_retries = 0; UINT32 max_retries = instance->settings->AutoReconnectMaxRetries; /* Only auto reconnect on network disconnects. */ - if (freerdp_error_info(instance) != 0) return FALSE; + if (freerdp_error_info(instance) != 0) + return FALSE; /* A network disconnect was detected */ fprintf(stderr, "Network disconnect!\n"); + if (!instance->settings->AutoReconnectionEnabled) { /* No auto-reconnect - just quit */ @@ -1397,6 +1391,7 @@ BOOL xf_auto_reconnect(freerdp* instance) /* Attempt the next reconnect */ fprintf(stderr, "Attempting reconnect (%u of %u)\n", num_retries, max_retries); + if (freerdp_reconnect(instance)) { xfc->disconnect = FALSE; @@ -1410,7 +1405,6 @@ BOOL xf_auto_reconnect(freerdp* instance) return FALSE; } -#endif /** Main loop for the rdp connection. * It will be run from the thread's entry point (thread_func()). @@ -1458,11 +1452,6 @@ void* xf_thread(void* param) ZeroMemory(wfds, sizeof(wfds)); ZeroMemory(&timeout, sizeof(struct timeval)); -#ifdef WITH_AUTORECONNECT - instance->settings->AutoReconnectionEnabled = TRUE; - instance->settings->AutoReconnectMaxRetries = 20; -#endif - status = freerdp_connect(instance); xfc = (xfContext*) instance->context; @@ -1607,9 +1596,9 @@ void* xf_thread(void* param) { if (freerdp_check_fds(instance) != TRUE) { -#ifdef WITH_AUTORECONNECT - if (xf_auto_reconnect(instance)) continue; -#endif + if (xf_auto_reconnect(instance)) + continue; + fprintf(stderr, "Failed to check FreeRDP file descriptor\n"); break; } @@ -1861,7 +1850,6 @@ static int xfreerdp_client_new(freerdp* instance, rdpContext* context) instance->Authenticate = xf_authenticate; instance->VerifyCertificate = xf_verify_certificate; instance->LogonErrorInfo = xf_logon_error_info; - instance->ReceiveChannelData = xf_receive_channel_data; context->channels = freerdp_channels_new(); diff --git a/client/X11/xf_client.h b/client/X11/xf_client.h index dec4876f2..a7e601006 100644 --- a/client/X11/xf_client.h +++ b/client/X11/xf_client.h @@ -20,6 +20,11 @@ #ifndef __XF_CLIENT_H #define __XF_CLIENT_H +#include +#include +#include +#include + #include #include #include @@ -31,11 +36,6 @@ #include #include -#include -#include -#include -#include - #ifdef __cplusplus extern "C" { #endif diff --git a/client/X11/xf_window.c b/client/X11/xf_window.c index b428048a5..5b7c96b17 100644 --- a/client/X11/xf_window.c +++ b/client/X11/xf_window.c @@ -539,8 +539,7 @@ xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int widt window->handle = XCreateWindow(xfc->display, RootWindowOfScreen(xfc->screen), x, y, window->width, window->height, 0, xfc->depth, InputOutput, xfc->visual, - CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap | - CWBorderPixel | CWWinGravity | CWBitGravity, &xfc->attribs); + 0, &xfc->attribs); DEBUG_X11_LMS("Create window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d rdp=0x%X", (UINT32) window->handle, window->left, window->top, window->right, window->bottom, diff --git a/client/common/CMakeLists.txt b/client/common/CMakeLists.txt index 3f1b29780..07f162386 100644 --- a/client/common/CMakeLists.txt +++ b/client/common/CMakeLists.txt @@ -18,9 +18,6 @@ set(MODULE_NAME "freerdp-client") set(MODULE_PREFIX "FREERDP_CLIENT") -include_directories(${OPENSSL_INCLUDE_DIR}) -include_directories(${ZLIB_INCLUDE_DIRS}) - set(${MODULE_PREFIX}_SRCS client.c cmdline.c @@ -40,6 +37,9 @@ endif() add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) +include_directories(${OPENSSL_INCLUDE_DIR}) +include_directories(${ZLIB_INCLUDE_DIRS}) + set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION} PREFIX "lib") set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} @@ -53,7 +53,10 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHI MODULE winpr MODULES winpr-crt winpr-utils) -set_target_properties(${MODULE_NAME} PROPERTIES LINK_INTERFACE_LIBRARIES "") +if(NOT WIN32) + set_target_properties(${MODULE_NAME} PROPERTIES LINK_INTERFACE_LIBRARIES "") + set_target_properties(${MODULE_NAME} PROPERTIES INTERFACE_LINK_LIBRARIES "") +endif() target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index c506eea57..a894a94f8 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -124,6 +124,8 @@ COMMAND_LINE_ARGUMENT_A args[] = { "cert-ignore", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "ignore certificate" }, { "pcb", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Preconnection Blob" }, { "pcid", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Preconnection Id" }, + { "spn-class", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "SPN authentication service class" }, + { "credentials-delegation", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Disable credentials delegation" }, { "vmconnect", COMMAND_LINE_VALUE_OPTIONAL, "", NULL, NULL, -1, NULL, "Hyper-V console (use port 2179, disable negotiation)" }, { "authentication", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "authentication (hack!)" }, { "encryption", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "encryption (hack!)" }, @@ -146,6 +148,7 @@ COMMAND_LINE_ARGUMENT_A args[] = { "help", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_HELP, NULL, NULL, NULL, -1, "?", "print help" }, { "play-rfx", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Replay rfx pcap file" }, { "auth-only", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Authenticate only." }, + { "auto-reconnect", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Automatic reconnection" }, { "reconnect-cookie", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Pass base64 reconnect cookie to the connection" }, { "print-reconnect-cookie", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Print base64 reconnect cookie after connecting" }, { "heartbeat", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Support heartbeat PDUs" }, @@ -195,7 +198,7 @@ int freerdp_client_print_command_line_help(int argc, char** argv) if (arg->Format) { - length = strlen(arg->Name) + strlen(arg->Format) + 2; + length = (int) (strlen(arg->Name) + strlen(arg->Format) + 2); str = (char*) malloc(length + 1); sprintf_s(str, length + 1, "%s:%s", arg->Name, arg->Format); printf("%-20s", str); @@ -210,7 +213,7 @@ int freerdp_client_print_command_line_help(int argc, char** argv) } else if (arg->Flags & COMMAND_LINE_VALUE_BOOL) { - length = strlen(arg->Name) + 32; + length = (int) strlen(arg->Name) + 32; str = (char*) malloc(length + 1); sprintf_s(str, length + 1, "%s (default:%s)", arg->Name, arg->Default ? "on" : "off"); @@ -266,7 +269,7 @@ int freerdp_client_command_line_pre_filter(void* context, int index, int argc, L int length; rdpSettings* settings; - length = strlen(argv[index]); + length = (int) strlen(argv[index]); if (length > 4) { @@ -745,7 +748,7 @@ int freerdp_parse_username(char* username, char** user, char** domain) if (p) { - length = p - username; + length = (int) (p - username); *domain = (char*) malloc(length + 1); strncpy(*domain, username, length); (*domain)[length] = '\0'; @@ -757,7 +760,7 @@ int freerdp_parse_username(char* username, char** user, char** domain) if (p) { - length = p - username; + length = (int) (p - username); *user = (char*) malloc(length + 1); strncpy(*user, username, length); (*user)[length] = '\0'; @@ -893,7 +896,7 @@ int freerdp_detect_command_line_pre_filter(void* context, int index, int argc, L if (index == 1) { - length = strlen(argv[index]); + length = (int) strlen(argv[index]); if (length > 4) { @@ -1127,7 +1130,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (p) { - length = p - arg->Value; + length = (int) (p - arg->Value); settings->ServerPort = atoi(&p[1]); settings->ServerHostname = (char*) malloc(length + 1); strncpy(settings->ServerHostname, arg->Value, length); @@ -1138,6 +1141,14 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, settings->ServerHostname = _strdup(arg->Value); } } + CommandLineSwitchCase(arg, "spn-class") + { + settings->AuthenticationServiceClass = _strdup(arg->Value); + } + CommandLineSwitchCase(arg, "credentials-delegation") + { + settings->DisableCredentialsDelegation = arg->Value ? FALSE : TRUE; + } CommandLineSwitchCase(arg, "vmconnect") { settings->ServerPort = 2179; @@ -1149,10 +1160,6 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, settings->PreconnectionBlob = _strdup(arg->Value); } } - CommandLineSwitchCase(arg, "port") - { - settings->ServerPort = atoi(arg->Value); - } CommandLineSwitchCase(arg, "w") { settings->DesktopWidth = atoi(arg->Value); @@ -1205,12 +1212,13 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, { if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) { + UINT32 i; char** p; - int i, count = 0; + int count = 0; p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count); - settings->NumMonitorIds = count; + settings->NumMonitorIds = (UINT32) count; settings->MonitorIds = (UINT32*) malloc(sizeof(UINT32) * settings->NumMonitorIds); for (i = 0; i < settings->NumMonitorIds; i++) @@ -1320,7 +1328,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (p) { - length = p - arg->Value; + length = (int) (p - arg->Value); settings->GatewayPort = atoi(&p[1]); settings->GatewayHostname = (char*) malloc(length + 1); strncpy(settings->GatewayHostname, arg->Value, length); @@ -1375,7 +1383,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, CommandLineSwitchCase(arg, "load-balance-info") { settings->LoadBalanceInfo = (BYTE*) _strdup(arg->Value); - settings->LoadBalanceInfoLength = strlen((char*) settings->LoadBalanceInfo); + settings->LoadBalanceInfoLength = (UINT32) strlen((char*) settings->LoadBalanceInfo); } CommandLineSwitchCase(arg, "app-name") { @@ -1709,6 +1717,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, { settings->AuthenticationOnly = arg->Value ? TRUE : FALSE; } + CommandLineSwitchCase(arg, "auto-reconnect") + { + settings->AutoReconnectionEnabled = arg->Value ? TRUE : FALSE; + } CommandLineSwitchCase(arg, "reconnect-cookie") { BYTE *base64; @@ -1755,6 +1767,13 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } } + arg = CommandLineFindArgumentA(args, "port"); + + if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT) + { + settings->ServerPort = atoi(arg->Value); + } + arg = CommandLineFindArgumentA(args, "p"); if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT) @@ -1792,7 +1811,7 @@ int freerdp_client_load_static_channel_addin(rdpChannels* channels, rdpSettings* int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) { - int index; + UINT32 index; ADDIN_ARGV* args; if ((freerdp_static_channel_collection_find(settings, "rdpsnd")) || diff --git a/client/common/compatibility.c b/client/common/compatibility.c index b86682fdf..094faf75e 100644 --- a/client/common/compatibility.c +++ b/client/common/compatibility.c @@ -263,8 +263,8 @@ int freerdp_client_old_command_line_pre_filter(void* context, int index, int arg if (p != NULL) { p = strchr(p, ':'); - length = p - a; - args->argv[j + 1] = malloc(length + 1); + length = (int) (p - a); + args->argv[j + 1] = (char*) malloc(length + 1); CopyMemory(args->argv[j + 1], a, length); args->argv[j + 1][length] = '\0'; p++; diff --git a/client/common/file.c b/client/common/file.c index acac04acb..cc3aa31b2 100644 --- a/client/common/file.c +++ b/client/common/file.c @@ -212,12 +212,12 @@ void freerdp_client_parse_rdp_file_integer_unicode(rdpFile* file, WCHAR* name, W char* nameA; char* valueA; - length = _wcslen(name); + length = (int) _wcslen(name); nameA = (char*) malloc(length + 1); WideCharToMultiByte(CP_UTF8, 0, name, length, nameA, length, NULL, NULL); nameA[length] = '\0'; - length = _wcslen(value); + length = (int) _wcslen(value); valueA = (char*) malloc(length + 1); WideCharToMultiByte(CP_UTF8, 0, value, length, valueA, length, NULL, NULL); valueA[length] = '\0'; @@ -353,12 +353,12 @@ void freerdp_client_parse_rdp_file_string_unicode(rdpFile* file, WCHAR* name, WC char* nameA; char* valueA; - length = _wcslen(name); + length = (int) _wcslen(name); nameA = (char*) malloc(length + 1); WideCharToMultiByte(CP_UTF8, 0, name, length, nameA, length, NULL, NULL); nameA[length] = '\0'; - length = _wcslen(value); + length = (int) _wcslen(value); valueA = (char*) malloc(length + 1); WideCharToMultiByte(CP_UTF8, 0, value, length, valueA, length, NULL, NULL); valueA[length] = '\0'; @@ -407,7 +407,7 @@ BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, const BYTE* buffe while (line) { - length = strlen(line); + length = (int) strlen(line); if (length > 1) { @@ -482,7 +482,7 @@ BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, const BYTE* buf while (line != NULL) { - length = _wcslen(line); + length = (int) _wcslen(line); if (length > 1) { @@ -661,7 +661,7 @@ BOOL freerdp_client_write_rdp_file(const rdpFile* file, const char* name, BOOL u int status = 0; WCHAR* unicodestr = NULL; - length = freerdp_client_write_rdp_file_buffer(file, NULL, 0); + length = (int) freerdp_client_write_rdp_file_buffer(file, NULL, 0); if (length < 0) { @@ -722,7 +722,7 @@ size_t freerdp_client_write_rdp_file_buffer(const rdpFile* file, char* buffer, s { line = &(file->lines[index]); - length = strlen(line->text); + length = (int) strlen(line->text); if (!buffer) { @@ -812,7 +812,7 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* if (~((size_t) file->LoadBalanceInfo)) { settings->LoadBalanceInfo = (BYTE*) _strdup(file->LoadBalanceInfo); - settings->LoadBalanceInfoLength = strlen((char*) settings->LoadBalanceInfo); + settings->LoadBalanceInfoLength = (int) strlen((char*) settings->LoadBalanceInfo); } if (~file->AuthenticationLevel) diff --git a/client/iOS/FreeRDP/ios_freerdp.m b/client/iOS/FreeRDP/ios_freerdp.m index 9a66dee05..a6eac2ce8 100644 --- a/client/iOS/FreeRDP/ios_freerdp.m +++ b/client/iOS/FreeRDP/ios_freerdp.m @@ -92,11 +92,6 @@ static BOOL ios_post_connect(freerdp* instance) return TRUE; } -static int ios_receive_channel_data(freerdp* instance, int channelId, UINT8* data, int size, int flags, int total_size) -{ - return freerdp_channels_data(instance, channelId, data, size, flags, total_size); -} - void ios_process_channel_event(rdpChannels* channels, freerdp* instance) { wMessage* event = freerdp_channels_pop_event(channels); @@ -283,7 +278,6 @@ freerdp* ios_freerdp_new() inst->Authenticate = ios_ui_authenticate; inst->VerifyCertificate = ios_ui_check_certificate; inst->VerifyChangedCertificate = ios_ui_check_changed_certificate; - inst->ReceiveChannelData = ios_receive_channel_data; inst->ContextSize = sizeof(mfContext); inst->ContextNew = ios_context_new; diff --git a/cmake/FindNPP.cmake b/cmake/FindNPP.cmake deleted file mode 100644 index 7b04ee43a..000000000 --- a/cmake/FindNPP.cmake +++ /dev/null @@ -1,119 +0,0 @@ -############################################################################### -# -# FindNPP.cmake -# -# NPP_LIBRARY_ROOT_DIR -- Path to the NPP dorectory. -# NPP_INCLUDES -- NPP Include directories. -# NPP_LIBRARIES -- NPP libraries. -# NPP_VERSION -- NPP version in format "major.minor.build". -# -# If not found automatically, please set NPP_LIBRARY_ROOT_DIR -# in CMake or set enviroment varivabe $NPP_ROOT -# -# Author: Anatoly Baksheev, Itseez Ltd. -# -# The MIT License -# -# License for the specific language governing rights and limitations under -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. -# -############################################################################### - -cmake_policy(PUSH) -cmake_minimum_required(VERSION 2.8.0) -cmake_policy(POP) - -if(NOT "${NPP_LIBRARY_ROOT_DIR}" STREQUAL "${NPP_LIBRARY_ROOT_DIR_INTERNAL}") - unset(NPP_INCLUDES CACHE) - unset(NPP_LIBRARIES CACHE) -endif() - -if(CMAKE_SIZEOF_VOID_P EQUAL 4) - if (UNIX OR APPLE) - set(NPP_SUFFIX "32") - else() - set(NPP_SUFFIX "-mt") - endif() -else(CMAKE_SIZEOF_VOID_P EQUAL 4) - if (UNIX OR APPLE) - set(NPP_SUFFIX "64") - else() - set(NPP_SUFFIX "-mt-x64") - endif() -endif(CMAKE_SIZEOF_VOID_P EQUAL 4) - -find_path(CUDA_ROOT_DIR "doc/CUDA_Toolkit_Release_Notes.txt" - PATHS "/Developer/NVIDIA" - PATH_SUFFIXES "CUDA-5.0" - DOC "CUDA root directory") - -find_path(NPP_INCLUDES "npp.h" - PATHS "${CUDA_ROOT_DIR}" - PATH_SUFFIXES "include" - DOC "NPP include directory") -mark_as_advanced(NPP_INCLUDES) - -find_library(NPP_LIBRARIES - NAMES "npp" "libnpp" "npp${NPP_SUFFIX}" "libnpp${NPP_SUFFIX}" - PATHS "${CUDA_ROOT_DIR}" - PATH_SUFFIXES "lib" - DOC "NPP library") -mark_as_advanced(NPP_LIBRARIES) - -if(EXISTS ${NPP_INCLUDES}/nppversion.h) - file(STRINGS ${NPP_INCLUDES}/nppversion.h npp_major REGEX "#define NPP_VERSION_MAJOR.*") - file(STRINGS ${NPP_INCLUDES}/nppversion.h npp_minor REGEX "#define NPP_VERSION_MINOR.*") - file(STRINGS ${NPP_INCLUDES}/nppversion.h npp_build REGEX "#define NPP_VERSION_BUILD.*") - - string(REGEX REPLACE "#define NPP_VERSION_MAJOR[ \t]+|//.*" "" npp_major ${npp_major}) - string(REGEX REPLACE "#define NPP_VERSION_MINOR[ \t]+|//.*" "" npp_minor ${npp_minor}) - string(REGEX REPLACE "#define NPP_VERSION_BUILD[ \t]+|//.*" "" npp_build ${npp_build}) - - string(REGEX MATCH "[0-9]+" npp_major ${npp_major}) - string(REGEX MATCH "[0-9]+" npp_minor ${npp_minor}) - string(REGEX MATCH "[0-9]+" npp_build ${npp_build}) - set(NPP_VERSION "${npp_major}.${npp_minor}.${npp_build}") -endif() - -if(NOT EXISTS ${NPP_LIBRARIES} OR NOT EXISTS ${NPP_INCLUDES}/npp.h) - set(NPP_FOUND FALSE) - message(WARNING "NPP headers/libraries are not found. Please specify NPP_LIBRARY_ROOT_DIR in CMake or set $NPP_ROOT_DIR.") -endif() - -include(FindPackageHandleStandardArgs) - -find_package_handle_standard_args(NPP - REQUIRED_VARS - NPP_INCLUDES - NPP_LIBRARIES - NPP_VERSION) - -if(APPLE) - # We need to add the path to cudart to the linker using rpath, since the library name for the cuda libraries is prepended with @rpath. - get_filename_component(_cuda_path_to_npp "${NPP_LIBRARIES}" PATH) - if(_cuda_path_to_npp) - list(APPEND NPP_LIBRARIES -Wl,-rpath "-Wl,${_cuda_path_to_npp}") - endif() -endif() - -set(NPP_FOUND TRUE) - -set(NPP_LIBRARY_ROOT_DIR_INTERNAL "${NPP_LIBRARY_ROOT_DIR}" CACHE INTERNAL - "This is the value of the last time NPP_LIBRARY_ROOT_DIR was set successfully." FORCE) - diff --git a/cmake/FindOpenSSL.cmake b/cmake/FindOpenSSL.cmake index 9ae015828..ee446f6e1 100644 --- a/cmake/FindOpenSSL.cmake +++ b/cmake/FindOpenSSL.cmake @@ -83,7 +83,7 @@ IF(WIN32 AND NOT CYGWIN) # * MTd for static-debug # Implementation details: - # We are using the libraries located in the VC subdir instead of the parent directory eventhough : + # We are using the libraries located in the VC subdir instead of the parent directory even though : # libeay32MD.lib is identical to ../libeay32.lib, and # ssleay32MD.lib is identical to ../ssleay32.lib @@ -143,14 +143,10 @@ IF(WIN32 AND NOT CYGWIN) "lib/VC" ) - if( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE ) - set( OPENSSL_LIBRARIES - optimized ${SSL_EAY_RELEASE} debug ${SSL_EAY_DEBUG} - optimized ${LIB_EAY_RELEASE} debug ${LIB_EAY_DEBUG} - ) - else() - set( OPENSSL_LIBRARIES ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} ) - endif() + set( OPENSSL_DEBUG_LIBRARIES ${SSL_EAY_DEBUG} ${LIB_EAY_DEBUG} ) + set( OPENSSL_RELEASE_LIBRARIES ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} ) + set( OPENSSL_LIBRARIES ${OPENSSL_RELEASE_LIBRARIES} ) + MARK_AS_ADVANCED(SSL_EAY_DEBUG SSL_EAY_RELEASE) MARK_AS_ADVANCED(LIB_EAY_DEBUG LIB_EAY_RELEASE) ELSEIF(MINGW) @@ -322,4 +318,4 @@ else (OPENSSL_VERSION) ) endif (OPENSSL_VERSION) -MARK_AS_ADVANCED(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES) +MARK_AS_ADVANCED(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES OPENSSL_DEBUG_LIBRARIES OPENSSL_RELEASE_LIBRARIES) diff --git a/cmake/FindPCSC.cmake b/cmake/FindPCSC.cmake index 0cee2aba6..8097010b8 100644 --- a/cmake/FindPCSC.cmake +++ b/cmake/FindPCSC.cmake @@ -1,18 +1,26 @@ +# - Try to find PCSC +# Once done this will define +# PCSC_FOUND - pcsc was found +# PCSC_INCLUDE_DIRS - pcsc include directories +# PCSC_LIBRARIES - libraries needed for linking include(FindPkgConfig) - if (PKG_CONFIG_FOUND) - pkg_check_modules(PCSC libpcsclite) + pkg_check_modules(PC_PCSC QUIET libpcsclite) endif() -find_path(PCSC_INCLUDE_DIR pcsclite.h - PATHS ${PCSC_INCLUDE_DIRS} - PATH_SUFFIXES PCSC) +find_path(PCSC_INCLUDE_DIR pcsclite.h WinSCard.h + HINTS ${PC_PCSC_INCLUDEDIR} ${PC_PCSC_INCLUDE_DIRS} + PATH_SUFFIXES PCSC) -find_library(PCSC_LIBRARY pcsclite - PATHS ${PCSC_LIBRARY_DIRS}) +find_library(PCSC_LIBRARY NAMES PCSC WinSCard pcsclite + HINTS ${PC_PCSC_LIBDIR} ${PC_PCSC_LIBRARY_DIRS}) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCSC DEFAULT_MSG PCSC_INCLUDE_DIR PCSC_LIBRARY) +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(PCSC DEFAULT_MSG PCSC_LIBRARY PCSC_INCLUDE_DIR) + +set(PCSC_LIBRARIES ${PCSC_LIBRARY}) +set(PCSC_INCLUDE_DIRS ${PCSC_INCLUDE_DIR}) mark_as_advanced(PCSC_INCLUDE_DIR PCSC_LIBRARY) diff --git a/include/freerdp/channels/channels.h b/include/freerdp/channels/channels.h index ffdeb3612..c136411dd 100644 --- a/include/freerdp/channels/channels.h +++ b/include/freerdp/channels/channels.h @@ -21,6 +21,9 @@ #ifndef FREERDP_CHANNELS_H #define FREERDP_CHANNELS_H +#include +#include + #include #include #include @@ -39,8 +42,6 @@ FREERDP_API int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* const char* name, void* data); FREERDP_API int freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance); FREERDP_API int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance); -FREERDP_API int freerdp_channels_data(freerdp* instance, int channel_id, void* data, int data_size, - int flags, int total_size); FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, wMessage* event); FREERDP_API BOOL freerdp_channels_get_fds(rdpChannels* channels, freerdp* instance, void** read_fds, int* read_count, void** write_fds, int* write_count); @@ -53,6 +54,11 @@ FREERDP_API void* freerdp_channels_get_static_channel_interface(rdpChannels* cha FREERDP_API HANDLE freerdp_channels_get_event_handle(freerdp* instance); FREERDP_API int freerdp_channels_process_pending_messages(freerdp* instance); +FREERDP_API int freerdp_channels_data(freerdp* instance, + UINT16 channelId, BYTE* data, int dataSize, int flags, int totalSize); + +FREERDP_API PWtsApiFunctionTable FreeRDP_InitWtsApi(void); + #ifdef __cplusplus } #endif diff --git a/include/freerdp/channels/wtsvc.h b/include/freerdp/channels/wtsvc.h index 3a01c525b..5f7865473 100644 --- a/include/freerdp/channels/wtsvc.h +++ b/include/freerdp/channels/wtsvc.h @@ -37,24 +37,11 @@ #include #include -//#include -typedef enum _WTS_VIRTUAL_CLASS -{ - WTSVirtualClientData, - WTSVirtualFileHandle, - WTSVirtualEventHandle, /* Extended */ - WTSVirtualChannelReady /* Extended */ -} WTS_VIRTUAL_CLASS; +#include -#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; +#define WTSVirtualEventHandle 3 /* Extended */ +#define WTSVirtualChannelReady 4 /* Extended */ #ifdef __cplusplus extern "C" { @@ -63,74 +50,12 @@ extern "C" { /** * WTSVirtualChannelManager functions are FreeRDP extensions to the API. */ -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 BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm); -FREERDP_API HANDLE WTSVirtualChannelManagerGetEventHandle(WTSVirtualChannelManager* vcm); +FREERDP_API void WTSVirtualChannelManagerGetFileDescriptor(HANDLE hServer, void** fds, int* fds_count); +FREERDP_API BOOL WTSVirtualChannelManagerCheckFileDescriptor(HANDLE hServer); +FREERDP_API HANDLE WTSVirtualChannelManagerGetEventHandle(HANDLE hServer); -/** - * Opens a static or dynamic virtual channel and return the handle. If the - * operation fails, a NULL handle is returned. - * - * The original MS API has 'DWORD SessionId' as the first argument, while we - * use our WTSVirtualChannelManager object instead. - * - * Static virtual channels must be opened from the main thread. Dynamic virtual channels - * can be opened from any thread. - */ - -// 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. - * - * Servers use this function to gain access to a virtual channel file handle - * that can be used for asynchronous I/O. - */ - -WINPR_API BOOL WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned); - -/** - * Frees memory allocated by WTSVirtualChannelQuery - */ - -WINPR_API VOID WTSFreeMemory(PVOID pMemory); - -/** - * Reads data from the server end of a virtual channel. - * - * FreeRDP behavior: - * - * This function will always return a complete channel data packet, i.e. chunks - * are already assembled. If BufferSize argument is smaller than the packet - * size, it will set the desired size in pBytesRead and return FALSE. The - * caller should allocate a large enough buffer and call this function again. - * Returning FALSE with pBytesRead set to zero indicates an error has occurred. - * If no pending packet to be read, it will set pBytesRead to zero and return - * TRUE. - * - * TimeOut is not supported, and this function will always return immediately. - * The caller should use the file handle returned by WTSVirtualChannelQuery to - * determine whether a packet has arrived. - */ - -WINPR_API BOOL WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead); - -/** - * Writes data to the server end of a virtual channel. - */ - -WINPR_API BOOL WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten); - -/** - * Closes an open virtual channel handle. - */ - -WINPR_API BOOL WTSVirtualChannelClose(HANDLE hChannelHandle); +FREERDP_API BOOL WTSVirtualChannelManagerIsChannelJoined(HANDLE hServer, const char* name); #ifdef __cplusplus } diff --git a/include/freerdp/codec/color.h b/include/freerdp/codec/color.h index 858db3779..fc14f1518 100644 --- a/include/freerdp/codec/color.h +++ b/include/freerdp/codec/color.h @@ -23,19 +23,115 @@ #include #include +#define FREERDP_PIXEL_FORMAT_TYPE_A 0 #define FREERDP_PIXEL_FORMAT_TYPE_ARGB 1 #define FREERDP_PIXEL_FORMAT_TYPE_ABGR 2 +#define FREERDP_PIXEL_FORMAT_TYPE_BGRA 3 +#define FREERDP_PIXEL_FORMAT_TYPE_RGBA 4 #define FREERDP_PIXEL_FLIP_NONE 0 #define FREERDP_PIXEL_FLIP_VERTICAL 1 #define FREERDP_PIXEL_FLIP_HORIZONTAL 2 -#define FREERDP_PIXEL_FORMAT(_bpp, _type, _flip) \ - ((_bpp << 24) | (_type << 16) | (_flip << 8)) +#define FREERDP_PIXEL_FORMAT(_bpp, _type, _a, _r, _g, _b) \ + ((_bpp << 24) | (_type << 16) | (_a << 12) | (_r << 8) | (_g << 4) | (_b)) -#define FREERDP_PIXEL_FORMAT_BPP(_format) (((_format) >> 24) & 0xFF) +#define FREERDP_PIXEL_FORMAT_FLIP(_format) (((_format) >> 30) & 0x02) +#define FREERDP_PIXEL_FORMAT_BPP(_format) (((_format) >> 24) & 0x3F) #define FREERDP_PIXEL_FORMAT_TYPE(_format) (((_format) >> 16) & 0xFF) -#define FREERDP_PIXEL_FORMAT_FLIP(_format) (((_format) >> 8) & 0xFF) +#define FREERDP_PIXEL_FORMAT_A(_format) (((_format) >> 12) & 0x0F) +#define FREERDP_PIXEL_FORMAT_R(_format) (((_format) >> 8) & 0x0F) +#define FREERDP_PIXEL_FORMAT_G(_format) (((_format) >> 4) & 0x0F) +#define FREERDP_PIXEL_FORMAT_B(_format) (((_format) ) & 0x0F) +#define FREERDP_PIXEL_FORMAT_RGB(_format) (((_format) ) & 0xFFF) +#define FREERDP_PIXEL_FORMAT_VIS(_format) (((_format) ) & 0xFFFF) + +#define FREERDP_PIXEL_FORMAT_DEPTH(_format) \ + (FREERDP_PIXEL_FORMAT_A(_format) + \ + FREERDP_PIXEL_FORMAT_R(_format) + \ + FREERDP_PIXEL_FORMAT_G(_format) + \ + FREERDP_PIXEL_FORMAT_B(_format)) + +/* 32bpp formats */ + +#define PIXEL_FORMAT_A8R8G8B8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 8, 8, 8, 8) +#define PIXEL_FORMAT_ARGB32 PIXEL_FORMAT_A8R8G8B8 + +#define PIXEL_FORMAT_X8R8G8B8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8) +#define PIXEL_FORMAT_XRGB32 PIXEL_FORMAT_X8R8G8B8 +#define PIXEL_FORMAT_RGB32 PIXEL_FORMAT_XRGB32 + +#define PIXEL_FORMAT_A8B8G8R8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 8, 8, 8, 8) +#define PIXEL_FORMAT_ABGR32 PIXEL_FORMAT_A8B8G8R8 + +#define PIXEL_FORMAT_X8B8G8R8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8) +#define PIXEL_FORMAT_XBGR32 PIXEL_FORMAT_X8B8G8R8 +#define PIXEL_FORMAT_BGR32 PIXEL_FORMAT_XBGR32 + +#define PIXEL_FORMAT_B8G8R8A8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 8, 8, 8, 8) +#define PIXEL_FORMAT_BGRA32 PIXEL_FORMAT_B8G8R8A8 + +#define PIXEL_FORMAT_B8G8R8X8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 0, 8, 8, 8) +#define PIXEL_FORMAT_BGRX32 PIXEL_FORMAT_B8G8R8X8 + +#define PIXEL_FORMAT_R8G8B8A8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 8, 8, 8, 8) +#define PIXEL_FORMAT_RGBA32 PIXEL_FORMAT_R8G8B8A8 + +#define PIXEL_FORMAT_R8G8B8X8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 0, 8, 8, 8) +#define PIXEL_FORMAT_RGBX32 PIXEL_FORMAT_R8G8B8X8 + +/* 24bpp formats */ + +#define PIXEL_FORMAT_R8G8B8 FREERDP_PIXEL_FORMAT(24, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8) +#define PIXEL_FORMAT_RGB24 PIXEL_FORMAT_R8G8B8 + +#define PIXEL_FORMAT_B8G8R8 FREERDP_PIXEL_FORMAT(24, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8) +#define PIXEL_FORMAT_BGR24 PIXEL_FORMAT_B8G8R8 + +/* 16bpp formats */ + +#define PIXEL_FORMAT_R5G6B5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 6, 5) +#define PIXEL_FORMAT_RGB565 PIXEL_FORMAT_R5G6B5 +#define PIXEL_FORMAT_RGB16 PIXEL_FORMAT_R5G6B5 + +#define PIXEL_FORMAT_B5G6R5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 6, 5) +#define PIXEL_FORMAT_BGR565 PIXEL_FORMAT_B5G6R5 +#define PIXEL_FORMAT_BGR16 PIXEL_FORMAT_B5G6R5 + +#define PIXEL_FORMAT_A1R5G5B5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 1, 5, 5, 5) +#define PIXEL_FORMAT_ARGB555 PIXEL_FORMAT_A1R5G5B5 +#define PIXEL_FORMAT_ARGB15 PIXEL_FORMAT_A1R5G5B5 + +#define PIXEL_FORMAT_X1R5G5B5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 5, 5) +#define PIXEL_FORMAT_XRGB555 PIXEL_FORMAT_X1R5G5B5 +#define PIXEL_FORMAT_RGB555 PIXEL_FORMAT_X1R5G5B5 +#define PIXEL_FORMAT_RGB15 PIXEL_FORMAT_X1R5G5B5 + +#define PIXEL_FORMAT_A1B5G5R5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 1, 5, 5, 5) +#define PIXEL_FORMAT_ABGR555 PIXEL_FORMAT_A1B5G5R5 +#define PIXEL_FORMAT_ABGR15 PIXEL_FORMAT_A1B5G5R5 + +#define PIXEL_FORMAT_X1B5G5R5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 5, 5) +#define PIXEL_FORMAT_XBGR555 PIXEL_FORMAT_X1B5G5R5 +#define PIXEL_FORMAT_BGR555 PIXEL_FORMAT_X1B5G5R5 +#define PIXEL_FORMAT_BGR15 PIXEL_FORMAT_X1B5G5R5 + +/* 8bpp formats */ + +#define PIXEL_FORMAT_A8 FREERDP_PIXEL_FORMAT(8, FREERDP_PIXEL_FORMAT_TYPE_A, 8, 0, 0, 0) +#define PIXEL_FORMAT_8BPP PIXEL_FORMAT_A8 +#define PIXEL_FORMAT_256 PIXEL_FORMAT_A8 + +/* 4 bpp formats */ + +#define PIXEL_FORMAT_A4 FREERDP_PIXEL_FORMAT(4, FREERDP_PIXEL_FORMAT_TYPE_A, 4, 0, 0, 0) +#define PIXEL_FORMAT_4BPP PIXEL_FORMAT_A4 + +/* 1bpp formats */ + +#define PIXEL_FORMAT_A1 FREERDP_PIXEL_FORMAT(1, FREERDP_PIXEL_FORMAT_TYPE_A, 1, 0, 0, 0) +#define PIXEL_FORMAT_1BPP PIXEL_FORMAT_A1 +#define PIXEL_FORMAT_MONO PIXEL_FORMAT_A1 #ifdef __cplusplus extern "C" { @@ -274,6 +370,9 @@ FREERDP_API UINT32 freerdp_color_convert_var_bgr(UINT32 srcColor, int srcBpp, in FREERDP_API HCLRCONV freerdp_clrconv_new(UINT32 flags); FREERDP_API void freerdp_clrconv_free(HCLRCONV clrconv); +FREERDP_API int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst, + int nWidth, int nHeight, BYTE* pSrcData, DWORD dwSrcFormat, int nSrcStep, int nXSrc, int nYSrc); + #ifdef __cplusplus } #endif diff --git a/include/freerdp/codec/mppc_dec.h b/include/freerdp/codec/mppc_dec.h index b5b92f7b7..6d39299fd 100644 --- a/include/freerdp/codec/mppc_dec.h +++ b/include/freerdp/codec/mppc_dec.h @@ -50,6 +50,7 @@ FREERDP_API int decompress_rdp_4(struct rdp_mppc_dec* dec, BYTE* cbuf, int len, FREERDP_API int decompress_rdp_5(struct rdp_mppc_dec* dec, BYTE* cbuf, int len, int ctype, UINT32* roff, UINT32* rlen); FREERDP_API int decompress_rdp_6(struct rdp_mppc_dec* dec, BYTE* cbuf, int len, int ctype, UINT32* roff, UINT32* rlen); FREERDP_API int decompress_rdp_61(struct rdp_mppc_dec* dec, BYTE* cbuf, int len, int ctype, UINT32* roff, UINT32* rlen); + FREERDP_API struct rdp_mppc_dec* mppc_dec_new(void); FREERDP_API void mppc_dec_free(struct rdp_mppc_dec* dec); diff --git a/include/freerdp/codec/region.h b/include/freerdp/codec/region.h new file mode 100644 index 000000000..eff10debb --- /dev/null +++ b/include/freerdp/codec/region.h @@ -0,0 +1,127 @@ +/** + * Copyright © 2014 Thincast Technologies GmbH + * Copyright © 2014 Hardening + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __REGION_H___ +#define __REGION_H___ + +#include + +struct _REGION16_DATA; +typedef struct _REGION16_DATA REGION16_DATA; + +/** + * @brief + */ +struct _REGION16 { + RECTANGLE_16 extents; + REGION16_DATA *data; +}; +typedef struct _REGION16 REGION16; + +/** computes if two rectangles intersect + * @param r1 first rectangle + * @param r2 second rectangle + * @return if the two rectangles intersect + */ +BOOL rectangles_intersects(const RECTANGLE_16 *r1, const RECTANGLE_16 *r2); + +/** computes the intersection of two rectangles + * @param r1 first rectangle + * @param r2 second rectangle + * @param dst resulting intersection + * @return if the two rectangles intersect + */ +BOOL rectangles_intersection(const RECTANGLE_16 *r1, const RECTANGLE_16 *r2, RECTANGLE_16 *dst); + +/** initialize a region16 + * @param region the region to initialise + */ +void region16_init(REGION16 *region); + +/** @return the number of rectangles of this region16 */ +int region16_n_rects(const REGION16 *region); + +/** returns a pointer on rectangles and the number of rectangles in this region. + * nbRect can be set to NULL if not interested by the numnber of rectangles. + * @param region the input region + * @param nbRects a pointer that will be filled with the number of rectangles + * @return a pointer on the rectangles + */ +const RECTANGLE_16 *region16_rects(const REGION16 *region, int *nbRects); + +/** @return the extents rectangle of this region */ +const RECTANGLE_16 *region16_extents(const REGION16 *region); + +/** returns if the region is empty + * @param region + * @return if the region is empty + */ +BOOL region16_is_empty(const REGION16 *region); + +/** clears the region, the region is resetted to a (0,0,0,0) region + * @param region + */ +void region16_clear(REGION16 *region); + +/** dumps the region on stderr + * @param region the region to dump + */ +void region16_print(const REGION16 *region); + +/** copies the region to another region + * @param dst destination region + * @param src source region + * @return if the operation was successful (false meaning out-of-memory) + */ +BOOL region16_copy(REGION16 *dst, const REGION16 *src); + +/** adds a rectangle in src and stores the resulting region in dst + * @param dst destination region + * @param src source region + * @param rect the rectangle to add + * @return if the operation was successful (false meaning out-of-memory) + */ +BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 *rect); + +/** returns if a rectangle intersects the region + * @param src the region + * @param arg2 the rectangle + * @return if region and rectangle intersect + */ +BOOL region16_intersects_rect(const REGION16 *src, const RECTANGLE_16 *arg2); + +/** computes the intersection between a region and a rectangle + * @param dst destination region + * @param src the source region + * @param arg2 the rectangle that intersects + * @return if the operation was successful (false meaning out-of-memory) + */ +BOOL region16_intersect_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 *arg2); + +/** release internal data associated with this region + * @param region the region to release + */ +void region16_uninit(REGION16 *region); + + +#endif /* __REGION_H___ */ diff --git a/include/freerdp/constants.h b/include/freerdp/constants.h index d5e1e9873..24517f7ce 100644 --- a/include/freerdp/constants.h +++ b/include/freerdp/constants.h @@ -32,37 +32,6 @@ enum RDP_CODEC_ID RDP_CODEC_ID_IMAGE_REMOTEFX = 0x04 }; -/** - * Static Virtual Channel Flags - */ -enum RDP_SVC_CHANNEL_FLAG -{ - CHANNEL_FLAG_MIDDLE = 0, - CHANNEL_FLAG_FIRST = 0x01, - CHANNEL_FLAG_LAST = 0x02, - CHANNEL_FLAG_ONLY = (CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST), - CHANNEL_FLAG_SHOW_PROTOCOL = 0x10, - CHANNEL_FLAG_SUSPEND = 0x20, - CHANNEL_FLAG_RESUME = 0x40, - CHANNEL_FLAG_FAIL = 0x100 -}; - -/** - * Static Virtual Channel Events - */ -enum RDP_SVC_CHANNEL_EVENT -{ - CHANNEL_EVENT_INITIALIZED = 0, - CHANNEL_EVENT_CONNECTED = 1, - CHANNEL_EVENT_V1_CONNECTED = 2, - CHANNEL_EVENT_DISCONNECTED = 3, - CHANNEL_EVENT_TERMINATED = 4, - CHANNEL_EVENT_DATA_RECEIVED = 10, - CHANNEL_EVENT_WRITE_COMPLETE = 11, - CHANNEL_EVENT_WRITE_CANCELLED = 12, - CHANNEL_EVENT_USER = 1000 -}; - /** * Pixel format */ @@ -79,11 +48,6 @@ enum RDP_PIXEL_FORMAT }; typedef enum RDP_PIXEL_FORMAT RDP_PIXEL_FORMAT; -/** - * Virtual Channel Constants - */ -#define CHANNEL_CHUNK_LENGTH 1600 - /** * CPU Optimization flags */ diff --git a/include/freerdp/freerdp.h b/include/freerdp/freerdp.h index 20f2a96d7..4a9c7aeac 100644 --- a/include/freerdp/freerdp.h +++ b/include/freerdp/freerdp.h @@ -65,8 +65,8 @@ typedef int (*pVerifyX509Certificate)(freerdp* instance, BYTE* data, int length, typedef int (*pLogonErrorInfo)(freerdp* instance, UINT32 data, UINT32 type); -typedef int (*pSendChannelData)(freerdp* instance, int channelId, BYTE* data, int size); -typedef int (*pReceiveChannelData)(freerdp* instance, int channelId, BYTE* data, int size, int flags, int total_size); +typedef int (*pSendChannelData)(freerdp* instance, UINT16 channelId, BYTE* data, int size); +typedef int (*pReceiveChannelData)(freerdp* instance, UINT16 channelId, BYTE* data, int size, int flags, int totalSize); /** * Defines the context for a given instance of RDP connection. diff --git a/include/freerdp/peer.h b/include/freerdp/peer.h index e447ba014..c89d37a07 100644 --- a/include/freerdp/peer.h +++ b/include/freerdp/peer.h @@ -42,8 +42,8 @@ typedef BOOL (*psPeerPostConnect)(freerdp_peer* client); typedef BOOL (*psPeerActivate)(freerdp_peer* client); typedef BOOL (*psPeerLogon)(freerdp_peer* client, SEC_WINNT_AUTH_IDENTITY* identity, BOOL automatic); -typedef int (*psPeerSendChannelData)(freerdp_peer* client, int channelId, BYTE* data, int size); -typedef int (*psPeerReceiveChannelData)(freerdp_peer* client, int channelId, BYTE* data, int size, int flags, int total_size); +typedef int (*psPeerSendChannelData)(freerdp_peer* client, UINT16 channelId, BYTE* data, int size); +typedef int (*psPeerReceiveChannelData)(freerdp_peer* client, UINT16 channelId, BYTE* data, int size, int flags, int totalSize); struct rdp_freerdp_peer { diff --git a/include/freerdp/server/audin.h b/include/freerdp/server/audin.h index 885c1674c..d8ddafa43 100644 --- a/include/freerdp/server/audin.h +++ b/include/freerdp/server/audin.h @@ -36,7 +36,7 @@ typedef void (*psAudinServerReceiveSamples)(audin_server_context* context, const struct _audin_server_context { - WTSVirtualChannelManager* vcm; + HANDLE vcm; /* Server self-defined pointer. */ void* data; @@ -94,7 +94,7 @@ struct _audin_server_context extern "C" { #endif -FREERDP_API audin_server_context* audin_server_context_new(WTSVirtualChannelManager* vcm); +FREERDP_API audin_server_context* audin_server_context_new(HANDLE vcm); FREERDP_API void audin_server_context_free(audin_server_context* context); #ifdef __cplusplus diff --git a/include/freerdp/server/channels.h b/include/freerdp/server/channels.h index 7d50ddfe7..cd14831fa 100644 --- a/include/freerdp/server/channels.h +++ b/include/freerdp/server/channels.h @@ -22,7 +22,5 @@ #include -FREERDP_API void* freerdp_channels_server_find_static_entry(const char* name, const char* entry); - #endif /* FREERDP_CHANNELS_SERVER */ diff --git a/include/freerdp/server/cliprdr.h b/include/freerdp/server/cliprdr.h index 256e736ae..c7d881c6b 100644 --- a/include/freerdp/server/cliprdr.h +++ b/include/freerdp/server/cliprdr.h @@ -39,7 +39,7 @@ typedef int (*psCliprdrStop)(CliprdrServerContext* context); struct _cliprdr_server_context { - WTSVirtualChannelManager* vcm; + HANDLE vcm; psCliprdrStart Start; psCliprdrStop Stop; @@ -47,7 +47,7 @@ struct _cliprdr_server_context CliprdrServerPrivate* priv; }; -FREERDP_API CliprdrServerContext* cliprdr_server_context_new(WTSVirtualChannelManager* vcm); +FREERDP_API CliprdrServerContext* cliprdr_server_context_new(HANDLE 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 index 31eb4ece6..9b41126de 100644 --- a/include/freerdp/server/drdynvc.h +++ b/include/freerdp/server/drdynvc.h @@ -36,7 +36,7 @@ typedef int (*psDrdynvcStop)(DrdynvcServerContext* context); struct _drdynvc_client_context { - WTSVirtualChannelManager* vcm; + HANDLE vcm; psDrdynvcStart Start; psDrdynvcStop Stop; @@ -44,7 +44,7 @@ struct _drdynvc_client_context DrdynvcServerPrivate* priv; }; -FREERDP_API DrdynvcServerContext* drdynvc_server_context_new(WTSVirtualChannelManager* vcm); +FREERDP_API DrdynvcServerContext* drdynvc_server_context_new(HANDLE 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 index d24be3fcd..3fe23e869 100644 --- a/include/freerdp/server/rdpdr.h +++ b/include/freerdp/server/rdpdr.h @@ -37,7 +37,7 @@ typedef int (*psRdpdrStop)(RdpdrServerContext* context); struct _rdpdr_server_context { - WTSVirtualChannelManager* vcm; + HANDLE vcm; psRdpdrStart Start; psRdpdrStop Stop; @@ -45,7 +45,7 @@ struct _rdpdr_server_context RdpdrServerPrivate* priv; }; -FREERDP_API RdpdrServerContext* rdpdr_server_context_new(WTSVirtualChannelManager* vcm); +FREERDP_API RdpdrServerContext* rdpdr_server_context_new(HANDLE 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 5b65cd8ff..1585389d5 100644 --- a/include/freerdp/server/rdpsnd.h +++ b/include/freerdp/server/rdpsnd.h @@ -40,7 +40,7 @@ typedef void (*psRdpsndServerActivated)(RdpsndServerContext* context); struct _rdpsnd_server_context { - WTSVirtualChannelManager* vcm; + HANDLE vcm; psRdpsndStart Start; psRdpsndStop Stop; @@ -105,7 +105,7 @@ struct _rdpsnd_server_context extern "C" { #endif -FREERDP_API RdpsndServerContext* rdpsnd_server_context_new(WTSVirtualChannelManager* vcm); +FREERDP_API RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm); FREERDP_API void rdpsnd_server_context_free(RdpsndServerContext* context); #ifdef __cplusplus diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index 11806054d..0ba697ee4 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -338,16 +338,6 @@ typedef struct rdp_rsa_key rdpRsaKey; /* Channels */ -struct rdp_channel -{ - char Name[8]; - UINT32 options; - int ChannelId; - BOOL joined; - void* handle; -}; -typedef struct rdp_channel rdpChannel; - struct _ADDIN_ARGV { int argc; @@ -597,6 +587,8 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL; #define FreeRDP_NegotiationFlags 1095 #define FreeRDP_NegotiateSecurityLayer 1096 #define FreeRDP_RestrictedAdminModeRequired 1097 +#define FreeRDP_AuthenticationServiceClass 1098 +#define FreeRDP_DisableCredentialsDelegation 1099 #define FreeRDP_MstscCookieMode 1152 #define FreeRDP_CookieMaxLength 1153 #define FreeRDP_PreconnectionId 1154 @@ -839,7 +831,7 @@ struct rdp_settings /* Client Network Data */ ALIGN64 UINT32 ChannelCount; /* 256 */ ALIGN64 UINT32 ChannelDefArraySize; /* 257 */ - ALIGN64 rdpChannel* ChannelDefArray; /* 258 */ + ALIGN64 CHANNEL_DEF* ChannelDefArray; /* 258 */ UINT64 padding0320[320 - 259]; /* 259 */ /* Client Cluster Data */ @@ -948,7 +940,9 @@ struct rdp_settings ALIGN64 UINT32 NegotiationFlags; /* 1095 */ ALIGN64 BOOL NegotiateSecurityLayer; /* 1096 */ ALIGN64 BOOL RestrictedAdminModeRequired; /* 1097 */ - UINT64 padding1152[1152 - 1098]; /* 1098 */ + ALIGN64 char* AuthenticationServiceClass; /* 1098 */ + ALIGN64 BOOL DisableCredentialsDelegation; /* 1099 */ + UINT64 padding1152[1152 - 1100]; /* 1100 */ /* Connection Cookie */ ALIGN64 BOOL MstscCookieMode; /* 1152 */ diff --git a/include/freerdp/svc.h b/include/freerdp/svc.h index 36213e9d8..fb9af4f47 100644 --- a/include/freerdp/svc.h +++ b/include/freerdp/svc.h @@ -17,87 +17,23 @@ * limitations under the License. */ -/** - * MS compatible SVC plugin interface - * reference: - * http://msdn.microsoft.com/en-us/library/aa383580.aspx - */ - #ifndef FREERDP_SVC_H #define FREERDP_SVC_H #include #include +#include + +#define CHANNEL_EVENT_USER 1000 + #define CHANNEL_EXPORT_FUNC_NAME "VirtualChannelEntry" -#define CHANNEL_NAME_LEN 7 - -struct _CHANNEL_DEF -{ - char name[8]; - UINT32 options; -}; - -typedef struct _CHANNEL_DEF CHANNEL_DEF; -typedef CHANNEL_DEF* PCHANNEL_DEF; -typedef CHANNEL_DEF** PPCHANNEL_DEF; - -typedef void (FREERDP_CC * PCHANNEL_INIT_EVENT_FN)(void* pInitHandle, UINT32 event, void* pData, UINT32 dataLength); - -typedef void (FREERDP_CC * PCHANNEL_OPEN_EVENT_FN)(UINT32 openHandle, UINT32 event, - void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags); - -#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 VIRTUAL_CHANNEL_VERSION_WIN2000 1 - -typedef UINT32 (FREERDP_CC * PVIRTUALCHANNELINIT)(void** ppInitHandle, PCHANNEL_DEF pChannel, - int channelCount, UINT32 versionRequested, PCHANNEL_INIT_EVENT_FN pChannelInitEventProc); - -typedef UINT32 (FREERDP_CC * PVIRTUALCHANNELOPEN)(void* pInitHandle, UINT32* pOpenHandle, - char* pChannelName, PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc); - -typedef UINT32 (FREERDP_CC * PVIRTUALCHANNELCLOSE)(UINT32 openHandle); - -typedef UINT32 (FREERDP_CC * PVIRTUALCHANNELWRITE)(UINT32 openHandle, void* pData, UINT32 dataLength, void* pUserData); - -typedef UINT32 (FREERDP_CC * PVIRTUALCHANNELEVENTPUSH)(UINT32 openHandle, wMessage* event); - -struct _CHANNEL_ENTRY_POINTS -{ - UINT32 cbSize; - UINT32 protocolVersion; - PVIRTUALCHANNELINIT pVirtualChannelInit; - PVIRTUALCHANNELOPEN pVirtualChannelOpen; - PVIRTUALCHANNELCLOSE pVirtualChannelClose; - PVIRTUALCHANNELWRITE pVirtualChannelWrite; -}; -typedef struct _CHANNEL_ENTRY_POINTS CHANNEL_ENTRY_POINTS; -typedef CHANNEL_ENTRY_POINTS* PCHANNEL_ENTRY_POINTS; - -typedef int (FREERDP_CC * PVIRTUALCHANNELENTRY)(PCHANNEL_ENTRY_POINTS pEntryPoints); +typedef UINT (FREERDP_CC * PVIRTUALCHANNELEVENTPUSH)(DWORD openHandle, wMessage* event); #define FREERDP_CHANNEL_MAGIC_NUMBER 0x46524450 -struct _CHANNEL_ENTRY_POINTS_EX +struct _CHANNEL_ENTRY_POINTS_FREERDP { UINT32 cbSize; UINT32 protocolVersion; @@ -113,7 +49,7 @@ struct _CHANNEL_ENTRY_POINTS_EX void** ppInterface; /* channel callback interface, use for initialization */ PVIRTUALCHANNELEVENTPUSH pVirtualChannelEventPush; }; -typedef struct _CHANNEL_ENTRY_POINTS_EX CHANNEL_ENTRY_POINTS_EX; -typedef CHANNEL_ENTRY_POINTS_EX* PCHANNEL_ENTRY_POINTS_EX; +typedef struct _CHANNEL_ENTRY_POINTS_FREERDP CHANNEL_ENTRY_POINTS_FREERDP; +typedef CHANNEL_ENTRY_POINTS_FREERDP* PCHANNEL_ENTRY_POINTS_FREERDP; #endif /* FREERDP_SVC_H */ diff --git a/include/freerdp/types.h b/include/freerdp/types.h index 2a1ce9162..3d26e0bf9 100644 --- a/include/freerdp/types.h +++ b/include/freerdp/types.h @@ -22,6 +22,7 @@ #define FREERDP_TYPES_H #include +#include #ifndef MIN #define MIN(x,y) (((x) < (y)) ? (x) : (y)) diff --git a/include/freerdp/utils/svc_plugin.h b/include/freerdp/utils/svc_plugin.h index 4b8376733..b18faa385 100644 --- a/include/freerdp/utils/svc_plugin.h +++ b/include/freerdp/utils/svc_plugin.h @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -40,7 +41,7 @@ typedef struct rdp_svc_plugin rdpSvcPlugin; struct rdp_svc_plugin { - CHANNEL_ENTRY_POINTS_EX channel_entry_points; + CHANNEL_ENTRY_POINTS_FREERDP channel_entry_points; CHANNEL_DEF channel_def; void (*connect_callback)(rdpSvcPlugin* plugin); @@ -51,7 +52,7 @@ struct rdp_svc_plugin HANDLE thread; wStream* data_in; void* InitHandle; - UINT32 OpenHandle; + DWORD OpenHandle; wMessagePipe* MsgPipe; }; diff --git a/libfreerdp/CMakeLists.txt b/libfreerdp/CMakeLists.txt index cea42c1c5..339cea3b3 100644 --- a/libfreerdp/CMakeLists.txt +++ b/libfreerdp/CMakeLists.txt @@ -58,7 +58,10 @@ if(MONOLITHIC_BUILD) set_target_properties(${MODULE_NAME} PROPERTIES LINKER_LANGUAGE C) set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION} PREFIX "lib") - target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS} ${PROFILER_LIBRARIES}) + list(APPEND FREERDP_LIBS ${PROFILER_LIBRARIES}) + list(REMOVE_DUPLICATES FREERDP_LIBS) + + target_link_libraries(${MODULE_NAME} ${FREERDP_LIBS}) install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries EXPORT FreeRDPTargets) diff --git a/libfreerdp/cache/palette.c b/libfreerdp/cache/palette.c index a8561bb8d..3436a686d 100644 --- a/libfreerdp/cache/palette.c +++ b/libfreerdp/cache/palette.c @@ -104,7 +104,7 @@ void palette_cache_free(rdpPaletteCache* paletteCache) { if (paletteCache) { - int i; + UINT32 i; for (i = 0; i< paletteCache->maxEntries; i++) { diff --git a/libfreerdp/codec/CMakeLists.txt b/libfreerdp/codec/CMakeLists.txt index d017b67df..6128c7e03 100644 --- a/libfreerdp/codec/CMakeLists.txt +++ b/libfreerdp/codec/CMakeLists.txt @@ -42,6 +42,7 @@ set(${MODULE_PREFIX}_SRCS rfx_rlgr.h rfx_types.h rfx.c + region.c nsc.c nsc_encode.c nsc_encode.h diff --git a/libfreerdp/codec/color.c b/libfreerdp/codec/color.c index 8c9499c68..69a871c84 100644 --- a/libfreerdp/codec/color.c +++ b/libfreerdp/codec/color.c @@ -1171,3 +1171,172 @@ void freerdp_clrconv_free(HCLRCONV clrconv) free(clrconv); } } + +int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst, + int nWidth, int nHeight, BYTE* pSrcData, DWORD dwSrcFormat, int nSrcStep, int nXSrc, int nYSrc) +{ + int i, j; + BYTE a, r, g, b; + int srcBitsPerPixel; + int srcBytesPerPixel; + int dstBitsPerPixel; + int dstBytesPerPixel; + + srcBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(dwSrcFormat); + srcBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(dwSrcFormat) / 8); + + dstBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(dwDstFormat); + dstBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(dwDstFormat) / 8); + + if (srcBytesPerPixel == 4) + { + if (nSrcStep < 0) + nSrcStep = srcBytesPerPixel * nWidth; + + if (srcBitsPerPixel == 24) + { + if (dstBytesPerPixel == 4) + { + if (dstBitsPerPixel == 32) + { + UINT32* pSrcPixel; + UINT32* pDstPixel; + + if (nDstStep < 0) + nDstStep = dstBytesPerPixel * nWidth; + + pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)]; + pDstPixel = (UINT32*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)]; + + for (i = 0; i < nHeight; i++) + { + for (j = 0; j < nWidth; j++) + { + GetARGB32(a, r, g, b, *pSrcPixel); + *pDstPixel = ARGB32(a, r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[(nSrcStep - (nWidth * srcBytesPerPixel))]; + pDstPixel = (UINT32*) &((BYTE*) pDstPixel)[(nDstStep - (nWidth * dstBytesPerPixel))]; + } + } + else if (dstBitsPerPixel == 24) + { + UINT32* pSrcPixel; + UINT32* pDstPixel; + + if (nDstStep < 0) + nDstStep = dstBytesPerPixel * nWidth; + + pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)]; + pDstPixel = (UINT32*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)]; + + for (i = 0; i < nHeight; i++) + { + for (j = 0; j < nWidth; j++) + { + GetRGB32(r, g, b, *pSrcPixel); + *pDstPixel = RGB32(r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[(nSrcStep - (nWidth * srcBytesPerPixel))]; + pDstPixel = (UINT32*) &((BYTE*) pDstPixel)[(nDstStep - (nWidth * dstBytesPerPixel))]; + } + } + } + else if (dstBytesPerPixel == 3) + { + UINT32* pSrcPixel; + BYTE* pDstPixel; + + if (nDstStep < 0) + nDstStep = dstBytesPerPixel * nWidth; + + pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)]; + pDstPixel = (BYTE*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)]; + + for (i = 0; i < nHeight; i++) + { + for (j = 0; j < nWidth; j++) + { + GetRGB32(r, g, b, *pSrcPixel); + + *(pDstPixel++) = r; + *(pDstPixel++) = g; + *(pDstPixel++) = b; + + pSrcPixel++; + } + + pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[(nSrcStep - (nWidth * srcBytesPerPixel))]; + pDstPixel = (BYTE*) &((BYTE*) pDstPixel)[(nDstStep - (nWidth * dstBytesPerPixel))]; + } + } + else if (dstBytesPerPixel == 2) + { + if (dstBitsPerPixel == 16) + { + UINT32* pSrcPixel; + UINT16* pDstPixel; + + if (nDstStep < 0) + nDstStep = dstBytesPerPixel * nWidth; + + pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)]; + + for (i = 0; i < nHeight; i++) + { + for (j = 0; j < nWidth; j++) + { + GetRGB32(r, g, b, *pSrcPixel); + RGB_888_565(r, g, b); + *pDstPixel = RGB565(r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[(nSrcStep - (nWidth * srcBytesPerPixel))]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[(nDstStep - (nWidth * dstBytesPerPixel))]; + } + } + else if (dstBitsPerPixel == 15) + { + UINT32* pSrcPixel; + UINT16* pDstPixel; + + if (nDstStep < 0) + nDstStep = dstBytesPerPixel * nWidth; + + pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)]; + + for (i = 0; i < nHeight; i++) + { + for (j = 0; j < nWidth; j++) + { + GetRGB32(r, g, b, *pSrcPixel); + RGB_888_555(r, g, b); + *pDstPixel = RGB555(r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[(nSrcStep - (nWidth * srcBytesPerPixel))]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[(nDstStep - (nWidth * dstBytesPerPixel))]; + } + } + } + } + } + + return 0; +} diff --git a/libfreerdp/codec/mppc_dec.c b/libfreerdp/codec/mppc_dec.c index 76238768a..2bb2de819 100644 --- a/libfreerdp/codec/mppc_dec.c +++ b/libfreerdp/codec/mppc_dec.c @@ -172,18 +172,18 @@ int decompress_rdp(struct rdp_mppc_dec* dec, BYTE* cbuf, int len, int ctype, UIN int decompress_rdp_4(struct rdp_mppc_dec* dec, BYTE* cbuf, int len, int ctype, UINT32* roff, UINT32* rlen) { - BYTE* history_buf; /* uncompressed data goes here */ - BYTE* history_ptr; /* points to next free slot in history_buf */ - UINT32 d32; /* we process 4 compressed bytes at a time */ - UINT16 copy_offset; /* location to copy data from */ - UINT16 lom; /* length of match */ - BYTE* src_ptr; /* used while copying compressed data */ - BYTE* cptr; /* points to next byte in cbuf */ - BYTE cur_byte; /* last byte fetched from cbuf */ - unsigned int bits_left; /* bits left in d34 for processing */ - unsigned int cur_bits_left; /* bits left in cur_byte for processing */ - int tmp; - UINT32 i32; + BYTE* history_buf; /* uncompressed data goes here */ + BYTE* history_ptr; /* points to next free slot in history_buf */ + UINT32 d32; /* we process 4 compressed bytes at a time */ + UINT16 copy_offset; /* location to copy data from */ + UINT16 lom; /* length of match */ + BYTE* src_ptr; /* used while copying compressed data */ + BYTE* cptr; /* points to next byte in cbuf */ + BYTE cur_byte; /* last byte fetched from cbuf */ + unsigned int bits_left; /* bits left in d34 for processing */ + unsigned int cur_bits_left; /* bits left in cur_byte for processing */ + int tmp; + UINT32 i32; fprintf(stderr, "decompress_rdp_4:\n"); diff --git a/libfreerdp/codec/region.c b/libfreerdp/codec/region.c new file mode 100644 index 000000000..c7fe1f112 --- /dev/null +++ b/libfreerdp/codec/region.c @@ -0,0 +1,758 @@ +/** + * Copyright © 2014 Thincast Technologies GmbH + * Copyright © 2014 Hardening + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +/* + * The functions in this file implement the Region abstraction largely inspired from + * pixman library. The following comment is taken from the pixman code. + * + * A Region is simply a set of disjoint(non-overlapping) rectangles, plus an + * "extent" rectangle which is the smallest single rectangle that contains all + * the non-overlapping rectangles. + * + * A Region is implemented as a "y-x-banded" array of rectangles. This array + * imposes two degrees of order. First, all rectangles are sorted by top side + * y coordinate first (y1), and then by left side x coordinate (x1). + * + * Furthermore, the rectangles are grouped into "bands". Each rectangle in a + * band has the same top y coordinate (y1), and each has the same bottom y + * coordinate (y2). Thus all rectangles in a band differ only in their left + * and right side (x1 and x2). Bands are implicit in the array of rectangles: + * there is no separate list of band start pointers. + * + * The y-x band representation does not minimize rectangles. In particular, + * if a rectangle vertically crosses a band (the rectangle has scanlines in + * the y1 to y2 area spanned by the band), then the rectangle may be broken + * down into two or more smaller rectangles stacked one atop the other. + * + * ----------- ----------- + * | | | | band 0 + * | | -------- ----------- -------- + * | | | | in y-x banded | | | | band 1 + * | | | | form is | | | | + * ----------- | | ----------- -------- + * | | | | band 2 + * -------- -------- + * + * An added constraint on the rectangles is that they must cover as much + * horizontal area as possible: no two rectangles within a band are allowed + * to touch. + * + * Whenever possible, bands will be merged together to cover a greater vertical + * distance (and thus reduce the number of rectangles). Two bands can be merged + * only if the bottom of one touches the top of the other and they have + * rectangles in the same places (of the same width, of course). + */ + +struct _REGION16_DATA { + long size; + long nbRects; +}; + +static REGION16_DATA empty_region = { 0, 0 }; + +void region16_init(REGION16 *region) +{ + assert(region); + + ZeroMemory(region, sizeof(REGION16)); + region->data = &empty_region; +} + +int region16_n_rects(const REGION16 *region) +{ + assert(region); + assert(region->data); + + return region->data->nbRects; +} + +const RECTANGLE_16 *region16_rects(const REGION16 *region, int *nbRects) +{ + REGION16_DATA *data; + + assert(region); + assert(region->data); + + data = region->data; + if (!data) + { + if (nbRects) + *nbRects = 0; + return 0; + } + + *nbRects = data->nbRects; + return (RECTANGLE_16 *)(data + 1); +} + +static INLINE RECTANGLE_16 *region16_rects_noconst(REGION16 *region) +{ + REGION16_DATA *data; + + data = region->data; + if (!data) + return 0; + + return (RECTANGLE_16 *)(data + 1); +} + +const RECTANGLE_16 *region16_extents(const REGION16 *region) +{ + return ®ion->extents; +} + +static RECTANGLE_16 *region16_extents_noconst(REGION16 *region) +{ + return ®ion->extents; +} + +BOOL region16_is_empty(const REGION16 *region) +{ + assert(region); + assert(region->data); + + return (region->data->nbRects == 0); +} + +BOOL rectangles_intersects(const RECTANGLE_16 *r1, const RECTANGLE_16 *r2) +{ + RECTANGLE_16 tmp; + return rectangles_intersection(r1, r2, &tmp); +} + +BOOL rectangles_intersection(const RECTANGLE_16 *r1, const RECTANGLE_16 *r2, + RECTANGLE_16 *dst) +{ + dst->left = MAX(r1->left, r2->left); + dst->right = MIN(r1->right, r2->right); + dst->top = MAX(r1->top, r2->top); + dst->bottom = MIN(r1->bottom, r2->bottom); + + return (dst->left < dst->right) && (dst->top < dst->bottom); +} + +void region16_clear(REGION16 *region) +{ + assert(region); + assert(region->data); + + if (region->data->size) + free(region->data); + region->data = &empty_region; + + ZeroMemory(®ion->extents, sizeof(region->extents)); +} + +static INLINE REGION16_DATA *allocateRegion(long nbItems) +{ + long allocSize = sizeof(REGION16_DATA) + nbItems * sizeof(RECTANGLE_16); + REGION16_DATA *ret = (REGION16_DATA *)malloc(allocSize); + if (!ret) + return ret; + + ret->size = allocSize; + ret->nbRects = nbItems; + return ret; +} + +BOOL region16_copy(REGION16 *dst, const REGION16 *src) +{ + assert(dst); + assert(dst->data); + assert(src); + assert(src->data); + + if (dst == src) + return TRUE; + + dst->extents = src->extents; + if (dst->data->size) + free(dst->data); + + if (!src->data->size) + { + dst->data = &empty_region; + } + else + { + dst->data = allocateRegion(src->data->nbRects); + if (!dst->data) + return FALSE; + + memcpy(dst->data, src->data, src->data->size); + } + return TRUE; +} + +void region16_print(const REGION16 *region) +{ + const RECTANGLE_16 *rects; + int nbRects, i; + int currentBandY = -1; + + rects = region16_rects(region, &nbRects); + fprintf(stderr, "nrects=%d", nbRects); + + for (i = 0; i < nbRects; i++, rects++) + { + if (rects->top != currentBandY) + { + currentBandY = rects->top; + fprintf(stderr, "\nband %d: ", currentBandY); + } + + fprintf(stderr, "(%d,%d-%d,%d)", rects->left, rects->top, rects->right, rects->bottom); + } + + fprintf(stderr, "\n"); +} + +void region16_copy_band_with_union(RECTANGLE_16 *dst, + const RECTANGLE_16 *src, const RECTANGLE_16 *end, + UINT16 newTop, UINT16 newBottom, + const RECTANGLE_16 *unionRect, + int *dstCounter, + const RECTANGLE_16 **srcPtr, RECTANGLE_16 **dstPtr) +{ + UINT16 refY = src->top; + const RECTANGLE_16 *startOverlap, *endOverlap; + + /* merges a band with the given rect + * Input: + * unionRect + * | | + * | | + * ==============+===============+================================ + * |Item1| |Item2| |Item3| |Item4| |Item5| Band + * ==============+===============+================================ + * before | overlap | after + * + * Resulting band: + * +-----+ +----------------------+ +-----+ + * |Item1| | Item2 | |Item3| + * +-----+ +----------------------+ +-----+ + * + * We first copy as-is items that are before Item2, the first overlapping + * item. + * Then we find the last one that overlap unionRect to agregate Item2, Item3 + * and Item4 to create Item2. + * Finally Item5 is copied as Item3. + * + * When no unionRect is provided, we skip the two first steps to just copy items + */ + + if (unionRect) + { + /* items before unionRect */ + while ((src < end) && (src->top == refY) && (src->right < unionRect->left)) + { + dst->top = newTop; + dst->bottom = newBottom; + dst->right = src->right; + dst->left = src->left; + + src++; dst++; *dstCounter += 1; + } + + /* treat items overlapping with unionRect */ + startOverlap = unionRect; + endOverlap = unionRect; + + if ((src < end) && (src->top == refY) && (src->left < unionRect->left)) + startOverlap = src; + + while ((src < end) && (src->top == refY) && (src->right < unionRect->right)) + { + src++; + } + + if ((src < end) && (src->top == refY) && (src->left < unionRect->right)) + { + endOverlap = src; + src++; + } + + dst->bottom = newBottom; + dst->top = newTop; + dst->left = startOverlap->left; + dst->right = endOverlap->right; + dst++; *dstCounter += 1; + } + + /* treat remaining items on the same band */ + while ((src < end) && (src->top == refY)) + { + dst->top = newTop; + dst->bottom = newBottom; + dst->right = src->right; + dst->left = src->left; + + src++; dst++; *dstCounter += 1; + } + + if(srcPtr) + *srcPtr = src; + *dstPtr = dst; +} + +static RECTANGLE_16 *next_band(RECTANGLE_16 *band1, RECTANGLE_16 *endPtr, int *nbItems) +{ + UINT16 refY = band1->top; + + *nbItems = 0; + while((band1 < endPtr) && (band1->top == refY)) { + band1++; + *nbItems += 1; + } + return band1; +} + +static BOOL band_match(const RECTANGLE_16 *band1, const RECTANGLE_16 *band2, RECTANGLE_16 *endPtr) +{ + int refBand2 = band2->top; + const RECTANGLE_16 *band2Start = band2; + + while ((band1 < band2Start) && (band2 < endPtr) && (band2->top == refBand2)) { + if ((band1->left != band2->left) || (band1->right != band2->right)) + return FALSE; + + band1++; + band2++; + } + + if (band1 != band2Start) + return FALSE; + + return (band2 == endPtr) || (band2->top != refBand2); +} + +/** compute if the rectangle is fully included in the band + * @param band a pointer on the beginning of the band + * @param endPtr end of the region + * @param rect the rectangle to test + * @return if rect is fully included in an item of the band + */ +static BOOL rectangle_contained_in_band(const RECTANGLE_16 *band, const RECTANGLE_16 *endPtr, + const RECTANGLE_16 *rect) +{ + UINT16 refY = band->top; + + if ((band->top > rect->top) || (rect->bottom > band->bottom)) + return FALSE; + + /* note: as the band is sorted from left to right, once we've seen an item + * that is after rect->left we're sure that the result is False. + */ + while( (band < endPtr) && (band->top == refY) && (band->left <= rect->left)) + { + if (rect->right <= band->right) + return TRUE; + + band++; + } + return FALSE; +} + +BOOL region16_simplify_bands(REGION16 *region) +{ + /** Simplify consecutive bands that touch and have the same items + * + * ==================== ==================== + * | 1 | | 2 | | | | | + * ==================== | | | | + * | 1 | | 2 | ====> | 1 | | 2 | + * ==================== | | | | + * | 1 | | 2 | | | | | + * ==================== ==================== + * + */ + RECTANGLE_16 *band1, *band2, *endPtr, *endBand, *tmp; + int nbRects, finalNbRects; + int bandItems, toMove; + + finalNbRects = nbRects = region16_n_rects(region); + if (nbRects < 2) + return TRUE; + + band1 = region16_rects_noconst(region); + endPtr = band1 + nbRects; + + do { + band2 = next_band(band1, endPtr, &bandItems); + if (band2 == endPtr) + break; + + if ((band1->bottom == band2->top) && band_match(band1, band2, endPtr)) + { + /* adjust the bottom of band1 items */ + tmp = band1; + while (tmp < band2) + { + tmp->bottom = band2->bottom; + tmp++; + } + + /* override band2, we don't move band1 pointer as the band after band2 + * may be merged too */ + endBand = band2 + bandItems; + toMove = (endPtr - endBand) * sizeof(RECTANGLE_16); + if (toMove) + memmove(band2, endBand, toMove); + finalNbRects -= bandItems; + endPtr -= bandItems; + } else { + band1 = band2; + } + } while(TRUE); + + if (finalNbRects != nbRects) + { + int allocSize = sizeof(REGION16_DATA) + finalNbRects * sizeof(RECTANGLE_16); + region->data = realloc(region->data, allocSize); + if (!region->data) + { + region->data = &empty_region; + return FALSE; + } + region->data->nbRects = finalNbRects; + region->data->size = allocSize; + } + return TRUE; +} + + +BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 *rect) +{ + const RECTANGLE_16 *srcExtents; + RECTANGLE_16 *dstExtents; + const RECTANGLE_16 *currentBand, *endSrcRect, *nextBand; + REGION16_DATA *newItems; + RECTANGLE_16 *dstRect; + int usedRects, srcNbRects; + UINT16 topInterBand; + + assert(src); + assert(src->data); + assert(dst); + + srcExtents = region16_extents(src); + dstExtents = region16_extents_noconst(dst); + + if (!region16_n_rects(src)) + { + /* source is empty, so the union is rect */ + dst->extents = *rect; + dst->data = allocateRegion(1); + if (!dst->data) + return FALSE; + + dstRect = region16_rects_noconst(dst); + *dstRect = *rect; + return TRUE; + } + + newItems = allocateRegion((1 + region16_n_rects(src)) * 2); + if (!newItems) + return FALSE; + + dstRect = (RECTANGLE_16 *)(newItems + 1); + usedRects = 0; + + /* adds the piece of rect that is on the top of src */ + if (rect->top < srcExtents->top) + { + dstRect->top = rect->top; + dstRect->left = rect->left; + dstRect->right = rect->right; + dstRect->bottom = srcExtents->top; + + usedRects++; + dstRect++; + } + + /* treat possibly overlapping region */ + currentBand = region16_rects(src, &srcNbRects); + endSrcRect = currentBand + srcNbRects; + + while (currentBand < endSrcRect) + { + if ((currentBand->bottom <= rect->top) || (rect->bottom <= currentBand->top) || + rectangle_contained_in_band(currentBand, endSrcRect, rect) + ) + { + /* no overlap between rect and the band, rect is totally below or totally above + * the current band, or rect is already covered by an item of the band. + * let's copy all the rectangles from this band + +----+ + | | rect (case 1) + +----+ + + ================= + band of srcRect + ================= + +----+ + | | rect (case 2) + +----+ + */ + region16_copy_band_with_union(dstRect, + currentBand, endSrcRect, + currentBand->top, currentBand->bottom, + NULL, &usedRects, + &nextBand, &dstRect); + topInterBand = rect->top; + } + else + { + + /* rect overlaps the band: + | | | | + ====^=================| |==| |=========================== band + | top split | | | | + v | 1 | | 2 | + ^ | | | | +----+ +----+ + | merge zone | | | | | | | 4 | + v +----+ | | | | +----+ + ^ | | | 3 | + | bottom split | | | | + ====v=========================| |==| |=================== + | | | | + + possible cases: + 1) no top split, merge zone then a bottom split. The band will be splitted + in two + 2) not band split, only the merge zone, band merged with rect but not splitted + 3) a top split, the merge zone and no bottom split. The band will be split + in two + 4) a top split, the merge zone and also a bottom split. The band will be + splitted in 3, but the coalesce algorithm may merge the created bands + */ + UINT16 mergeTop = currentBand->top; + UINT16 mergeBottom = currentBand->bottom; + + /* test if we need a top split, case 3 and 4 */ + if (rect->top > currentBand->top) + { + region16_copy_band_with_union(dstRect, + currentBand, endSrcRect, + currentBand->top, rect->top, + NULL, &usedRects, + &nextBand, &dstRect); + mergeTop = rect->top; + } + + /* do the merge zone (all cases ) */ + if (rect->bottom < currentBand->bottom) + mergeBottom = rect->bottom; + region16_copy_band_with_union(dstRect, + currentBand, endSrcRect, + mergeTop, mergeBottom, + rect, &usedRects, + &nextBand, &dstRect); + + /* test if we need a bottom split, case 1 and 4 */ + if (rect->bottom < currentBand->bottom) + { + region16_copy_band_with_union(dstRect, + currentBand, endSrcRect, + mergeBottom, currentBand->bottom, + NULL, &usedRects, + &nextBand, &dstRect); + } + topInterBand = currentBand->bottom; + } + + /* test if a piece of rect should be inserted as a new band between + * the current band and the next one. band n and n+1 shouldn't touch. + * + * ============================================================== + * band n + * +------+ +------+ + * ===========| rect |====================| |=============== + * | | +------+ | | + * +------+ | rect | | rect | + * +------+ | | + * =======================================| |================ + * +------+ band n+1 + * =============================================================== + * + */ + if ((nextBand < endSrcRect) && (nextBand->top != currentBand->bottom) && + (rect->bottom > currentBand->bottom) && (rect->top < nextBand->top)) + { + dstRect->right = rect->right; + dstRect->left = rect->left; + dstRect->top = topInterBand; + dstRect->bottom = MIN(nextBand->top, rect->bottom); + dstRect++; usedRects++; + } + + currentBand = nextBand; + } + + /* adds the piece of rect that is below src */ + if (srcExtents->bottom < rect->bottom) + { + dstRect->top = MAX(srcExtents->bottom, rect->top); + dstRect->left = rect->left; + dstRect->right = rect->right; + dstRect->bottom = rect->bottom; + + usedRects++; + dstRect++; + } + + if ((src == dst) && (src->data->size)) + free(src->data); + + dstExtents->top = MIN(rect->top, srcExtents->top); + dstExtents->left = MIN(rect->left, srcExtents->left); + dstExtents->bottom = MAX(rect->bottom, srcExtents->bottom); + dstExtents->right = MAX(rect->right, srcExtents->right); + + newItems->size = sizeof(REGION16_DATA) + usedRects * sizeof(RECTANGLE_16); + dst->data = realloc(newItems, newItems->size); + if (!dst->data) + { + free(newItems); + return FALSE; + } + dst->data->nbRects = usedRects; + + return region16_simplify_bands(dst); +} + + +BOOL region16_intersects_rect(const REGION16 *src, const RECTANGLE_16 *arg2) +{ + const RECTANGLE_16 *rect, *endPtr, *srcExtents; + int nbRects; + + assert(src); + assert(src->data); + + rect = region16_rects(src, &nbRects); + if (!nbRects) + return FALSE; + + srcExtents = region16_extents(src); + if (nbRects == 1) + return rectangles_intersects(srcExtents, arg2); + + if (!rectangles_intersects(srcExtents, arg2)) + return FALSE; + + endPtr = rect + nbRects; + + for (endPtr = rect + nbRects; (rect < endPtr) && (arg2->bottom > rect->top); rect++) + { + if (rectangles_intersects(rect, arg2)) + return TRUE; + } + + return FALSE; +} + +BOOL region16_intersect_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 *rect) +{ + REGION16_DATA *newItems; + const RECTANGLE_16 *srcPtr, *endPtr, *srcExtents; + RECTANGLE_16 *dstPtr; + int nbRects, usedRects; + RECTANGLE_16 common, newExtents; + + assert(src); + assert(src->data); + + srcPtr = region16_rects(src, &nbRects); + if (!nbRects) + { + region16_clear(dst); + return TRUE; + } + + srcExtents = region16_extents(src); + if (nbRects == 1) + { + BOOL intersects = rectangles_intersection(srcExtents, rect, &common); + + region16_clear(dst); + if (intersects) + return region16_union_rect(dst, dst, &common); + return TRUE; + } + + newItems = allocateRegion(nbRects); + if (!newItems) + return FALSE; + dstPtr = (RECTANGLE_16 *)(newItems + 1); + usedRects = 0; + ZeroMemory(&newExtents, sizeof(newExtents)); + + /* accumulate intersecting rectangles, the final region16_simplify_bands() will + * do all the bad job to recreate correct rectangles + */ + for(endPtr = srcPtr + nbRects; (srcPtr < endPtr) && (rect->bottom > srcPtr->top); srcPtr++) + { + if (rectangles_intersection(srcPtr, rect, &common)) + { + *dstPtr = common; + usedRects++; + dstPtr++; + + newExtents.top = MIN(common.top, newExtents.top); + newExtents.left = MIN(common.left, newExtents.left); + newExtents.bottom = MAX(common.bottom, newExtents.bottom); + newExtents.right = MAX(common.right, newExtents.right); + } + } + + newItems->nbRects = usedRects; + newItems->size = sizeof(REGION16_DATA) + usedRects * sizeof(RECTANGLE_16); + + if (dst->data->size) + free(dst->data); + + dst->data = realloc(newItems, newItems->size); + if (!dst->data) + return FALSE; + + dst->extents = newExtents; + return region16_simplify_bands(dst); +} + +void region16_uninit(REGION16 *region) { + assert(region); + assert(region->data); + + if(region->data->size) + free(region->data); + region->data = 0; +} + + + + diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index f8e736d88..b838a8e01 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "rfx_constants.h" #include "rfx_types.h" @@ -51,6 +52,7 @@ #include "rfx_sse2.h" #include "rfx_neon.h" + #ifndef RFX_INIT_SIMD #define RFX_INIT_SIMD(_rfx_context) do { } while (0) #endif @@ -183,24 +185,13 @@ void rfx_decoder_tile_free(RFX_TILE* tile) 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; + return (RFX_TILE *)calloc(1, sizeof(RFX_TILE)); } void rfx_encoder_tile_free(RFX_TILE* tile) { if (tile) - { free(tile); - } } RFX_CONTEXT* rfx_context_new(BOOL encoder) @@ -212,36 +203,42 @@ RFX_CONTEXT* rfx_context_new(BOOL encoder) DWORD dwValue; SYSTEM_INFO sysinfo; RFX_CONTEXT* context; + wObject *pool; + RFX_CONTEXT_PRIV *priv; - context = (RFX_CONTEXT*) malloc(sizeof(RFX_CONTEXT)); - ZeroMemory(context, sizeof(RFX_CONTEXT)); + context = (RFX_CONTEXT*)calloc(1, sizeof(RFX_CONTEXT)); + if (!context) + return NULL; context->encoder = encoder; - - context->priv = (RFX_CONTEXT_PRIV*) malloc(sizeof(RFX_CONTEXT_PRIV)); - ZeroMemory(context->priv, sizeof(RFX_CONTEXT_PRIV)); + context->priv = priv = (RFX_CONTEXT_PRIV *)calloc(1, sizeof(RFX_CONTEXT_PRIV) ); + if (!priv) + goto error_priv; WLog_Init(); - context->priv->log = WLog_Get("com.freerdp.codec.rfx"); - WLog_OpenAppender(context->priv->log); + priv->log = WLog_Get("com.freerdp.codec.rfx"); + WLog_OpenAppender(priv->log); #ifdef WITH_DEBUG_RFX - WLog_SetLogLevel(context->priv->log, WLOG_DEBUG); + WLog_SetLogLevel(priv->log, WLOG_DEBUG); #endif - context->priv->TilePool = ObjectPool_New(TRUE); - ObjectPool_Object(context->priv->TilePool)->fnObjectInit = (OBJECT_INIT_FN) rfx_tile_init; + priv->TilePool = ObjectPool_New(TRUE); + if (!priv->TilePool) + goto error_tilePool; + pool = ObjectPool_Object(priv->TilePool); + pool->fnObjectInit = (OBJECT_INIT_FN) rfx_tile_init; 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; + pool->fnObjectNew = (OBJECT_NEW_FN) rfx_encoder_tile_new; + pool->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; + pool->fnObjectNew = (OBJECT_NEW_FN) rfx_decoder_tile_new; + pool->fnObjectFree = (OBJECT_FREE_FN) rfx_decoder_tile_free; } /* @@ -258,7 +255,9 @@ RFX_CONTEXT* rfx_context_new(BOOL encoder) * We then multiply by 3 to use a single, partioned buffer for all 3 channels. */ - context->priv->BufferPool = BufferPool_New(TRUE, (8192 + 32) * 3, 16); + priv->BufferPool = BufferPool_New(TRUE, (8192 + 32) * 3, 16); + if (!priv->BufferPool) + goto error_BufferPool; #ifdef _WIN32 { @@ -271,16 +270,16 @@ RFX_CONTEXT* rfx_context_new(BOOL encoder) GetVersionExA(&verinfo); isVistaOrLater = ((verinfo.dwMajorVersion >= 6) && (verinfo.dwMinorVersion >= 0)) ? TRUE : FALSE; - context->priv->UseThreads = isVistaOrLater; + priv->UseThreads = isVistaOrLater; } #else - context->priv->UseThreads = TRUE; + priv->UseThreads = TRUE; #endif GetNativeSystemInfo(&sysinfo); - context->priv->MinThreadCount = sysinfo.dwNumberOfProcessors; - context->priv->MaxThreadCount = 0; + priv->MinThreadCount = sysinfo.dwNumberOfProcessors; + priv->MaxThreadCount = 0; status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\RemoteFX"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey); @@ -289,33 +288,35 @@ RFX_CONTEXT* rfx_context_new(BOOL encoder) dwSize = sizeof(dwValue); if (RegQueryValueEx(hKey, _T("UseThreads"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS) - context->priv->UseThreads = dwValue ? 1 : 0; + priv->UseThreads = dwValue ? 1 : 0; if (RegQueryValueEx(hKey, _T("MinThreadCount"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS) - context->priv->MinThreadCount = dwValue; + priv->MinThreadCount = dwValue; if (RegQueryValueEx(hKey, _T("MaxThreadCount"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS) - context->priv->MaxThreadCount = dwValue; + priv->MaxThreadCount = dwValue; RegCloseKey(hKey); } - if (context->priv->UseThreads) + if (priv->UseThreads) { /* Call primitives_get here in order to avoid race conditions when using primitives_get */ /* from multiple threads. This call will initialize all function pointers correctly */ /* before any decoding threads are started */ primitives_get(); - context->priv->ThreadPool = CreateThreadpool(NULL); - InitializeThreadpoolEnvironment(&context->priv->ThreadPoolEnv); - SetThreadpoolCallbackPool(&context->priv->ThreadPoolEnv, context->priv->ThreadPool); + priv->ThreadPool = CreateThreadpool(NULL); + if (!priv->ThreadPool) + goto error_threadPool; + InitializeThreadpoolEnvironment(&priv->ThreadPoolEnv); + SetThreadpoolCallbackPool(&priv->ThreadPoolEnv, priv->ThreadPool); - if (context->priv->MinThreadCount) - SetThreadpoolThreadMinimum(context->priv->ThreadPool, context->priv->MinThreadCount); + if (priv->MinThreadCount) + SetThreadpoolThreadMinimum(priv->ThreadPool, priv->MinThreadCount); - if (context->priv->MaxThreadCount) - SetThreadpoolThreadMaximum(context->priv->ThreadPool, context->priv->MaxThreadCount); + if (priv->MaxThreadCount) + SetThreadpoolThreadMaximum(priv->ThreadPool, priv->MaxThreadCount); } /* initialize the default pixel format */ @@ -335,29 +336,47 @@ RFX_CONTEXT* rfx_context_new(BOOL encoder) RFX_INIT_SIMD(context); context->state = RFX_STATE_SEND_HEADERS; - return context; + +error_threadPool: + BufferPool_Free(priv->BufferPool); +error_BufferPool: + ObjectPool_Free(priv->TilePool); +error_tilePool: + free(priv); +error_priv: + free(context); + return NULL; } void rfx_context_free(RFX_CONTEXT* context) { + RFX_CONTEXT_PRIV *priv; + assert(NULL != context); assert(NULL != context->priv); assert(NULL != context->priv->TilePool); assert(NULL != context->priv->BufferPool); + priv = context->priv; if (context->quants) free(context->quants); - ObjectPool_Free(context->priv->TilePool); + ObjectPool_Free(priv->TilePool); rfx_profiler_print(context); rfx_profiler_free(context); - if (context->priv->UseThreads) + if (priv->UseThreads) { CloseThreadpool(context->priv->ThreadPool); DestroyThreadpoolEnvironment(&context->priv->ThreadPoolEnv); + + if (priv->workObjects) + free(priv->workObjects); + if (priv->tileWorkParams) + free(priv->tileWorkParams); + #ifdef WITH_PROFILER fprintf(stderr, "\nWARNING: Profiling results probably unusable with multithreaded RemoteFX codec!\n"); #endif @@ -453,7 +472,7 @@ static BOOL rfx_process_message_codec_versions(RFX_CONTEXT* context, wStream* s) return FALSE; } - if (Stream_GetRemainingLength(s) < 2 * numCodecs) + if (Stream_GetRemainingLength(s) < (size_t) (2 * numCodecs)) { DEBUG_WARN("RfxCodecVersion packet too small for numCodecs=%d", numCodecs); return FALSE; @@ -490,7 +509,7 @@ static BOOL rfx_process_message_channels(RFX_CONTEXT* context, wStream* s) return TRUE; } - if (Stream_GetRemainingLength(s) < numChannels * 5) + if (Stream_GetRemainingLength(s) < (size_t) (numChannels * 5)) { DEBUG_WARN("RfxMessageChannels packet too small for numChannels=%d", numChannels); return FALSE; @@ -604,16 +623,15 @@ static BOOL rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* messag return TRUE; } - if (Stream_GetRemainingLength(s) < 8 * message->numRects) + if (Stream_GetRemainingLength(s) < (size_t) (8 * message->numRects)) { DEBUG_WARN("RfxMessageRegion packet too small for num_rects=%d", message->numRects); return FALSE; } - if (message->rects) - message->rects = (RFX_RECT*) realloc(message->rects, message->numRects * sizeof(RFX_RECT)); - else - message->rects = (RFX_RECT*) malloc(message->numRects * sizeof(RFX_RECT)); + message->rects = (RFX_RECT*) realloc(message->rects, message->numRects * sizeof(RFX_RECT)); + if (!message->rects) + return FALSE; /* rects */ for (i = 0; i < message->numRects; i++) @@ -624,8 +642,9 @@ static BOOL rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* messag Stream_Read_UINT16(s, message->rects[i].width); /* width (2 bytes) */ Stream_Read_UINT16(s, message->rects[i].height); /* height (2 bytes) */ - WLog_Print(context->priv->log, WLOG_DEBUG, "rect %d (%d %d %d %d).", - i, message->rects[i].x, message->rects[i].y, message->rects[i].width, message->rects[i].height); + WLog_Print(context->priv->log, WLOG_DEBUG, "rect %d (x,y=%d,%d w,h=%d %d).", i, + message->rects[i].x, message->rects[i].y, + message->rects[i].width, message->rects[i].height); } return TRUE; @@ -695,15 +714,12 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa Stream_Read_UINT32(s, tilesDataSize); /* tilesDataSize (4 bytes) */ - if (context->quants != NULL) - context->quants = (UINT32*) realloc((void*) context->quants, context->numQuant * 10 * sizeof(UINT32)); - else - context->quants = (UINT32*) malloc(context->numQuant * 10 * sizeof(UINT32)); + context->quants = (UINT32 *)realloc((void*) context->quants, context->numQuant * 10 * sizeof(UINT32)); quants = context->quants; /* quantVals */ - if (Stream_GetRemainingLength(s) < context->numQuant * 5) + if (Stream_GetRemainingLength(s) < (size_t) (context->numQuant * 5)) { DEBUG_WARN("RfxMessageTileSet packet too small for num_quants=%d", context->numQuant); return FALSE; @@ -1119,7 +1135,6 @@ struct _RFX_TILE_COMPOSE_WORK_PARAM RFX_TILE* tile; RFX_CONTEXT* context; }; -typedef struct _RFX_TILE_COMPOSE_WORK_PARAM RFX_TILE_COMPOSE_WORK_PARAM; void CALLBACK rfx_compose_message_tile_work_callback(PTP_CALLBACK_INSTANCE instance, void* context, PTP_WORK work) { @@ -1127,37 +1142,82 @@ void CALLBACK rfx_compose_message_tile_work_callback(PTP_CALLBACK_INSTANCE insta rfx_encode_rgb(param->context, param->tile); } -RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, - int numRects, BYTE* data, int width, int height, int scanline) + +static BOOL computeRegion(const RFX_RECT* rects, int numRects, REGION16 *region, int width, int height) { - int i, close_cnt; - int xIdx; - int yIdx; - int numTilesX; - int numTilesY; - UINT16 ax, ay; + int i; + const RFX_RECT *rect = rects; + const RECTANGLE_16 mainRect = { 0, 0, width, height }; + + for(i = 0; i < numRects; i++, rect++) { + RECTANGLE_16 rect16; + + rect16.left = rect->x; + rect16.top = rect->y; + rect16.right = rect->x + rect->width; + rect16.bottom = rect->y + rect->height; + + if (!region16_union_rect(region, region, &rect16)) + return FALSE; + } + + return region16_intersect_rect(region, region, &mainRect); +} + +#define TILE_NO(v) ((v) / 64) + +BOOL setupWorkers(RFX_CONTEXT *context, int nbTiles) +{ + RFX_CONTEXT_PRIV *priv = context->priv; + + if (!context->priv->UseThreads) + return TRUE; + + priv->workObjects = (PTP_WORK *)realloc(priv->workObjects, sizeof(PTP_WORK) * nbTiles); + if (!priv->workObjects) + return FALSE; + + priv->tileWorkParams = (RFX_TILE_COMPOSE_WORK_PARAM *) + realloc(priv->tileWorkParams, sizeof(RFX_TILE_COMPOSE_WORK_PARAM) * nbTiles); + if (!priv->tileWorkParams) + return FALSE; + + return TRUE; +} + + +RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int numRects, + BYTE* data, int width, int height, int scanline) +{ + int i, maxNbTiles, maxTilesX, maxTilesY; + int xIdx, yIdx, regionNbRects; + int gridRelX, gridRelY, ax, ay, bytesPerPixel; RFX_TILE* tile; - RFX_RECT* rect; - int BytesPerPixel; + RFX_RECT* rfxRect; RFX_MESSAGE* message = NULL; - PTP_WORK* work_objects = NULL; - RFX_TILE_COMPOSE_WORK_PARAM* params = NULL; + PTP_WORK* workObject = NULL; + RFX_TILE_COMPOSE_WORK_PARAM *workParam = NULL; - message = (RFX_MESSAGE*) malloc(sizeof(RFX_MESSAGE)); + REGION16 rectsRegion, tilesRegion; + RECTANGLE_16 currentTileRect; + const RECTANGLE_16 *regionRect; + const RECTANGLE_16 *extents; + assert(data); + assert(rects); + assert(numRects > 0); + assert(width > 0); + assert(height > 0); + assert(scanline > 0); + + message = (RFX_MESSAGE *)calloc(1, sizeof(RFX_MESSAGE)); if (!message) return NULL; - ZeroMemory(message, sizeof(RFX_MESSAGE)); - if (context->state == RFX_STATE_SEND_HEADERS) rfx_update_context_properties(context); message->frameIdx = context->frameIdx++; - - message->numRects = numRects; - message->rects = (RFX_RECT*) rects; - if (!context->numQuant) { context->numQuant = 1; @@ -1167,133 +1227,187 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, context->quantIdxCb = 0; context->quantIdxCr = 0; } - - rect = (RFX_RECT*) &rects[0]; - BytesPerPixel = (context->bits_per_pixel / 8); - message->numQuant = context->numQuant; message->quantVals = context->quants; - numTilesX = (width + 63) / 64; - numTilesY = (height + 63) / 64; + bytesPerPixel = (context->bits_per_pixel / 8); - message->numTiles = numTilesX * numTilesY; - if (message->numTiles) - { - message->tiles = (RFX_TILE**) malloc(sizeof(RFX_TILE*) * message->numTiles); - ZeroMemory(message->tiles, sizeof(RFX_TILE*) * message->numTiles); - } + region16_init(&rectsRegion); + if (!computeRegion(rects, numRects, &rectsRegion, width, height)) + goto out_free_message; - WLog_Print(context->priv->log, WLOG_DEBUG, "x: %d y: %d width: %d height: %d scanline: %d BytesPerPixel: %d", - rect->x, rect->y, width, height, scanline, BytesPerPixel); + extents = region16_extents(&rectsRegion); + assert(extents->right - extents->left > 0); + assert(extents->bottom - extents->top > 0); + + maxTilesX = 1 + TILE_NO(extents->right - 1) - TILE_NO(extents->left); + maxTilesY = 1 + TILE_NO(extents->bottom - 1) - TILE_NO(extents->top); + maxNbTiles = maxTilesX * maxTilesY; + + message->tiles = calloc(maxNbTiles, sizeof(RFX_TILE*)); + if (!message->tiles) + goto out_free_message; + + if (!setupWorkers(context, maxNbTiles)) + goto out_clean_tiles; if (context->priv->UseThreads) { - if (message->numTiles) - work_objects = (PTP_WORK*) malloc(sizeof(PTP_WORK) * message->numTiles); - if (!work_objects) - { - free(message); - return NULL; - } - params = (RFX_TILE_COMPOSE_WORK_PARAM*) - malloc(sizeof(RFX_TILE_COMPOSE_WORK_PARAM) * message->numTiles); - if (!params) - { - if (message->tiles) - free(message->tiles); - free(message); - free(work_objects); - return NULL; - } - ZeroMemory(work_objects, sizeof(PTP_WORK) * message->numTiles); - ZeroMemory(params, sizeof(RFX_TILE_COMPOSE_WORK_PARAM) * message->numTiles); + workObject = context->priv->workObjects; + workParam = context->priv->tileWorkParams; } - close_cnt = 0; - for (yIdx = 0; yIdx < numTilesY; yIdx++) + regionRect = region16_rects(&rectsRegion, ®ionNbRects); + message->rects = rfxRect = calloc(regionNbRects, sizeof(RFX_RECT)); + if (!message->rects) + goto out_clean_tiles; + message->numRects = regionNbRects; + + region16_init(&tilesRegion); + + for (i = 0; i < regionNbRects; i++, regionRect++, rfxRect++) { - for (xIdx = 0; xIdx < numTilesX; xIdx++) + int startTileX = regionRect->left / 64; + int endTileX = (regionRect->right - 1) / 64; + + int startTileY = regionRect->top / 64; + int endTileY = (regionRect->bottom - 1) / 64; + + rfxRect->x = regionRect->left; + rfxRect->y = regionRect->top; + rfxRect->width = (regionRect->right - regionRect->left); + rfxRect->height = (regionRect->bottom - regionRect->top); + + + for (yIdx = startTileY, gridRelY = startTileY * 64; yIdx <= endTileY; yIdx++, gridRelY += 64 ) { - i = yIdx * numTilesX + xIdx; + int tileHeight = 64; + if ((yIdx == endTileY) && (gridRelY + 64 > height)) + tileHeight = height - gridRelY; - tile = message->tiles[i] = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool); + currentTileRect.top = gridRelY; + currentTileRect.bottom = gridRelY + tileHeight; - tile->xIdx = xIdx; - tile->yIdx = yIdx; - tile->x = tile->xIdx * 64; - tile->y = tile->yIdx * 64; - tile->scanline = scanline; - tile->width = (xIdx < numTilesX - 1) ? 64 : width - xIdx * 64; - tile->height = (yIdx < numTilesY - 1) ? 64 : height - yIdx * 64; - - ax = rect->x + tile->x; - ay = rect->y + tile->y; - if (tile->data && tile->allocated) + for (xIdx = startTileX, gridRelX = startTileX * 64; xIdx <= endTileX; xIdx++, gridRelX += 64) { - free(tile->data); - tile->allocated = FALSE; - } - tile->data = &data[(ay * scanline) + (ax * BytesPerPixel)]; + int tileWidth = 64; + if ((xIdx == endTileX) && (gridRelX + 64 > width)) + tileWidth = width - gridRelX; - tile->quantIdxY = context->quantIdxY; - tile->quantIdxCb = context->quantIdxCb; - tile->quantIdxCr = context->quantIdxCr; + currentTileRect.left = gridRelX; + currentTileRect.right = gridRelX + tileWidth; - tile->YLen = 0; - tile->CbLen = 0; - tile->CrLen = 0; + /* checks if this tile is already treated */ + if (region16_intersects_rect(&tilesRegion, ¤tTileRect)) + continue; - tile->YCbCrData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1); + tile = (RFX_TILE *)ObjectPool_Take(context->priv->TilePool); + if (!tile) + goto out_clean_rects;; - 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]); + tile->xIdx = xIdx; + tile->yIdx = yIdx; + tile->x = gridRelX; + tile->y = gridRelY; + tile->scanline = scanline; + tile->width = tileWidth; + tile->height = tileHeight; - if (context->priv->UseThreads) - { - assert(params); + ax = gridRelX; + ay = gridRelY; + if (tile->data && tile->allocated) + { + free(tile->data); + tile->allocated = FALSE; + } + tile->data = &data[(ay * scanline) + (ax * bytesPerPixel)]; - params[i].context = context; - params[i].tile = tile; + tile->quantIdxY = context->quantIdxY; + tile->quantIdxCb = context->quantIdxCb; + tile->quantIdxCr = context->quantIdxCr; - work_objects[i] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_compose_message_tile_work_callback, - (void*) ¶ms[i], &context->priv->ThreadPoolEnv); + tile->YLen = tile->CbLen = tile->CrLen = 0; - SubmitThreadpoolWork(work_objects[i]); - close_cnt = i + 1; - } - else - { - rfx_encode_rgb(context, tile); - } - } + tile->YCbCrData = (BYTE *)BufferPool_Take(context->priv->BufferPool, -1); + if (!tile->YCbCrData) + goto out_clean_rects; + + 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) + { + workParam->context = context; + workParam->tile = tile; + + *workObject = CreateThreadpoolWork( + (PTP_WORK_CALLBACK)rfx_compose_message_tile_work_callback, + (void *)workParam, + &context->priv->ThreadPoolEnv + ); + + SubmitThreadpoolWork(*workObject); + + workObject++; + workParam++; + } + else + { + rfx_encode_rgb(context, tile); + } + + message->tiles[message->numTiles] = tile; + message->numTiles++; + + if (!region16_union_rect(&tilesRegion, &tilesRegion, ¤tTileRect)) + goto out_clean_rects; + } /* xIdx */ + } /* yIdx */ + } /* rects */ + + if (message->numTiles != maxNbTiles) + { + message->tiles = realloc(message->tiles, sizeof(RFX_TILE *) * message->numTiles); + if (!message->tiles) + goto out_clean_rects; } - message->tilesDataSize = 0; + region16_uninit(&tilesRegion); - for (i = 0; i < close_cnt; i++) + /* when using threads ensure all computations are done */ + message->tilesDataSize = 0; + workObject = context->priv->workObjects; + for (i = 0; i < message->numTiles; i++) { tile = message->tiles[i]; - - if (context->priv->UseThreads && work_objects) + if (context->priv->UseThreads) { - WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE); - CloseThreadpoolWork(work_objects[i]); + WaitForThreadpoolWorkCallbacks(*workObject, FALSE); + CloseThreadpoolWork(*workObject); + workObject++; } message->tilesDataSize += rfx_tile_length(tile); } - if (work_objects) - free(work_objects); - - if (params) - free(params); + region16_uninit(&rectsRegion); return message; + +out_clean_rects: + free(message->rects); +out_clean_tiles: + free(message->tiles); + region16_uninit(&tilesRegion); +out_free_message: + fprintf(stderr, "remoteFx error\n"); + region16_uninit(&rectsRegion); + free(message); + return 0; } + RFX_MESSAGE* rfx_split_message(RFX_CONTEXT* context, RFX_MESSAGE* message, int* numMessages, int maxDataSize) { int i, j; @@ -1313,7 +1427,7 @@ RFX_MESSAGE* rfx_split_message(RFX_CONTEXT* context, RFX_MESSAGE* message, int* { tileDataSize = rfx_tile_length(message->tiles[i]); - if ((messages[j].tilesDataSize + tileDataSize) > maxDataSize) + if ((messages[j].tilesDataSize + tileDataSize) > ((UINT32) maxDataSize)) j++; if (!messages[j].numTiles) @@ -1432,14 +1546,8 @@ void rfx_write_message_region(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* mes { /* Clipping rectangles are relative to destLeft, destTop */ -#if 1 - Stream_Write_UINT16(s, 0); /* x (2 bytes) */ - Stream_Write_UINT16(s, 0); /* y (2 bytes) */ -#else Stream_Write_UINT16(s, message->rects[i].x); /* x (2 bytes) */ Stream_Write_UINT16(s, message->rects[i].y); /* y (2 bytes) */ -#endif - Stream_Write_UINT16(s, message->rects[i].width); /* width (2 bytes) */ Stream_Write_UINT16(s, message->rects[i].height); /* height (2 bytes) */ } @@ -1483,3 +1591,4 @@ void rfx_compose_message(RFX_CONTEXT* context, wStream* s, rfx_message_free(context, message); } + diff --git a/libfreerdp/codec/rfx_types.h b/libfreerdp/codec/rfx_types.h index 309bd553c..250c14964 100644 --- a/libfreerdp/codec/rfx_types.h +++ b/libfreerdp/codec/rfx_types.h @@ -38,12 +38,17 @@ #define DEBUG_RFX(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif +typedef struct _RFX_TILE_COMPOSE_WORK_PARAM RFX_TILE_COMPOSE_WORK_PARAM; + struct _RFX_CONTEXT_PRIV { wLog* log; wObjectPool* TilePool; BOOL UseThreads; + PTP_WORK* workObjects; + RFX_TILE_COMPOSE_WORK_PARAM* tileWorkParams; + DWORD MinThreadCount; DWORD MaxThreadCount; diff --git a/libfreerdp/codec/test/CMakeLists.txt b/libfreerdp/codec/test/CMakeLists.txt index e1bced145..62d358883 100644 --- a/libfreerdp/codec/test/CMakeLists.txt +++ b/libfreerdp/codec/test/CMakeLists.txt @@ -5,7 +5,10 @@ set(MODULE_PREFIX "TEST_FREERDP_CODEC") set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) set(${MODULE_PREFIX}_TESTS - TestFreeRDPCodecPlanar.c) + TestFreeRDPRegion.c + TestFreeRDPCodecMppc.c + TestFreeRDPCodecPlanar.c + TestFreeRDPCodecRemoteFX.c) create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} diff --git a/libfreerdp/codec/test/TestFreeRDPCodecMppc.c b/libfreerdp/codec/test/TestFreeRDPCodecMppc.c new file mode 100644 index 000000000..4f46e4bed --- /dev/null +++ b/libfreerdp/codec/test/TestFreeRDPCodecMppc.c @@ -0,0 +1,684 @@ +#include +#include + +#include +#include +#include + +static BYTE TEST_RDP5_COMPRESSED_DATA[] = +{ + 0x24, 0x02, 0x03, 0x09, 0x00, 0x20, 0x0c, 0x05, 0x10, 0x01, 0x40, 0x0a, 0xbf, 0xdf, 0xc3, 0x20, + 0x80, 0x00, 0x1f, 0x0a, 0x00, 0x00, 0x07, 0x43, 0x4e, 0x00, 0x68, 0x02, 0x00, 0x22, 0x00, 0x34, + 0xcb, 0xfb, 0xf8, 0x18, 0x40, 0x01, 0x00, 0x27, 0xe2, 0x90, 0x0f, 0xc3, 0x91, 0xa8, 0x00, 0x08, + 0x00, 0x00, 0x68, 0x50, 0x60, 0x65, 0xfc, 0x0e, 0xfe, 0x04, 0x00, 0x08, 0x00, 0x06, 0x0c, 0x00, + 0x01, 0x00, 0xf8, 0x40, 0x20, 0x00, 0x00, 0x90, 0x00, 0xcf, 0x95, 0x1f, 0x44, 0x90, 0x00, 0x6e, + 0x03, 0xf4, 0x40, 0x21, 0x9f, 0x26, 0x01, 0xbf, 0x88, 0x10, 0x90, 0x00, 0x08, 0x04, 0x00, 0x04, + 0x30, 0x03, 0xe4, 0xc7, 0xea, 0x05, 0x1e, 0x87, 0xf8, 0x20, 0x1c, 0x00, 0x10, 0x84, 0x22, 0x1f, + 0x71, 0x0d, 0x0e, 0xb9, 0x88, 0x9f, 0x5c, 0xee, 0x41, 0x97, 0xfb, 0xf8, 0x88, 0x68, 0x08, 0x6d, + 0xd0, 0x44, 0xfc, 0x34, 0x06, 0xe6, 0x16, 0x21, 0x04, 0x11, 0x0f, 0xb9, 0x85, 0x86, 0x5d, 0x44, + 0x4f, 0xae, 0xb7, 0x40, 0xa8, 0xcd, 0x5b, 0xed, 0x02, 0xee, 0xc2, 0x21, 0x40, 0x21, 0x21, 0x23, + 0x17, 0xb7, 0x00, 0x60, 0x00, 0x3b, 0xfd, 0xfc, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x34, 0x00, 0x33, + 0xc7, 0xe0, 0xc0, 0x0f, 0x07, 0x12, 0x42, 0x01, 0xe8, 0x6c, 0xc7, 0x83, 0x07, 0x8c, 0xd4, 0x30, + 0x07, 0x20, 0x01, 0x90, 0xa3, 0xf1, 0xdb, 0xf5, 0xd4, 0x13, 0xc2, 0x4f, 0x0f, 0xe5, 0xe2, 0xc7, + 0x87, 0xf2, 0xf0, 0x93, 0xc3, 0xf9, 0x78, 0xb0, 0x1a, 0x03, 0xe1, 0xf1, 0xd0, 0x08, 0x4c, 0x66, + 0xac, 0x32, 0x31, 0x70, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0xf0, 0x36, 0x1f, 0xe5, 0xe0, + 0x6c, 0xbc, 0x26, 0xf0, 0x36, 0x5f, 0xe5, 0xe0, 0x6c, 0xbc, 0x26, 0xf0, 0x34, 0xf9, 0x94, 0x32, + 0x31, 0x74, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xbf, 0x87, 0xdf, 0xef, 0xfe, 0x4b, 0xbf, 0x02, 0xfa, + 0xde, 0xa7, 0x79, 0x32, 0x44, 0x7c, 0x20, 0x82, 0x00, 0x5f, 0xef, 0xff, 0x09, 0xe1, 0x05, 0x74, + 0x32, 0xea, 0x09, 0xe1, 0x0f, 0x55, 0x83, 0x85, 0x2a, 0xa0, 0x1d, 0x50, 0x0e, 0x0e, 0x0b, 0x01, + 0x01, 0x43, 0x06, 0x02, 0xbe, 0x5f, 0x00, 0x00, 0x0c, 0x3d, 0x4d, 0x87, 0xa6, 0x5e, 0xa6, 0xcb, + 0xc3, 0xcf, 0x53, 0x65, 0xe9, 0x97, 0xa9, 0xb2, 0xf5, 0x9b, 0xd4, 0xd3, 0xee, 0xcd, 0xc0, 0x7c, + 0xae, 0xe0, 0x65, 0x1f, 0xe5, 0xe0, 0x6c, 0xbc, 0x26, 0xf0, 0x36, 0x5f, 0xe5, 0xe0, 0x6c, 0xbc, + 0x26, 0xf0, 0x34, 0xfb, 0xb3, 0xf2, 0x41, 0x30, 0x20, 0x04, 0xa0, 0x80, 0x93, 0xf3, 0xf2, 0x1b, + 0xed, 0xf6, 0x0f, 0x04, 0x82, 0x7b, 0xcc, 0x00, 0x65, 0xef, 0x4f, 0x86, 0x02, 0xf7, 0xa7, 0xe0, + 0x0a, 0x88, 0x1c, 0x34, 0x02, 0x02, 0x02, 0x60, 0x60, 0x49, 0x40, 0xc1, 0x2f, 0x14, 0xca, 0x60, + 0xc1, 0x81, 0x80, 0x07, 0xc3, 0x00, 0x00, 0x39, 0xfa, 0x86, 0x38, 0x93, 0x47, 0x08, 0x27, 0x08, + 0xfc, 0xb8, 0x4e, 0x38, 0x47, 0xe5, 0xc2, 0x09, 0xc2, 0x3f, 0x2e, 0x13, 0x8e, 0x11, 0xf3, 0xc3, + 0x57, 0x1a, 0x88, 0x7d, 0x44, 0x3c, 0x3c, 0x04, 0x0f, 0xd4, 0x3f, 0x83, 0x8d, 0x82, 0x00, 0x25, + 0x04, 0x84, 0xdf, 0xe0, 0x17, 0xf8, 0x04, 0x03, 0xe1, 0x47, 0xc4, 0xaf, 0x9c, 0x00, 0x00, 0x31, + 0xf5, 0x4c, 0x71, 0x78, 0x8f, 0x54, 0xfb, 0x1c, 0x97, 0xa4, 0x04, 0x13, 0xd5, 0x2f, 0x77, 0xc7, + 0xb8, 0x9e, 0xef, 0xcb, 0xc2, 0x6f, 0x77, 0xe5, 0xee, 0x27, 0xbb, 0xf2, 0xf7, 0xe3, 0xdd, 0xf3, + 0xc6, 0xfb, 0x2a, 0x78, 0x6d, 0x3c, 0x34, 0x37, 0xc0, 0xaf, 0x25, 0xc7, 0x81, 0x7d, 0x6e, 0x5d, + 0x5c, 0xd6, 0xe3, 0x43, 0xc0, 0x82, 0xd0, 0x95, 0x90, 0xd8, 0xbd, 0xfc, 0x00, 0x09, 0xc0, 0x34, + 0x39, 0x46, 0x84, 0x20, 0x40, 0x38, 0xa3, 0x42, 0x12, 0xb0, 0x55, 0xbe, 0x28, 0xc0, 0x70, 0x64, + 0x28, 0xc8, 0x48, 0x42, 0x08, 0xb2, 0x1b, 0x46, 0xa6, 0x09, 0x54, 0x2e, 0x5f, 0x73, 0x84, 0xfc, + 0x28, 0x4a, 0x73, 0x79, 0xf2, 0x6c, 0x5d, 0x82, 0x82, 0x6e, 0xc2, 0x27, 0xd7, 0x6b, 0xb8, 0x4f, + 0xa4, 0xa4, 0x22, 0xee, 0x22, 0x7e, 0x10, 0x03, 0x78, 0x08, 0xf4, 0x94, 0x5e, 0x02, 0x01, 0xef, + 0x02, 0x27, 0xd7, 0x8b, 0xc8, 0x3f, 0xa4, 0xa4, 0x1a, 0xf3, 0xd1, 0x84, 0x0c, 0x32, 0x31, 0x75, + 0x60, 0x05, 0xe2, 0x30, 0xb7, 0xad, 0x5b, 0x15, 0xd5, 0xc3, 0xc0, 0x00, 0x11, 0x81, 0x81, 0x69, + 0x8f, 0x06, 0x0f, 0x14, 0xcf, 0xa6, 0xe8, 0xb1, 0x22, 0x77, 0xeb, 0xd7, 0x45, 0x89, 0xf0, 0xb6, + 0x3e, 0x23, 0x06, 0x80, 0xf8, 0x5b, 0x0f, 0x04, 0x83, 0xfc, 0x2d, 0x8f, 0x88, 0xc1, 0xa0, 0x3e, + 0x16, 0x1d, 0x00, 0x83, 0x74, 0x58, 0xa0, 0xc0, 0x10, 0xce, 0x8b, 0x17, 0xe0, 0x68, 0xff, 0x20, + 0xff, 0x03, 0x63, 0xe5, 0xcf, 0x1f, 0xa0, 0x40, 0x00, 0x00, 0x2a, 0xff, 0xd6, 0xd1, 0xc0, 0xb9, + 0xe0, 0x5f, 0x6b, 0x81, 0x73, 0xc9, 0x93, 0xd1, 0x63, 0x50, 0xf0, 0x9b, 0xf0, 0x48, 0x4f, 0xaf, + 0xe0, 0x1b, 0xef, 0x82, 0x6f, 0xc2, 0x40, 0xe0, 0xe4, 0x60, 0xa0, 0x69, 0xa1, 0xa1, 0xbe, 0xba, + 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x42, 0x00, 0x44, 0x00, 0x88, 0x01, 0x10, 0x02, + 0x21, 0x02, 0x22, 0x04, 0x44, 0x08, 0x9c, 0x8f, 0xcd, 0xe0, 0x02, 0x20, 0x88, 0x02, 0x10, 0x40, + 0x01, 0xf0, 0x60, 0x44, 0xc0, 0xce, 0xb1, 0x8f, 0xd0, 0x30, 0x00, 0x60, 0x00, 0xa0, 0x00, 0xc4, + 0x00, 0xcc, 0x01, 0x98, 0x03, 0x28, 0x03, 0x31, 0x03, 0x33, 0x06, 0x66, 0x07, 0x0e, 0x2c, 0xe3, + 0x7b, 0x18, 0x85, 0xc7, 0xd6, 0x51, 0x71, 0x0f, 0x0e, 0xb8, 0x88, 0x9f, 0x5c, 0x6e, 0x41, 0xde, + 0xeb, 0x71, 0x20, 0x5c, 0xba, 0xf7, 0xc8, 0x6f, 0xba, 0xc1, 0xf7, 0x30, 0xd0, 0xce, 0xc1, 0x31, + 0x74, 0xec, 0x13, 0x41, 0x77, 0x41, 0x13, 0xa0, 0x10, 0xbf, 0x7c, 0x45, 0xd3, 0xa5, 0xbc, 0x55, + 0x84, 0xaa, 0x41, 0xc1, 0xc1, 0xe0, 0xe0, 0x29, 0x01, 0x20, 0x81, 0x00, 0x03, 0x80, 0x07, 0xc0, + 0x0f, 0xe0, 0x06, 0xbe, 0x16, 0x75, 0xe7, 0x9f, 0xfb, 0x1e, 0x17, 0x90, 0xef, 0x0b, 0xbb, 0x15, + 0x03, 0x7c, 0x2b, 0x7e, 0x22, 0x78, 0x56, 0x83, 0xae, 0x77, 0x40, 0xcf, 0xb0, 0xf0, 0x98, 0x28, + 0x04, 0x2f, 0xaf, 0x0e, 0x40, 0xfc, 0x01, 0x1c, 0x5c, 0xb1, 0xf2, 0xbf, 0xa5, 0xd7, 0x8f, 0x97, + 0xc0, 0xfe, 0x9f, 0x02, 0xe7, 0x24, 0x79, 0xe0, 0x9b, 0xa9, 0xfd, 0x74, 0x3b, 0xaf, 0x2d, 0xf8, + 0x4b, 0xd2, 0xf7, 0x84, 0x54, 0x04, 0x2a, 0x02, 0x02, 0x01, 0xe1, 0x1e, 0xf0, 0x87, 0xff, 0x77, + 0x07, 0x00, 0x02, 0x00, 0x0d, 0xbd, 0xe1, 0xf0, 0x01, 0x1e, 0xf0, 0xfd, 0x80, 0x4c, 0x24, 0x11, + 0x2c, 0x10, 0x24, 0x02, 0x01, 0x40, 0xb0, 0x5c, 0x2c, 0x14, 0x08, 0x07, 0x1b, 0x80, 0x01, 0xa7, + 0xbd, 0x3e, 0x00, 0x27, 0xde, 0x9f, 0xb0, 0x85, 0x01, 0xfb, 0xd2, 0x04, 0x0c, 0x1c, 0x2e, 0x0e, + 0x06, 0x18, 0x03, 0xd4, 0x00, 0x00, 0x67, 0xef, 0x4f, 0x80, 0x0a, 0xf7, 0xa7, 0xe3, 0x94, 0xe0, + 0xe0, 0x10, 0x1b, 0xfd, 0xfc, 0x74, 0x62, 0xe8, 0xc0, 0x1d, 0x62, 0x00, 0x0b, 0x00, 0xb7, 0x70, + 0xe6, 0x8a, 0x68, 0x75, 0x38, 0x3c, 0x3c, 0x4c, 0x2f, 0x87, 0xef, 0x01, 0xc7, 0xb2, 0x40, 0x21, + 0xa3, 0x23, 0x0a, 0x08, 0x01, 0xa1, 0xa1, 0xe1, 0x80, 0x69, 0x40, 0xe1, 0x00, 0x00, 0x40, 0xd0, + 0xea, 0xe5, 0xe1, 0xc0, 0x81, 0x87, 0xed, 0x68, 0x1a, 0x08, 0x94, 0x0c, 0x0c, 0xf1, 0x7c, 0xbe, + 0x5f, 0x2f, 0x8f, 0x00, 0x00, 0x0d, 0x1f, 0x68, 0x7a, 0x1a, 0x04, 0x05, 0xce, 0xe6, 0x2a, 0x0c, + 0x01, 0xc2, 0x00, 0x40, 0x42, 0x61, 0xc0, 0x49, 0x41, 0x60, 0xa0, 0x80, 0x01, 0xc0, 0x03, 0xe0, + 0x07, 0xf0, 0x07, 0xfa, 0x00, 0x07, 0x3b, 0x99, 0x01, 0x0f, 0x19, 0x18, 0x54, 0x40, 0xe0, 0x60, + 0xee, 0xd0, 0x0e, 0x19, 0x0a, 0x03, 0xa5, 0x7d, 0x05, 0xd0, 0x83, 0x98, 0x5a, 0x96, 0x21, 0x4b, + 0x10, 0x10, 0xe6, 0x17, 0xaf, 0xeb, 0xaf, 0x34, 0x3c, 0xc8, 0x0f, 0xf0, 0x64, 0x3f, 0xd0, 0x0f, + 0xe0, 0x03, 0xfe, 0x10, 0x02, 0x7d, 0x47, 0x2d, 0x58, 0xfc, 0x35, 0xe0, 0xca, 0x0f, 0x19, 0x0a, + 0xf9, 0xf1, 0xe0, 0xb9, 0xc0, 0x81, 0x10, 0x03, 0xe0, 0xbd, 0x4f, 0xea, 0x61, 0xf7, 0xeb, 0xf6, + 0x02, 0xd4, 0x7a, 0xf9, 0xff, 0x15, 0x30, 0xfa, 0x88, 0x68, 0x68, 0xd8, 0x80, 0x12, 0x60, 0x50, + 0x50, 0xf0, 0x03, 0xfc, 0x01, 0xfe, 0x01, 0x7f, 0xa0, 0x7c, 0x28, 0xbf, 0xd0, 0x3e, 0x64, 0x0f, + 0x00, 0x37, 0x00, 0x08, 0x80, 0x20, 0x0b, 0x88, 0x81, 0xa5, 0x04, 0x84, 0x60, 0x40, 0x36, 0x04, + 0x1b, 0x8f, 0x88, 0x01, 0x00, 0xa1, 0x80, 0x1e, 0x00, 0x36, 0xfd, 0xb9, 0x12, 0x02, 0x4c, 0x09, + 0x08, 0x1e, 0x00, 0x61, 0x80, 0x20, 0x60, 0x44, 0x17, 0xdc, 0x7c, 0x62, 0x00, 0x03, 0x67, 0xdb, + 0x81, 0xb1, 0x30, 0x34, 0xb0, 0xa0, 0xaf, 0xa0, 0x80, 0x75, 0x35, 0x20, 0x7c, 0x49, 0xfc, 0x0f, + 0xf5, 0x0d, 0x7f, 0x7e, 0x45, 0x00, 0x53, 0x42, 0x82, 0x83, 0xc0, 0x0c, 0x28, 0x1f, 0x72, 0x3e, + 0xd3, 0xf5, 0x62, 0xd4, 0x00, 0x22, 0xa8, 0x81, 0xec, 0x67, 0x96, 0x02, 0xa0, 0x49, 0x7d, 0xfd, + 0x6b, 0xbf, 0xcc, 0x7c, 0x4a, 0xf8, 0xd0, 0x00, 0x00, 0xcf, 0xd5, 0xd2, 0x23, 0x35, 0x60, 0x01, + 0xf1, 0x60, 0x14, 0xc0, 0xb0, 0xbe, 0xb3, 0x02, 0x0f, 0x89, 0x5f, 0x1b, 0x00, 0x02, 0x0b, 0xfd, + 0x80, 0x00, 0x01, 0x9b, 0xf3, 0x40, 0x42, 0x10, 0x00, 0xd8, 0xb8, 0x0f, 0xa8, 0x17, 0xfe, 0x59, + 0xef, 0x14, 0x61, 0xf2, 0x30, 0x65, 0xfc, 0x51, 0xe2, 0xc1, 0x18, 0xc0, 0x07, 0x5e, 0x68, 0x08, + 0xe8, 0x46, 0xf8, 0x95, 0xf1, 0xb0, 0xf9, 0x13, 0x7f, 0xbc, 0x00, 0x00, 0x32, 0x7e, 0xa8, 0xeb, + 0xcd, 0x03, 0x20, 0x09, 0xa1, 0x81, 0x97, 0xfb, 0x87, 0x80, 0xb0, 0xf9, 0x19, 0x7c, 0xa8, 0x63, + 0xf3, 0xe6, 0x20, 0x22, 0xbd, 0x85, 0x9e, 0x62, 0x00, 0x8b, 0x7c, 0x87, 0x91, 0x00, 0x22, 0xff, + 0x21, 0xe2, 0xa0, 0x08, 0xc7, 0xc8, 0x78, 0x20, 0x02, 0x33, 0xf2, 0x1c, 0x10, 0x41, 0xe3, 0x40, + 0x69, 0x7c, 0x45, 0x72, 0x62, 0xf0, 0x04, 0x7f, 0x60, 0x68, 0x6f, 0x80, 0x00, 0x08, 0x1f, 0xf7, + 0xad, 0x51, 0x03, 0xf3, 0xf8, 0xa0, 0x9d, 0xa8, 0x40, 0x00, 0x23, 0x42, 0x37, 0x46, 0x0f, 0xde, + 0xa6, 0x06, 0xd3, 0x3c, 0x33, 0xe1, 0x78, 0xd8, 0x34, 0x32, 0x14, 0x67, 0xdb, 0xd2, 0x38, 0xaf, + 0xc7, 0x9c, 0xdf, 0xd0, 0x21, 0xe6, 0xd7, 0x80, 0x40, 0x22, 0x3f, 0x21, 0xe8, 0xd8, 0x12, 0xf9, + 0x0f, 0xb4, 0x01, 0x13, 0xf9, 0x0f, 0x46, 0xc0, 0xa7, 0x13, 0x37, 0x1e, 0x67, 0x07, 0x8b, 0x01, + 0xfd, 0xfe, 0x0f, 0xf7, 0x7a, 0xf0, 0x16, 0x36, 0x0a, 0x92, 0x08, 0x08, 0xc1, 0x70, 0xb8, 0x30, + 0x34, 0xf1, 0xf3, 0x72, 0x27, 0x8f, 0x4b, 0x60, 0x21, 0xc4, 0xdd, 0xe2, 0xdf, 0x0b, 0xca, 0x4f, + 0x2e, 0x4f, 0x9c, 0xde, 0x59, 0xe9, 0xf1, 0x55, 0x00, 0x8d, 0xf2, 0x20, 0x53, 0x3c, 0xc4, 0xf6, + 0x46, 0x7e, 0x24, 0xee, 0xf2, 0x0c, 0x0d, 0x81, 0x83, 0xf9, 0x98, 0x0e, 0x00, 0x02, 0x10, 0x11, + 0x01, 0x08, 0x95, 0x2a, 0xfc, 0x28, 0x95, 0x2a, 0x84, 0x80, 0xbf, 0x81, 0x06, 0x80, 0x0d, 0x00, + 0x86, 0xe0, 0x6b, 0xa5, 0xc3, 0xd8, 0x8f, 0x22, 0xa0, 0x3e, 0xe9, 0x8f, 0x90, 0xf2, 0x6b, 0x85, + 0x77, 0x57, 0x99, 0x43, 0x5c, 0x66, 0x5f, 0x9e, 0x85, 0x7c, 0x3f, 0x1f, 0xb3, 0xce, 0xc0, 0x0e, + 0x64, 0x20, 0x0e, 0x20, 0xdc, 0x7e, 0x18, 0x81, 0x90, 0xa3, 0x13, 0x4e, 0x52, 0x71, 0x81, 0x03, + 0xa4, 0x30, 0x30, 0x6c, 0x73, 0x8f, 0xc4, 0x50, 0x60, 0x16, 0x38, 0x03, 0xbf, 0x6f, 0x89, 0x3e, + 0x00, 0x77, 0x00, 0xb1, 0xc0, 0x28, 0x3d, 0x73, 0x98, 0x06, 0xfe, 0x00, 0xe9, 0x81, 0xa3, 0xb8, + 0x1c, 0x85, 0x20, 0x45, 0x45, 0xe1, 0xa1, 0x23, 0x63, 0xa0, 0x29, 0x61, 0x41, 0x27, 0xf4, 0x03, + 0xfa, 0x01, 0x02, 0x05, 0xff, 0xe1, 0x20, 0x34, 0x08, 0x08, 0x04, 0x04, 0x02, 0xff, 0xeb, 0x96, + 0x05, 0x24, 0x8e, 0x0a, 0xb1, 0xce, 0xf2, 0x06, 0xc7, 0xb9, 0x01, 0xd7, 0x20, 0x52, 0x04, 0x03, + 0xe1, 0x47, 0xc4, 0xa4, 0x0b, 0xfd, 0x03, 0x01, 0xc0, 0x47, 0xe6, 0xc0, 0x2c, 0x7c, 0x09, 0x10, + 0x1c, 0x0a, 0xfd, 0x7e, 0xc0, 0xd2, 0x94, 0x7a, 0x1a, 0x06, 0x07, 0xcf, 0x12, 0x2a, 0x8c, 0x1e, + 0xe7, 0x07, 0x08, 0x81, 0x81, 0x91, 0x90, 0x72, 0x26, 0x9e, 0x55, 0x44, 0x0e, 0x4d, 0x21, 0x00, + 0x08, 0x40, 0x02, 0x20, 0x01, 0x17, 0x2c, 0xd4, 0x22, 0x00, 0x88, 0x80, 0x44, 0x40, 0x23, 0xcd, + 0xf8, 0xf1, 0xc8, 0x9b, 0x02, 0x10, 0x0c, 0x02, 0x99, 0x30, 0x00, 0x0a, 0x06, 0x01, 0x4b, 0x18, + 0x00, 0x46, 0x00, 0x29, 0x9c, 0xa3, 0x86, 0x60, 0x11, 0x98, 0x05, 0x32, 0x80, 0xcc, 0xc0, 0xf3, + 0xc3, 0xb8, 0x7a, 0x21, 0x7d, 0xbe, 0xfa, 0xce, 0x2a, 0x9d, 0xfa, 0xa0, 0x3c, 0x32, 0xfb, 0x7d, + 0x13, 0x22, 0x05, 0xeb, 0x0b, 0xbb, 0xb8, 0x00, 0x15, 0xfe, 0xfe, 0x1a, 0x14, 0x7e, 0x1c, 0x00, + 0x01, 0x82, 0x3a, 0xa7, 0xd2, 0x6c, 0x11, 0xdd, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x18, 0x23, 0x5a, + 0x00, 0x80, 0xb0, 0x47, 0x84, 0x7c, 0xa8, 0x03, 0xa7, 0x82, 0x48, 0x83, 0x01, 0x50, 0x11, 0x2a, + 0x37, 0xfb, 0xfc, 0x03, 0x03, 0xd1, 0xa3, 0x35, 0x68, 0xcd, 0x58, 0x40, 0x03, 0xe3, 0x47, 0xc4, + 0xaf, 0x8d, 0x1f, 0x42, 0x84, 0x20, 0x81, 0x08, 0x57, 0xfb, 0xff, 0xd0, 0x98, 0x27, 0xc8, 0xaf, + 0x99, 0x1f, 0x12, 0x04, 0x3e, 0x84, 0xfe, 0x08, 0x1c, 0xc1, 0x31, 0x58, 0x80, 0x3a, 0xd1, 0x99, + 0x8a, 0x40, 0x02, 0x5a, 0x04, 0x00, 0x02, 0x1a, 0x38, 0xf3, 0x08, 0x00, 0x01, 0xda, 0xe3, 0x35, + 0x60, 0x5f, 0x88, 0x00, 0x03, 0x6e, 0xbf, 0xdf, 0xc0, 0xbe, 0x20, 0x00, 0x42, 0x80, 0x01, 0x77, + 0x9e, 0x80, 0xd0, 0x30, 0x4a, 0x32, 0x81, 0xe3, 0x94, 0x04, 0x21, 0x0a, 0x9c, 0xcc, 0x52, 0x03, + 0x7d, 0xa7, 0x0c, 0x51, 0x80, 0x6f, 0xa5, 0xc0, 0x3f, 0x3e, 0x80, 0xa0, 0x22, 0x10, 0x40, 0x68, + 0x17, 0x9f, 0x60, 0x1e, 0x9b, 0x09, 0x52, 0x03, 0x2d, 0x03, 0x81, 0x88, 0x41, 0x3c, 0x65, 0x14, + 0x98, 0xcd, 0x58, 0x6a, 0x04, 0x21, 0x80, 0x9b, 0x81, 0x45, 0x21, 0x24, 0xe1, 0x8c, 0xf1, 0x9a, + 0xb0, 0xa9, 0x38, 0xef, 0xe7, 0x90, 0xdf, 0x98, 0x00, 0x19, 0xa8, 0x18, 0x42, 0x6a, 0xc0, 0x7f, + 0xda, 0x00, 0x00, 0x2b, 0x1e, 0x36, 0x7c, 0xaa, 0xa0, 0x00, 0xc0, 0xf8, 0xa0, 0xbe, 0x60, 0x2e, + 0xb1, 0x09, 0xab, 0x60, 0x3e, 0x38, 0xf9, 0x6f, 0xa9, 0x3e, 0x08, 0x81, 0xa6, 0x8c, 0x13, 0xae, + 0x83, 0x7e, 0x0a, 0xfb, 0x0f, 0x60, 0x86, 0x3e, 0x90, 0x6d, 0xa2, 0x33, 0x56, 0x06, 0xfa, 0xcf, + 0xc5, 0x1f, 0x12, 0x38, 0x49, 0x3d, 0x04, 0x03, 0xa6, 0x42, 0x54, 0x82, 0x3e, 0xd3, 0xd1, 0xd0, + 0x08, 0x58, 0x06, 0xdc, 0x10, 0x85, 0xe8, 0xf8, 0xf8, 0x94, 0x10, 0x84, 0x21, 0xe7, 0xa3, 0x85, + 0xfe, 0xfe, 0xc1, 0xe9, 0x77, 0xa3, 0x27, 0xe7, 0xbd, 0x31, 0x98, 0x17, 0xa1, 0xe2, 0x13, 0xe8, + 0x5a, 0xf1, 0x44, 0x7c, 0x4a, 0x00, 0x00, 0x07, 0x2d, 0x03, 0x2d, 0x05, 0xa3, 0x46, 0x6a, 0xc1, + 0x9e, 0x9f, 0x9f, 0x51, 0xc0, 0x55, 0x1a, 0x13, 0x56, 0x0e, 0xf4, 0xa4, 0x85, 0xfd, 0x4c, 0x47, + 0x10, 0x0d, 0x70, 0x24, 0x9b, 0xfa, 0x45, 0x41, 0x3a, 0x33, 0xea, 0x28, 0x60, 0x00, 0x80, 0x00, + 0xbc, 0x00, 0x80, 0x7b, 0x2e, 0x43, 0x10, 0x0b, 0x00, 0xec, 0x1e, 0x98, 0x8a, 0xb4, 0x26, 0xac, + 0x5f, 0xf9, 0x20, 0x03, 0xf2, 0xc1, 0xdf, 0xca, 0x14, 0x40, 0x07, 0x40, 0x1e, 0x00, 0x3d, 0x10, + 0xe1, 0x37, 0x90, 0x64, 0x17, 0xec, 0x3d, 0x4c, 0xf5, 0x94, 0x20, 0x15, 0x80, 0xdc, 0x3e, 0x74, + 0x7f, 0x87, 0x87, 0xa9, 0xa6, 0x33, 0x56, 0x16, 0xfd, 0xcf, 0xa9, 0x1f, 0x12, 0x23, 0x35, 0x60, + 0xaf, 0xa4, 0x04, 0xf5, 0xb0, 0x1f, 0xe4, 0x3d, 0x75, 0x1c, 0x20, 0xeb, 0xd7, 0x19, 0x00, 0xb8, + 0x04, 0x21, 0x7a, 0xd3, 0xbe, 0x15, 0xeb, 0x4a, 0xf1, 0x84, 0x78, 0x52, 0x3e, 0x25, 0x03, 0x16, + 0x81, 0xc3, 0x7d, 0x59, 0x1f, 0x12, 0x30, 0x50, 0xe3, 0xe1, 0xcf, 0xc5, 0x8f, 0xa1, 0x1c, 0x0e, + 0x9e, 0xd0, 0x0d, 0x7b, 0x18, 0x14, 0xcc, 0x21, 0x04, 0x1b, 0x6a, 0x8c, 0xd5, 0x86, 0xe0, 0x31, + 0x9a, 0xb0, 0x4f, 0xc8, 0x0b, 0x7c, 0x40, 0x37, 0xc4, 0x5c, 0x22, 0x80, 0x3e, 0x54, 0x71, 0x10, + 0xbf, 0x26, 0xf9, 0xa2, 0x1c, 0x0b, 0x82, 0xf0, 0x8f, 0x22, 0x47, 0x8a, 0xab, 0xca, 0xd4, 0x31, + 0x08, 0xf1, 0xe6, 0x51, 0x9a, 0xb7, 0xcc, 0x80, 0x7f, 0xc9, 0xc2, 0x13, 0x08, 0xfd, 0x95, 0xfe, + 0x23, 0xc0, 0x14, 0x0f, 0x08, 0xe1, 0xb5, 0x5f, 0x4a, 0x38, 0x10, 0x47, 0x1b, 0x17, 0x0a, 0x07, + 0x1d, 0x38, 0xe3, 0xcb, 0x42, 0x10, 0x4f, 0x5d, 0x40, 0x3f, 0xf8, 0xe1, 0x0a, 0xe0, 0x45, 0xa8, + 0x47, 0xe0, 0x78, 0x23, 0x0f, 0x91, 0x5f, 0x4a, 0x7f, 0xe3, 0xc9, 0x11, 0xe0, 0x4a, 0x09, 0xfe, + 0x5a, 0xf0, 0xea, 0x8f, 0x21, 0x57, 0x82, 0xa3, 0xfa, 0x47, 0xc4, 0x8e, 0x0d, 0x8f, 0xcc, 0xfe, + 0x11, 0xf1, 0x22, 0x33, 0x56, 0xe1, 0xf9, 0x1f, 0x9a, 0x83, 0x79, 0x2d, 0xe3, 0xf5, 0x23, 0xf6, + 0x50, 0x64, 0x17, 0xce, 0x4f, 0x12, 0x58, 0x5f, 0xe0, 0xc4, 0x32, 0x0d, 0xfc, 0xab, 0xd5, 0x54, + 0x15, 0x04, 0xfd, 0x91, 0xf1, 0x20, 0x32, 0x0d, 0xe1, 0x48, 0xf8, 0x91, 0xe5, 0x48, 0x09, 0xfc, + 0xdb, 0x7b, 0xab, 0x84, 0x22, 0x0d, 0xfd, 0x23, 0xda, 0xd1, 0xf2, 0x20, 0x2a, 0x11, 0xfe, 0x23, + 0xe7, 0x4f, 0x8c, 0x2f, 0x80, 0xe7, 0x1f, 0x09, 0x40, 0x2f, 0x00, 0xee, 0x7f, 0xf5, 0x1f, 0x12, + 0x3c, 0x0d, 0x40, 0xff, 0xa9, 0xc3, 0x1b, 0x01, 0x42, 0xce, 0x18, 0x5b, 0x52, 0xd9, 0x8a, 0x79, + 0xa7, 0xbc, 0xc5, 0x01, 0x08, 0x41, 0x21, 0xb5, 0xfc, 0x1b, 0x93, 0x1e, 0x8f, 0x60, 0x02, 0x98, + 0xf8, 0xe0, 0x0c, 0x1c, 0x2e, 0x15, 0x00, 0xe7, 0x61, 0x08, 0x02, 0xfd, 0x16, 0x5c, 0xdb, 0xf2, + 0xb8, 0x4f, 0x03, 0xfd, 0x81, 0x8a, 0x88, 0x52, 0x05, 0x20, 0x0e, 0xe9, 0xf9, 0xaa, 0xed, 0x7f, + 0xbf, 0xd0, 0x0b, 0x0b, 0x42, 0x60, 0x85, 0xa1, 0x3f, 0x0a, 0x0b, 0x42, 0x40, 0x08, 0xa8, 0x02, + 0x04, 0xa9, 0x60, 0x46, 0x00, 0x45, 0x40, 0x5c, 0xa7, 0xa6, 0xfa, 0x5c, 0x07, 0xf0, 0xe0, 0xa4, + 0x0f, 0x94, 0xc4, 0x16, 0x82, 0x96, 0x82, 0x94, 0x83, 0x71, 0x76, 0x04, 0x94, 0x8f, 0xa1, 0xf3, + 0x40, 0x00, 0x93, 0x85, 0xa2, 0x50, 0xc0, 0x00, 0x28, 0x1c, 0xbb, 0x03, 0x09, 0x12, 0x5e, 0x91, + 0xaf, 0x21, 0x42, 0x05, 0x09, 0x6b, 0xe5, 0x59, 0x27, 0xcf, 0x8f, 0x88, 0x24, 0x00, 0x90, 0x7c, + 0x60, 0x00, 0x00, 0x17, 0x1a, 0x02, 0x40, 0x2c, 0x03, 0x94, 0x1a, 0xf8, 0x02, 0xa0, 0x80, 0xd2, + 0x15, 0xf5, 0x64, 0x00, 0xc0, 0x32, 0x01, 0x83, 0xa4, 0xc0, 0x5e, 0xb2, 0x0e, 0x70, 0x9a, 0x7b, + 0x12, 0x23, 0x35, 0x6f, 0x26, 0x43, 0x7f, 0x40, 0x6a, 0x04, 0xe8, 0x14, 0x04, 0xa4, 0xb3, 0x14, + 0x81, 0x30, 0x2f, 0x16, 0x84, 0xd0, 0x0c, 0x0b, 0x42, 0x6e, 0x14, 0x00, 0x9a, 0x00, 0x87, 0x76, + 0x80, 0x07, 0x98, 0x2c, 0x03, 0x99, 0x9c, 0xf3, 0xbb, 0x7f, 0xb8, 0xa4, 0xdb, 0xde, 0xfc, 0x4a, + 0x00, 0x05, 0xa4, 0xc2, 0x6a, 0xc0, 0xed, 0x3d, 0x15, 0xc1, 0x04, 0xe1, 0x30, 0x2e, 0x2c, 0xf1, + 0x50, 0x69, 0x84, 0xa9, 0x0f, 0xf8, 0xc2, 0xbe, 0x35, 0xa8, 0x87, 0x50, 0x10, 0x0e, 0x00, 0xe5, + 0x1e, 0xc6, 0xa9, 0x55, 0xfe, 0xff, 0x48, 0xf5, 0xe0, 0x53, 0xdc, 0x78, 0x80, 0x10, 0x51, 0x89, + 0x52, 0xc0, 0x06, 0xab, 0x03, 0x14, 0x6f, 0xed, 0x85, 0xde, 0x80, 0x03, 0x09, 0x52, 0xe5, 0xff, + 0x5e, 0x02, 0xbf, 0x8f, 0x8f, 0xc9, 0xcf, 0xe5, 0xeb, 0xf3, 0x72, 0xbb, 0x80, 0x00, 0xc6, 0x6a, + 0xd8, 0x08, 0x95, 0xf4, 0xb2, 0xf9, 0x4f, 0xa1, 0xc1, 0xc2, 0x5a, 0xef, 0xf7, 0xfa, 0x81, 0xdd, + 0xbd, 0xef, 0xee, 0xe0, 0xd1, 0xe5, 0x72, 0xc5, 0xcd, 0xf0, 0x2c, 0x00, 0x03, 0xcb, 0x98, 0xf0, + 0x7f, 0x52, 0x00 +}; + +static BYTE TEST_RDP5_UNCOMPRESSED_DATA[] = +{ + 0x24, 0x02, 0x03, 0x09, 0x00, 0x20, 0x0c, 0x05, 0x10, 0x01, 0x40, 0x0a, 0xff, 0xff, 0x0c, 0x84, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x0d, 0x38, 0x01, 0xc0, 0x10, 0x01, 0x10, + 0x01, 0xcc, 0xff, 0x7f, 0x03, 0x08, 0x00, 0x20, 0x04, 0x05, 0x10, 0x01, 0x40, 0x0a, 0x00, 0x0c, + 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x01, 0x00, 0x00, 0x0d, 0x0a, + 0x0c, 0x0c, 0xff, 0x03, 0xff, 0x02, 0x00, 0x04, 0x00, 0x03, 0x06, 0x00, 0x00, 0x80, 0x00, 0x80, + 0x00, 0x02, 0x00, 0x00, 0x09, 0x00, 0x0c, 0x80, 0x00, 0x80, 0x00, 0x06, 0x00, 0x00, 0x48, 0x00, + 0x37, 0x01, 0x02, 0x00, 0x00, 0x01, 0x0c, 0x48, 0x00, 0x37, 0x01, 0x06, 0x01, 0x00, 0x00, 0x04, + 0x24, 0x00, 0x02, 0x01, 0x00, 0x01, 0x0c, 0x00, 0x04, 0x24, 0x00, 0x02, 0x00, 0x00, 0x09, 0x0a, + 0x3d, 0x0f, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, + 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, + 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, + 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x09, 0x18, 0xfb, 0x70, 0x06, 0x00, 0x03, + 0xff, 0xff, 0x00, 0x03, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x00, 0x80, 0x0c, 0x00, 0x0f, + 0x00, 0x01, 0x49, 0x08, 0x07, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x72, 0x00, 0x19, + 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0xff, 0xff, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, + 0xf3, 0xf2, 0x0c, 0x08, 0x42, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, + 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x10, 0x84, 0x11, + 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x3a, 0x01, 0x09, 0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01, + 0x11, 0x01, 0x01, 0x01, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, + 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, + 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, + 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, + 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, + 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, + 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, + 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, + 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11, + 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xdd, 0x0c, 0xf5, + 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, + 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, + 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, + 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x60, 0x00, 0x00, 0x00, 0xd0, 0x0e, 0xd0, 0x0e, 0x0e, 0x0b, + 0x01, 0x01, 0x43, 0x06, 0x02, 0xfc, 0xfc, 0x00, 0x00, 0x30, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, + 0xf5, 0x04, 0xff, 0xff, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0x08, + 0x42, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x99, 0xd6, 0x11, 0x0f, + 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x10, 0x84, 0x11, 0x0d, 0x01, 0x0b, 0xf6, + 0x11, 0x3a, 0x01, 0x09, 0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, + 0x01, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, + 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, + 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, + 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, + 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, + 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, + 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, + 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, + 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xdd, 0x0c, 0xf5, 0x04, 0x08, 0x42, 0x11, + 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, + 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, + 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, + 0x18, 0xf4, 0x60, 0x00, 0x00, 0x00, 0xd0, 0x0e, 0xd0, 0x0e, 0x0e, 0x13, 0x02, 0x00, 0x4a, 0x08, + 0x09, 0x3f, 0x3f, 0x21, 0xfd, 0xfd, 0x87, 0x84, 0x84, 0xfc, 0x00, 0x00, 0x00, 0x32, 0x00, 0x19, + 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0xff, 0xff, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, + 0xf3, 0xf2, 0x0c, 0x08, 0x42, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, + 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x10, 0x84, 0x11, + 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x3a, 0x01, 0x09, 0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01, + 0x11, 0x01, 0x01, 0x01, 0x02, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, + 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, + 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, + 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, + 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, + 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, + 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, + 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, + 0x0a, 0x01, 0x09, 0x19, 0x18, 0x54, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0x13, 0x03, 0x02, 0x4a, + 0x06, 0x09, 0x78, 0xcc, 0xcc, 0x18, 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x73, 0x00, + 0x19, 0x0a, 0x3f, 0xdd, 0x0c, 0xf5, 0x04, 0xff, 0xff, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, + 0x3e, 0xf3, 0xf2, 0x0c, 0x08, 0x42, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, + 0x0b, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x10, 0x84, + 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x3a, 0x01, 0x09, 0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0xd1, + 0x0f, 0xd1, 0x0f, 0x0f, 0x01, 0x03, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, + 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, + 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, + 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, + 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, + 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, + 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, + 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, + 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0x54, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0x1b, 0x04, 0x00, + 0x4a, 0x09, 0x09, 0xff, 0x80, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0xff, 0x80, 0x00, 0x00, 0x31, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, + 0xff, 0xff, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0x08, 0x42, 0x11, + 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0b, + 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x10, 0x84, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x3a, + 0x01, 0x09, 0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0x04, 0x19, + 0x0a, 0x3f, 0xdd, 0x0c, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, + 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, + 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, + 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0xcf, + 0x0d, 0xcf, 0x0d, 0x0d, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, + 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, + 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, + 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, + 0x20, 0xff, 0xff, 0x00, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xee, 0x34, 0x3c, 0x08, 0x2d, 0x09, 0x59, 0x0d, 0x97, + 0xff, 0x00, 0x02, 0x70, 0x0d, 0x0e, 0x51, 0xc2, 0x10, 0x20, 0x1c, 0x51, 0xc2, 0x12, 0xe0, 0xd6, + 0x51, 0xc2, 0x12, 0x30, 0x1c, 0x19, 0x0a, 0x32, 0x12, 0x10, 0x84, 0x59, 0x0d, 0xc6, 0xcc, 0x12, + 0xd0, 0xf2, 0x51, 0xc2, 0x10, 0x20, 0x1c, 0x51, 0xc2, 0x12, 0xe0, 0xd6, 0x51, 0xc2, 0x12, 0x30, + 0x1c, 0x19, 0x0a, 0x3f, 0x0a, 0x12, 0xb9, 0xf9, 0x08, 0x42, 0x11, 0x0f, 0xf6, 0x0a, 0x09, 0xf6, + 0x11, 0x3e, 0xf6, 0xf7, 0x09, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x08, 0xf7, 0x11, 0x3f, 0x08, 0x01, + 0xf8, 0x08, 0x10, 0x84, 0x11, 0x0f, 0xf8, 0x08, 0x07, 0xf8, 0x11, 0x3e, 0xf8, 0xf9, 0x07, 0x99, + 0xd6, 0x11, 0x0d, 0x01, 0x06, 0xf9, 0x11, 0x0a, 0x01, 0x06, 0x19, 0x18, 0xf5, 0x60, 0x05, 0x00, + 0x00, 0x00, 0xef, 0x5a, 0xec, 0x57, 0x57, 0x0f, 0x00, 0x00, 0x46, 0x06, 0x05, 0xcc, 0x78, 0x30, + 0x78, 0xcc, 0x00, 0x00, 0x00, 0x72, 0x00, 0x19, 0x0a, 0x3f, 0x13, 0xfe, 0xfa, 0x04, 0xff, 0xff, + 0x11, 0x0f, 0xf6, 0x0a, 0x09, 0xf6, 0x11, 0x3e, 0xf6, 0xf7, 0x09, 0x08, 0x42, 0x11, 0x0d, 0x01, + 0x08, 0xf7, 0x11, 0x3f, 0x08, 0x01, 0xf8, 0x08, 0x99, 0xd6, 0x11, 0x0f, 0xf8, 0x08, 0x07, 0xf8, + 0x11, 0x3e, 0xf8, 0xf9, 0x07, 0x10, 0x84, 0x11, 0x0d, 0x01, 0x06, 0xf9, 0x11, 0x3a, 0x01, 0x06, + 0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0x0c, 0x01, 0x0c, 0x01, 0x01, 0x01, 0x00, 0x19, 0x0a, 0x3f, + 0x13, 0xfe, 0xfa, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf6, 0x0a, 0x09, 0xf6, 0x11, 0x3e, 0xf6, 0xf7, + 0x09, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x08, 0xf7, 0x11, 0x3f, 0x08, 0x01, 0xf8, 0x08, 0x10, 0x84, + 0x11, 0x0f, 0xf8, 0x08, 0x07, 0xf8, 0x11, 0x3e, 0xf8, 0xf9, 0x07, 0x99, 0xd6, 0x11, 0x0d, 0x01, + 0x06, 0xf9, 0x11, 0x0a, 0x01, 0x06, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0a, 0xff, 0x0a, + 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x13, 0xfe, 0xfa, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf6, 0x0a, 0x09, + 0xf6, 0x11, 0x3e, 0xf6, 0xf7, 0x09, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x08, 0xf7, 0x11, 0x3f, 0x08, + 0x01, 0xf8, 0x08, 0x10, 0x84, 0x11, 0x0f, 0xf8, 0x08, 0x07, 0xf8, 0x11, 0x3e, 0xf8, 0xf9, 0x07, + 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x06, 0xf9, 0x11, 0x0a, 0x01, 0x06, 0x19, 0x18, 0xf4, 0x20, 0xff, + 0xff, 0x00, 0x0c, 0x01, 0x0c, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x19, 0x0a, 0x0f, 0x09, 0xfe, 0x09, 0x09, 0x19, 0x18, 0xf5, 0x60, 0x06, 0xff, 0xff, + 0x00, 0x09, 0xfe, 0x12, 0x07, 0x07, 0x23, 0x05, 0x03, 0x4d, 0x0d, 0x0d, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x88, 0x01, 0x10, 0x02, 0x20, 0x04, 0x40, 0x08, 0x88, + 0x11, 0x10, 0x22, 0x20, 0x44, 0x40, 0x00, 0x00, 0x6f, 0x00, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, + 0x1f, 0x06, 0x04, 0x4c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x60, 0x00, 0xc0, + 0x01, 0x90, 0x03, 0x30, 0x06, 0x60, 0x0c, 0xc0, 0x19, 0x90, 0x33, 0x30, 0x66, 0x60, 0x70, 0x00, + 0x19, 0x0a, 0x37, 0xe3, 0x10, 0xf1, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, + 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, + 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, + 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x60, 0x00, 0x00, + 0x00, 0xd6, 0x12, 0xd2, 0x0e, 0x0e, 0x0f, 0x07, 0x01, 0x48, 0x09, 0x04, 0x08, 0x00, 0x1c, 0x00, + 0x3e, 0x00, 0x7f, 0x00, 0x35, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x10, 0x84, 0x11, + 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x0e, 0xf1, 0xf2, 0x0e, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, + 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x0e, 0xf3, + 0xf4, 0x0c, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x0a, 0x01, 0x0b, 0x19, 0x18, 0xf0, 0x60, 0x11, + 0x01, 0x11, 0x01, 0x01, 0x01, 0x07, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, + 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, + 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, + 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, + 0xd6, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, + 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, + 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, + 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, + 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x11, + 0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, + 0x0a, 0x3f, 0xdd, 0x0e, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, + 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, + 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, + 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x60, 0x00, 0x00, + 0x00, 0xd0, 0x10, 0xd0, 0x10, 0x10, 0x0f, 0x08, 0x01, 0x48, 0x09, 0x04, 0x7f, 0x00, 0x3e, 0x00, + 0x1c, 0x00, 0x08, 0x00, 0x36, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x10, 0x84, 0x11, + 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x0e, 0xf1, 0xf2, 0x0e, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, + 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x0e, 0xf3, + 0xf4, 0x0c, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x0a, 0x01, 0x0b, 0x19, 0x18, 0xf0, 0x60, 0x11, + 0x01, 0x11, 0x01, 0x01, 0x01, 0x08, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, + 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, + 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, + 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, + 0xd6, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, + 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, + 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, + 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, + 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x11, + 0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, + 0x0a, 0x3f, 0xdd, 0x0e, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, + 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, + 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, + 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x60, 0x00, 0x00, + 0x00, 0xd0, 0x10, 0xd0, 0x10, 0x10, 0x13, 0x09, 0x04, 0x4b, 0x04, 0x09, 0x00, 0x80, 0xc0, 0xe0, + 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, + 0x04, 0x10, 0x84, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x0e, 0xf1, 0xf2, 0x0e, 0x11, 0x0d, + 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, + 0xf3, 0x11, 0x0e, 0xf3, 0xf4, 0x0c, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x0a, 0x01, 0x0b, 0x19, + 0x18, 0xf0, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0x09, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, + 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, + 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, + 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, + 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, + 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, + 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, + 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, + 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20, + 0xff, 0xff, 0x00, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xdd, 0x0e, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, + 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, + 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, + 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, + 0xf4, 0x60, 0x00, 0x00, 0x00, 0xd0, 0x10, 0xd0, 0x10, 0x10, 0x13, 0x0a, 0x03, 0x4b, 0x04, 0x09, + 0x00, 0x10, 0x30, 0x70, 0xf0, 0x70, 0x30, 0x10, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x19, 0x0a, + 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x10, 0x84, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x0e, 0xf1, + 0xf2, 0x0e, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x99, 0xd6, 0x11, + 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x0e, 0xf3, 0xf4, 0x0c, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, + 0x0a, 0x01, 0x0b, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0x0a, 0x19, 0x0a, + 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, + 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, + 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, + 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, + 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, + 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, + 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, + 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, + 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, + 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xce, 0x0e, 0x01, 0x01, 0xff, 0xff, + 0x1d, 0x18, 0xf4, 0x60, 0x0e, 0xe2, 0x00, 0x0b, 0x00, 0xee, 0x00, 0x00, 0x00, 0x00, 0xcd, 0x0e, + 0xce, 0x0f, 0x0f, 0x13, 0x0b, 0x04, 0x4b, 0x04, 0x09, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xe0, 0xc0, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x19, 0x0a, 0x01, 0x0d, 0x19, 0x18, 0x50, 0x40, 0x0d, + 0x0d, 0x0f, 0x0c, 0x03, 0x4a, 0x07, 0x08, 0x00, 0x02, 0x06, 0x8e, 0xdc, 0xf8, 0x70, 0x20, 0x61, + 0x00, 0x19, 0x0a, 0x01, 0x0d, 0x19, 0x18, 0x50, 0x40, 0x0d, 0x0d, 0x0f, 0x0d, 0x04, 0x4a, 0x06, + 0x06, 0x78, 0xfc, 0xfc, 0xfc, 0xfc, 0x78, 0x00, 0x00, 0x68, 0x00, 0x19, 0x0a, 0x3d, 0x0d, 0x02, + 0x02, 0x99, 0xd6, 0x19, 0x18, 0xd0, 0x60, 0x0e, 0x10, 0x02, 0x02, 0x13, 0x0e, 0x02, 0x4a, 0x0b, + 0x05, 0x04, 0x00, 0x0e, 0x00, 0x1f, 0x00, 0x3f, 0x80, 0x7f, 0xc0, 0x00, 0x00, 0x35, 0x00, 0x19, + 0x0a, 0x01, 0x0f, 0x19, 0x18, 0x54, 0x40, 0x10, 0x00, 0x00, 0x0f, 0x0f, 0x01, 0x0e, 0x19, 0x0a, + 0x03, 0xca, 0x0f, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0xcb, 0x10, 0xcb, 0x10, 0x10, 0x11, + 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x01, 0x0f, 0x19, 0x18, + 0x54, 0x40, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x13, 0x0f, 0x02, 0x4a, 0x0b, 0x05, 0x7f, 0xc0, 0x3f, + 0x80, 0x1f, 0x00, 0x0e, 0x00, 0x04, 0x00, 0x00, 0x00, 0x36, 0x00, 0x19, 0x0a, 0x01, 0x0f, 0x19, + 0x18, 0x54, 0x40, 0x10, 0x00, 0x00, 0x0f, 0x0f, 0x01, 0x0f, 0x19, 0x0a, 0x01, 0x0f, 0x19, 0x18, + 0xf4, 0x20, 0xff, 0xff, 0x00, 0x10, 0x01, 0x10, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xd3, 0x0f, 0xfe, 0xfe, 0xff, 0xff, 0x19, 0x18, + 0xf4, 0x60, 0x00, 0x00, 0x00, 0xd3, 0x0f, 0xd1, 0x0d, 0x0d, 0x1b, 0x10, 0x02, 0x4c, 0x0a, 0x0a, + 0x1e, 0x00, 0x7f, 0x80, 0x7f, 0x80, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0x7f, 0x80, + 0x7f, 0x80, 0x1e, 0x00, 0x6e, 0x00, 0x11, 0x00, 0x40, 0x17, 0x11, 0x03, 0x4a, 0x09, 0x08, 0x01, + 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0xc3, 0x00, 0x3c, 0x00, 0x6d, + 0x00, 0x11, 0x00, 0x40, 0x17, 0x12, 0x02, 0x4c, 0x09, 0x08, 0x1e, 0x00, 0x61, 0x80, 0x40, 0x00, + 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x6c, 0x00, 0x11, 0x00, 0x40, 0x1b, + 0x13, 0x03, 0x4b, 0x0a, 0x0a, 0x00, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, + 0x40, 0x00, 0x80, 0x00, 0x80, 0xc3, 0x00, 0x3c, 0x00, 0x6b, 0x00, 0x11, 0x00, 0x40, 0x1b, 0x14, + 0x01, 0x4d, 0x0a, 0x0a, 0x0f, 0x00, 0x30, 0xc0, 0x40, 0x00, 0x40, 0x00, 0x80, 0x00, 0x80, 0x00, + 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x6a, 0x00, 0x11, 0x54, 0x40, 0xff, 0xff, 0x00, + 0x0d, 0x0d, 0x1b, 0x15, 0x02, 0x4b, 0x09, 0x09, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, + 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0x00, 0x00, 0x67, 0x00, 0x11, 0x04, + 0x40, 0x99, 0xd6, 0x00, 0x1f, 0x16, 0x01, 0x4c, 0x0b, 0x0b, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, + 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0xff, 0xe0, + 0x00, 0x00, 0x66, 0x00, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x1b, 0x17, 0x01, 0x4c, 0x0a, 0x0a, + 0xff, 0xc0, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, + 0x80, 0x00, 0x80, 0x00, 0x65, 0x00, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x23, 0x18, 0x00, 0x4d, + 0x0d, 0x0d, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, + 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0xff, 0xf8, 0x00, 0x00, 0x64, 0x00, + 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x1f, 0x19, 0x00, 0x4d, 0x0c, 0x0c, 0xff, 0xf0, 0x80, 0x00, + 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, + 0x80, 0x00, 0x80, 0x00, 0x63, 0x00, 0x11, 0x54, 0x40, 0xff, 0xff, 0x00, 0x0d, 0x0d, 0x01, 0x15, + 0x11, 0x04, 0x40, 0x99, 0xd6, 0x00, 0x01, 0x16, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x17, + 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x19, + 0x11, 0x04, 0x40, 0x00, 0x00, 0x00, 0x0f, 0x1a, 0x03, 0x4b, 0x07, 0x08, 0x00, 0x02, 0x06, 0x8e, + 0xdc, 0xf8, 0x70, 0x20, 0x62, 0x00, 0x11, 0x54, 0x40, 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x15, + 0x11, 0x00, 0x40, 0x01, 0x16, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x17, 0x11, 0x04, 0x40, + 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x19, 0x11, 0x54, 0x40, + 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x15, 0x11, 0x00, 0x40, 0x01, 0x16, 0x11, 0x04, 0x40, 0x08, + 0x42, 0x00, 0x01, 0x17, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04, 0x40, 0x10, + 0x84, 0x00, 0x01, 0x19, 0x11, 0x04, 0x40, 0x00, 0x00, 0x00, 0x01, 0x1a, 0x11, 0xf4, 0x60, 0x99, + 0xd6, 0x00, 0xcc, 0x0d, 0xcc, 0x0d, 0x0d, 0x01, 0x15, 0x11, 0x00, 0x40, 0x01, 0x16, 0x11, 0x04, + 0x40, 0x08, 0x42, 0x00, 0x01, 0x17, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04, + 0x40, 0x10, 0x84, 0x00, 0x01, 0x19, 0x11, 0x00, 0x40, 0x01, 0x1a, 0x19, 0x0a, 0x33, 0x0d, 0x0d, + 0x00, 0x00, 0x19, 0x18, 0x54, 0x40, 0xff, 0xff, 0x00, 0x0d, 0x0d, 0x01, 0x10, 0x11, 0x04, 0x40, + 0x99, 0xd6, 0x00, 0x01, 0x11, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x12, 0x11, 0x04, 0x40, + 0xff, 0xff, 0x00, 0x01, 0x13, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x14, 0x19, 0x0a, 0x01, + 0x0d, 0x19, 0x18, 0x54, 0x40, 0xff, 0xff, 0x00, 0x0d, 0x0d, 0x01, 0x10, 0x11, 0x04, 0x40, 0x99, + 0xd6, 0x00, 0x01, 0x11, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x12, 0x11, 0x04, 0x40, 0xff, + 0xff, 0x00, 0x01, 0x13, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x14, 0x11, 0x04, 0x40, 0x00, + 0x00, 0x00, 0x0b, 0x1b, 0x05, 0x49, 0x04, 0x04, 0x60, 0xf0, 0xf0, 0x60, 0x69, 0x00, 0x19, 0x0a, + 0x01, 0x0d, 0x19, 0x18, 0x54, 0x40, 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x10, 0x11, 0x00, 0x40, + 0x01, 0x11, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x12, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, + 0x01, 0x13, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x14, 0x19, 0x0a, 0x01, 0x0d, 0x19, 0x18, + 0x54, 0x40, 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x10, 0x11, 0x00, 0x40, 0x01, 0x11, 0x11, 0x04, + 0x40, 0x08, 0x42, 0x00, 0x01, 0x12, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x13, 0x11, 0x04, + 0x40, 0x10, 0x84, 0x00, 0x01, 0x14, 0x11, 0x04, 0x40, 0x00, 0x00, 0x00, 0x01, 0x1b, 0x19, 0x0a, + 0x03, 0xcc, 0x0d, 0x19, 0x18, 0xf4, 0x60, 0x99, 0xd6, 0x00, 0xcc, 0x0d, 0xcc, 0x0d, 0x0d, 0x01, + 0x10, 0x11, 0x00, 0x40, 0x01, 0x11, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x12, 0x11, 0x04, + 0x40, 0xff, 0xff, 0x00, 0x01, 0x13, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x14, 0x11, 0x00, + 0x40, 0x01, 0x1b, 0x03, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x08, 0x08, 0x81, 0x08, 0xaa, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0x09, 0x01, 0x7f, 0x02, 0x0d, 0x00, 0x1a, 0x01, 0x0d, + 0x00, 0x0d, 0x00, 0xf0, 0xff, 0xff, 0x00, 0x99, 0xd6, 0x00, 0x81, 0x19, 0x18, 0x54, 0x40, 0x99, + 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x16, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x17, 0x11, 0x04, + 0x40, 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x19, 0x11, 0x00, + 0x40, 0x01, 0x1a, 0x11, 0x54, 0x40, 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x15, 0x11, 0x00, 0x40, + 0x01, 0x16, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x17, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, + 0x01, 0x18, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x19, 0x11, 0x00, 0x40, 0x01, 0x1a, 0x11, + 0x54, 0x40, 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x15, 0x11, 0x00, 0x40, 0x01, 0x16, 0x11, 0x04, + 0x40, 0x08, 0x42, 0x00, 0x01, 0x17, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04, + 0x40, 0x10, 0x84, 0x00, 0x01, 0x19, 0x11, 0x00, 0x40, 0x01, 0x1a, 0x19, 0x0a, 0x31, 0x34, 0xff, + 0xff, 0x19, 0x18, 0x54, 0x40, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x1b, 0x1c, 0x02, 0x4b, 0x09, 0x09, + 0xc1, 0x80, 0xe3, 0x80, 0x77, 0x00, 0x3e, 0x00, 0x1c, 0x00, 0x3e, 0x00, 0x77, 0x00, 0xe3, 0x80, + 0xc1, 0x80, 0x00, 0x00, 0x72, 0x00, 0x19, 0x0a, 0x03, 0xcc, 0x0d, 0x1d, 0x18, 0xf0, 0x60, 0xa0, + 0x45, 0x45, 0xcc, 0x0d, 0xcc, 0x0d, 0x0d, 0x1b, 0x1d, 0x01, 0x4b, 0x0a, 0x09, 0x3f, 0xc0, 0x3f, + 0xc0, 0x20, 0x40, 0xff, 0x40, 0xff, 0x40, 0x81, 0xc0, 0x81, 0x00, 0x81, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x32, 0x00, 0x19, 0x0a, 0x01, 0x0d, 0x19, 0x18, 0x50, 0x40, 0x0d, 0x0d, 0x1b, 0x1e, 0x01, + 0x4c, 0x0a, 0x0a, 0xff, 0xc0, 0xff, 0xc0, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, + 0x40, 0x80, 0x40, 0x80, 0x40, 0xff, 0xc0, 0x31, 0x00, 0x19, 0x0a, 0x01, 0x0d, 0x19, 0x18, 0x50, + 0x40, 0x0d, 0x0d, 0x0b, 0x1f, 0x02, 0x44, 0x07, 0x02, 0xfe, 0xfe, 0x00, 0x00, 0x30, 0x00, 0x19, + 0x0a, 0x3d, 0x0d, 0x03, 0x03, 0x99, 0xd6, 0x19, 0x18, 0xd4, 0x60, 0xff, 0xff, 0x00, 0x0e, 0x11, + 0x03, 0x03, 0x23, 0x20, 0x00, 0x4d, 0x0d, 0x0d, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, + 0x10, 0x00, 0x88, 0x00, 0x44, 0x00, 0x22, 0x00, 0x11, 0x00, 0x88, 0x80, 0x44, 0x40, 0x22, 0x20, + 0x11, 0x10, 0x00, 0x00, 0x78, 0x00, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x1f, 0x21, 0x00, 0x4c, + 0x0c, 0x0c, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x98, 0x00, 0xcc, 0x00, + 0x66, 0x00, 0x33, 0x00, 0x99, 0x80, 0xcc, 0xc0, 0x66, 0x60, 0x79, 0x00, 0x19, 0x0a, 0x3d, 0x10, + 0xfd, 0xfd, 0xff, 0xff, 0x19, 0x18, 0xd4, 0x60, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0xfd, 0xfd, 0x13, + 0x22, 0x05, 0x4b, 0x04, 0x09, 0x00, 0x10, 0x30, 0x70, 0xf0, 0x70, 0x30, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x77, 0x00, 0x02, 0xff, 0xff, 0x0d, 0x0a, 0x3f, 0x0e, 0x00, 0x00, 0xff, 0x03, 0xff, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x48, 0x00, 0x37, + 0x01, 0x02, 0x02, 0x00, 0x09, 0x00, 0x0c, 0x48, 0x00, 0x37, 0x01, 0x03, 0xcf, 0x04, 0xa2, 0x0c, + 0x05, 0x40, 0x44, 0xd1, 0xff, 0xff, 0x80, 0x00, 0xff, 0xff, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, + 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, + 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84, 0x08, 0x42, 0xff, 0xff, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84, + 0xff, 0xff, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84, + 0xff, 0xff, 0x99, 0xd6, 0x10, 0x84, 0x08, 0x42, 0x1c, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x75, 0xc6, 0x66, 0x29, 0x00, 0x09, 0x68, 0x10, 0x00, 0x08, 0x68, 0x10, 0x84, + 0x00, 0x20, 0x00, 0x07, 0x6b, 0x99, 0xd6, 0x05, 0x6b, 0x99, 0xd6, 0x00, 0x03, 0x6e, 0xff, 0xff, + 0x02, 0x6e, 0xff, 0xff, 0x00, 0x10, 0xc0, 0x00, 0xf7, 0xbd, 0x01, 0xc0, 0x00, 0x08, 0x42, 0xc0, + 0x00, 0xff, 0xff, 0x81, 0x08, 0x42, 0xce, 0x66, 0x29, 0x01, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd, + 0x2e, 0x01, 0x81, 0x08, 0x42, 0xce, 0x66, 0x29, 0x02, 0x81, 0x10, 0x84, 0x06, 0x82, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xcd, 0x89, 0x52, 0x03, 0x2d, 0x03, 0x83, 0x10, 0x84, 0x99, 0xd6, 0x99, 0xd6, + 0xc9, 0x99, 0xd6, 0x1a, 0x82, 0x10, 0x00, 0x10, 0x00, 0x0a, 0x29, 0x09, 0x27, 0x0c, 0x67, 0x99, + 0xd6, 0x15, 0x27, 0x1d, 0x82, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x67, 0x99, 0xd6, 0x00, 0x19, 0xd0, + 0x30, 0x89, 0xd6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x99, 0xd6, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x83, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xd8, 0x89, + 0xd6, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x83, 0x99, 0xd6, 0x10, 0x00, 0x10, + 0x00, 0x1a, 0x68, 0x00, 0x00, 0x09, 0x86, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x99, 0xd6, 0x18, 0x68, 0x00, 0x00, 0x1b, 0x68, 0x99, 0xd6, 0x06, 0x86, 0x99, 0xd6, 0x10, + 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x19, 0x6b, 0x99, 0xd6, 0x03, 0xcc, 0x89, + 0x52, 0x08, 0x68, 0x99, 0xd6, 0x05, 0x6b, 0x99, 0xd6, 0x04, 0x2c, 0x03, 0x6e, 0x08, 0x42, 0x02, + 0x6e, 0xff, 0xff, 0x02, 0x6e, 0xff, 0xff, 0x02, 0x6e, 0x08, 0x42, 0x10, 0x81, 0x08, 0x42, 0x70, + 0xff, 0xff, 0x60, 0x00, 0x08, 0x42, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0x81, 0x08, 0x42, 0xce, 0x66, + 0x29, 0x01, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd, 0x2e, 0x02, 0xcd, 0x89, 0x52, 0x03, 0x89, 0x10, + 0x84, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x2d, 0x03, 0x2d, 0x05, 0xc6, 0x99, 0xd6, 0x0c, 0x84, 0x99, 0xd6, 0x99, 0xd6, 0x99, + 0xd6, 0x99, 0xd6, 0x0a, 0xc6, 0x89, 0xd6, 0x0e, 0x82, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x84, 0x99, + 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x1c, 0x40, 0x35, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xd0, 0x4e, 0x99, 0xd6, 0x03, 0x00, 0x00, 0x60, 0x00, 0x80, 0x01, 0x78, 0x01, 0x00, 0x82, + 0x10, 0x00, 0x10, 0x00, 0x0c, 0x40, 0x2c, 0x03, 0xe0, 0x05, 0x00, 0x00, 0x00, 0xd6, 0x89, 0xd6, + 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x4e, 0x99, 0xd6, 0x3b, 0x00, 0x00, 0x00, 0x28, 0x80, + 0x1d, 0x00, 0x78, 0x00, 0x86, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99, + 0xd6, 0x0c, 0x85, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x40, 0x2b, 0x01, + 0xf0, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x89, 0xd6, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x99, + 0xd6, 0x16, 0x86, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x0a, + 0x69, 0x99, 0xd6, 0x04, 0xcc, 0x89, 0x52, 0x07, 0x69, 0x99, 0xd6, 0x08, 0x68, 0x99, 0xd6, 0x03, + 0x6e, 0xff, 0xff, 0x02, 0x6e, 0x08, 0x42, 0x02, 0x6e, 0xff, 0xff, 0x02, 0x6e, 0xff, 0xff, 0x01, + 0x70, 0x08, 0x42, 0x70, 0xff, 0xff, 0x60, 0x00, 0x08, 0x42, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0x81, + 0x08, 0x42, 0xce, 0x66, 0x29, 0x01, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd, 0x2e, 0x02, 0xcd, 0x89, + 0x52, 0x03, 0x8a, 0x10, 0x84, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x2d, 0x03, 0x8d, 0x99, 0xd6, 0x99, 0xd6, 0x99, + 0xd6, 0x99, 0xd6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x99, + 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x06, 0xc6, 0x99, 0xd6, 0x1a, 0xc6, 0x89, 0xd6, 0x0a, 0x66, 0x10, + 0x84, 0x1b, 0x6a, 0x99, 0xd6, 0x1b, 0x81, 0x99, 0xd6, 0x09, 0x6a, 0x99, 0xd6, 0x16, 0x6a, 0x99, + 0xd6, 0x06, 0x6a, 0x99, 0xd6, 0xf0, 0x94, 0x01, 0xcc, 0x89, 0x52, 0x00, 0x03, 0x6e, 0xff, 0xff, + 0x02, 0x6e, 0x08, 0x42, 0x02, 0x6e, 0xff, 0xff, 0x02, 0x6e, 0xff, 0xff, 0x01, 0x70, 0x08, 0x42, + 0x70, 0xff, 0xff, 0x60, 0x00, 0x08, 0x42, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0x81, 0x08, 0x42, 0xce, + 0x66, 0x29, 0x01, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd, 0x2e, 0x02, 0xcd, 0x89, 0x52, 0x03, 0x10, + 0x2d, 0x03, 0x2d, 0x17, 0x88, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, + 0xd6, 0x00, 0x00, 0x00, 0x00, 0x18, 0x88, 0xff, 0xff, 0xff, 0xff, 0x99, 0xd6, 0x99, 0xd6, 0x99, + 0xd6, 0x99, 0xd6, 0xff, 0xff, 0xff, 0xff, 0x07, 0x88, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, + 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x09, 0x88, 0x99, 0xd6, 0x00, 0x00, 0x00, + 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x07, 0x88, 0x10, 0x00, 0x10, + 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, 0x10, 0x00, 0x08, 0x89, 0x10, + 0x84, 0x10, 0x84, 0xff, 0xff, 0xff, 0xff, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84, 0x10, 0x84, 0x99, + 0xd6, 0x07, 0x88, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, + 0x00, 0x99, 0xd6, 0x0a, 0x86, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, + 0xd6, 0x08, 0x88, 0x99, 0xd6, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, 0x10, + 0x00, 0x99, 0xd6, 0x08, 0x88, 0x99, 0xd6, 0x10, 0x84, 0x10, 0x84, 0xff, 0xff, 0xff, 0xff, 0x10, + 0x84, 0x10, 0x84, 0x99, 0xd6, 0x09, 0x86, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x99, 0xd6, 0x0c, 0x84, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x0a, 0x86, 0x99, + 0xd6, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x0a, 0x86, 0x99, 0xd6, 0x10, + 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x99, 0xd6, 0x0b, 0x84, 0x99, 0xd6, 0x00, 0x00, 0x00, + 0x00, 0x99, 0xd6, 0x0d, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x84, 0x99, + 0xd6, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x0c, 0x85, 0x99, 0xd6, 0x10, 0x84, 0x10, 0x84, 0xff, + 0xff, 0xff, 0xff, 0x0b, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x86, 0x00, + 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x84, 0x10, 0x00, 0x10, + 0x00, 0x10, 0x00, 0x10, 0x00, 0x0c, 0x86, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0xff, + 0xff, 0xff, 0xff, 0x09, 0x86, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, + 0x00, 0x0a, 0x88, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x86, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, 0x10, + 0x00, 0x0a, 0x88, 0x10, 0x84, 0x10, 0x84, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84, 0x10, 0x84, 0xff, + 0xff, 0xff, 0xff, 0x07, 0x88, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, + 0xd6, 0x00, 0x00, 0x00, 0x00, 0x09, 0x6a, 0x99, 0xd6, 0x05, 0x88, 0x10, 0x00, 0x10, 0x00, 0x99, + 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, 0x10, 0x00, 0x08, 0x89, 0x10, 0x84, 0x10, + 0x84, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84, 0x10, 0x84, 0x99, 0xd6, 0x07, + 0x6a, 0x99, 0xd6, 0x16, 0x6a, 0x99, 0xd6, 0x06, 0x6a, 0x99, 0xd6, 0x14, 0x2c, 0x00, 0x03, 0x6e, + 0xff, 0xff, 0x02, 0x6e, 0x08, 0x42, 0x02, 0x6e, 0xff, 0xff, 0x02, 0xcb, 0x66, 0x29, 0x84, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x42, 0x09, 0x0d, 0xdf, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x03, 0x15, 0x00, 0xa2, 0x0c, + 0x05, 0x40, 0x40, 0x17, 0xff, 0xff, 0x00, 0x1c, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0xbc, 0x0f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x0a, 0x40, + 0xc8, 0x03, 0xf4, 0x00, 0xa2, 0x0c, 0x05, 0x40, 0x40, 0xf6, 0xff, 0xff, 0xc0, 0x2c, 0x2d, 0x09, + 0x84, 0x2d, 0x09, 0x2d, 0x09, 0x2d, 0x09, 0x2d, 0x09, 0x00, 0x22, 0xc0, 0x10, 0x25, 0x4b, 0x02, + 0x30, 0x02, 0x2a, 0x02, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd, 0x2e, 0x03, 0xfd, 0x2e, 0x03, 0xfd, + 0x29, 0x03, 0xcd, 0x89, 0x52, 0x03, 0x2d, 0x05, 0x2d, 0x05, 0x29, 0x06, 0xc6, 0x99, 0xd6, 0x09, + 0x29, 0x1f, 0x43, 0x03, 0x00, 0x00, 0x01, 0x27, 0x0b, 0x44, 0xc3, 0x00, 0x00, 0xc0, 0x68, 0x99, + 0xd6, 0x18, 0x48, 0xa5, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc2, 0x5a, 0x00, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0xa0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x81, 0x99, 0xd6, 0x48, 0x05, 0x80, 0x05, 0x00, 0x00, 0xfc, + 0x01, 0x50, 0x40, 0x69, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x80, 0x06, 0x00, + 0x00, 0x02, 0x6a, 0x99, 0xd6, 0x1c, 0x86, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x2d, + 0x09, 0x2d, 0x09, 0x6f, 0xff, 0xff, 0x02, 0x6e, 0xff, 0xff, 0x04, 0x6e, 0xff, 0xff, 0x04, 0xc9, + 0x66, 0x29, 0x02, 0x60, 0x5e, 0x2d, 0x09, 0xc0, 0x30, 0x2d, 0x09, 0xf0, 0xc0, 0x09, 0xc0, 0x10, + 0x08, 0x42, 0x00, 0x00, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd, 0x2e, 0x00, 0x02, 0xcd, 0x89, 0x52, + 0x03, 0x83, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0xc9, 0xef, 0x7b, 0x81, 0x99, 0xd6, 0x00, 0x05, + 0xc9, 0x89, 0xd6, 0x07, 0x69, 0x10, 0x84, 0x00, 0x08, 0x27, 0x09, 0x82, 0xff, 0xff, 0x99, 0xd6, + 0xd0, 0x69, 0x89, 0x52, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x51, 0x0e, 0xc0, 0x40, 0x38, 0x03, 0xa8, 0x00, 0xa2, 0x0c, 0x05, 0x40, 0x40, 0xaa, + 0xff, 0xff, 0xc8, 0x2d, 0x09, 0x00, 0x14, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0xc6, 0x25, 0x4b, 0x00, 0x1a, 0xd8, 0x18, 0xc6, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf7, 0xc0, 0x01, 0x89, 0x52, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, + 0x00, 0x01, 0x99, 0xd6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x3b, 0xef, + 0x7b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x2d, 0x09, 0x00, 0x58, 0xf3, 0x7c, + 0x0b, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x0a, 0x40, 0xc8, +}; + +int TestFreeRDPCodecMppc(int argc, char* argv[]) +{ + BOOL status; + UINT32 roff; + UINT32 rlen; + struct rdp_mppc_enc* enc; + struct rdp_mppc_dec* rmppc; + + /* Decompression */ + + rmppc = mppc_dec_new(); + + status = decompress_rdp_5(rmppc, TEST_RDP5_COMPRESSED_DATA, + sizeof(TEST_RDP5_COMPRESSED_DATA), PACKET_COMPRESSED, &roff, &rlen); + + if (!status) + { + printf("RDP5 decompression failure: %d\n", status); + return -1; + } + + if (memcmp(TEST_RDP5_UNCOMPRESSED_DATA, rmppc->history_buf, sizeof(TEST_RDP5_UNCOMPRESSED_DATA)) != 0) + { + printf("RDP5 decompression failure\n"); + return -1; + } + + mppc_dec_free(rmppc); + rmppc = mppc_dec_new(); + + /* Compression */ + + enc = mppc_enc_new(PROTO_RDP_50); + + status = compress_rdp(enc, TEST_RDP5_UNCOMPRESSED_DATA, sizeof(TEST_RDP5_UNCOMPRESSED_DATA)); + + if (!status) + { + printf("RDP5 decompression failure: %d\n", status); + return -1; + } + + if (enc->flags & PACKET_COMPRESSED) + { + status = decompress_rdp_5(rmppc, (BYTE*) enc->outputBuffer, + enc->bytes_in_opb, enc->flags, &roff, &rlen); + + if (!status) + { + printf("RDP5 compression/decompression failure: %d\n", status); + return -1; + } + + if (rlen != sizeof(TEST_RDP5_UNCOMPRESSED_DATA)) + { + printf("RDP5 compression/decompression failure: size mismatch: Actual: %d, Expected: %d\n", + rlen, sizeof(TEST_RDP5_UNCOMPRESSED_DATA)); + return -1; + } + + if (memcmp(TEST_RDP5_UNCOMPRESSED_DATA, &rmppc->history_buf[roff], rlen) != 0) + { + printf("RDP5 compression/decompression failure\n"); + return -1; + } + } + + if (enc->bytes_in_opb != sizeof(TEST_RDP5_UNCOMPRESSED_DATA)) + { + printf("RDP5 decompression failure: size mismatch: Actual: %d, Expected: %d\n", + enc->bytes_in_opb, sizeof(TEST_RDP5_UNCOMPRESSED_DATA)); + return -1; + } + + if (memcmp(TEST_RDP5_COMPRESSED_DATA, enc->outputBuffer, sizeof(TEST_RDP5_COMPRESSED_DATA)) != 0) + { + printf("RDP5 decompression failure\n"); + return -1; + } + + mppc_enc_free(enc); + mppc_dec_free(rmppc); + + return 0; +} diff --git a/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c b/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c index e4f096c76..6eb326589 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c @@ -3120,7 +3120,7 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[]) srcBitmap32 = freerdp_image_convert(srcBitmap16, NULL, 32, 32, 16, 32, clrconv); - format = FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, FREERDP_PIXEL_FLIP_NONE); + format = PIXEL_FORMAT_ARGB32; #if 0 freerdp_bitmap_compress_planar(planar, srcBitmap32, format, 32, 32, 32 * 4, NULL, &dstSize); diff --git a/libfreerdp/codec/test/TestFreeRDPCodecRemoteFX.c b/libfreerdp/codec/test/TestFreeRDPCodecRemoteFX.c new file mode 100644 index 000000000..9e2c042ae --- /dev/null +++ b/libfreerdp/codec/test/TestFreeRDPCodecRemoteFX.c @@ -0,0 +1,762 @@ +#include +#include + +#include +#include + +/** + * The following is an annotated dump of a TS_RFX_TILESET message containing a single encoded 64x64 tile. + * + * + * c7 cc -> TS_RFX_TILESET::CodecChannelT::blockType = WBT_EXTENSION + * 3e 0b 00 00 -> TS_RFX_TILESET::CodecChannelT::blockLen = 2878 + * 01 -> TS_RFX_TILESET::codecId = 1 + * 00 -> TS_RFX_TILESET::channelId = 0 + * c2 ca -> TS_RFX_TILESET::subtype = CBT_TILESET + * 00 00 -> TS_RFX_TILESET::idx = 0x00 + * 51 50 -> TS_RFX_TILESET::properties + * TS_RFX_TILESET::properties::lt = TRUE (1) + * TS_RFX_TILESET::properties::flags = VIDEO_MODE (0) + * TS_RFX_TILESET::properties::cct = COL_CONV_ICT (1) + * TS_RFX_TILESET::properties::xft = CLW_XFORM_DWT_53_A (1) + * TS_RFX_TILESET::properties::et = CLW_ENTROPY_RLGR3 (4) + * TS_RFX_TILESET::properties::qt = SCALAR_QUANTIZATION (1) + * 01 -> TS_RFX_TILESET::numQuant = 1 + * 40 -> TS_RFX_TILESET::tileSize = 64 + * 01 00 -> TS_RFX_TILESET::numTiles = 1 + * 23 0b 00 00 -> TS_RFX_TILESET::tilesDataSize = 2851 + * 66 66 77 88 98 -> TS_RFX_TILESET::quantVals + * TS_RFX_TILESET::quantVals::LL3 = 6 + * TS_RFX_TILESET::quantVals::LH3 = 6 + * TS_RFX_TILESET::quantVals::HL3 = 6 + * TS_RFX_TILESET::quantVals::HH3 = 6 + * TS_RFX_TILESET::quantVals::LH2 = 7 + * TS_RFX_TILESET::quantVals::HL2 = 7 + * TS_RFX_TILESET::quantVals::HH2 = 8 + * TS_RFX_TILESET::quantVals::LH1 = 8 + * TS_RFX_TILESET::quantVals::HL1 = 8 + * TS_RFX_TILESET::quantVals::HH1 = 9 + * + * TS_RFX_TILE message (section 2.2.2.3.4.1). + * + * c3 ca -> TS_RFX_TILE::BlockT::blockType = CBT_TILE + * 23 0b -> TS_RFX_TILE::BlockT::blockLen = 2851 + * 00 -> TS_RFX_TILE::quantIdxY = 0 + * 00 -> TS_RFX_TILE::quantIdxCb = 0 + * 00 -> TS_RFX_TILE::quantIdxCr = 0 + * 00 00 -> TS_RFX_TILE::xIdx = 0 + * 00 00 -> TS_RFX_TILE::yIdx = 0 + * ae 03 -> TS_RFX_TILE::YLen = 942 + * cf 03 -> TS_RFX_TILE::CbLen = 975 + * 93 03 -> TS_RFX_TILE::CrLen = 915 + * 0000002e:000003db -> TS_RFX_TILE::YData + * 000003dc:000007aa -> TS_RFX_TILE::CbData + * 000007ab:00000b3d -> TS_RFX_TILE::CrData + */ + +const BYTE TEST_RFX_TILESET[2878] = + "\xc7\xcc\x3e\x0b\x00\x00\x01\x01\xc2\xca\x00\x00\x51\x50\x01\x40" + "\x01\x00\x23\x0b\x00\x00\x66\x66\x77\x88\x98\xc3\xca\x23\x0b\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\xae\x03\xcf\x03\x93\x03\xc0\x01" + "\x01\x15\x48\x99\xc7\x41\xa1\x12\x68\x11\xdc\x22\x29\x74\xef\xfd" + "\x20\x92\xe0\x4e\xa8\x69\x3b\xfd\x41\x83\xbf\x28\x53\x0c\x1f\xe2" + "\x54\x0c\x77\x7c\xa3\x05\x7c\x30\xd0\x9c\xe8\x09\x39\x1a\x5d\xff" + "\xe2\x01\x22\x13\x80\x90\x87\xd2\x9f\xfd\xfd\x50\x09\x0d\x24\xa0" + "\x8f\xab\xfe\x3c\x04\x84\xc6\x9c\xde\xf8\x80\xc3\x22\x50\xaf\x4c" + "\x2a\x7f\xfe\xe0\x5c\xa9\x52\x8a\x06\x7d\x3d\x09\x03\x65\xa3\xaf" + "\xd2\x61\x1f\x72\x04\x50\x8d\x3e\x16\x4a\x3f\xff\xfd\x41\x42\x87" + "\x24\x37\x06\x17\x2e\x56\x05\x9c\x1c\xb3\x84\x6a\xff\xfb\x43\x8b" + "\xa3\x7a\x32\x43\x28\xe1\x1f\x50\x54\xfc\xca\xa5\xdf\xff\x08\x04" + "\x48\x15\x61\xd9\x76\x43\xf8\x2a\x07\xe9\x65\xf7\xc6\x89\x2d\x40" + "\xa1\xc3\x35\x8d\xf5\xed\xf5\x91\xae\x2f\xcc\x01\xce\x03\x48\xc0" + "\x8d\x63\xf4\xfd\x50\x20\x2d\x0c\x9b\xb0\x8d\x13\xc0\x8a\x09\x52" + "\x1b\x02\x6e\x42\x3b\xd0\x13\x4e\x84\x01\x26\x88\x6a\x04\x84\x34" + "\x2a\xa5\x00\xba\x54\x48\x58\xea\x54\x02\xb4\x1d\xa7\xfa\x47\x82" + "\xec\x7a\x77\xfd\x00\x92\x66\x62\x04\xa6\x9b\xff\xf6\x80\xc0\x69" + "\x01\xc2\x3e\x90\x14\x20\x2f\xfc\x40\x96\x59\x58\x0c\xb1\x13\x68" + "\x20\x2e\xb5\xf5\xdf\xff\xf8\xfc\x56\x88\x60\x24\x53\xb5\x41\x46" + "\x5f\xf8\xf1\x7e\xde\x4a\x08\x97\xe0\x55\x03\x8f\xe5\x75\x61\x03" + "\xf2\xe1\x90\x01\xa2\x8e\x88\x04\x98\x05\x93\x6b\xff\xea\xc0\x60" + "\xa1\x88\x04\x49\xbf\xf7\xff\x8c\xb4\x59\x90\x80\x30\x64\x53\xff" + "\xf5\xc4\x48\xda\xda\xcb\x80\x38\x61\x57\xb2\xaf\x00\xe8\x7b\x46" + "\xe6\xd8\x02\x03\x8a\x06\x18\x14\x32\x83\xd0\x8a\xee\xbc\x81\xb4" + "\x28\xc4\x7f\xf9\xa1\x69\x00\x91\xc5\x51\xff\xfe\x3f\xe9\xf1\x70" + "\x30\x24\x10\xa7\xcb\x1f\x8a\x24\x93\xed\x83\x00\x36\x20\xd1\x50" + "\xe7\xd8\xad\x58\x20\x09\x22\x80\xd0\xca\x5d\x1a\xd7\xf1\x60\x75" + "\x2a\xf2\xd7\xf8\xc0\x32\x45\x86\x00\x43\x01\xfe\x80\xf7\x42\x81" + "\x74\x84\x4c\xa1\x60\x4c\xcb\x14\x58\x01\x4d\x18\xa1\xaa\x47\x0e" + "\x11\x1a\x40\x7d\x41\x02\xe3\x30\xcd\x33\x81\x34\x06\x46\x83\xa2" + "\x47\x1c\x04\xaa\x20\x12\xa2\x8b\x81\xc4\x9c\xa0\x2e\x06\x32\xf8" + "\x86\x85\x01\xe8\x70\xf9\x46\x09\x6a\xbf\xe0\xf5\xa4\xc8\x78\xe7" + "\xd2\x97\x0b\xbc\x3c\x97\xff\xd5\x40\x94\xb2\xc1\x18\x18\x11\x1f" + "\x43\xc1\x18\xc3\x83\x7f\x9a\x31\xc4\x8e\x70\x56\xda\xf6\x17\xde" + "\xd1\x02\x0d\x42\x21\x13\xdc\x3a\x3c\x40\x9e\xf4\x01\x43\xea\x0c" + "\x46\x73\xa2\x7b\x0c\x80\xff\xe4\xad\x2e\x09\xb4\x63\xb0\x8c\x54" + "\x59\xfa\xac\x76\x36\x10\x05\xf0\x98\x88\x83\x42\x00\x20\x71\xcc" + "\xc1\xa9\x97\x3e\x5a\x0d\x04\x50\x92\x23\x20\x0d\x0a\x1c\x57\xd7" + "\xff\x10\xf2\x03\x0f\x58\x1b\xa5\x11\xf8\xf1\xb4\x12\xdb\x1a\x48" + "\x56\x1f\xe3\xc7\x50\xe9\x16\xb4\xbc\xb0\x40\x93\xea\xb5\x5b\x2f" + "\xfc\x50\x0a\x6f\xcc\x25\xe0\x06\xab\x5f\x24\xfe\x8b\xcb\x42\x43" + "\x7e\x69\x02\x25\xc7\x38\x00\x6e\xe5\x80\xa8\xa4\x30\x44\x15\x8f" + "\xe9\x0c\xd3\xa6\xc2\x14\x34\x4a\xfe\x03\x7f\x06\xa5\x91\x02\x54" + "\xf1\xa1\xa1\x53\xbf\x11\xf2\x8f\x83\x67\x80\x09\x08\x12\x3f\xfd" + "\x44\x91\xc2\x83\x30\x50\x07\x02\x82\x4d\x31\x34\x06\x41\x79\x6f" + "\xf0\xcc\x03\x79\x00\x2c\x05\x24\xec\x8d\x29\x15\xaf\x44\xc8\xeb" + "\x4f\xe1\xfd\xf1\x41\x48\x81\x08\xaf\xfe\x51\x48\xce\xe7\xf9\xb6" + "\x0a\x30\x83\x11\xf0\x0c\x3b\xd2\xa6\x24\x24\xef\x25\xfa\x5a\x3e" + "\x92\x3e\x79\x0e\x35\x61\xc8\xaa\x1c\x2e\x9a\x27\x7f\xff\xf0\x7d" + "\x30\x5b\xbc\x91\xff\xfe\x43\x24\x28\x66\xa7\x70\x99\x28\x6e\x2b" + "\x18\x2b\xd4\xa1\x77\x3b\x96\x9f\xf7\xeb\xbe\x1f\x04\x34\x75\x84" + "\x31\x42\x4c\x65\xaa\x09\x50\xa0\xc4\x51\x31\xd3\x26\x3a\x1b\xf4" + "\x6e\x4a\x4e\x17\x25\x84\x78\x7d\x2c\x3f\x46\x18\xca\x5f\xf9\xe5" + "\x38\x2f\xd8\x71\x94\x94\xe2\xcc\xa3\x15\xb0\xda\xa9\xcb\x58\xe4" + "\x18\x77\x93\x8a\x51\xc6\x23\xc4\x4e\x6d\xd9\x14\x1e\x9b\x8d\xbc" + "\xcb\x9d\xc4\x18\x05\xf5\xa9\x29\xf8\x6d\x29\x38\xc7\x44\xe5\x3a" + "\xcd\xba\x61\x98\x4a\x57\x02\x96\x42\x02\xd9\x37\x11\xde\x2d\xd4" + "\x3f\xfe\x61\xe7\x33\xd7\x89\x4a\xdd\xb0\x34\x47\xf4\xdc\xad\xaa" + "\xc9\x9d\x7e\x6d\x4b\xcc\xdc\x17\x89\x57\xfd\xbb\x37\x75\x47\x5a" + "\xec\x2c\x6e\x3c\x15\x92\x54\x64\x2c\xab\x9e\xab\x2b\xdd\x3c\x66" + "\xa0\x8f\x47\x5e\x93\x1a\x37\x16\xf4\x89\x23\x00\x00\xb0\x33\x56" + "\xfa\x14\x1e\xff\x48\x7a\x7e\x0f\x10\x1f\xf4\x91\xc8\x10\x56\x84" + "\xff\x08\xec\xb4\xac\x0e\x0f\xff\xad\xc5\xe0\x1a\x2f\x82\x04\x9f" + "\x91\xc2\x0e\xfe\x48\x36\x79\x01\x42\x14\xff\xfe\x30\xf0\x08\x18" + "\xf1\x81\x45\x9a\x60\xc1\x79\xf0\x14\x12\x10\xce\xea\x31\x5a\xff" + "\xfc\x20\x13\x82\x2f\xc9\x02\x1f\x81\xcb\x00\xe1\x10\xd2\xb4\xbe" + "\x87\xff\xb0\x1e\x27\x81\xb7\x04\x06\x3c\xc2\x04\xf6\x06\x0e\x28" + "\xbc\x40\xbf\x12\x1e\x86\xd4\x6a\x7f\x18\x1b\x96\x85\x4c\x16\x80" + "\xdf\x2c\xa5\x8d\x86\xa3\x4a\x8a\xb4\x1b\xa1\x38\xa9\xd5\xff\xff" + "\xea\x06\x20\xd2\x95\x1e\xf4\x2f\xb2\x12\x0e\x61\x78\x4a\x17\x52" + "\x5d\xe4\x25\x1f\xfe\xc0\xb3\x1f\xff\xff\xec\x02\x82\x80\x90\x41" + "\x88\xde\x48\x2c\x42\x52\x0b\x2f\x43\x7e\x50\x78\xf2\x67\x78\x41" + "\x34\x3d\xc8\x0f\x67\xa1\xeb\x21\xfe\xc0\x1f\x22\x60\x41\x6c\x00" + "\x92\x4b\x60\x10\xd0\x0d\x01\x35\x05\x0e\x87\xa2\xa0\x5d\x1f\xa3" + "\xaf\x7f\xf1\xbe\x8f\xcd\xa5\x00\x1c\x10\x40\x15\x76\x81\x05\xef" + "\xee\x00\x60\x84\x00\x99\x40\x4a\x82\x17\xe9\xfc\xc4\x7f\xff\xfd" + "\x04\x80\x06\x06\xdc\xaf\xa7\x7e\x94\x75\x74\x01\x00\xe0\x91\x00" + "\x85\x7f\x8e\xd6\x0b\x20\x21\x30\xca\x62\x8e\x07\x04\xe9\x45\x40" + "\x5f\x47\x4a\x30\x15\x41\xcb\xdf\xff\xfc\xbf\xc3\xb4\x46\x6a\x01" + "\x40\xd0\xa7\x34\x18\x24\x1c\x2a\x45\xfe\xa8\x05\x08\x61\xfd\xa8" + "\x80\x71\x01\x25\x9c\xc1\x47\x17\x37\x02\x7a\x15\xff\xf3\x01\x45" + "\x7f\xd6\x80\x60\x83\x67\xf8\x9d\x2f\xf4\xdd\x8c\x30\x01\x51\x42" + "\xbc\x43\x7a\x6b\x9f\x84\x1e\x00\x48\xc1\xe0\xb7\xe0\x7e\x99\xf2" + "\x4a\xe9\x40\x02\x81\xc3\x00\x24\x3a\xc5\x52\x0f\x91\xc8\x68\x25" + "\x40\x99\xa4\x25\x1a\x04\xd0\xa2\x91\xdd\xeb\x93\x00\x21\x49\x24" + "\x8b\x40\x75\x38\x14\xa1\xfd\x3f\x88\x25\xbf\x32\x00\xe3\x19\xfc" + "\xb9\xf8\x6f\x81\xc0\x01\xb3\x93\x20\x09\x08\x25\x84\xe1\x34\xd4" + "\x1b\x48\x88\x11\xa0\x15\x59\xd7\x07\x81\x81\x3b\xa1\x40\x2e\x2f" + "\x48\x70\x09\xc4\x76\x49\x0f\x2e\x50\x2e\x46\x19\xa4\x16\xa2\x1b" + "\x84\xa2\x89\x58\xfc\x4f\x3f\x40\x90\x4c\xa3\x01\x32\x09\x02\x80" + "\x9c\x91\x13\x2c\xba\xde\x5d\x99\xf2\xff\xff\x3d\x5a\x1f\xa9\x02" + "\x90\x8f\xf3\x08\xbd\x01\xf8\xd0\x2a\x95\x41\x0c\x40\x0a\x20\xc4" + "\xd4\xcc\x6b\x0f\xf0\x80\xb1\x5d\x28\x3d\x08\xc2\xf8\x31\x02\x49" + "\x88\x14\x28\xed\xe8\x86\x3b\x00\x9f\x95\x06\x37\x15\xa4\x59\xc8" + "\x80\xb6\x10\xf0\xe5\xb8\x18\x00\x56\x1c\xff\x95\x21\x0e\x7f\x2b" + "\xc5\x08\x59\x10\xe1\x46\x31\x8d\xec\xe0\xa1\x99\xbb\x21\xff\xfe" + "\x30\x10\xd0\x05\xe3\x08\x50\xfc\xf3\x0e\x00\x8d\x68\x8e\x07\xa6" + "\x80\x34\x42\xed\x1f\x88\x00\xf0\x8a\x21\xae\xf7\xfb\x80\x28\x86" + "\x0f\xff\xff\x82\xea\x47\x95\x91\xe0\x04\x01\x44\x0c\x29\xff\x0e" + "\x33\xe8\xc0\x54\x04\x23\xfc\x81\x5b\xf0\x3c\x07\x10\x70\x30\xd8" + "\x21\x6f\xef\xde\x46\x09\x43\xfa\x5f\xff\x0d\x72\x30\xdd\x00\xdb" + "\xe4\x48\x24\x97\x08\x46\xb1\x49\xc4\x4d\x80\x12\x60\xff\xa4\xa6" + "\xff\xf6\x8c\x00\x40\x05\x02\xb4\x0f\xf0\x3e\xfc\x84\x38\x81\x94" + "\x8b\xfe\x49\xef\xc0\x10\x49\x88\x28\xa2\x1c\x2a\x8b\x64\xd4\x86" + "\xd7\xff\xff\xff\xeb\x91\x6b\x11\x10\x00\x69\x4c\xbf\xb4\x1c\xd8" + "\x00\x07\x16\x80\x60\x0a\x1c\x82\x42\x27\x82\x43\xc9\x0a\x64\x20" + "\x5a\x5f\x4e\xbf\x8c\x38\x82\x36\x02\x07\x72\x79\x07\x23\xb4\xbb" + "\x57\x5f\xe8\x04\xdd\x39\xe9\x07\x95\xbe\x04\x2b\xdd\x8e\x22\xdc" + "\x14\x2c\x61\xa3\xa9\xcd\x4f\x82\x5d\xa0\x44\xdf\xf4\x96\xff\xf5" + "\x2b\xff\xfe\x01\x19\xd2\xa2\x9e\x43\xa5\x7f\xf0\x4c\x4c\x2b\x3c" + "\x33\xe2\x55\xff\x04\x06\x29\x2c\x0d\x22\x5d\x7c\x93\xba\x18\xaf" + "\xf9\x32\xa6\xc3\x99\x46\x79\xe3\x06\xa6\x38\x8b\x92\x22\x4b\xdb" + "\x1b\x36\x20\xb0\x6c\x20\xce\x37\x42\xe1\x66\xd4\x49\x34\x42\x8b" + "\xfa\x9c\x12\x99\xdc\x06\x87\xfa\x46\xf8\x2f\x04\xa9\xd8\x82\x07" + "\xa6\x30\x0f\xc0\xdf\x35\xe8\x90\xf0\xff\xff\xa8\xe0\xd7\x02\x60" + "\x1a\xc3\x20\x28\xa2\x31\x29\x3c\xeb\x04\xa5\xdd\x48\x0e\x82\xa4" + "\xb6\x56\x22\x06\x57\xe0\xda\x10\x27\x31\x0e\x11\x77\xfe\x02\x60" + "\x16\x48\x81\x8c\x0d\x05\x17\x7f\xcb\xbb\x7e\x25\x2a\x41\xfd\x8a" + "\x7f\xc9\x36\x7c\xe0\x98\x7e\x92\xef\x7e\x06\x03\x13\x3e\x20\x3a" + "\xbf\x4c\xc3\x0f\x2e\x80\x74\xbf\x39\x3c\xf0\xa6\xb2\xe9\x3f\x41" + "\x55\x1f\x2c\xf5\xd2\x7e\x8c\xae\x4e\xaa\x61\x3c\xbc\x3f\xc4\xc7" + "\x36\xdc\x23\xc8\xb8\x52\xe2\x8a\x80\x18\x00\x00\xb2\x46\xa2\x56" + "\x0d\x12\x94\xaa\xbd\x01\x07\xff\xfa\x34\x0c\x5f\xf8\x0c\x12\x50" + "\xaf\xd6\xd1\x89\x40\xa4\xff\xe0\xce\xc4\x49\x25\x9d\xc1\xff\x7e" + "\x60\x24\x5d\xcc\x10\xc0\xbe\x5a\x12\xd3\xc3\xfe\x2d\x40\x7c\x28" + "\x9e\x71\x01\xd2\x6e\x86\x0b\xc8\xf2\x9b\x45\x08\x4c\x04\x52\x7e" + "\xf2\x7e\xd9\xcc\x0b\x1c\x20\x80\xae\xaf\xfe\xb0\x6d\x23\xf2\x41" + "\xe3\x2e\x20\x11\x4b\x74\x89\xdd\xff\xa8\x38\xa3\x95\x82\x15\xf0" + "\xd0\xd5\xf1\x92\x8e\xee\xc0\x26\x81\xe9\x47\xff\xee\x0d\x20\x34" + "\x31\x3a\xef\x40\xb2\x29\x47\x19\x7f\x04\x27\xf1\x90\x85\x09\x86" + "\x7d\x42\xe2\x54\x5d\x5f\xe8\x0e\xd0\x2c\xaa\x16\xbf\x04\xa7\xf8" + "\xa2\x46\x0b\x08\x7a\x79\xe9\x28\x62\x7c\x33\xf4\x0b\x14\x82\xfa" + "\x61\xeb\xc1\xff\x4c\xa4\x11\x7f\x03\x68\x44\xc1\x1f\x81\x3a\x6c" + "\x77\x95\x02\x2b\x53\x80\xe5\x10\x1e\x90\xe8\xfd\x1f\xa6\x40\x0b" + "\x13\xff\x4e\x4d\x7f\x52\xe8\xaf\x9a\xc1\x80\x0f\x0a\x14\x02\x3c" + "\xc0\x09\x13\xe7\xdc\xc0\x1a\x28\xa0\xe4\x83\x8e\x03\x88\xd5\xaf" + "\x1a\xbd\x91\x00\xb7\x4e\xba\xdf\xf8\xdb\xcc\x02\x43\xc4\x14\x2a" + "\x3f\xc8\x0d\x09\x1c\x44\xf4\x01\x3c\xca\x28\x56\x80\xa6\x85\x00" + "\xea\x3e\x8f\xeb\x9f\xfc\x6e\x07\xc4\xe0\x30\x78\xa0\x1e\x6f\x54" + "\x78\x51\xff\x56\x4a\x01\x47\x02\x4c\x21\x3b\xfb\x90\x0a\xcc\x1d" + "\xd2\x47\xff\xfc\x70\x18\x22\xc0\xb9\x2f\xe9\x7f\x91\xd3\x66\x2f" + "\x80\x2c\x24\xa7\xfa\x84\x51\xab\x6b\x72\x00\xab\x33\x04\xcf\x43" + "\xff\x17\x51\x84\x0c\x01\x50\x10\x8f\x90\x34\x41\x44\x84\x8e\x08" + "\x19\x04\x48\x50\x84\x38\x3d\x02\x52\xf9\x7c\xd2\xd0\x1f\x13\x42" + "\xa0\x21\x41\xc4\x02\x02\x3d\x09\xc8\xfd\x60\x7d\x35\x4f\x7f\xff" + "\xf9\x97\x6a\xd8\x00\xc3\x83\x00\x09\x50\x4b\x90\x8a\xc7\x94\x4d" + "\x47\xc1\x62\x32\x28\x24\x09\x52\x2e\x2e\x1c\x96\x44\xa0\x09\xc8" + "\xce\x64\xa9\x1c\x19\x0e\x52\x3e\x3e\x19\x93\xa0\x36\x26\x22\x08" + "\x9a\x00\xdd\x66\x3a\x93\xd5\x89\xd1\x40\x06\xd4\xa8\x22\x73\x7b" + "\x3d\x3f\xe3\x04\x94\xff\xff\xff\xff\x0c\x56\x77\xac\xe0\xc4\x06" + "\x1f\xb8\xa5\x80\xfd\x68\x1c\x32\x16\x03\xde\x71\x2a\x3d\x14\x19" + "\xbe\xc2\x88\xd9\x24\x92\x5f\xc5\x90\x0a\x85\xc2\x3f\x87\x03\xa8" + "\x26\x17\xc4\x06\x86\x12\x87\x76\x0a\x48\x16\xed\x96\x93\xec\x1b" + "\x30\x73\xe8\x1a\x3f\xff\x4d\xce\x40\xf3\x0c\x51\x4b\x84\x9e\x67" + "\x2b\x15\x40\x1a\xa0\xfc\x10\x0f\xd8\x81\x35\x87\xff\x98\x0f\x40" + "\x00\xba\xc0\x71\xe2\x00\x18\x28\xb3\x82\xcc\x80\x6a\xa0\x43\xff" + "\x2d\xd6\x04\x8a\x68\xff\xff\xff\xfc\x1a\xf3\x1a\x2a\x06\xc0\x01" + "\x40\x0c\x30\xc1\xd0\xd7\x4f\xcb\x74\x1f\x07\xd3\xb4\x0d\x88\x98" + "\xea\xda\x9f\xce\x2b\x3c\x55\xb3\x40\x14\xff\xff\xff\xea\xdb\x9b" + "\x92\xd8\x68\x08\x0b\x41\x09\x26\x40\x8c\xf1\xb0\x9a\x98\xc0\x80" + "\x8b\xf0\x3d\xe7\xec\x19\x68\x21\x03\x29\x7f\xe1\x6d\x4c\x0f\x01" + "\xd1\x51\x01\x1a\x50\x2a\x59\x27\x80\xc1\x6e\x33\xf1\x80\xe1\x49" + "\x08\xe9\x17\xff\xff\xff\x80\x5a\x10\x10\x36\x5e\xca\xf8\x3a\x00" + "\x1e\xb0\x06\x84\x01\xf3\x07\x1b\x4a\xc0\x1e\x21\x43\x8e\xa5\x55" + "\x77\xc7\x65\x7c\xc2\xdf\x5e\x0c\x42\x20\xd2\x48\x61\xc8\x1c\x65" + "\xf8\xfe\x4c\x88\x71\x1f\x82\x50\x81\xa3\x54\x09\x13\x28\x52\xf5" + "\xe0\x82\xc3\x06\x7f\xfa\x2c\xcf\xf8\xf4\x7f\xff\xfd\x01\x49\xa4" + "\xb8\xde\x62\x84\xfe\xed\x65\x1f\x3c\x3c\xb2\x50\x76\x30\x5b\x03" + "\xc0\x08\xa6\x64\x90\xc8\xcd\x14\x6e\x69\x46\x7a\xc6\x1c\x87\xd7" + "\x48\x7b\x49\x05\x2d\x5e\x7f\xcb\x67\xf0\xd9\x0d\x1e\x9e\x53\xb7" + "\x64\xa5\xa5\x10\x39\x06\x11\x3f\xb1\xa9\xa6\xe8\x4d\x47\x77\xda" + "\x43\x76\x89\x45\x09\x70\xc2\x38\x0f\x09\x6f\xe7\x2d\x82\x35\x07" + "\xfe\x64\x18\x2e\xb8\x04\x42\x54\x80\x43\x12\x6c\x9a\x55\xc9\x0a" + "\xa0\x79\x47\x52\x65\x2a\xff\x50\x11\xc9\x4e\xfe\x5b\x30\xa4\xe8" + "\x30\x63\xff\x21\x12\x1b\xdc\x1c\x01\x41\x51\x1f\xff\xfa\xc3\xe3" + "\x55\xf1\x66\xe2\xd5\x78\x5e\xfa\x4d\xf2\x61\x01\x26\x15\xa9\xf9" + "\xd9\x32\x41\x90\x36\x4e\xae\xe3\x0b\x16\x56\x8c\x6e\x42\x5d\xd8" + "\x1e\xfe\x1d\x40\x3a\x50\x9f\x09\x14\xeb\x6e\x48\x7a\x91\x88\x7b" + "\x7d\x8f\x72\x42\x39\xb0\x1c\x65\x18\x23\x8b\x60\x30\x00"; + +/** + * 64x64 XRGB Image + */ + +const UINT32 TEST_RFX_XRGB_IMAGE[4096] = +{ + 0x00229cdf, 0x00249de0, 0x00259fe2, 0x002ca5e8, 0x00229cdf, 0x00229ce0, 0x00239de0, 0x00229ce0, + 0x00229cdf, 0x00229cdf, 0x00239ce0, 0x00249ce0, 0x00249ce0, 0x00219ce3, 0x001e9ce6, 0x00209ae2, + 0x002299dd, 0x002199de, 0x00209adf, 0x00209ae0, 0x001f9be0, 0x001e9ae0, 0x001d99e0, 0x001c98e0, + 0x001b97df, 0x001e96dc, 0x002194d9, 0x001f93dd, 0x001d93e0, 0x001b94dc, 0x001895d8, 0x001c92db, + 0x00208fde, 0x001b91de, 0x001693df, 0x001793df, 0x001992df, 0x001891df, 0x00178fdf, 0x00178edf, + 0x00168dde, 0x00158cdd, 0x00148cdc, 0x00128cda, 0x00118cd9, 0x00118bd9, 0x00128ada, 0x001289da, + 0x001288db, 0x001187da, 0x001186da, 0x001085da, 0x000f85d9, 0x000f84d9, 0x000e83d9, 0x000d82d8, + 0x000d82d8, 0x000d81d8, 0x000d80d7, 0x000d7fd7, 0x000d7ed6, 0x000d7ed6, 0x000d7ed6, 0x000d7ed6, + 0x00259fe1, 0x0027a1e2, 0x0029a2e3, 0x002ba4e6, 0x00249fe1, 0x00249fe1, 0x00249fe1, 0x00249ee1, + 0x00239ee1, 0x00249ee1, 0x00249ee1, 0x00259de1, 0x00259de2, 0x00249de2, 0x00229de2, 0x00229ce1, + 0x00229bdf, 0x00219ce0, 0x00209ce1, 0x00209ce2, 0x00209ce2, 0x00209ae0, 0x002199de, 0x001f99df, + 0x001d98e0, 0x001e97e0, 0x001f97e0, 0x001d96df, 0x001c95de, 0x001c94e0, 0x001c94e1, 0x001d93e1, + 0x001d92e0, 0x001b93de, 0x001a94dc, 0x001a93de, 0x001a93e0, 0x001992e0, 0x001891df, 0x00188fdf, + 0x00178edf, 0x00168ede, 0x00158edd, 0x00148ddc, 0x00138ddb, 0x00138cdb, 0x00138bdb, 0x00128adb, + 0x001289db, 0x001288db, 0x001187db, 0x001186db, 0x001085db, 0x000f84da, 0x000e83d9, 0x000e83d9, + 0x000e83d9, 0x000e82d9, 0x000e81d8, 0x000e80d8, 0x000d7fd7, 0x000d7fd7, 0x000d7fd7, 0x000d7fd7, + 0x0027a3e3, 0x002aa4e3, 0x002ea6e3, 0x002aa4e3, 0x0026a2e3, 0x0026a1e3, 0x0025a1e3, 0x0025a0e3, + 0x0025a0e3, 0x0025a0e3, 0x00259fe3, 0x00269fe3, 0x00269ee4, 0x00279ee1, 0x00279edf, 0x00259ee0, + 0x00239ee1, 0x00219ee2, 0x00209ee4, 0x00209de4, 0x00219de3, 0x00229be0, 0x002499dc, 0x002299de, + 0x001f98e0, 0x001d99e4, 0x001b9ae7, 0x001c98e2, 0x001c96dc, 0x001e94e3, 0x002092ea, 0x001d94e6, + 0x001a96e2, 0x001c96de, 0x001d95da, 0x001c94de, 0x001b94e1, 0x001a93e0, 0x001a92e0, 0x001991e0, + 0x001890e0, 0x001790df, 0x00178fde, 0x00168fde, 0x00158edd, 0x00148ddd, 0x00138cdc, 0x00138bdc, + 0x00128adc, 0x001289dc, 0x001188dc, 0x001187dd, 0x001086dd, 0x000f85db, 0x000e83d9, 0x000e84da, + 0x000f84da, 0x000e83da, 0x000e82d9, 0x000e81d9, 0x000e80d8, 0x000e80d8, 0x000e80d8, 0x000e80d8, + 0x002aa7e5, 0x002da7e4, 0x0031a8e3, 0x002ca6e3, 0x0027a4e4, 0x0027a3e4, 0x0027a3e4, 0x0027a3e4, + 0x0026a2e4, 0x0026a2e4, 0x0027a1e5, 0x0027a0e5, 0x0027a0e6, 0x0026a0e5, 0x0025a0e4, 0x00259fe4, + 0x00259ee3, 0x00239ee5, 0x00229fe6, 0x00229fe5, 0x00229fe4, 0x0013a5e6, 0x001b9fe8, 0x0016a0e8, + 0x0011a0e7, 0x00129fef, 0x00139ef7, 0x001b99ec, 0x00179ae2, 0x00149ce4, 0x001d98e5, 0x001c97e6, + 0x001b96e7, 0x001c98dc, 0x001d97df, 0x001c96e1, 0x001c94e2, 0x001b94e1, 0x001b93e1, 0x001a93e0, + 0x001a92e0, 0x001991e0, 0x001890e0, 0x001790df, 0x00168fdf, 0x00158ede, 0x00158dde, 0x00148cdd, + 0x00138bdc, 0x00128add, 0x001289dd, 0x001188de, 0x001187de, 0x000f85dc, 0x000d83da, 0x000f85db, + 0x001086db, 0x000f84db, 0x000f83da, 0x000e82da, 0x000e81da, 0x000e81da, 0x000e81da, 0x000e81da, + 0x002caae7, 0x0030aae5, 0x0034abe3, 0x002ea8e4, 0x0029a6e5, 0x0028a6e5, 0x0028a5e5, 0x0028a5e5, + 0x0028a5e6, 0x0028a4e6, 0x0028a3e7, 0x0028a2e7, 0x0028a1e8, 0x0025a2e9, 0x0023a3ea, 0x0025a0e8, + 0x00279ee6, 0x00259fe7, 0x0023a0e9, 0x0018a4f5, 0x000ea7ff, 0x001ba6de, 0x00558ebb, 0x006f839c, + 0x0089797e, 0x008d797c, 0x00917979, 0x007f7b94, 0x005687af, 0x00229bd6, 0x0004a4fd, 0x00109df4, + 0x001c97eb, 0x001c9ada, 0x001c98e4, 0x001c97e3, 0x001d95e2, 0x001c95e2, 0x001c94e2, 0x001c94e1, + 0x001b94e1, 0x001a93e1, 0x001a92e1, 0x001991e1, 0x001890e1, 0x00178fe0, 0x00158edf, 0x00148dde, + 0x00138cdd, 0x00128bde, 0x00128adf, 0x001289df, 0x001188e0, 0x000f85dd, 0x000d83da, 0x000f85db, + 0x001187dd, 0x001086dc, 0x000f84dc, 0x000e83db, 0x000e81db, 0x000e81db, 0x000e81db, 0x000e81db, + 0x0030abe5, 0x0036afe8, 0x0034abe4, 0x002faae5, 0x002ba8e6, 0x0036aee8, 0x0026a6e8, 0x0029a7e7, + 0x002ca8e7, 0x002da7e6, 0x002fa5e5, 0x002ca5e7, 0x0029a4e9, 0x002ba5e5, 0x002ca5e2, 0x0010aaef, + 0x0013adf6, 0x0023a3f8, 0x006091a5, 0x00a6755d, 0x00ec5915, 0x00ff490c, 0x00fa5504, 0x00ff590f, + 0x00ff5d1b, 0x00ff6116, 0x00fa6412, 0x00ff550f, 0x00ff4b0d, 0x00fb4918, 0x00f54823, 0x008e737e, + 0x00269eda, 0x0006a2ff, 0x001d97e2, 0x001799ea, 0x001c97e4, 0x001a98e4, 0x001898e4, 0x001a96e3, + 0x001b95e3, 0x001a94e2, 0x001a93e0, 0x001992e1, 0x001891e2, 0x001790e1, 0x00168fe0, 0x00158fdf, + 0x00138ede, 0x00138ddf, 0x00138ce0, 0x00128be0, 0x001189e0, 0x001087de, 0x000f85db, 0x00138ae0, + 0x000f87dc, 0x000f86dc, 0x000f85dc, 0x000f84dc, 0x000e83db, 0x000e83db, 0x000e83db, 0x000e83db, + 0x0034abe2, 0x003cb4ec, 0x0034ace5, 0x0031abe6, 0x002daae8, 0x0044b6eb, 0x0024a7ea, 0x0029aaea, + 0x002face9, 0x0032a9e6, 0x0035a7e3, 0x0030a7e6, 0x002ba8ea, 0x0025aaf0, 0x0020adf6, 0x004d8ba7, + 0x00b8674c, 0x00ff5510, 0x00f7650c, 0x00f86313, 0x00fa611b, 0x00f0671f, 0x00fc6222, 0x00fb6926, + 0x00f96f29, 0x00f67122, 0x00f3721b, 0x00f26b20, 0x00f16424, 0x00ff5622, 0x00ff531f, 0x00ff4b17, + 0x00ff440e, 0x00b1615b, 0x001f95e0, 0x00129bf0, 0x001c9ae5, 0x00189ae6, 0x00159be7, 0x001898e6, + 0x001b95e5, 0x001b95e2, 0x001995e0, 0x001994e1, 0x001892e2, 0x001792e1, 0x001691e0, 0x001590df, + 0x00148fdf, 0x00148fe0, 0x00148fe1, 0x00128de1, 0x00108be0, 0x001189de, 0x001186dd, 0x00178fe4, + 0x000e87db, 0x000e87dc, 0x000f87dd, 0x000f85dc, 0x000e84dc, 0x000e84dc, 0x000e84dc, 0x000e84dc, + 0x0036b1eb, 0x0036b4f0, 0x002eafed, 0x002caeec, 0x002aadec, 0x0041b4ef, 0x0029abe9, 0x002cabe8, + 0x002fabe7, 0x0031abe6, 0x0032aae6, 0x002faae7, 0x002ca9e8, 0x0025a7eb, 0x00946a5f, 0x00ff3e06, + 0x00f95618, 0x00e27312, 0x00f87329, 0x00f77427, 0x00f77626, 0x00f27628, 0x00f8712b, 0x00f9772e, + 0x00f97e30, 0x00f77f2e, 0x00f5812b, 0x00f57b2c, 0x00f5752d, 0x00fd6a2b, 0x00fb652a, 0x00f65e2c, + 0x00f1572e, 0x00ff4810, 0x00ff460f, 0x00817680, 0x0002a7f1, 0x002496ea, 0x00199be4, 0x001b98e4, + 0x001d96e5, 0x001b96e2, 0x001a96e0, 0x001995e1, 0x001794e3, 0x001793e2, 0x001692e1, 0x001691e0, + 0x001590df, 0x001591e1, 0x001591e3, 0x00138fe1, 0x00108ce0, 0x00128be0, 0x00158ae0, 0x00168de2, + 0x000f89dd, 0x000f88dd, 0x000f88dd, 0x000f86dd, 0x000f85dc, 0x000f85dc, 0x000f85dc, 0x000f85dc, + 0x005fc1e7, 0x0057bee8, 0x004fbbe9, 0x004ebae6, 0x004ebae3, 0x0051b6ee, 0x002eaee8, 0x002eade6, + 0x002fabe5, 0x002face7, 0x002eade9, 0x002eace7, 0x002daae5, 0x0015b2ff, 0x00ec4310, 0x00f15016, + 0x00f75d1c, 0x00f87123, 0x00f9862a, 0x00f6882d, 0x00f48b31, 0x00f48532, 0x00f47f33, 0x00f78535, + 0x00fa8c37, 0x00f88e39, 0x00f7903a, 0x00f88b38, 0x00f98635, 0x00f87e35, 0x00f77635, 0x00f76d34, + 0x00f76532, 0x00f85e31, 0x00f95730, 0x00ff5125, 0x00f65237, 0x0003a5fd, 0x001e9be1, 0x001e98e3, + 0x001f96e5, 0x001c97e2, 0x001a97df, 0x001896e1, 0x001795e4, 0x001794e3, 0x001793e2, 0x001692e1, + 0x001692e0, 0x001693e2, 0x001794e4, 0x001391e2, 0x000f8ee0, 0x00148ee1, 0x00198ee3, 0x00148ce1, + 0x000f8bde, 0x000f8ade, 0x000f89de, 0x000f88dd, 0x000f86dd, 0x000f86dd, 0x000f86dd, 0x000f86dd, + 0x003cb6ee, 0x0036b4ef, 0x0030b2f0, 0x0030b1ee, 0x002fb1ec, 0x0038b0ef, 0x002eaee9, 0x002faee8, + 0x0031ade6, 0x002fafe8, 0x002eb1ea, 0x0031adec, 0x0029afee, 0x0030aac8, 0x00ff3d05, 0x00fa501a, + 0x00f96021, 0x00f87428, 0x00f7882f, 0x00fa9638, 0x00f59b38, 0x00f5973b, 0x00f6923e, 0x00f89440, + 0x00fa9742, 0x00fa9a44, 0x00fa9d46, 0x00f99845, 0x00f89444, 0x00f98d43, 0x00fa8641, 0x00f97d3f, + 0x00f9743d, 0x00f77039, 0x00f56d35, 0x00ff6122, 0x00bf6c63, 0x00129eef, 0x00229ae8, 0x001c99ed, + 0x00179ce4, 0x001498f0, 0x001b94e1, 0x001a96e2, 0x001998e3, 0x001897e4, 0x001896e5, 0x001895e4, + 0x001993e2, 0x001792e1, 0x001590df, 0x001692e2, 0x001793e5, 0x001490e4, 0x00128ee2, 0x00118de3, + 0x00108de3, 0x00118bde, 0x001289d9, 0x000f88e2, 0x000c89dd, 0x001085e0, 0x000987e4, 0x000987e4, + 0x0040b5e9, 0x003bb4e9, 0x0037b2ea, 0x0037b2e9, 0x0038b1e8, 0x0033b0ea, 0x002eaeeb, 0x0030afe9, + 0x0033afe8, 0x0030b2ea, 0x002eb5ec, 0x0034aff2, 0x0025b4f7, 0x008d7f86, 0x00f64f00, 0x00ed5c1e, + 0x00fa6326, 0x00f7762d, 0x00f58a35, 0x00fea242, 0x00f7ab3f, 0x00f7a843, 0x00f7a548, 0x00f9a34a, + 0x00faa24c, 0x00fba64f, 0x00fcaa52, 0x00f9a652, 0x00f7a252, 0x00fa9c50, 0x00fd974e, 0x00fc8d4b, + 0x00fb8348, 0x00f68341, 0x00f1823a, 0x00f5732c, 0x00718cac, 0x00179af0, 0x002599ef, 0x002697e9, + 0x00269bc6, 0x001696f1, 0x001d91e3, 0x001c96e3, 0x001b9be3, 0x001a99e6, 0x001998e9, 0x001b97e7, + 0x001c95e5, 0x001891df, 0x00138dda, 0x001992e2, 0x001e98ea, 0x001592e6, 0x000b8de2, 0x000e8ee5, + 0x00108fe9, 0x00128cdf, 0x001489d4, 0x000e88e6, 0x00088cdc, 0x001184e4, 0x000488ec, 0x000488ec, + 0x003eb6ea, 0x003bb5eb, 0x0038b4eb, 0x0038b4eb, 0x0038b3eb, 0x0035b2eb, 0x0033b1ec, 0x0034b1eb, + 0x0035b1ea, 0x0032b3e9, 0x0030b5e9, 0x0034b0f0, 0x0023b6f8, 0x00c56044, 0x00f9540c, 0x00f26322, + 0x00f77029, 0x00f77d2f, 0x00f78b35, 0x00fba142, 0x00f6b046, 0x00fbb44f, 0x00f7b051, 0x00f9af54, + 0x00fbad56, 0x00fcb25a, 0x00feb75d, 0x00fab35f, 0x00f6b061, 0x00faac5d, 0x00fda95a, 0x00fb9f55, + 0x00f99551, 0x00f7914b, 0x00f68d45, 0x00ff7e23, 0x001ba5f0, 0x00129ef4, 0x002896f1, 0x00239fb1, + 0x006c9600, 0x003c9c82, 0x00179ef8, 0x00169cf4, 0x00149de3, 0x00169ae5, 0x001897e7, 0x001995e6, + 0x001a93e5, 0x001993e3, 0x001793e0, 0x001c98e6, 0x001a95e5, 0x001692e5, 0x00138fe5, 0x00138ceb, + 0x00138be3, 0x000087e4, 0x00007cf5, 0x001a86d3, 0x000d8cf1, 0x00008fe2, 0x000d85ea, 0x000886f1, + 0x003cb7ec, 0x003bb7ed, 0x003ab6ed, 0x0039b6ed, 0x0038b5ed, 0x0037b5ed, 0x0037b4ed, 0x0037b3ed, + 0x0036b3ec, 0x0034b4e9, 0x0031b5e5, 0x0035b1ef, 0x0021b8fa, 0x00fd4203, 0x00fc581e, 0x00f86a26, + 0x00f47c2d, 0x00f78431, 0x00f98c36, 0x00f8a041, 0x00f6b54d, 0x00fec05b, 0x00f6bc5a, 0x00f8ba5d, + 0x00fbb861, 0x00fdbe65, 0x00ffc469, 0x00fbc16c, 0x00f5bd70, 0x00fabc6b, 0x00febb66, 0x00fab160, + 0x00f6a75a, 0x00f89f55, 0x00fa984f, 0x00df956f, 0x0008a6fc, 0x00259ddb, 0x00159ff3, 0x004aa172, + 0x0069a90d, 0x0062a406, 0x005a981b, 0x0034969b, 0x000e99ff, 0x001297f2, 0x001695e4, 0x001793e5, + 0x001892e5, 0x001995e6, 0x001a98e7, 0x00209deb, 0x001593df, 0x001892e4, 0x001a91e9, 0x002095eb, + 0x00259dd1, 0x00d0f772, 0x00c1f396, 0x000083f1, 0x001782a0, 0x003c7e2f, 0x001787cc, 0x000b8ada, + 0x003db9ed, 0x003cb8ed, 0x003bb8ed, 0x003ab7ed, 0x0039b7ed, 0x0039b7ed, 0x0039b6ed, 0x003ab6ed, + 0x003ab6ed, 0x0037b4ed, 0x0034b2ec, 0x0035abf3, 0x006e96b3, 0x00ff4601, 0x00f86520, 0x00f67329, + 0x00f58131, 0x00f78b37, 0x00f9953e, 0x00f8a649, 0x00f8b854, 0x00fcc260, 0x00f8c465, 0x00f9c36a, + 0x00fac26e, 0x00fac773, 0x00facb77, 0x00fbcb7b, 0x00fccb7e, 0x00fac87b, 0x00f8c578, 0x00f9bc72, + 0x00fbb46d, 0x00f6b069, 0x00feaa57, 0x0094a0a5, 0x0013a1f3, 0x00219df0, 0x00199eff, 0x0071c124, + 0x0079b826, 0x0072b21e, 0x006aaa24, 0x0067a125, 0x00649a19, 0x00419d72, 0x001f9fcb, 0x001994ff, + 0x001399f1, 0x00199cf4, 0x001ea0f8, 0x001b9cff, 0x001193f6, 0x001293f1, 0x001393ec, 0x000083ff, + 0x0072cca0, 0x00cbf982, 0x00d0ffac, 0x0079a046, 0x00337700, 0x003a7c03, 0x000d8de2, 0x000d8edb, + 0x003fbbee, 0x003ebaed, 0x003db9ed, 0x003cb9ed, 0x003bb8ed, 0x003bb8ed, 0x003cb9ee, 0x003cb9ee, + 0x003db9ef, 0x003ab4f1, 0x0037aff3, 0x0032b3fe, 0x00b48f7d, 0x00ff5907, 0x00f37122, 0x00f57c2b, + 0x00f68735, 0x00f7923d, 0x00f89d45, 0x00f9ac50, 0x00f9bb5a, 0x00f9c465, 0x00facd71, 0x00facd76, + 0x00facd7b, 0x00f7cf80, 0x00f4d286, 0x00fcd689, 0x00ffd98c, 0x00fbd48b, 0x00f3cf8a, 0x00f9c885, + 0x00ffc17f, 0x00f5c27d, 0x00ffbc5e, 0x0048abdc, 0x001e9deb, 0x001ea2e8, 0x001da8e5, 0x0099d31c, + 0x008acb22, 0x0082c427, 0x007abc2c, 0x0075b429, 0x0070ad25, 0x006dab17, 0x006ba908, 0x005ea912, + 0x00519f54, 0x00489b6d, 0x003e9887, 0x003b9592, 0x00389880, 0x00449663, 0x00509446, 0x0083b43c, + 0x004f851b, 0x00afe187, 0x009fcc83, 0x00368011, 0x0043821c, 0x0032853c, 0x000492f9, 0x001092dd, + 0x0040bcee, 0x003fbcee, 0x003ebbee, 0x003dbaed, 0x003cbaed, 0x003cb9ed, 0x003cb9ec, 0x003cb9ec, + 0x003cb8ec, 0x003fb4f0, 0x0043aff5, 0x000ebbe9, 0x00ffb897, 0x00f7814d, 0x00f57623, 0x00f6812e, + 0x00f88c39, 0x00f89943, 0x00f8a64d, 0x00f8b257, 0x00f9bd60, 0x00fac96d, 0x00fbd47b, 0x00fad681, + 0x00fad788, 0x00fbd98e, 0x00fbda93, 0x00fae5a1, 0x00fed692, 0x00fadea0, 0x00f9db98, 0x00fad694, + 0x00fbd090, 0x00ffd285, 0x00ffc778, 0x00009afd, 0x0026a8f2, 0x0020a4f8, 0x0053bea5, 0x00a4da31, + 0x009dd638, 0x0097d03a, 0x0091ca3d, 0x008bc539, 0x0085c035, 0x007dbe31, 0x0074bc2d, 0x0076b81c, + 0x0077b027, 0x0072ab25, 0x006da724, 0x006ba328, 0x0068a31f, 0x0058951a, 0x0078b745, 0x00bbf181, + 0x0073ad4c, 0x00417c15, 0x00508b1e, 0x0043861c, 0x00498614, 0x0017868b, 0x000b90f6, 0x00168ee8, + 0x0042beef, 0x0041bdee, 0x0040bcee, 0x003fbced, 0x003ebbed, 0x003dbaec, 0x003db9eb, 0x003cb8ea, + 0x003bb7e9, 0x0039b9f0, 0x0037bbf7, 0x0050b5dc, 0x00ff9744, 0x00fec49d, 0x00f87a24, 0x00f88530, + 0x00f9913d, 0x00f8a049, 0x00f7af55, 0x00f8b85d, 0x00f9c065, 0x00face75, 0x00fcdb85, 0x00fbde8d, + 0x00fae195, 0x00fee29b, 0x00ffe2a0, 0x00fbe9a4, 0x00ffbe6b, 0x00fdde9f, 0x00ffe8a6, 0x00fbe3a3, + 0x00f8dea0, 0x00fdd899, 0x00b6bdab, 0x00119ff1, 0x001ea4e9, 0x001a9fff, 0x0089d465, 0x00b0e245, + 0x00b0e04e, 0x00acdc4e, 0x00a7d94e, 0x00a1d649, 0x009ad345, 0x0097ce3d, 0x0094c935, 0x008dc534, + 0x0086c133, 0x007bbc32, 0x006fb731, 0x006db330, 0x006cae2e, 0x007eba3f, 0x0070a531, 0x007bb54f, + 0x00579a20, 0x005c9f2b, 0x00519425, 0x0080b965, 0x00609a1d, 0x000390e3, 0x00118ef2, 0x001c89f2, + 0x0044c0ef, 0x0043bfef, 0x0042beee, 0x0040bdee, 0x003fbcee, 0x003fbbed, 0x0040baeb, 0x003eb9ed, + 0x003cb9ee, 0x0037b9eb, 0x0027bcf7, 0x00949c8f, 0x00fb9637, 0x00f9bc7c, 0x00f9b585, 0x00f7994a, + 0x00f69b43, 0x00f6a64e, 0x00f7b259, 0x00f8bc66, 0x00fac672, 0x00fad380, 0x00fae08d, 0x00f9e698, + 0x00f9eba2, 0x00feeaa6, 0x00ffeaab, 0x00fcefa9, 0x00faba62, 0x00fbdc99, 0x00fff4b9, 0x00fbecb2, + 0x00f7e6ab, 0x00ffe5a3, 0x0064b1d1, 0x00199ff0, 0x00269fe9, 0x000499f2, 0x00e3f051, 0x00d5ef58, + 0x00c0e364, 0x00bde165, 0x00bae065, 0x00b5de5d, 0x00b0dc56, 0x00aad74e, 0x00a3d346, 0x009bd043, + 0x0093cd3f, 0x008cc93e, 0x0084c63c, 0x0081c139, 0x007dbc36, 0x008bc746, 0x0089c245, 0x0063a02c, + 0x0065aa2c, 0x005ea42d, 0x00509626, 0x00a4cf98, 0x00d9eadd, 0x00b9ddff, 0x00389ef4, 0x00008fd4, + 0x0046c1ef, 0x0044c0ef, 0x0043bfef, 0x0042beef, 0x0040bdef, 0x0042bced, 0x0043baec, 0x0040baf0, + 0x003dbaf4, 0x0035b8e7, 0x0017bdf7, 0x00d97f50, 0x00f79147, 0x00f7a554, 0x00ffdbba, 0x00f8a24d, + 0x00f3a549, 0x00f5ad53, 0x00f7b55e, 0x00f9c16f, 0x00fbcc7f, 0x00f9d88a, 0x00f8e595, 0x00f8eda2, + 0x00f8f5ae, 0x00fff3b2, 0x00fff2b6, 0x00fef5ae, 0x00f4b659, 0x00f9db93, 0x00feffcd, 0x00fbf6c1, + 0x00f7edb6, 0x00fff2ac, 0x0013a4f7, 0x0016a5f0, 0x0018a5e8, 0x0056b4cd, 0x00f1f271, 0x00d5ef84, + 0x00cfe67b, 0x00cde77c, 0x00cbe77c, 0x00c9e672, 0x00c7e567, 0x00bce15f, 0x00b1dd57, 0x00a9dc51, + 0x00a0da4b, 0x009dd749, 0x009ad447, 0x0094cf43, 0x008fcb3f, 0x0088c43c, 0x0082be39, 0x0072b430, + 0x0063a928, 0x0059a028, 0x004e9827, 0x00a0c479, 0x00fffbf7, 0x007fd3f5, 0x00038fe2, 0x000e89e2, + 0x0048c3ef, 0x0046c2ef, 0x0045c1f0, 0x0043c0f0, 0x0042bff0, 0x0042beee, 0x0043bdec, 0x0041bcef, + 0x003fbcf2, 0x002fc0fe, 0x0036bdfc, 0x00f54c00, 0x00ff8a52, 0x00faa65e, 0x00fdc48e, 0x00fbc185, + 0x00f5ae50, 0x00f7b65e, 0x00f9be6c, 0x00fac978, 0x00fbd485, 0x00fede98, 0x00ffe8aa, 0x00fdeeae, + 0x00f9f5b2, 0x00fcf6ba, 0x00fff7c2, 0x00fcf0b2, 0x00f7cc6e, 0x00fbde91, 0x00fdfcca, 0x00fffbd1, + 0x00fffdc8, 0x00cae4c8, 0x0016a1f2, 0x001da4ef, 0x0012a1f1, 0x009fd5b9, 0x00eaf28c, 0x00dcf095, + 0x00d9eb90, 0x00d9ec93, 0x00d9ec95, 0x00d6eb8c, 0x00d4ea83, 0x00c9e779, 0x00bfe36f, 0x00b8e368, + 0x00b1e262, 0x00afe05e, 0x00addf5a, 0x00a3d952, 0x0099d449, 0x008ecb41, 0x0084c33a, 0x0075b833, + 0x0066ac2c, 0x005da329, 0x00559927, 0x004b9421, 0x002499b9, 0x001593fe, 0x000993d8, 0x000f90d8, + 0x004ac5ef, 0x0048c4f0, 0x0046c2f0, 0x0045c1f1, 0x0043c0f1, 0x0043bfef, 0x0043bfed, 0x0042beee, + 0x0041bdf0, 0x0038bbf0, 0x0072a1b8, 0x00ff5d1e, 0x00f97931, 0x00f5a151, 0x00f9ad61, 0x00fee0bd, + 0x00f8b758, 0x00fabf69, 0x00fcc87a, 0x00fcd282, 0x00fcdc8b, 0x00fbde8f, 0x00fbe193, 0x00fbeba4, + 0x00fbf5b5, 0x00faf8c2, 0x00f9fcce, 0x00f9ecb7, 0x00fae183, 0x00fee290, 0x00fbfac8, 0x00fdf8d8, + 0x00fffccb, 0x008bcedc, 0x00189fee, 0x0025a3ee, 0x000b9dfb, 0x00e8f6a5, 0x00e4f1a6, 0x00e4f0a6, + 0x00e4efa6, 0x00e5f1aa, 0x00e6f2ad, 0x00e3f1a6, 0x00e0ef9e, 0x00d7ec93, 0x00cde987, 0x00c8ea80, + 0x00c2eb78, 0x00c1ea73, 0x00c0e96e, 0x00b1e360, 0x00a3dd53, 0x0094d247, 0x0086c83b, 0x0078bc35, + 0x0069b030, 0x0062a52b, 0x005b9b27, 0x0057920a, 0x000995fc, 0x000d96e5, 0x001091eb, 0x001091eb, + 0x004ac5f0, 0x0049c4f0, 0x0047c3f1, 0x0045c2f1, 0x0044c1f2, 0x0041c1f2, 0x003fc1f2, 0x003fbff1, + 0x003fbcf0, 0x0032c3fe, 0x00be7f6e, 0x00fe6526, 0x00f67b35, 0x00f59a4d, 0x00f8ab5c, 0x00fbd0a0, + 0x00f7c783, 0x00fec16b, 0x00fdd17f, 0x00fbdb87, 0x00f9e590, 0x00f8ed9a, 0x00f7f4a5, 0x00fbea9a, + 0x00ffdf8e, 0x00fce3a0, 0x00f7e6b1, 0x00fceecc, 0x00fffbcb, 0x00fff3c7, 0x00fcf1c3, 0x00fef5d2, + 0x00fffcd3, 0x004bb5e7, 0x0021a5ed, 0x001ca2ee, 0x003daae2, 0x00eef6ac, 0x00e6f2b1, 0x00e8f2b5, + 0x00e9f3b8, 0x00eaf4ba, 0x00ebf5bc, 0x00e8f3b6, 0x00e6f2af, 0x00e0f0a8, 0x00dbeea2, 0x00d6ef9a, + 0x00d1f092, 0x00c9ed82, 0x00c1eb73, 0x00b0e362, 0x00a1dc51, 0x0094d347, 0x0088ca3e, 0x007bbf38, + 0x006eb433, 0x0066a92e, 0x005da01b, 0x003d9448, 0x000a93f6, 0x000e94ec, 0x001193f0, 0x001193f0, + 0x004bc5f1, 0x004ac5f1, 0x0048c4f1, 0x0047c3f2, 0x0045c3f2, 0x0040c3f4, 0x003bc4f6, 0x003cbff3, + 0x003ebbf0, 0x002dcaff, 0x00ff5d25, 0x00fe6d2f, 0x00f37d39, 0x00f59348, 0x00f8a958, 0x00f7c083, + 0x00f7d7ae, 0x00ffc36d, 0x00ffda84, 0x00fbe48c, 0x00f7ee94, 0x00f8ed9e, 0x00faeca7, 0x00f9f1b4, + 0x00f8f6c1, 0x00fcf6c8, 0x00fff6d0, 0x00fef2d3, 0x00fcf4ba, 0x00fffee8, 0x00f7fdea, 0x00fdfde3, + 0x00fffcdc, 0x000b9df1, 0x002aaaed, 0x001baaf6, 0x0080c8da, 0x00fdffbb, 0x00e8f2bd, 0x00ebf4c4, + 0x00eff7cb, 0x00eff7cb, 0x00eff7cb, 0x00edf6c5, 0x00ebf5c0, 0x00eaf4be, 0x00e8f3bd, 0x00e4f4b4, + 0x00e0f6ab, 0x00d0f191, 0x00c1ec77, 0x00b0e463, 0x009edb4e, 0x0095d448, 0x008bcc42, 0x007fc23b, + 0x0073b935, 0x006aac31, 0x0060a510, 0x00229687, 0x000b91f1, 0x000e93f3, 0x001294f5, 0x001294f5, + 0x004cc6f1, 0x004bc5f2, 0x0049c5f2, 0x0047c4f2, 0x0046c4f2, 0x0043c4f1, 0x0040c4f0, 0x0042c0f3, + 0x0039c1f6, 0x005eacca, 0x00fb591e, 0x00f36e31, 0x00f88135, 0x00fb923f, 0x00fbaf5e, 0x00ffc373, + 0x00fde2ba, 0x00ffcd75, 0x00ffd372, 0x00ffe584, 0x00fff796, 0x00fef4a2, 0x00fdf1ae, 0x00fff8c2, + 0x00fcf8cd, 0x00fef8d2, 0x00fff9d6, 0x00fef6e1, 0x00fcf5dd, 0x00fffbee, 0x00fbfce8, 0x00fffce0, + 0x00b2e0e8, 0x0019a4f0, 0x0026abec, 0x0016a8f6, 0x00c2e4d8, 0x00f9fac5, 0x00eff6cb, 0x00f0f7ce, + 0x00f1f8d2, 0x00f1f8d1, 0x00f2f9d1, 0x00f1f9cd, 0x00f1f9ca, 0x00f2fbca, 0x00f4fdca, 0x00e7f8b6, + 0x00daf3a2, 0x00cbef8a, 0x00bcec71, 0x00b0e661, 0x00a5e151, 0x009ad949, 0x008fd240, 0x0083c73b, + 0x0077bc35, 0x006ab31d, 0x005ea905, 0x00138dea, 0x001193ef, 0x001093f0, 0x000f93f0, 0x000f93f0, + 0x004dc6f2, 0x004cc6f2, 0x004ac5f3, 0x0048c5f3, 0x0047c5f3, 0x0046c4ef, 0x0046c4eb, 0x0048c0f3, + 0x0034c7fb, 0x00989591, 0x00fc6428, 0x00f1773b, 0x00fc8432, 0x00ff9135, 0x00ffb564, 0x00ffbe5a, + 0x00f3ddb6, 0x00ccd097, 0x00b4cea5, 0x00b0d3b1, 0x00abd7bd, 0x00c3e1bf, 0x00daebc1, 0x00f5fdc7, + 0x00ffffbd, 0x00fffecd, 0x00fffcdc, 0x00fffce0, 0x00fbfce5, 0x00fdfbe6, 0x00fffae7, 0x00fffbdd, + 0x0061c4f4, 0x0026aaee, 0x0022abec, 0x0010a7f6, 0x00ffffd7, 0x00f5f5d0, 0x00f6fad9, 0x00f4f9d9, + 0x00f2f9da, 0x00f3fad8, 0x00f4fbd7, 0x00f5fcd5, 0x00f7fdd4, 0x00f3face, 0x00f0f7c8, 0x00e2f4b0, + 0x00d4f199, 0x00c5ee82, 0x00b7eb6b, 0x00b1e95f, 0x00abe754, 0x009fdf49, 0x0094d83f, 0x0087cc3a, + 0x007bc034, 0x006bb425, 0x005ba332, 0x000495f9, 0x001795ee, 0x001293ed, 0x000c91eb, 0x000c91eb, + 0x004fc8f3, 0x004dc8f3, 0x004cc8f4, 0x004bc8f4, 0x0049c8f4, 0x0047c5f2, 0x0045c2ef, 0x0042c2f8, + 0x0034c8ff, 0x00df6746, 0x00ff632a, 0x00ff701b, 0x00e18b53, 0x00a4a185, 0x0063c1cd, 0x0026c0ff, + 0x002ab8ff, 0x0025b5f1, 0x0027b7f9, 0x0026b5f6, 0x0023b3f2, 0x0024b5fa, 0x0025b7ff, 0x00189ddf, + 0x0043bbf4, 0x009edae8, 0x00f9f9dc, 0x00f3fbe6, 0x00ffffea, 0x00fdffe6, 0x00fafce2, 0x00ffffff, + 0x001ea8ef, 0x001ca8f1, 0x001ba8f2, 0x005bc4f1, 0x00ffffe7, 0x00fbf9e1, 0x00fbfce3, 0x00f8fbe0, + 0x00f5fadd, 0x00f5fbdb, 0x00f5fbda, 0x00f6fcd7, 0x00f6fdd3, 0x00f0f8c9, 0x00ebf4be, 0x00dff2a9, + 0x00d4f094, 0x00c7f47b, 0x00baf862, 0x00b0ef58, 0x00a6e64e, 0x00a3e248, 0x0098d73a, 0x008acd38, + 0x007bc435, 0x0070b821, 0x003b9c84, 0x000d93f4, 0x001394ed, 0x001193e9, 0x000f92e6, 0x000f92e6, + 0x0050c9f4, 0x004fcaf4, 0x004ecaf5, 0x004dcaf5, 0x004ccaf6, 0x0048c5f4, 0x0045c0f3, 0x0047c2ef, + 0x004ac4eb, 0x00ff521f, 0x00a79a92, 0x0051b7e6, 0x0028c7ff, 0x002cc4f9, 0x0031c1f1, 0x003fbbf0, + 0x0037c0ef, 0x0039b9f0, 0x003bb3f1, 0x0038b5f4, 0x0036b7f7, 0x0032b9f0, 0x002fbbe8, 0x002fb8eb, + 0x002fb5ed, 0x0020acf3, 0x0010a3fa, 0x0070c9f3, 0x00f5f9df, 0x00f6fbde, 0x00f6fdde, 0x00d8ebe4, + 0x0011a5ee, 0x002db2f5, 0x0014a5f8, 0x00a5e2ec, 0x00fffff8, 0x00fffef3, 0x00fffded, 0x00fcfde6, + 0x00f8fce0, 0x00f7fcde, 0x00f6fcdd, 0x00f6fcd8, 0x00f5fdd3, 0x00edf7c4, 0x00e5f1b4, 0x00e5f5b8, + 0x00e4f9bb, 0x00ecfed2, 0x00f3ffe9, 0x00edfedb, 0x00e8f9cd, 0x00caef89, 0x009cd636, 0x0084c72e, + 0x006bb826, 0x006cb315, 0x001a95d6, 0x001591ef, 0x001093eb, 0x001193e6, 0x001294e1, 0x001294e1, + 0x0052cbf4, 0x0050caf4, 0x004ecaf4, 0x004ccaf3, 0x004ac9f3, 0x0048c8f5, 0x0046c7f6, 0x0040bfed, + 0x0041bfeb, 0x0041d4f9, 0x0033c9fc, 0x002fc9ff, 0x0042c3ec, 0x0040c3f4, 0x003ec3fc, 0x0035bbf4, + 0x0033bbf3, 0x0049bdf7, 0x0039b7f9, 0x0037b7f6, 0x0035b7f2, 0x002eb5f4, 0x0028b3f5, 0x002fbbf8, + 0x002fbaf2, 0x0030b5f2, 0x0031b0f1, 0x001facf6, 0x000dabed, 0x007fd2ed, 0x00ffffe6, 0x0080d9d2, + 0x002faaf8, 0x001dafec, 0x0003aae6, 0x00fff8ff, 0x00fffffe, 0x00fffff9, 0x00fffdf4, 0x00fdfeeb, + 0x00fbfee3, 0x00f9fde1, 0x00f7fce0, 0x00f5fdd8, 0x00f4fdcf, 0x00f5fce2, 0x00f6fde8, 0x00f3fde8, + 0x00f1fde9, 0x00ebfdd3, 0x00e6fdbe, 0x00e0f8ba, 0x00daf2b7, 0x00eafcd2, 0x00f2fde6, 0x00b7de8d, + 0x0084c73d, 0x009ab848, 0x0014a1f9, 0x000494f3, 0x001094ef, 0x001095ec, 0x001095e9, 0x001095e9, + 0x0054ccf5, 0x0051cbf4, 0x004ecaf3, 0x004cc9f2, 0x0049c8f1, 0x0048cbf5, 0x0048cef9, 0x0040c4f3, + 0x0049cafc, 0x0040c2f1, 0x0047caf5, 0x0046c7f4, 0x0046c4f3, 0x0039b5ee, 0x002ca5e8, 0x002eb1e1, + 0x0056c1ea, 0x006dc9e9, 0x0037c2e5, 0x0051caeb, 0x006bd2f1, 0x0074d1f5, 0x007dcff9, 0x0056c7f8, + 0x001fafe8, 0x0025b1ee, 0x002cb3f4, 0x003eb5f9, 0x002bb3ee, 0x001baff5, 0x0032b5f0, 0x003fb2f9, + 0x0026a9f2, 0x001faeeb, 0x003fb8f4, 0x00fcfff3, 0x00ffffff, 0x00ffffff, 0x00fffefb, 0x00fefff1, + 0x00feffe6, 0x00fbffe5, 0x00f8fde3, 0x00f5fdd7, 0x00f3fecb, 0x00f5fbeb, 0x00f7feee, 0x00f2fdde, + 0x00edfccf, 0x00e3f9b0, 0x00d9f692, 0x00d2f48b, 0x00ccf184, 0x00ceee97, 0x00d0eaa9, 0x00daebc1, + 0x00f4fbe9, 0x007fc679, 0x005ac1ff, 0x001aa1eb, 0x001195f2, 0x000f96f2, 0x000e97f2, 0x000e97f2, + 0x0054cdf5, 0x0052ccf4, 0x004fcbf3, 0x004dc9f3, 0x004ac8f2, 0x0049c6f2, 0x0047c4f2, 0x0049d2f3, + 0x0046c8f3, 0x004dc5fc, 0x002c9add, 0x001883cd, 0x00046cbe, 0x000080c5, 0x000f96d4, 0x002eaddb, + 0x0060c6eb, 0x0076cdef, 0x0051caea, 0x0069d2f0, 0x0081daf5, 0x009ae4f7, 0x00b3eff9, 0x00cffaff, + 0x00e3feff, 0x009ae1ff, 0x0048bcf7, 0x0011b5dd, 0x0032aef0, 0x0028acfc, 0x0031b2f3, 0x0034b1f6, + 0x0025adf0, 0x0026acf6, 0x0098d1fc, 0x00fffdf8, 0x00ffffff, 0x00fffffb, 0x00fefff4, 0x00fdffee, + 0x00fcfde7, 0x00fbfee4, 0x00faffe0, 0x00f8fde7, 0x00f7fcef, 0x00f3fbeb, 0x00effdd9, 0x00e9fbc2, + 0x00e3f9ac, 0x00d9f49b, 0x00ceef8b, 0x00c1ea76, 0x00b4e562, 0x00abdd5a, 0x00a2d261, 0x00c1e98e, + 0x00dbe8b9, 0x0096d4ff, 0x008ed0fa, 0x0042aeee, 0x001095f1, 0x001096f1, 0x000f96f1, 0x000f96f1, + 0x0055cef5, 0x0053ccf4, 0x0050cbf4, 0x004ecaf4, 0x004cc8f4, 0x0051caf7, 0x0057cbfa, 0x0045c0ea, + 0x001a75c7, 0x000058ad, 0x00015bb4, 0x00066fc0, 0x000b84cd, 0x000093ce, 0x0011a7e0, 0x003eb9e6, + 0x006bcbeb, 0x007ed1f6, 0x006cd3f0, 0x0082dbf4, 0x0098e3f9, 0x00a5ecf7, 0x00b2f4f5, 0x00c7f7f9, + 0x00ddfafd, 0x00f2ffff, 0x00f8fff6, 0x00bcebfe, 0x0022b4f2, 0x0029afff, 0x002fb0f7, 0x0029b1f2, + 0x0023b1ee, 0x001aa7fa, 0x00cae6f4, 0x00f7f8f4, 0x00feffff, 0x00fefff7, 0x00feffed, 0x00fcffeb, + 0x00fbfae9, 0x00fbfee3, 0x00fbffdc, 0x00fbffe9, 0x00fbfff7, 0x00f1fedd, 0x00e7fbc3, 0x00e0f6b4, + 0x00d8f0a5, 0x00ceec94, 0x00c4e884, 0x00b8e678, 0x00ace36c, 0x00a0df53, 0x0094d455, 0x0080bd41, + 0x00d2e599, 0x002ca1f4, 0x0030a2f6, 0x00209cf3, 0x001096f1, 0x001096f1, 0x001096f1, 0x001096f1, + 0x0055cef4, 0x0053cdf4, 0x0051cbf5, 0x0050cbf5, 0x004ecaf6, 0x004dc9f4, 0x0054d0fa, 0x002b86ce, + 0x000752b1, 0x00045fb9, 0x000a74c9, 0x000882ce, 0x000691d4, 0x0002a0d5, 0x0024b5e7, 0x004cc4ea, + 0x0074d3ee, 0x0083d9f5, 0x007fddf4, 0x0093e4f6, 0x00a8ecf9, 0x00b6f2f9, 0x00c3f9f9, 0x00d3fafb, + 0x00e3fcfc, 0x00edfefb, 0x00f0f9f3, 0x00ffffff, 0x00fffdff, 0x007edcef, 0x0026adfd, 0x002aaff7, + 0x002db2f2, 0x0034b1e0, 0x0009a7f7, 0x008dd3f5, 0x00fdfbf9, 0x00fffff6, 0x00fdffeb, 0x00fcffe6, + 0x00fcfce0, 0x00f9fcde, 0x00f7fcdd, 0x00fcffef, 0x00f9fdec, 0x00e8f5d0, 0x00dff5bd, 0x00d9f1ad, + 0x00d2ed9d, 0x00c5e97e, 0x00b8e26d, 0x00abdd5e, 0x009fd74f, 0x0098c95f, 0x0092c735, 0x008bc942, + 0x0080b34d, 0x00009bf2, 0x001894f8, 0x001595f5, 0x001397f2, 0x001296f1, 0x001195f0, 0x001195f0, + 0x0056cff4, 0x0054cdf5, 0x0052ccf5, 0x0051cbf7, 0x0051cbf9, 0x0049c8f1, 0x0051d5fa, 0x001662c1, + 0x00005cbb, 0x000874cd, 0x00037cce, 0x00028dd4, 0x00019edb, 0x0009aedc, 0x0037c2ee, 0x005acfef, + 0x007edcf0, 0x0088e1f4, 0x0092e6f8, 0x00a5eef8, 0x00b9f5f9, 0x00c7f9fb, 0x00d5fdfe, 0x00dffdfc, + 0x00e9fdfa, 0x00f0fefe, 0x00f8ffff, 0x00fafffe, 0x00fdfffc, 0x00fdfbff, 0x001db0e8, 0x002ab1ee, + 0x0037b2f5, 0x0025b9f7, 0x0029b4f8, 0x0022aff5, 0x001baaf2, 0x009fd7f6, 0x00fdffea, 0x00fcfee0, + 0x00fcfdd7, 0x00f8fada, 0x00f4f7dd, 0x00fdfef5, 0x00f6fae1, 0x00dfecc3, 0x00d8efb6, 0x00d2eca6, + 0x00ccea95, 0x00bce567, 0x00abdb56, 0x009fd344, 0x0092cb33, 0x0085c824, 0x0079b46a, 0x003a9eaf, + 0x000c97ff, 0x001994f9, 0x000f9bee, 0x00139af0, 0x001699f3, 0x001497f1, 0x001295ef, 0x001295ef, + 0x0058d0f5, 0x0056cef5, 0x0053cdf4, 0x0053ccf6, 0x0052cbf8, 0x0053d6fb, 0x004fc8fc, 0x00004cad, + 0x00096fca, 0x000b80d4, 0x000588d5, 0x000598db, 0x0005a8e1, 0x0018b6e6, 0x003fc8f2, 0x0063d3f3, + 0x0086dff5, 0x0091e4f7, 0x009ce9fa, 0x00aef0f9, 0x00c0f7f9, 0x00cbfafb, 0x00d7fdfd, 0x00defdfc, + 0x00e6fefb, 0x00f0fffe, 0x00faffff, 0x00f2fefb, 0x00fefffd, 0x00c6e9fb, 0x001eb0ec, 0x0030b4f6, + 0x0030b7f8, 0x0019a8f7, 0x0026b0f0, 0x0022aef3, 0x001eabf5, 0x0027aafa, 0x001ca6f6, 0x007dcdea, + 0x00dff4dd, 0x00eaffb0, 0x00fdfeed, 0x00ffffef, 0x00fcf9d3, 0x00edeeb4, 0x00e6e9ac, 0x00d9e68a, + 0x00cbe367, 0x00b9e153, 0x00a6dd4d, 0x0075c57f, 0x0043adb0, 0x00229bf3, 0x000a9cff, 0x000998f6, + 0x00109cef, 0x00189aee, 0x00149ded, 0x00159bf0, 0x001599f2, 0x001397f0, 0x001195ee, 0x001195ee, + 0x005ad1f6, 0x0057cff5, 0x0054cef4, 0x0054cdf6, 0x0053cbf8, 0x004dd3f4, 0x002c9add, 0x00045ec1, + 0x000572c9, 0x000683d2, 0x000794dc, 0x0008a2e2, 0x0008b1e8, 0x0028bfef, 0x0048cef6, 0x006bd8f8, + 0x008fe3fa, 0x009be8fa, 0x00a6edfb, 0x00b7f3fb, 0x00c7f9fa, 0x00d0fbfc, 0x00d9fdfd, 0x00defefd, + 0x00e2fffc, 0x00effffe, 0x00fcffff, 0x00ebfef7, 0x00fffffe, 0x008fd7f8, 0x001eb0f1, 0x002eb0f6, + 0x0018abec, 0x00e0f7fd, 0x0024ade9, 0x0023acf1, 0x0021acf8, 0x0026aef7, 0x002cb0f6, 0x001aa9f5, + 0x0008a3f4, 0x0022a7f9, 0x004cc2f2, 0x006dcdef, 0x007ec9db, 0x007fcac2, 0x0081c6c6, 0x0061bccb, + 0x0041b3d0, 0x0024a7e9, 0x00089bff, 0x00119dff, 0x001a9fff, 0x000f99e9, 0x00149cf9, 0x00159cf7, + 0x00159cf5, 0x00179df1, 0x00199eed, 0x00179cef, 0x001599f1, 0x001397ef, 0x001195ed, 0x001195ed, + 0x005cd2f6, 0x0059d0f5, 0x0055cff3, 0x0054cdf5, 0x0053ccf8, 0x0051d5f6, 0x00167bcf, 0x000467c6, + 0x00067bcf, 0x00068bd7, 0x00059cdf, 0x0008a9e5, 0x000ab6eb, 0x002bc4f1, 0x004cd2f7, 0x006ddbf9, + 0x008ee5fa, 0x009deafb, 0x00aceffb, 0x00bdf5fb, 0x00cefbfa, 0x00d5fbfc, 0x00dcfcfd, 0x00dcfefd, + 0x00ddfffd, 0x00e4fffd, 0x00eafffd, 0x00fffffe, 0x00ffffff, 0x0027c0de, 0x0026b5f6, 0x001fb0f9, + 0x004dc6ff, 0x00fff9ef, 0x00fefffa, 0x008bd8f7, 0x0018a7f3, 0x001daaf4, 0x0023acf6, 0x0022acf3, + 0x0022abf0, 0x001aa3f2, 0x001aa6ee, 0x0018a8f5, 0x000ea2f3, 0x0011a4f2, 0x0014a4ff, 0x0015a3fc, + 0x0016a3fa, 0x0017a2f3, 0x0019a2ec, 0x000e99fe, 0x00169bed, 0x0000a1ff, 0x002b9de8, 0x0061b5b0, + 0x00109af7, 0x00149cf2, 0x00189eed, 0x00169cef, 0x00149af0, 0x001298ee, 0x001096ec, 0x001096ec, + 0x005fd3f7, 0x005bd2f5, 0x0056d0f3, 0x0055cef5, 0x0053cdf7, 0x0056d8f8, 0x00005cc0, 0x000370cb, + 0x000785d6, 0x000594dc, 0x0004a3e2, 0x0008afe8, 0x000cbcee, 0x002ec8f3, 0x0050d5f9, 0x006fdefa, + 0x008de7fb, 0x009fecfb, 0x00b1f2fb, 0x00c3f7fb, 0x00d4fcfa, 0x00d9fcfc, 0x00defcfd, 0x00dbfdfd, + 0x00d9fffd, 0x00d9fdfb, 0x00d9fcfa, 0x00e5fafa, 0x00a4eaf7, 0x002badfb, 0x002fb9fa, 0x001aaeed, + 0x0099dbf8, 0x00ffffff, 0x00fefdfc, 0x00fffefd, 0x00fffffd, 0x008cd4fa, 0x0019a9f6, 0x0018a9f7, + 0x0016aaf9, 0x001aa7f3, 0x001ea5ee, 0x001fa7f2, 0x0021a9f6, 0x001ea7f7, 0x001ba5f7, 0x0017a4f9, + 0x0012a2fb, 0x000b9dfd, 0x000399fe, 0x0026a2fa, 0x006fc0b0, 0x00cfca5e, 0x00ffe528, 0x0074b4b3, + 0x000b98fa, 0x00119af4, 0x00179dee, 0x00159cee, 0x00139aef, 0x001198ed, 0x000f96eb, 0x000f96eb, + 0x005dd1f6, 0x005bd2f5, 0x0058d2f4, 0x0053cef4, 0x0056d2fb, 0x0040b2e6, 0x000164c6, 0x000376cf, + 0x000487d7, 0x000296dd, 0x0001a4e4, 0x0004b1ea, 0x0007bdf1, 0x001bc8f2, 0x0043d5fc, 0x0064ddfb, + 0x0085e6fb, 0x0098ebfc, 0x00acf1fd, 0x00bef9ff, 0x00cfffff, 0x00cffdff, 0x00cff9fb, 0x00d2fefe, + 0x00d5ffff, 0x00c6f9ff, 0x00b8efff, 0x005ad7d9, 0x0040b9e9, 0x002fb9ff, 0x002bb2f0, 0x0028afeb, + 0x00def0f2, 0x00ffffff, 0x00feffff, 0x00fffefe, 0x00fffefa, 0x00fffffa, 0x00fffff9, 0x00c2e8f0, + 0x0084cde7, 0x0053bbe9, 0x0022a9eb, 0x0014a1ff, 0x00069ff8, 0x000fa0f8, 0x0019a3eb, 0x0043b1e1, + 0x006ec2c9, 0x00b0d79a, 0x00f2eb6b, 0x00ebee32, 0x00f8e647, 0x00ffe23a, 0x00fde142, 0x000098f4, + 0x0019a1fc, 0x00169ef7, 0x00129bf1, 0x00139af1, 0x00149af0, 0x001298ee, 0x001096ec, 0x001096ec, + 0x005ccff6, 0x005bd2f6, 0x005ad4f6, 0x0052cdf2, 0x005ad6fe, 0x00298cd5, 0x00026ccc, 0x00027bd2, + 0x000189d8, 0x000097df, 0x0000a6e6, 0x0000b2ed, 0x0002bef4, 0x0009c7f1, 0x0035d5ff, 0x0059ddfd, + 0x007ce5fb, 0x0091eafd, 0x00a6f0ff, 0x00b1f2ff, 0x00bbf5ff, 0x00bef5fc, 0x00c1f6f9, 0x00c1f7f7, + 0x00c1f9f4, 0x00c7fdfc, 0x00cdffff, 0x00c2f9f8, 0x005acdf4, 0x0039b1f3, 0x0038baf5, 0x002ab4f7, + 0x00fcfbf8, 0x00fdfeff, 0x00feffff, 0x00fffeff, 0x00fffcf6, 0x00fdfef2, 0x00f7ffee, 0x00fcffea, + 0x00ffffe5, 0x00ffffd8, 0x00ffffcb, 0x00fffbf1, 0x00ffffdf, 0x00fdfdc2, 0x00f7ff88, 0x00fbfe92, + 0x00ffff7f, 0x00fdfc6c, 0x00faf759, 0x00f8f059, 0x00f7e958, 0x00f7e359, 0x00d0d368, 0x000998ff, + 0x00189aef, 0x00129af2, 0x000c99f5, 0x001199f3, 0x001599f2, 0x001397f0, 0x001195ee, 0x001195ee, + 0x005fd2f9, 0x005cd3f8, 0x0059d4f6, 0x0058d3f8, 0x005edaff, 0x001971cd, 0x00026ecd, 0x00037bd3, + 0x000488d9, 0x000497e0, 0x0005a6e6, 0x0001ade7, 0x0000b5e8, 0x0007beea, 0x0023cbf5, 0x004cd7f8, + 0x0074e4fc, 0x0089e8fd, 0x009fecfe, 0x00a5edfe, 0x00abeffe, 0x00aeeffc, 0x00b0eff9, 0x00b3f3f9, + 0x00b6f6f8, 0x00b6f9fc, 0x00b5fcff, 0x00daf3ff, 0x001ab9f1, 0x0028b3f4, 0x002bb3f6, 0x0073cef4, + 0x00fdfdf5, 0x00fdfefa, 0x00fdfffe, 0x00fffef9, 0x00fffdf3, 0x00fdfeee, 0x00faffe9, 0x00fdffe4, + 0x00ffffde, 0x00ffffd0, 0x00ffffc2, 0x00fdfad7, 0x00fffcf3, 0x00ffffc0, 0x00fcfbc5, 0x00fcff84, + 0x00fcfb8b, 0x00fbf67a, 0x00f9f269, 0x00f7ed5e, 0x00f4e954, 0x00f7e948, 0x0087bda9, 0x00109afc, + 0x00179cf2, 0x00149bf1, 0x00119af1, 0x001399f2, 0x001698f3, 0x001496f1, 0x001294ef, 0x001294ef, + 0x0062d4fc, 0x005dd4f9, 0x0059d4f6, 0x0056d1f6, 0x0053cef5, 0x00014ebe, 0x00026fcd, 0x00057bd4, + 0x000787da, 0x000996e0, 0x000ca5e7, 0x000bb0e9, 0x0009bbeb, 0x0015c5f3, 0x0021d0fc, 0x0046dafc, + 0x006ce3fc, 0x0082e6fd, 0x0097e9fe, 0x0099e9fe, 0x009ce8fe, 0x009ee9fb, 0x00a0e9f9, 0x00a6eefa, + 0x00acf3fc, 0x00b0effc, 0x00b5ecfb, 0x0089ddf9, 0x0028b4f3, 0x003ebef7, 0x001eadf7, 0x00bde8f0, + 0x00fefff2, 0x00fefff3, 0x00fdfff4, 0x00fefef2, 0x00fefef0, 0x00fefeea, 0x00fefee4, 0x00fefede, + 0x00fefed8, 0x00fcffc9, 0x00fbffba, 0x00f6fea0, 0x00ffffce, 0x00fff9f6, 0x00ffffc9, 0x00fdf7be, + 0x00f8f87a, 0x00f9f66b, 0x00f9f35c, 0x00f5ee56, 0x00f1e84f, 0x00f8ee37, 0x003fa7ea, 0x00189df5, + 0x00179df4, 0x00169cf1, 0x00159bee, 0x00169af2, 0x001798f5, 0x001596f3, 0x001394f1, 0x001394f1, + 0x0066d7fc, 0x005fd1f5, 0x0060d4f6, 0x0059d8f9, 0x00399ddb, 0x000858be, 0x00096ccd, 0x000c7ad2, + 0x001087d7, 0x001296df, 0x0013a6e8, 0x0013b0eb, 0x001bc3f5, 0x000fc8f3, 0x0017d0f9, 0x0027d3f4, + 0x004bd7f7, 0x0061dbf8, 0x0077def9, 0x007fe0fa, 0x0088e1fa, 0x008de4fb, 0x0091e7fb, 0x0096eafc, + 0x009aedfd, 0x009feafb, 0x00a3e7fa, 0x005eccfb, 0x002db7f5, 0x0024b8f9, 0x0014b1f5, 0x00fffbff, + 0x00feffec, 0x00ffffed, 0x00ffffee, 0x00ffffec, 0x00fefdeb, 0x00fefde4, 0x00fefddd, 0x00fefed6, + 0x00fefece, 0x00fcfdc1, 0x00fcfcb5, 0x00f6fb8d, 0x00f8fc8a, 0x00f8facc, 0x00f8fef2, 0x00f9ffbe, + 0x00fbf9c2, 0x00fbf8ac, 0x00fcf796, 0x00faf491, 0x00f7f18d, 0x00ffe5a9, 0x000096f7, 0x00089af7, + 0x00159ef7, 0x00169df4, 0x00169cf0, 0x00169bf2, 0x001699f4, 0x001497f3, 0x001396f1, 0x001396f1, + 0x006bd9fb, 0x0061cef1, 0x0067d3f7, 0x005cdefd, 0x001f6cc0, 0x000f63bf, 0x000f6acd, 0x001478d1, + 0x001887d4, 0x001997df, 0x001aa6e9, 0x0014a9e4, 0x001dbbef, 0x000dbeeb, 0x0023c5f6, 0x0013c6ed, + 0x002acbf3, 0x0040cff4, 0x0056d4f4, 0x0065d7f6, 0x0074daf7, 0x007bdffb, 0x0083e5fe, 0x0086e6fe, + 0x0089e8fd, 0x008ee5fb, 0x0092e2fa, 0x0033bcfc, 0x0032b9f7, 0x0031bafd, 0x0057c5f7, 0x00f4ffde, + 0x00fdffe7, 0x00ffffe7, 0x00ffffe7, 0x00ffffe6, 0x00fdfce6, 0x00fdfddd, 0x00fdfdd5, 0x00fdfdcd, + 0x00fefdc5, 0x00fdfaba, 0x00fcf8af, 0x00fef99f, 0x00fffb8e, 0x00fafe77, 0x00f4fb7d, 0x00f9f8d2, + 0x00fdffee, 0x00fefedf, 0x00fffcd0, 0x00fefacd, 0x00fdf9ca, 0x00a6d3ce, 0x000399eb, 0x001ea1ec, + 0x00149ffa, 0x00159ef6, 0x00179ef2, 0x00169cf3, 0x00159af3, 0x001499f2, 0x001398f1, 0x001398f1, + 0x0055d4f4, 0x005bd1f1, 0x0069d6f6, 0x006ee2ff, 0x000c50a8, 0x001161be, 0x000f6acd, 0x001f83d6, + 0x001f89dc, 0x000f8cdd, 0x001a9be0, 0x0022b1f4, 0x001dabe1, 0x0014aedf, 0x0026bdee, 0x0015bae7, + 0x001fc1ef, 0x0025c7ef, 0x002bcdef, 0x003dcdf1, 0x004ecef3, 0x005bd6f9, 0x0068defe, 0x006eddfc, + 0x0073ddfb, 0x0076ddf5, 0x0070d3f7, 0x0031bafb, 0x0033b9f6, 0x0024b6ff, 0x00a4dee5, 0x00f9ffdc, + 0x00fdfedc, 0x00ffffdc, 0x00ffffdc, 0x00fefedb, 0x00fcfdda, 0x00fdfdd2, 0x00fdfdcb, 0x00fdfdc3, + 0x00fefdbc, 0x00fdfbaf, 0x00fcfaa2, 0x00fdfb93, 0x00fefb83, 0x00fcfd6b, 0x00f9fc60, 0x00fbf85d, + 0x00fdf74c, 0x00fef576, 0x00fff2a1, 0x00f6ec87, 0x00f8e360, 0x0051bbb4, 0x000d9afe, 0x001a9ef7, + 0x00159ef6, 0x00159df4, 0x00159df2, 0x00149bf2, 0x001299f2, 0x001299f2, 0x001299f2, 0x001299f2, + 0x0067d4fd, 0x0069d6f9, 0x006cd9f5, 0x004fb7dc, 0x001953af, 0x001c67c6, 0x00005abd, 0x001a7eca, + 0x00157bd4, 0x000581dc, 0x002aa1e7, 0x000189d3, 0x002dabe3, 0x0023a7dc, 0x0029b4e6, 0x0017ade1, + 0x0014b7ec, 0x0015b9ea, 0x0016bbe9, 0x001fbfec, 0x0028c2ef, 0x003bcdf7, 0x004ed8ff, 0x0056d5fb, + 0x005dd2f8, 0x005ed6f0, 0x004ec5f4, 0x002fb9fa, 0x0035b8f4, 0x0017b1ff, 0x00f0f7d2, 0x00feffda, + 0x00fdfcd2, 0x00fdfdd1, 0x00fdfed1, 0x00fdfecf, 0x00fcfecd, 0x00fcfdc7, 0x00fdfdc0, 0x00fdfdb9, + 0x00fdfdb2, 0x00fdfca4, 0x00fdfc95, 0x00fdfc87, 0x00fdfc79, 0x00fdfa6c, 0x00fef85f, 0x00f9f645, + 0x00f6ef47, 0x00f2e938, 0x00efe428, 0x00eee425, 0x00ffdd05, 0x000399ff, 0x0017a1f5, 0x00179ef4, + 0x00169cf3, 0x00159cf3, 0x00149cf3, 0x00129bf1, 0x001099f0, 0x00119af1, 0x00129bf2, 0x00129bf2, + 0x0066d5fb, 0x0070d5fc, 0x0078e2ff, 0x003b86c7, 0x00235fba, 0x001e6aba, 0x00227ad1, 0x002787d8, + 0x00248cd7, 0x001d8dd4, 0x002189d1, 0x002ca1ea, 0x002296d5, 0x0031aaef, 0x0020a1db, 0x0017a1dd, + 0x000ea1e0, 0x001aace3, 0x0013b1eb, 0x0010b8ed, 0x000dc0ef, 0x001cc1ef, 0x002cc3f0, 0x0036c4f2, + 0x0040c5f4, 0x0047c9f2, 0x0045c3f6, 0x0031bafa, 0x0031b7f7, 0x004cc2f4, 0x00f5fac0, 0x00fdffc6, + 0x00fdfcc5, 0x00fdfdc4, 0x00fdfdc4, 0x00fcfdc2, 0x00fbfdc1, 0x00f8f9b6, 0x00fdfdb3, 0x00fdfdab, + 0x00fdfca3, 0x00fcfc95, 0x00fcfb88, 0x00fcfb7b, 0x00fbfb6d, 0x00fcf962, 0x00fcf757, 0x00f8f245, + 0x00f4eb41, 0x00f0e532, 0x00ebe023, 0x00fbe01c, 0x00c5d244, 0x000aa2fe, 0x00169ff9, 0x00179ff6, + 0x00189ff3, 0x00179ef2, 0x00159df2, 0x00179ff5, 0x0018a1f8, 0x00159ef5, 0x00129bf2, 0x00129bf2, + 0x0065d7fa, 0x0064d1f7, 0x005de7ff, 0x0004439b, 0x000e4ca5, 0x00317bcd, 0x000455c1, 0x000053c9, + 0x000368c6, 0x002687ca, 0x002881ca, 0x002789d1, 0x002791d7, 0x000774c9, 0x00178dcf, 0x001f9ce1, + 0x00179be4, 0x001e9eda, 0x000097de, 0x0003a5e6, 0x0008b1ee, 0x0009b0e8, 0x000aafe2, 0x0017b4e9, + 0x0024b9ef, 0x0030bdf4, 0x003cc1f9, 0x0034bcf9, 0x002cb6f9, 0x0080d2e8, 0x00fafdaf, 0x00fcfdb3, + 0x00fdfcb7, 0x00fdfcb7, 0x00fdfdb7, 0x00fcfcb6, 0x00fbfcb5, 0x00f4f4a5, 0x00fdfda5, 0x00fcfc9d, + 0x00fcfc94, 0x00fbfb87, 0x00fbfb7b, 0x00fafa6e, 0x00fafa61, 0x00faf758, 0x00faf54e, 0x00f7ee44, + 0x00f3e73a, 0x00ede12c, 0x00e7db1e, 0x00ffd21a, 0x0078b090, 0x0009a0fd, 0x00159dfd, 0x0018a0f8, + 0x001aa2f2, 0x0018a0f2, 0x00169ef2, 0x00139bf2, 0x001099f1, 0x00119af2, 0x00129bf3, 0x00129bf3, + 0x0060d4f7, 0x0067dcfd, 0x004fc2f0, 0x00002c8a, 0x002e6bc0, 0x000547ad, 0x000044ba, 0x003685c4, + 0x00064ebc, 0x001462c3, 0x002d70cb, 0x000f5ab4, 0x002274cd, 0x001169c2, 0x001979c2, 0x001d80d0, + 0x001980d7, 0x001a86d3, 0x001090de, 0x00038dda, 0x000599e6, 0x00059ce1, 0x00049edd, 0x0005a6e1, + 0x0000a7de, 0x001fb6ee, 0x0039bdf7, 0x0038bcf6, 0x0024b5fc, 0x00bfe8b9, 0x00fafea2, 0x00fbfca5, + 0x00fcfaa8, 0x00fcfca7, 0x00fdfda6, 0x00fbfca3, 0x00f9fb9f, 0x00f6f795, 0x00fafb92, 0x00fbfb8b, + 0x00fbfb85, 0x00fafa79, 0x00fafa6d, 0x00f9f961, 0x00f8f956, 0x00f9f64c, 0x00f9f442, 0x00f5ec39, + 0x00f2e531, 0x00efde28, 0x00ecd620, 0x00eed900, 0x0032a6e5, 0x0019a4ff, 0x0029a4f4, 0x0020a2f4, + 0x0018a0f5, 0x00179ef4, 0x00159df4, 0x00139bf3, 0x001199f2, 0x00129af2, 0x00129af3, 0x00129af3, + 0x005bd1f5, 0x0063dffa, 0x00318dcc, 0x00062d91, 0x000e499a, 0x0000369f, 0x00003897, 0x00155fb6, + 0x0053aad9, 0x0031a6e2, 0x0045bcef, 0x006dddff, 0x0076defa, 0x006dd9f9, 0x0064d5f9, 0x0054c5f3, + 0x0045b5ed, 0x00238ed6, 0x001277ce, 0x00006cc6, 0x000282de, 0x000187db, 0x00008dd7, 0x00079be1, + 0x000099dc, 0x0022b1f0, 0x0036baf4, 0x003cbcf4, 0x001cb5ff, 0x00fffe89, 0x00fbff96, 0x00fbfc98, + 0x00fbf99a, 0x00fcfb98, 0x00fdfd96, 0x00fafb90, 0x00f6f98a, 0x00f7f984, 0x00f8fa7f, 0x00fafa7a, + 0x00fbfb75, 0x00fafa6a, 0x00f9f960, 0x00f8f855, 0x00f7f84a, 0x00f7f540, 0x00f8f336, 0x00f4eb2f, + 0x00f0e328, 0x00f0da24, 0x00f0d121, 0x00e9ca24, 0x00049bff, 0x0020a3f6, 0x0016a1f7, 0x0016a0f7, + 0x00169ef7, 0x00159df6, 0x00149cf5, 0x00139bf4, 0x00129af3, 0x00129af3, 0x00129af3, 0x00129af3, + 0x005ae3ff, 0x0064d8ff, 0x000d4798, 0x00002682, 0x001d6bb7, 0x003aa2de, 0x005fe5ff, 0x0052d8fd, + 0x004dd6f6, 0x0048ccf5, 0x005fd0f6, 0x0068d9ff, 0x0061d3f8, 0x005bd2f8, 0x0042cbff, 0x0053cefe, + 0x0051cff5, 0x0049caf6, 0x004acdff, 0x0040baff, 0x000e7edb, 0x000069c2, 0x000584da, 0x000184d5, + 0x00068cd8, 0x0038bef8, 0x003abef7, 0x0035beff, 0x0062c7e2, 0x00fbf379, 0x00f8fa83, 0x00f9f983, + 0x00faf884, 0x00f9f77f, 0x00f7f77b, 0x00f8f979, 0x00f9fa77, 0x00f8f972, 0x00f7f86c, 0x00fcfc6c, + 0x00f9f864, 0x00f8f85b, 0x00f8f752, 0x00f7f649, 0x00f6f53f, 0x00f5f237, 0x00f4ef2f, 0x00f1e628, + 0x00eede20, 0x00ead61f, 0x00f2cc11, 0x009db96c, 0x000c9ffe, 0x001ba3f9, 0x0017a2f9, 0x0017a0f9, + 0x00169ef8, 0x00169df7, 0x00159cf6, 0x00149bf5, 0x00139af5, 0x00139af5, 0x00139af5, 0x00139af5, + 0x0060d8f9, 0x005bd9f8, 0x004cadd7, 0x0069ddff, 0x0056ddf8, 0x0055d6fc, 0x0055d0ff, 0x005cd5ff, + 0x0053cbf2, 0x004bcaf6, 0x0043cafa, 0x0047c9f8, 0x004cc8f6, 0x005ccff1, 0x0046ccf8, 0x0055caff, + 0x003ec4fa, 0x0043c3fb, 0x0048c2fd, 0x003ebff4, 0x0044ccfb, 0x0037b3fc, 0x000b7bdd, 0x00006dc9, + 0x000d80d4, 0x004eccff, 0x003ec3fa, 0x002ec2ff, 0x00a7dea8, 0x00f8ec5b, 0x00f5f570, 0x00f7f66f, + 0x00faf76e, 0x00f5f467, 0x00f1f060, 0x00f6f663, 0x00fbfc65, 0x00f8f95f, 0x00f6f659, 0x00fefe5d, + 0x00f7f652, 0x00f7f54c, 0x00f7f545, 0x00f6f33d, 0x00f6f235, 0x00f3ef2f, 0x00f1eb29, 0x00efe221, + 0x00ecd818, 0x00e5d21a, 0x00f3c700, 0x0052a9b4, 0x0014a4fb, 0x0015a3fb, 0x0017a3fc, 0x0017a1fa, + 0x00179ff8, 0x00169df8, 0x00159cf7, 0x00159bf7, 0x001499f6, 0x001499f6, 0x001499f6, 0x001499f6, + 0x0058cff2, 0x0059ddfd, 0x0055d5f9, 0x005ddeff, 0x004dcef3, 0x004dcbf3, 0x004cc8f3, 0x0056d2fc, + 0x0059d3fd, 0x0050cefb, 0x0047cafa, 0x0048c9f9, 0x0049c7f9, 0x0051cbf6, 0x0045c9f9, 0x004bc8fd, + 0x003fc5f9, 0x0041c4fa, 0x0043c2fb, 0x003bbdf3, 0x003ac0f4, 0x003ec7fc, 0x003ac6fc, 0x0025a1e3, + 0x001f8dd9, 0x0037b9f7, 0x0026bbfa, 0x002abbf4, 0x00ced857, 0x00f9fa5b, 0x00d9db49, 0x00edec58, + 0x00faf560, 0x00f2ef4d, 0x00e9ea3b, 0x00eeef46, 0x00f2f451, 0x00f9f34f, 0x00edf145, 0x00fef84b, + 0x00f4f542, 0x00f5f43d, 0x00f6f337, 0x00f5f131, 0x00f5ef2b, 0x00f2eb27, 0x00f0e622, 0x00eedb1d, + 0x00ecd117, 0x00f1cc09, 0x00f5c509, 0x000fadff, 0x0017a1f9, 0x0018a1f9, 0x0018a1f8, 0x0018a0f9, + 0x00179ff9, 0x00169df9, 0x00169cf8, 0x00159bf8, 0x001599f8, 0x001599f8, 0x001599f8, 0x001599f8, + 0x0060d5fb, 0x005bd3fb, 0x0056d2fb, 0x0055d1fc, 0x0055d0fe, 0x0054d0fa, 0x0053d1f6, 0x0051cef7, + 0x004ecbf8, 0x004dcbf9, 0x004ccafb, 0x0049c8fb, 0x0047c6fc, 0x0045c6fb, 0x0043c6fa, 0x0041c6fa, + 0x0040c7f9, 0x003fc5f9, 0x003ec3f9, 0x003fc3fb, 0x0041c4fd, 0x0038baf2, 0x0040c1f8, 0x003dc3fb, + 0x003bc5fe, 0x0037c1f6, 0x0034beef, 0x002ebcf0, 0x00ded722, 0x00bfdc38, 0x00dee142, 0x00ecea4a, + 0x00eae442, 0x00eee942, 0x00f2ee42, 0x00eeed3f, 0x00eaec3d, 0x00fbee3f, 0x00e5ec31, 0x00fff239, + 0x00f2f531, 0x00f4f32e, 0x00f5f12a, 0x00f5ee25, 0x00f4ec21, 0x00f2e71e, 0x00f0e11c, 0x00eed519, + 0x00ecc917, 0x00dec40c, 0x00bbbe39, 0x000798f8, 0x001a9ff8, 0x001a9ff7, 0x001a9ff5, 0x00189ff7, + 0x00179ff9, 0x00179ef9, 0x00169cf9, 0x00169bf9, 0x001699f9, 0x001699f9, 0x001699f9, 0x001699f9, + 0x005cd4f9, 0x0058d4f9, 0x0055d3f9, 0x0056d2fa, 0x0058d0fb, 0x0056d0f8, 0x0054d0f6, 0x0051cef7, + 0x004dccf9, 0x004ccbfa, 0x004bcafb, 0x0049c8fb, 0x0047c7fb, 0x0045c7fb, 0x0043c6fa, 0x0041c6fa, + 0x0040c6f9, 0x003fc4f9, 0x003ec3f9, 0x003ec2fa, 0x003ec2fb, 0x003abef5, 0x003ec2f8, 0x003bc1f9, + 0x0037c0f9, 0x0036beff, 0x0035bbff, 0x0067bb84, 0x00b0d219, 0x00b4d31a, 0x00d3da39, 0x00e2dd3d, + 0x00d6d532, 0x00e1df38, 0x00ece93e, 0x00e1e636, 0x00e9e536, 0x00f1e634, 0x00e5e42b, 0x00f6e62e, + 0x00e9eb29, 0x00f0ee2a, 0x00f0e824, 0x00ece420, 0x00e9e01d, 0x00ebdb1c, 0x00edd71c, 0x00e9ce19, + 0x00e5c516, 0x00e7c004, 0x006cb292, 0x00109dfc, 0x0018a1f7, 0x001aa0f5, 0x001ca0f3, 0x0019a0f6, + 0x00179ff9, 0x00169ef9, 0x00169cf9, 0x00159bf8, 0x00159af8, 0x001499f8, 0x001499f7, 0x001499f7, + 0x0058d4f6, 0x0056d4f6, 0x0054d5f7, 0x0057d3f7, 0x005bd1f8, 0x0058d0f6, 0x0054cff5, 0x0050cef8, + 0x004dcdfa, 0x004bcbfb, 0x004acafb, 0x0048c9fb, 0x0046c7fb, 0x0045c7fa, 0x0043c7fa, 0x0042c6fa, + 0x0040c6f9, 0x003fc4f9, 0x003ec3f9, 0x003dc1f9, 0x003cc0f9, 0x003cc1f8, 0x003cc2f7, 0x0038bff6, + 0x0034bbf5, 0x0035bdfd, 0x0037beff, 0x0046bcfc, 0x0082c92c, 0x00a0be02, 0x00b8c420, 0x00d8cf31, + 0x00d2d632, 0x00d4d52e, 0x00d7d42a, 0x00cdd725, 0x00e9df2f, 0x00e6dd2a, 0x00e4dc25, 0x00edd922, + 0x00e0e220, 0x00ede927, 0x00eae01e, 0x00e4da1c, 0x00ded319, 0x00e5d01a, 0x00ebcd1b, 0x00e5c818, + 0x00dec214, 0x00f0bc00, 0x001da5eb, 0x0019a1ff, 0x0016a2f7, 0x0019a2f4, 0x001ea2f1, 0x001aa0f5, + 0x00169ff9, 0x00169ef8, 0x00159df8, 0x00159cf8, 0x00149bf8, 0x00139af7, 0x001299f6, 0x001299f6, + 0x005ed5f9, 0x0063d6fc, 0x0068d6ff, 0x005fd3fc, 0x0056d0f8, 0x0053cff8, 0x0051cef8, 0x004ecdf9, + 0x004bccfb, 0x004acbfb, 0x0048cafb, 0x0047c9fa, 0x0046c8fb, 0x0044c7fa, 0x0043c7fa, 0x0042c6fa, + 0x0040c5f9, 0x003fc4f9, 0x003ec3f9, 0x003dc1f9, 0x003cc0f9, 0x003bc1f9, 0x003bc1f8, 0x0038bff7, + 0x0036bdf7, 0x0035bdfa, 0x0034bdfe, 0x0022c3f6, 0x0027bbfc, 0x0053b0b2, 0x009bc606, 0x00c1d322, + 0x00d3dd36, 0x00b4ba12, 0x00c4c71f, 0x00c5cf22, 0x00d9d82d, 0x00dfdb30, 0x00dcd52b, 0x00e8d520, + 0x00d5d51c, 0x00e8e428, 0x00ece324, 0x00d1ce1f, 0x00d3c51d, 0x00dcc302, 0x00cfc312, 0x00e3c209, + 0x00e3be00, 0x0084bf6e, 0x000ca0f6, 0x00129ffd, 0x0018a2f6, 0x0019a1f5, 0x001ba1f4, 0x0018a0f6, + 0x00169ff8, 0x00159ef8, 0x00159df8, 0x00149cf7, 0x00139bf7, 0x00129af6, 0x001098f4, 0x001098f4, + 0x0065d7fb, 0x005dd4fa, 0x0056d2f8, 0x0053d0f9, 0x0050cff9, 0x004fcef9, 0x004dcdfa, 0x004bcdfa, + 0x004accfb, 0x0048cbfb, 0x0047cafb, 0x0046c9fa, 0x0045c8fa, 0x0044c7fa, 0x0043c7fa, 0x0042c6fa, + 0x0040c5fa, 0x003fc4f9, 0x003ec3f9, 0x003dc1f9, 0x003bc0f9, 0x003ac0f9, 0x0039c0f9, 0x0038bff9, + 0x0037bff9, 0x0034bef8, 0x0031bcf7, 0x0033bbf8, 0x0035bbfa, 0x002cbcff, 0x0061c2df, 0x0093cb85, + 0x00c5d52b, 0x00cbd82f, 0x00b0bb13, 0x00b5be17, 0x00b9c21b, 0x00c7c826, 0x00c5bf21, 0x00dbc817, + 0x00cac819, 0x00dbd722, 0x00ddd61a, 0x00b7bd0d, 0x00c8bd04, 0x00d0c000, 0x00adc951, 0x006cb8b1, + 0x0004a3ff, 0x0013a4fb, 0x0021a4f5, 0x001ea3f5, 0x001aa1f6, 0x0019a1f6, 0x0018a0f7, 0x0017a0f7, + 0x00169ff8, 0x00159ef7, 0x00149ef7, 0x00139df7, 0x00139cf6, 0x00119af4, 0x000f98f2, 0x000f98f2, + 0x005cd5f9, 0x0058d3f8, 0x0053d1f8, 0x0052d0f9, 0x0050cff9, 0x004ecefa, 0x004ccdfa, 0x004accfa, + 0x0048ccfa, 0x0047cbfa, 0x0046cafa, 0x0045c9fa, 0x0044c8fa, 0x0043c7fa, 0x0042c7fa, 0x0041c6fa, + 0x0040c5fa, 0x003fc4f9, 0x003ec2f9, 0x003cc1f9, 0x003bc0f9, 0x003ac0f9, 0x0038bff9, 0x0037bff9, + 0x0036bff9, 0x0035bdf6, 0x0034bbf3, 0x0035b9f7, 0x0035b8fb, 0x0022b5ff, 0x002fb5ff, 0x004dbae6, + 0x006bbfce, 0x0027b1c5, 0x006cbc7c, 0x008abd49, 0x00a7be15, 0x00b9bf09, 0x00ccc000, 0x00dac43d, + 0x00bbca20, 0x00aec73e, 0x0099bc54, 0x005aad8b, 0x0036abc4, 0x0004b3ff, 0x0015a7ff, 0x0021a4ff, + 0x0019a0fb, 0x001ba2fa, 0x001da4f9, 0x001ba3f8, 0x001aa1f7, 0x0019a1f7, 0x0018a0f7, 0x0017a0f7, + 0x00169ff8, 0x00159ef7, 0x00149ef7, 0x00139df7, 0x00129cf6, 0x00119af5, 0x000f99f3, 0x000f99f3, + 0x0053d2f6, 0x0052d1f7, 0x0051d1f8, 0x0050d0f9, 0x004fcffa, 0x004dcefa, 0x004bcdfa, 0x0049ccfa, + 0x0047cbfa, 0x0046caf9, 0x0045caf9, 0x0044c9f9, 0x0044c8fa, 0x0043c7fa, 0x0042c6f9, 0x0041c6f9, + 0x0040c5fa, 0x003fc4f9, 0x003dc2f9, 0x003cc1f9, 0x003ac0f9, 0x0039c0f9, 0x0038bff9, 0x0036bff9, + 0x0035bef8, 0x0036bcf4, 0x0038baf0, 0x0036b8f6, 0x0034b5fc, 0x002cb6f9, 0x0023b7f6, 0x0025b5fa, + 0x0028b4ff, 0x0028b6ff, 0x0029b7ff, 0x001fb5ff, 0x0015b2ff, 0x0020aef7, 0x003cb9ff, 0x005acbf0, + 0x0042befa, 0x002ab6fc, 0x0012adff, 0x0018acfc, 0x001eacfa, 0x001ea9fd, 0x001ea7ff, 0x001ba8fa, + 0x0018a8f4, 0x0018a6f8, 0x0018a4fd, 0x0019a3fa, 0x001aa1f7, 0x0019a1f7, 0x0018a0f8, 0x0017a0f8, + 0x00169ff8, 0x00159ef7, 0x00149df7, 0x00139cf6, 0x00129bf6, 0x00119af5, 0x001099f4, 0x001099f4, + 0x0054d1f8, 0x0052d1f8, 0x0051d0f9, 0x004fcff9, 0x004ecffa, 0x004ccefa, 0x004acdf9, 0x0048ccf9, + 0x0045cbf9, 0x0045caf9, 0x0044c9f9, 0x0043c8f9, 0x0043c8f9, 0x0042c7f9, 0x0042c6f9, 0x0041c5f9, + 0x0040c5fa, 0x003fc4f9, 0x003dc2f9, 0x003bc1f9, 0x003ac0fa, 0x0038bff9, 0x0037bff9, 0x0036bef9, + 0x0034bef8, 0x0035bcf6, 0x0035baf5, 0x0034b8f8, 0x0033b6fc, 0x002eb6f9, 0x0029b6f7, 0x0029b5f8, + 0x002ab4fa, 0x002ab5fb, 0x002ab5fc, 0x002ab2f6, 0x002aafef, 0x001ba9f6, 0x009bcfd9, 0x006dcfe9, + 0x0074c7e4, 0x0080c9dd, 0x0019adfb, 0x001cacf9, 0x001fabf8, 0x001fa9f9, 0x001ea7fb, 0x001ca7f9, + 0x001aa7f6, 0x001aa5f8, 0x001aa4fb, 0x001aa3fa, 0x001aa2f8, 0x0019a1f8, 0x0018a0f8, 0x0017a0f8, + 0x00169ff8, 0x00159ef7, 0x00149df7, 0x00139cf6, 0x00129bf6, 0x00119bf5, 0x00119af5, 0x00119af5, + 0x0055d0f9, 0x0053d0fa, 0x0051d0fa, 0x004fcffa, 0x004dcffa, 0x004bcefa, 0x0049cdf9, 0x0046ccf9, + 0x0044caf8, 0x0043caf8, 0x0043c9f8, 0x0043c8f9, 0x0042c8f9, 0x0042c7f9, 0x0041c6f9, 0x0041c6f9, + 0x0040c5fa, 0x003ec3f9, 0x003dc2fa, 0x003bc1fa, 0x0039c0fa, 0x0038bff9, 0x0036bff9, 0x0035bef9, + 0x0034bdf8, 0x0033bcf9, 0x0033bafa, 0x0032b9fb, 0x0032b8fc, 0x0030b7fa, 0x002eb6f8, 0x002db5f7, + 0x002bb4f5, 0x002bb4f6, 0x002bb3f7, 0x0029b2f9, 0x0028b2fc, 0x0030b2f7, 0x0012a8fe, 0x007fd4e1, + 0x0058bbe6, 0x0015aafb, 0x001fadf8, 0x0020acf7, 0x0020aaf5, 0x001fa9f6, 0x001ea8f7, 0x001da6f7, + 0x001ca5f8, 0x001ca4f8, 0x001ba3f9, 0x001ba3f9, 0x001ba2f9, 0x0019a1f9, 0x0018a0f8, 0x0017a0f8, + 0x00169ff8, 0x00159ef7, 0x00149df7, 0x00139cf6, 0x00129bf5, 0x00129bf5, 0x00129bf5, 0x00129bf5, + 0x0055d0f9, 0x0053d0fa, 0x0051d0fa, 0x004fcffa, 0x004dcffa, 0x004bcefa, 0x0049cdf9, 0x0046ccf9, + 0x0044caf8, 0x0043caf8, 0x0043c9f8, 0x0043c8f9, 0x0042c8f9, 0x0042c7f9, 0x0041c6f9, 0x0041c6f9, + 0x0040c5fa, 0x003ec3f9, 0x003dc2fa, 0x003bc1fa, 0x0039c0fa, 0x0038bff9, 0x0036bff9, 0x0035bef9, + 0x0034bdf8, 0x0033bcf9, 0x0033bafa, 0x0032b9fb, 0x0032b8fc, 0x0030b7fa, 0x002eb6f8, 0x002db5f7, + 0x002bb4f5, 0x002bb4f6, 0x002bb3f7, 0x002ab2f8, 0x0029b2fa, 0x002db6f5, 0x001db5f6, 0x00239bff, + 0x0020b6f3, 0x000cacfb, 0x001eacf7, 0x001fabf6, 0x0020aaf5, 0x001fa9f6, 0x001ea8f7, 0x001da6f7, + 0x001ca5f8, 0x001ca4f8, 0x001ba3f9, 0x001ba3f9, 0x001ba2f9, 0x0019a1f9, 0x0018a0f8, 0x0017a0f8, + 0x00169ff8, 0x00159ef7, 0x00149df7, 0x00139cf6, 0x00129bf5, 0x00129bf5, 0x00129bf5, 0x00129bf5, + 0x0055d0f9, 0x0053d0fa, 0x0051d0fa, 0x004fcffa, 0x004dcffa, 0x004bcefa, 0x0049cdf9, 0x0046ccf9, + 0x0044caf8, 0x0043caf8, 0x0043c9f8, 0x0043c8f9, 0x0042c8f9, 0x0042c7f9, 0x0041c6f9, 0x0041c6f9, + 0x0040c5fa, 0x003ec3f9, 0x003dc2fa, 0x003bc1fa, 0x0039c0fa, 0x0038bff9, 0x0036bff9, 0x0035bef9, + 0x0034bdf8, 0x0033bcf9, 0x0033bafa, 0x0032b9fb, 0x0032b8fc, 0x0030b7fa, 0x002eb6f8, 0x002db5f7, + 0x002bb4f5, 0x002bb4f6, 0x002bb3f7, 0x002bb2f8, 0x002bb1f8, 0x0022aff9, 0x0019acfa, 0x001eadf7, + 0x0024aef3, 0x0020adf5, 0x001dabf6, 0x001fabf6, 0x0020aaf5, 0x001fa9f6, 0x001ea8f7, 0x001da6f7, + 0x001ca5f8, 0x001ca4f8, 0x001ba3f9, 0x001ba3f9, 0x001ba2f9, 0x0019a1f9, 0x0018a0f8, 0x0017a0f8, + 0x00169ff8, 0x00159ef7, 0x00149df7, 0x00139cf6, 0x00129bf5, 0x00129bf5, 0x00129bf5, 0x00129bf5, + 0x0055d0f9, 0x0053d0fa, 0x0051d0fa, 0x004fcffa, 0x004dcffa, 0x004bcefa, 0x0049cdf9, 0x0046ccf9, + 0x0044caf8, 0x0043caf8, 0x0043c9f8, 0x0043c8f9, 0x0042c8f9, 0x0042c7f9, 0x0041c6f9, 0x0041c6f9, + 0x0040c5fa, 0x003ec3f9, 0x003dc2fa, 0x003bc1fa, 0x0039c0fa, 0x0038bff9, 0x0036bff9, 0x0035bef9, + 0x0034bdf8, 0x0033bcf9, 0x0033bafa, 0x0032b9fb, 0x0032b8fc, 0x0030b7fa, 0x002eb6f8, 0x002db5f7, + 0x002bb4f5, 0x002bb4f6, 0x002bb3f7, 0x002bb2f8, 0x002bb1f8, 0x0022aff9, 0x0019acfa, 0x001eadf7, + 0x0024aef3, 0x0020adf5, 0x001dabf6, 0x001fabf6, 0x0020aaf5, 0x001fa9f6, 0x001ea8f7, 0x001da6f7, + 0x001ca5f8, 0x001ca4f8, 0x001ba3f9, 0x001ba3f9, 0x001ba2f9, 0x0019a1f9, 0x0018a0f8, 0x0017a0f8, + 0x00169ff8, 0x00159ef7, 0x00149df7, 0x00139cf6, 0x00129bf5, 0x00129bf5, 0x00129bf5, 0x00129bf5 +}; + +int TestFreeRDPCodecRemoteFX(int argc, char* argv[]) +{ + return 0; +} diff --git a/libfreerdp/codec/test/TestFreeRDPRegion.c b/libfreerdp/codec/test/TestFreeRDPRegion.c new file mode 100644 index 000000000..0136b238b --- /dev/null +++ b/libfreerdp/codec/test/TestFreeRDPRegion.c @@ -0,0 +1,709 @@ +/** + * Copyright © 2014 Thincast Technologies GmbH + * Copyright © 2014 Hardening + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include + + +static BOOL compareRectangles(const RECTANGLE_16 *src1, const RECTANGLE_16 *src2, int nb) +{ + int i; + for (i = 0; i< nb; i++, src1++, src2++) + { + if (memcmp(src1, src2, sizeof(RECTANGLE_16))) + { + fprintf(stderr, "expecting rect %d (%d,%d-%d,%d) and have (%d,%d-%d,%d)\n", + i, src2->left, src2->top, src2->right, src2->bottom, + src1->left, src1->top, src1->right, src1->bottom + ); + return FALSE; + } + } + return TRUE; +} + + +static int test_basic() { + REGION16 region; + int retCode = -1; + const RECTANGLE_16 *rects; + int nbRects; + + /* R1 + R2 ==> disjointed rects */ + RECTANGLE_16 r1 = { 0, 101, 200, 201}; + RECTANGLE_16 r2 = {150, 301, 250, 401}; + + RECTANGLE_16 r1_r2[] = { + {0, 101, 200, 201}, + {150, 301, 250, 401} + }; + + /* r1 */ + region16_init(®ion); + if (!region16_union_rect(®ion, ®ion, &r1)) + goto out;; + rects = region16_rects(®ion, &nbRects); + if (!rects || nbRects != 1 || memcmp(rects, &r1, sizeof(RECTANGLE_16))) + goto out; + + /* r1 + r2 */ + if (!region16_union_rect(®ion, ®ion, &r2)) + goto out;; + rects = region16_rects(®ion, &nbRects); + if (!rects || nbRects != 2 || !compareRectangles(rects, r1_r2, nbRects)) + goto out; + + + /* clear region */ + region16_clear(®ion); + region16_rects(®ion, &nbRects); + if (nbRects) + goto out; + + retCode = 0; +out: + region16_uninit(®ion); + return retCode; +} + + +static int test_r1_r3() { + REGION16 region; + int retCode = -1; + const RECTANGLE_16 *rects; + int nbRects; + + RECTANGLE_16 r1 = { 0, 101, 200, 201}; + RECTANGLE_16 r3 = {150, 151, 250, 251}; + RECTANGLE_16 r1_r3[] = { + { 0, 101, 200, 151}, + { 0, 151, 250, 201}, + {150, 201, 250, 251} + }; + + region16_init(®ion); + /* + * +=============================================================== + * | + * |+-----+ +-----+ + * || r1 | | | + * || +-+------+ +-----+--------+ + * || | r3 | | | + * |+---+ | ====> +-----+--------+ + * | | | | | + * | +--------+ +--------+ + */ + + /* R1 + R3 */ + if (!region16_union_rect(®ion, ®ion, &r1)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r3)) + goto out; + rects = region16_rects(®ion, &nbRects); + if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r3, nbRects)) + goto out; + + + /* R3 + R1 */ + region16_clear(®ion); + if (!region16_union_rect(®ion, ®ion, &r3)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r1)) + goto out; + rects = region16_rects(®ion, &nbRects); + if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r3, nbRects)) + goto out; + + retCode = 0; +out: + region16_uninit(®ion); + return retCode; +} + + +static int test_r9_r10() { + REGION16 region; + int retCode = -1; + const RECTANGLE_16 *rects; + int nbRects; + + /* + * +=============================================================== + * | + * | +---+ +---+ + * |+--|r10|-+ +--+---+-+ + * ||r9| | | | | + * || | | | | | + * || | | | =====> | | + * || | | | | | + * || | | | | | + * |+--| |-+ +--+---+-+ + * | +---+ +---+ + */ + RECTANGLE_16 r9 = { 0, 100, 400, 200}; + RECTANGLE_16 r10 = {200, 0, 300, 300}; + RECTANGLE_16 r9_r10[] = { + {200, 0, 300, 100}, + { 0, 100, 400, 200}, + {200, 200, 300, 300}, + }; + + region16_init(®ion); + if (!region16_union_rect(®ion, ®ion, &r9)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r10)) + goto out; + rects = region16_rects(®ion, &nbRects); + if (!rects || nbRects != 3 || !compareRectangles(rects, r9_r10, nbRects)) + goto out; + + retCode = 0; +out: + region16_uninit(®ion); + return retCode; +} + + +static int test_r1_r5() { + REGION16 region; + int retCode = -1; + const RECTANGLE_16 *rects; + int nbRects; + + RECTANGLE_16 r1 = { 0, 101, 200, 201}; + RECTANGLE_16 r5 = {150, 121, 300, 131}; + + RECTANGLE_16 r1_r5[] = { + { 0, 101, 200, 121}, + { 0, 121, 300, 131}, + { 0, 131, 200, 201} + }; + + region16_init(®ion); + /* + * +=============================================================== + * | + * |+--------+ +--------+ + * || r1 | | | + * || +--+----+ +--------+----+ + * || | r5 | =====> | | + * || +-------+ +--------+----+ + * || | | | + * |+--------+ +--------+ + * | + * + */ + if (!region16_union_rect(®ion, ®ion, &r1)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r5)) + goto out; + rects = region16_rects(®ion, &nbRects); + if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r5, nbRects)) + goto out; + + + retCode = 0; +out: + region16_uninit(®ion); + return retCode; +} + +static int test_r1_r6() { + REGION16 region; + int retCode = -1; + const RECTANGLE_16 *rects; + int nbRects; + + RECTANGLE_16 r1 = { 0, 101, 200, 201}; + RECTANGLE_16 r6 = {150, 121, 170, 131}; + + region16_init(®ion); + /* + * +=============================================================== + * | + * |+--------+ +--------+ + * || r1 | | | + * || +--+ | | | + * || |r6| | =====> | | + * || +--+ | | | + * || | | | + * |+--------+ +--------+ + * | + */ + region16_clear(®ion); + if (!region16_union_rect(®ion, ®ion, &r1)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r6)) + goto out; + rects = region16_rects(®ion, &nbRects); + if (!rects || nbRects != 1 || !compareRectangles(rects, &r1, nbRects)) + goto out; + + retCode = 0; +out: + region16_uninit(®ion); + return retCode; +} + + +static int test_r1_r2_r4() { + REGION16 region; + int retCode = -1; + const RECTANGLE_16 *rects; + int nbRects; + RECTANGLE_16 r1 = { 0, 101, 200, 201}; + RECTANGLE_16 r2 = {150, 301, 250, 401}; + RECTANGLE_16 r4 = {150, 251, 250, 301}; + RECTANGLE_16 r1_r2_r4[] = { + { 0, 101, 200, 201}, + {150, 251, 250, 401} + }; + + /* + * +=============================================================== + * | + * |+-----+ +-----+ + * || r1 | | | + * || | | | + * || | | | + * |+-----+ ====> +-----+ + * | + * | +--------+ +--------+ + * | | r4 | | | + * | +--------+ | | + * | | r2 | | | + * | | | | | + * | +--------+ +--------+ + * + */ + region16_init(®ion); + if (!region16_union_rect(®ion, ®ion, &r1)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r2)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r4)) + goto out; + rects = region16_rects(®ion, &nbRects); + if (!rects || nbRects != 2 || !compareRectangles(rects, r1_r2_r4, nbRects)) + goto out; + + retCode = 0; +out: + region16_uninit(®ion); + return retCode; +} + + +static int test_r1_r7_r8() { + REGION16 region; + int retCode = -1; + const RECTANGLE_16 *rects; + int nbRects; + RECTANGLE_16 r1 = { 0, 101, 200, 201}; + RECTANGLE_16 r7 = {300, 101, 500, 201}; + RECTANGLE_16 r8 = {150, 121, 400, 131}; + + RECTANGLE_16 r1_r7_r8[] = { + { 0, 101, 200, 121}, + {300, 101, 500, 121}, + { 0, 121, 500, 131}, + { 0, 131, 200, 201}, + {300, 131, 500, 201}, + }; + + /* + * +=============================================================== + * | + * |+--------+ +--------+ +--------+ +--------+ + * || r1 | | r7 | | | | | + * || +------------+ | +--------+---+--------+ + * || | r8 | | =====> | | + * || +------------+ | +--------+---+--------+ + * || | | | | | | | + * |+--------+ +--------+ +--------+ +--------+ + * | + */ + region16_init(®ion); + if (!region16_union_rect(®ion, ®ion, &r1)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r7)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r8)) + goto out; + rects = region16_rects(®ion, &nbRects); + if (!rects || nbRects != 5 || !compareRectangles(rects, r1_r7_r8, nbRects)) + goto out; + + region16_clear(®ion); + if (!region16_union_rect(®ion, ®ion, &r1)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r8)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r7)) + goto out; + rects = region16_rects(®ion, &nbRects); + if (!rects || nbRects != 5 || !compareRectangles(rects, r1_r7_r8, nbRects)) + goto out; + + region16_clear(®ion); + if (!region16_union_rect(®ion, ®ion, &r8)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r7)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r1)) + goto out; + rects = region16_rects(®ion, &nbRects); + if (!rects || nbRects != 5 || !compareRectangles(rects, r1_r7_r8, nbRects)) + goto out; + + retCode = 0; +out: + region16_uninit(®ion); + return retCode; +} + + +static int test_r1_r2_r3_r4() { + REGION16 region; + int retCode = -1; + const RECTANGLE_16 *rects; + int nbRects; + RECTANGLE_16 r1 = { 0, 101, 200, 201}; + RECTANGLE_16 r2 = {150, 301, 250, 401}; + RECTANGLE_16 r3 = {150, 151, 250, 251}; + RECTANGLE_16 r4 = {150, 251, 250, 301}; + + RECTANGLE_16 r1_r2_r3[] = { + { 0, 101, 200, 151}, + { 0, 151, 250, 201}, + {150, 201, 250, 251}, + {150, 301, 250, 401} + }; + + RECTANGLE_16 r1_r2_r3_r4[] = { + { 0, 101, 200, 151}, + { 0, 151, 250, 201}, + {150, 201, 250, 401} + }; + + region16_init(®ion); + /* + * +=============================================================== + * | + * |+-----+ +-----+ + * || r1 | | | + * || +-+------+ +-----+--------+ + * || | r3 | | | + * |+---+ | ====> +-----+--------+ + * | | | | | + * | +--------+ +--------+ + * | +--------+ +--------+ + * | | r2 | | | + * | | | | | + * | +--------+ +--------+ + */ + if (!region16_union_rect(®ion, ®ion, &r1)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r2)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r3)) + goto out; + rects = region16_rects(®ion, &nbRects); + if (!rects || nbRects != 4 || !compareRectangles(rects, r1_r2_r3, 4)) + goto out; + + /* + * +=============================================================== + * | + * |+-----+ +-----+ + * || | | | + * |+-----+--------+ +-----+--------+ + * || | ==> | | + * |+-----+--------+ +-----+--------+ + * | | | | | + * | +--------+ | | + * | | + r4 | | | + * | +--------+ | | + * | | | | | + * | | | | | + * | +--------+ +--------+ + */ + if (!region16_union_rect(®ion, ®ion, &r4)) + goto out; + rects = region16_rects(®ion, &nbRects); + if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r2_r3_r4, 3)) + goto out; + + retCode = 0; +out: + region16_uninit(®ion); + return retCode; +} + + +static int test_from_weston() +{ + /* + * 0: 0,0 -> 640,32 (w=640 h=32) + * 1: 236,169 -> 268,201 (w=32 h=32) + * 2: 246,258 -> 278,290 (w=32 h=32) + */ + REGION16 region; + int retCode = -1; + const RECTANGLE_16 *rects; + int nbRects; + RECTANGLE_16 r1 = { 0, 0, 640, 32}; + RECTANGLE_16 r2 = {236, 169, 268, 201}; + RECTANGLE_16 r3 = {246, 258, 278, 290}; + + RECTANGLE_16 r1_r2_r3[] = { + { 0, 0, 640, 32}, + {236, 169, 268, 201}, + {246, 258, 278, 290} + }; + + region16_init(®ion); + /* + * +=============================================================== + * |+-------------------------------------------------------------+ + * || r1 | + * |+-------------------------------------------------------------+ + * | + * | +---------------+ + * | | r2 | + * | +---------------+ + * | + * | +---------------+ + * | | r3 | + * | +---------------+ + * | + */ + if (!region16_union_rect(®ion, ®ion, &r1)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r2)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r3)) + goto out; + + rects = region16_rects(®ion, &nbRects); + if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r2_r3, 3)) + goto out; + + retCode = 0; +out: + region16_uninit(®ion); + return retCode; +} + +static int test_r1_inter_r3() { + REGION16 region, intersection; + int retCode = -1; + const RECTANGLE_16 *rects; + int nbRects; + RECTANGLE_16 r1 = { 0, 101, 200, 201}; + RECTANGLE_16 r3 = {150, 151, 250, 251}; + + RECTANGLE_16 r1_inter_r3[] = { + {150, 151, 200, 201}, + }; + + region16_init(®ion); + region16_init(&intersection); + + /* + * +=============================================================== + * | + * |+-----+ + * || r1 | + * || +-+------+ +-+ + * || | r3 | r1&r3 | | + * |+---+ | ====> +-+ + * | | | + * | +--------+ + */ + if (!region16_union_rect(®ion, ®ion, &r1)) + goto out; + if (!region16_intersects_rect(®ion, &r3)) + goto out; + + if (!region16_intersect_rect(&intersection, ®ion, &r3)) + goto out; + rects = region16_rects(&intersection, &nbRects); + if (!rects || nbRects != 1 || !compareRectangles(rects, r1_inter_r3, nbRects)) + goto out; + + + retCode = 0; +out: + region16_uninit(®ion); + return retCode; +} + +static int test_r1_r3_inter_r11() { + REGION16 region, intersection; + int retCode = -1; + const RECTANGLE_16 *rects; + int nbRects; + RECTANGLE_16 r1 = { 0, 101, 200, 201}; + RECTANGLE_16 r3 = {150, 151, 250, 251}; + RECTANGLE_16 r11 ={170, 151, 600, 301}; + + RECTANGLE_16 r1_r3_inter_r11[] = { + {170, 151, 250, 251}, + }; + + region16_init(®ion); + region16_init(&intersection); + + /* + * +=============================================================== + * | + * |+-----+ + * || | + * || +------+ + * || r1+r3 | (r1+r3) & r11 + * || +----------------+ +--------+ + * |+---+ | | | ====> | | + * | | | | | | | + * | | | | | | | + * | +-|------+ | +--------+ + * | | r11 | + * | +----------------+ + * + * + * R1+R3 is made of 3 bands, R11 overlap the second and the third band. The + * intersection is made of two band that must be reassembled to give only + * one + */ + if (!region16_union_rect(®ion, ®ion, &r1)) + goto out; + if (!region16_union_rect(®ion, ®ion, &r3)) + goto out; + + if (!region16_intersects_rect(®ion, &r11)) + goto out; + + if (!region16_intersect_rect(&intersection, ®ion, &r11)) + goto out; + rects = region16_rects(&intersection, &nbRects); + if (!rects || nbRects != 1 || !compareRectangles(rects, r1_r3_inter_r11, nbRects)) + goto out; + + retCode = 0; +out: + region16_uninit(&intersection); + region16_uninit(®ion); + return retCode; +} + +static int test_norbert_case() { + REGION16 region, intersection; + int retCode = -1; + const RECTANGLE_16 *rects; + int nbRects, i; + + RECTANGLE_16 inRectangles[5] = { + {1680, 0, 1920, 242}, + { 294, 242, 971, 776}, + {1680, 242, 1920, 776}, + {1680, 776, 1920, 1036}, + { 2, 1040, 53, 1078} + }; + + RECTANGLE_16 screenRect = { + 0, 0, 1920, 1080 + }; + RECTANGLE_16 expected_inter_extents = { + 0, 0, 1920, 1078 + }; + + region16_init(®ion); + region16_init(&intersection); + + for (i = 0; i < 5; i++) + { + if (!region16_union_rect(®ion, ®ion, &inRectangles[i])) + goto out; + } + + if (!region16_intersect_rect(&intersection, ®ion, &screenRect)) + goto out; + rects = region16_rects(&intersection, &nbRects); + if (!rects || nbRects != 5 || !compareRectangles(rects, inRectangles, nbRects)) + goto out; + + if (!compareRectangles(region16_extents(&intersection), &expected_inter_extents, 1) ) + goto out; + + retCode = 0; +out: + region16_uninit(&intersection); + region16_uninit(®ion); + return retCode; +} + + +typedef int (*TestFunction)(); +struct UnitaryTest { + const char *name; + TestFunction func; +}; + +struct UnitaryTest tests[] = { + {"Basic trivial tests", test_basic}, + {"R1+R3 and R3+R1", test_r1_r3}, + {"R1+R5", test_r1_r5}, + {"R1+R6", test_r1_r6}, + {"R9+R10", test_r9_r10}, + {"R1+R2+R4", test_r1_r2_r4}, + {"R1+R7+R8 in many orders", test_r1_r7_r8}, + {"R1+R2+R3+R4", test_r1_r2_r3_r4}, + {"data from weston", test_from_weston}, + {"R1 & R3", test_r1_inter_r3}, + {"(R1+R3)&R11 (band merge)",test_r1_r3_inter_r11}, + {"norbert case", test_norbert_case}, + + {NULL, NULL} +}; + +int TestFreeRDPRegion(int argc, char* argv[]) +{ + int i, testNb; + int retCode = -1; + + for (i = 0; tests[i].func; i++) + { + testNb++; + fprintf(stderr, "%d: %s\n", testNb, tests[i].name); + retCode = tests[i].func(); + if (retCode < 0) + break; + } + + if (retCode < 0) + fprintf(stderr, "failed for test %d\n", testNb); + + return retCode; +} diff --git a/libfreerdp/codec/test/rfx.bmp b/libfreerdp/codec/test/rfx.bmp new file mode 100644 index 000000000..2b6665173 Binary files /dev/null and b/libfreerdp/codec/test/rfx.bmp differ diff --git a/libfreerdp/common/settings.c b/libfreerdp/common/settings.c index ef4493f4e..19bf5f784 100644 --- a/libfreerdp/common/settings.c +++ b/libfreerdp/common/settings.c @@ -147,7 +147,7 @@ void freerdp_device_collection_add(rdpSettings* settings, RDPDR_DEVICE* device) RDPDR_DEVICE* freerdp_device_collection_find(rdpSettings* settings, const char* name) { - int index; + UINT32 index; RDPDR_DEVICE* device; for (index = 0; index < settings->DeviceCount; index++) @@ -234,7 +234,7 @@ RDPDR_DEVICE* freerdp_device_clone(RDPDR_DEVICE* device) void freerdp_device_collection_free(rdpSettings* settings) { - int index; + UINT32 index; RDPDR_DEVICE* device; for (index = 0; index < settings->DeviceCount; index++) @@ -288,7 +288,7 @@ void freerdp_static_channel_collection_add(rdpSettings* settings, ADDIN_ARGV* ch ADDIN_ARGV* freerdp_static_channel_collection_find(rdpSettings* settings, const char* name) { - int index; + UINT32 index; ADDIN_ARGV* channel; for (index = 0; index < settings->StaticChannelCount; index++) @@ -322,7 +322,8 @@ ADDIN_ARGV* freerdp_static_channel_clone(ADDIN_ARGV* channel) void freerdp_static_channel_collection_free(rdpSettings* settings) { - int i, j; + int j; + UINT32 i; for (i = 0; i < settings->StaticChannelCount; i++) { @@ -354,7 +355,7 @@ void freerdp_dynamic_channel_collection_add(rdpSettings* settings, ADDIN_ARGV* c ADDIN_ARGV* freerdp_dynamic_channel_collection_find(rdpSettings* settings, const char* name) { - int index; + UINT32 index; ADDIN_ARGV* channel; for (index = 0; index < settings->DynamicChannelCount; index++) @@ -388,7 +389,7 @@ ADDIN_ARGV* freerdp_dynamic_channel_clone(ADDIN_ARGV* channel) void freerdp_dynamic_channel_collection_free(rdpSettings* settings) { - int index; + UINT32 index; for (index = 0; index < settings->DynamicChannelCount; index++) { @@ -653,6 +654,10 @@ BOOL freerdp_get_param_bool(rdpSettings* settings, int id) return settings->RestrictedAdminModeRequired; break; + case FreeRDP_DisableCredentialsDelegation: + return settings->DisableCredentialsDelegation; + break; + case FreeRDP_MstscCookieMode: return settings->MstscCookieMode; break; @@ -1121,6 +1126,10 @@ int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param) settings->RestrictedAdminModeRequired = param; break; + case FreeRDP_DisableCredentialsDelegation: + settings->DisableCredentialsDelegation = param; + break; + case FreeRDP_MstscCookieMode: settings->MstscCookieMode = param; break; @@ -2136,6 +2145,10 @@ char* freerdp_get_param_string(rdpSettings* settings, int id) return settings->DynamicDSTTimeZoneKeyName; break; + case FreeRDP_AuthenticationServiceClass: + return settings->AuthenticationServiceClass; + break; + case FreeRDP_PreconnectionBlob: return settings->PreconnectionBlob; break; @@ -2316,6 +2329,11 @@ int freerdp_set_param_string(rdpSettings* settings, int id, const char* param) settings->DynamicDSTTimeZoneKeyName = _strdup(param); break; + case FreeRDP_AuthenticationServiceClass: + free(settings->AuthenticationServiceClass); + settings->AuthenticationServiceClass = _strdup(param); + break; + case FreeRDP_PreconnectionBlob: free(settings->PreconnectionBlob); settings->PreconnectionBlob = _strdup(param); diff --git a/libfreerdp/core/CMakeLists.txt b/libfreerdp/core/CMakeLists.txt index 2bb80cf13..8f7d2642e 100644 --- a/libfreerdp/core/CMakeLists.txt +++ b/libfreerdp/core/CMakeLists.txt @@ -75,6 +75,10 @@ set(${MODULE_PREFIX}_SRCS orders.h freerdp.c graphics.c + client.c + client.h + server.c + server.h capabilities.c capabilities.h certificate.c @@ -109,8 +113,8 @@ set(${MODULE_PREFIX}_SRCS update.h message.c message.h - channel.c - channel.h + channels.c + channels.h window.c window.h listener.c @@ -142,7 +146,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-handle winpr-crt) + MODULES winpr-registry winpr-utils winpr-interlocked winpr-dsparse winpr-sspi winpr-rpc winpr-wtsapi winpr-handle winpr-crt) if(MONOLITHIC_BUILD) set(FREERDP_LIBS ${FREERDP_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE) diff --git a/libfreerdp/core/activation.c b/libfreerdp/core/activation.c index eb5bb38dc..15ec293bb 100644 --- a/libfreerdp/core/activation.c +++ b/libfreerdp/core/activation.c @@ -61,7 +61,7 @@ BOOL rdp_send_server_synchronize_pdu(rdpRdp* rdp) s = rdp_data_pdu_init(rdp); rdp_write_synchronize_pdu(s, rdp->settings); - return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->user_id); + return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId); } BOOL rdp_recv_client_synchronize_pdu(rdpRdp* rdp, wStream* s) @@ -92,7 +92,7 @@ BOOL rdp_send_client_synchronize_pdu(rdpRdp* rdp) rdp_write_synchronize_pdu(s, rdp->settings); - return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->user_id); + return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId); } BOOL rdp_recv_control_pdu(wStream* s, UINT16* action) @@ -146,7 +146,7 @@ BOOL rdp_send_server_control_cooperate_pdu(rdpRdp* rdp) Stream_Write_UINT16(s, 0); /* grantId (2 bytes) */ Stream_Write_UINT32(s, 0); /* controlId (4 bytes) */ - return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->user_id); + return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId); } BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp) @@ -156,10 +156,10 @@ BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp) s = rdp_data_pdu_init(rdp); Stream_Write_UINT16(s, CTRLACTION_GRANTED_CONTROL); /* action (2 bytes) */ - Stream_Write_UINT16(s, rdp->mcs->user_id); /* grantId (2 bytes) */ + Stream_Write_UINT16(s, rdp->mcs->userId); /* grantId (2 bytes) */ Stream_Write_UINT32(s, 0x03EA); /* controlId (4 bytes) */ - return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->user_id); + return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId); } BOOL rdp_send_client_control_pdu(rdpRdp* rdp, UINT16 action) @@ -169,7 +169,7 @@ BOOL rdp_send_client_control_pdu(rdpRdp* rdp, UINT16 action) s = rdp_data_pdu_init(rdp); rdp_write_client_control_pdu(s, action); - return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->user_id); + return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId); } void rdp_write_persistent_list_entry(wStream* s, UINT32 key1, UINT32 key2) @@ -204,7 +204,7 @@ BOOL rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp) s = rdp_data_pdu_init(rdp); rdp_write_client_persistent_key_list_pdu(s, rdp->settings); - return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST, rdp->mcs->user_id); + return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST, rdp->mcs->userId); } BOOL rdp_recv_client_font_list_pdu(wStream* s) @@ -230,7 +230,7 @@ BOOL rdp_send_client_font_list_pdu(rdpRdp* rdp, UINT16 flags) s = rdp_data_pdu_init(rdp); rdp_write_client_font_list_pdu(s, flags); - return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_LIST, rdp->mcs->user_id); + return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_LIST, rdp->mcs->userId); } BOOL rdp_recv_font_map_pdu(rdpRdp* rdp, wStream* s) @@ -273,7 +273,7 @@ BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp) Stream_Write_UINT16(s, FONTLIST_FIRST | FONTLIST_LAST); /* mapFlags (2 bytes) */ Stream_Write_UINT16(s, 4); /* entrySize (2 bytes) */ - return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_MAP, rdp->mcs->user_id); + return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_MAP, rdp->mcs->userId); } BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s) @@ -337,7 +337,7 @@ BOOL rdp_send_deactivate_all(rdpRdp* rdp) Stream_Write_UINT16(s, 1); /* lengthSourceDescriptor (2 bytes) */ Stream_Write_UINT8(s, 0); /* sourceDescriptor (should be 0x00) */ - status = rdp_send_pdu(rdp, s, PDU_TYPE_DEACTIVATE_ALL, rdp->mcs->user_id); + status = rdp_send_pdu(rdp, s, PDU_TYPE_DEACTIVATE_ALL, rdp->mcs->userId); Stream_Free(s, TRUE); diff --git a/libfreerdp/core/autodetect.c b/libfreerdp/core/autodetect.c index a8077ef4f..4518b763a 100644 --- a/libfreerdp/core/autodetect.c +++ b/libfreerdp/core/autodetect.c @@ -38,8 +38,11 @@ static BOOL autodetect_send_rtt_measure_response(rdpRdp* rdp, UINT16 sequenceNum wStream* s; /* Send the response PDU to the server */ + s = rdp_message_channel_pdu_init(rdp); - if (s == NULL) return FALSE; + + if (s == NULL) + return FALSE; DEBUG_AUTODETECT("sending RTT Measure Response PDU"); @@ -60,8 +63,11 @@ static BOOL autodetect_send_bandwidth_measure_results(rdpRdp* rdp, UINT16 respon timeDelta = GetTickCount() - rdp->autodetect->bandwidthMeasureStartTime; /* Send the result PDU to the server */ + s = rdp_message_channel_pdu_init(rdp); - if (s == NULL) return FALSE; + + if (s == NULL) + return FALSE; DEBUG_AUTODETECT("sending Bandwidth Measure Results PDU -> timeDelta=%u, byteCount=%u", timeDelta, rdp->autodetect->bandwidthMeasureByteCount); @@ -75,13 +81,16 @@ static BOOL autodetect_send_bandwidth_measure_results(rdpRdp* rdp, UINT16 respon return rdp_send_message_channel_pdu(rdp, s, SEC_AUTODETECT_RSP); } -static BOOL autodetect_send_netchar_sync(rdpRdp* rdp, UINT16 sequenceNumber) +BOOL autodetect_send_netchar_sync(rdpRdp* rdp, UINT16 sequenceNumber) { wStream* s; /* Send the response PDU to the server */ + s = rdp_message_channel_pdu_init(rdp); - if (s == NULL) return FALSE; + + if (s == NULL) + return FALSE; DEBUG_AUTODETECT("sending Network Characteristics Sync PDU -> bandwidth=%u, rtt=%u", rdp->autodetect->netCharBandwidth, rdp->autodetect->netCharAverageRTT); @@ -273,16 +282,17 @@ int rdp_recv_autodetect_packet(rdpRdp* rdp, wStream* s) rdpAutoDetect* autodetect_new(void) { - rdpAutoDetect* autodetect = (rdpAutoDetect*)malloc(sizeof(rdpAutoDetect)); - if (autodetect) + rdpAutoDetect* autoDetect = (rdpAutoDetect*) malloc(sizeof(rdpAutoDetect)); + + if (autoDetect) { - memset(autodetect, 0, sizeof(rdpAutoDetect)); + ZeroMemory(autoDetect, sizeof(rdpAutoDetect)); } - return autodetect; + return autoDetect; } -void autodetect_free(rdpAutoDetect* autodetect) +void autodetect_free(rdpAutoDetect* autoDetect) { - free(autodetect); + free(autoDetect); } diff --git a/libfreerdp/core/capabilities.c b/libfreerdp/core/capabilities.c index 39bdd66d1..b5f2d499e 100644 --- a/libfreerdp/core/capabilities.c +++ b/libfreerdp/core/capabilities.c @@ -2977,7 +2977,7 @@ BOOL rdp_print_capability_sets(wStream* s, UINT16 numberCapabilities, BOOL recei em = bm + length; - if (Stream_GetRemainingLength(s) < length - 4) + if (Stream_GetRemainingLength(s) < (size_t) (length - 4)) { fprintf(stderr, "error processing stream\n"); return FALSE; @@ -3176,7 +3176,7 @@ BOOL rdp_read_capability_sets(wStream* s, rdpSettings* settings, UINT16 numberCa em = bm + length; - if (Stream_GetRemainingLength(s) < length - 4) + if (Stream_GetRemainingLength(s) < ((size_t) length - 4)) { fprintf(stderr, "error processing stream\n"); return FALSE; @@ -3389,7 +3389,7 @@ BOOL rdp_recv_get_active_header(rdpRdp* rdp, wStream* s, UINT16* pChannelId) if (*pChannelId != MCS_GLOBAL_CHANNEL_ID) { - UINT16 mcsMessageChannelId = rdp->mcs->message_channel_id; + UINT16 mcsMessageChannelId = rdp->mcs->messageChannelId; if ((mcsMessageChannelId == 0) || (*pChannelId != mcsMessageChannelId)) { @@ -3526,11 +3526,11 @@ BOOL rdp_send_demand_active(rdpRdp* rdp) s = Stream_New(NULL, 4096); rdp_init_stream_pdu(rdp, s); - rdp->settings->ShareId = 0x10000 + rdp->mcs->user_id; + rdp->settings->ShareId = 0x10000 + rdp->mcs->userId; rdp_write_demand_active(s, rdp->settings); - status = rdp_send_pdu(rdp, s, PDU_TYPE_DEMAND_ACTIVE, rdp->mcs->user_id); + status = rdp_send_pdu(rdp, s, PDU_TYPE_DEMAND_ACTIVE, rdp->mcs->userId); Stream_Free(s, TRUE); @@ -3555,7 +3555,7 @@ BOOL rdp_recv_confirm_active(rdpRdp* rdp, wStream* s) Stream_Read_UINT16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */ Stream_Read_UINT16(s, lengthCombinedCapabilities); /* lengthCombinedCapabilities (2 bytes) */ - if (Stream_GetRemainingLength(s) < lengthSourceDescriptor + 4) + if (((int) Stream_GetRemainingLength(s)) < lengthSourceDescriptor + 4) return FALSE; Stream_Seek(s, lengthSourceDescriptor); /* sourceDescriptor */ @@ -3741,7 +3741,7 @@ BOOL rdp_send_confirm_active(rdpRdp* rdp) rdp_write_confirm_active(s, rdp->settings); - status = rdp_send_pdu(rdp, s, PDU_TYPE_CONFIRM_ACTIVE, rdp->mcs->user_id); + status = rdp_send_pdu(rdp, s, PDU_TYPE_CONFIRM_ACTIVE, rdp->mcs->userId); Stream_Free(s, TRUE); diff --git a/libfreerdp/core/certificate.c b/libfreerdp/core/certificate.c index 6a28ab3b2..e679cfbee 100644 --- a/libfreerdp/core/certificate.c +++ b/libfreerdp/core/certificate.c @@ -248,7 +248,7 @@ BOOL certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info) error++; - if (Stream_GetRemainingLength(s) < modulus_length) + if (((int) Stream_GetRemainingLength(s)) < modulus_length) goto error1; info->ModulusLength = modulus_length; @@ -261,7 +261,7 @@ BOOL certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info) error++; - if (Stream_GetRemainingLength(s) < exponent_length || exponent_length > 4) + if ((((int) Stream_GetRemainingLength(s)) < exponent_length) || (exponent_length > 4)) goto error2; Stream_Read(s, &info->exponent[4 - exponent_length], exponent_length); diff --git a/libfreerdp/core/channel.c b/libfreerdp/core/channel.c deleted file mode 100644 index e9b14c27f..000000000 --- a/libfreerdp/core/channel.c +++ /dev/null @@ -1,132 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Virtual Channels - * - * Copyright 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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include -#include -#include -#include - -#include "rdp.h" -#include "channel.h" - -BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channel_id, BYTE* data, int size) -{ - wStream* s; - UINT32 flags; - int i, left; - int chunk_size; - rdpChannel* channel = NULL; - - for (i = 0; i < rdp->settings->ChannelCount; i++) - { - if (rdp->settings->ChannelDefArray[i].ChannelId == channel_id) - { - channel = &rdp->settings->ChannelDefArray[i]; - break; - } - } - - if (!channel) - { - fprintf(stderr, "freerdp_channel_send: unknown channel_id %d\n", channel_id); - return FALSE; - } - - flags = CHANNEL_FLAG_FIRST; - left = size; - - while (left > 0) - { - s = rdp_send_stream_init(rdp); - - if (left > (int) rdp->settings->VirtualChannelChunkSize) - { - chunk_size = rdp->settings->VirtualChannelChunkSize; - } - else - { - chunk_size = left; - flags |= CHANNEL_FLAG_LAST; - } - - if ((channel->options & CHANNEL_OPTION_SHOW_PROTOCOL)) - { - flags |= CHANNEL_FLAG_SHOW_PROTOCOL; - } - - Stream_Write_UINT32(s, size); - Stream_Write_UINT32(s, flags); - Stream_EnsureCapacity(s, chunk_size); - Stream_Write(s, data, chunk_size); - - rdp_send(rdp, s, channel_id); - - data += chunk_size; - left -= chunk_size; - flags = 0; - } - - return TRUE; -} - -BOOL freerdp_channel_process(freerdp* instance, wStream* s, UINT16 channel_id) -{ - UINT32 length; - UINT32 flags; - int chunk_length; - - if (Stream_GetRemainingLength(s) < 8) - return FALSE; - - Stream_Read_UINT32(s, length); - Stream_Read_UINT32(s, flags); - chunk_length = Stream_GetRemainingLength(s); - - IFCALL(instance->ReceiveChannelData, instance, - channel_id, Stream_Pointer(s), chunk_length, flags, length); - - return TRUE; -} - -BOOL freerdp_channel_peer_process(freerdp_peer* client, wStream* s, UINT16 channel_id) -{ - UINT32 length; - UINT32 flags; - int chunk_length; - - if (Stream_GetRemainingLength(s) < 8) - return FALSE; - - Stream_Read_UINT32(s, length); - Stream_Read_UINT32(s, flags); - chunk_length = Stream_GetRemainingLength(s); - - IFCALL(client->ReceiveChannelData, client, - channel_id, Stream_Pointer(s), chunk_length, flags, length); - - return TRUE; -} diff --git a/libfreerdp/core/channels.c b/libfreerdp/core/channels.c new file mode 100644 index 000000000..54cfa99cf --- /dev/null +++ b/libfreerdp/core/channels.c @@ -0,0 +1,222 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Virtual Channels + * + * Copyright 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rdp.h" +#include "client.h" +#include "server.h" +#include "channels.h" + +BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, BYTE* data, int size) +{ + DWORD i; + int left; + wStream* s; + UINT32 flags; + int chunkSize; + rdpMcs* mcs = rdp->mcs; + rdpMcsChannel* channel = NULL; + + for (i = 0; i < mcs->channelCount; i++) + { + if (mcs->channels[i].ChannelId == channelId) + { + channel = &mcs->channels[i]; + break; + } + } + + if (!channel) + { + fprintf(stderr, "freerdp_channel_send: unknown channelId %d\n", channelId); + return FALSE; + } + + flags = CHANNEL_FLAG_FIRST; + left = size; + + while (left > 0) + { + s = rdp_send_stream_init(rdp); + + if (left > (int) rdp->settings->VirtualChannelChunkSize) + { + chunkSize = rdp->settings->VirtualChannelChunkSize; + } + else + { + chunkSize = left; + flags |= CHANNEL_FLAG_LAST; + } + + if ((channel->options & CHANNEL_OPTION_SHOW_PROTOCOL)) + { + flags |= CHANNEL_FLAG_SHOW_PROTOCOL; + } + + Stream_Write_UINT32(s, size); + Stream_Write_UINT32(s, flags); + Stream_EnsureCapacity(s, chunkSize); + Stream_Write(s, data, chunkSize); + + rdp_send(rdp, s, channelId); + + data += chunkSize; + left -= chunkSize; + flags = 0; + } + + return TRUE; +} + +BOOL freerdp_channel_process(freerdp* instance, wStream* s, UINT16 channelId) +{ + UINT32 length; + UINT32 flags; + int chunkLength; + + if (Stream_GetRemainingLength(s) < 8) + return FALSE; + + Stream_Read_UINT32(s, length); + Stream_Read_UINT32(s, flags); + chunkLength = Stream_GetRemainingLength(s); + + IFCALL(instance->ReceiveChannelData, instance, + channelId, Stream_Pointer(s), chunkLength, flags, length); + + return TRUE; +} + +BOOL freerdp_channel_peer_process(freerdp_peer* client, wStream* s, UINT16 channelId) +{ + UINT32 length; + UINT32 flags; + int chunkLength; + + if (Stream_GetRemainingLength(s) < 8) + return FALSE; + + Stream_Read_UINT32(s, length); + Stream_Read_UINT32(s, flags); + chunkLength = Stream_GetRemainingLength(s); + + IFCALL(client->ReceiveChannelData, client, + channelId, Stream_Pointer(s), chunkLength, flags, length); + + return TRUE; +} + +static WtsApiFunctionTable FreeRDP_WtsApiFunctionTable = +{ + 0, /* dwVersion */ + 0, /* dwFlags */ + + FreeRDP_WTSStopRemoteControlSession, /* StopRemoteControlSession */ + FreeRDP_WTSStartRemoteControlSessionW, /* StartRemoteControlSessionW */ + FreeRDP_WTSStartRemoteControlSessionA, /* StartRemoteControlSessionA */ + FreeRDP_WTSConnectSessionW, /* ConnectSessionW */ + FreeRDP_WTSConnectSessionA, /* ConnectSessionA */ + FreeRDP_WTSEnumerateServersW, /* EnumerateServersW */ + FreeRDP_WTSEnumerateServersA, /* EnumerateServersA */ + FreeRDP_WTSOpenServerW, /* OpenServerW */ + FreeRDP_WTSOpenServerA, /* OpenServerA */ + FreeRDP_WTSOpenServerExW, /* OpenServerExW */ + FreeRDP_WTSOpenServerExA, /* OpenServerExA */ + FreeRDP_WTSCloseServer, /* CloseServer */ + FreeRDP_WTSEnumerateSessionsW, /* EnumerateSessionsW */ + FreeRDP_WTSEnumerateSessionsA, /* EnumerateSessionsA */ + FreeRDP_WTSEnumerateSessionsExW, /* EnumerateSessionsExW */ + FreeRDP_WTSEnumerateSessionsExA, /* EnumerateSessionsExA */ + FreeRDP_WTSEnumerateProcessesW, /* EnumerateProcessesW */ + FreeRDP_WTSEnumerateProcessesA, /* EnumerateProcessesA */ + FreeRDP_WTSTerminateProcess, /* TerminateProcess */ + FreeRDP_WTSQuerySessionInformationW, /* QuerySessionInformationW */ + FreeRDP_WTSQuerySessionInformationA, /* QuerySessionInformationA */ + FreeRDP_WTSQueryUserConfigW, /* QueryUserConfigW */ + FreeRDP_WTSQueryUserConfigA, /* QueryUserConfigA */ + FreeRDP_WTSSetUserConfigW, /* SetUserConfigW */ + FreeRDP_WTSSetUserConfigA, /* SetUserConfigA */ + FreeRDP_WTSSendMessageW, /* SendMessageW */ + FreeRDP_WTSSendMessageA, /* SendMessageA */ + FreeRDP_WTSDisconnectSession, /* DisconnectSession */ + FreeRDP_WTSLogoffSession, /* LogoffSession */ + FreeRDP_WTSShutdownSystem, /* ShutdownSystem */ + FreeRDP_WTSWaitSystemEvent, /* WaitSystemEvent */ + FreeRDP_WTSVirtualChannelOpen, /* VirtualChannelOpen */ + FreeRDP_WTSVirtualChannelOpenEx, /* VirtualChannelOpenEx */ + FreeRDP_WTSVirtualChannelClose, /* VirtualChannelClose */ + FreeRDP_WTSVirtualChannelRead, /* VirtualChannelRead */ + FreeRDP_WTSVirtualChannelWrite, /* VirtualChannelWrite */ + FreeRDP_WTSVirtualChannelPurgeInput, /* VirtualChannelPurgeInput */ + FreeRDP_WTSVirtualChannelPurgeOutput, /* VirtualChannelPurgeOutput */ + FreeRDP_WTSVirtualChannelQuery, /* VirtualChannelQuery */ + FreeRDP_WTSFreeMemory, /* FreeMemory */ + FreeRDP_WTSRegisterSessionNotification, /* RegisterSessionNotification */ + FreeRDP_WTSUnRegisterSessionNotification, /* UnRegisterSessionNotification */ + FreeRDP_WTSRegisterSessionNotificationEx, /* RegisterSessionNotificationEx */ + FreeRDP_WTSUnRegisterSessionNotificationEx, /* UnRegisterSessionNotificationEx */ + FreeRDP_WTSQueryUserToken, /* QueryUserToken */ + FreeRDP_WTSFreeMemoryExW, /* FreeMemoryExW */ + FreeRDP_WTSFreeMemoryExA, /* FreeMemoryExA */ + FreeRDP_WTSEnumerateProcessesExW, /* EnumerateProcessesExW */ + FreeRDP_WTSEnumerateProcessesExA, /* EnumerateProcessesExA */ + FreeRDP_WTSEnumerateListenersW, /* EnumerateListenersW */ + FreeRDP_WTSEnumerateListenersA, /* EnumerateListenersA */ + FreeRDP_WTSQueryListenerConfigW, /* QueryListenerConfigW */ + FreeRDP_WTSQueryListenerConfigA, /* QueryListenerConfigA */ + FreeRDP_WTSCreateListenerW, /* CreateListenerW */ + FreeRDP_WTSCreateListenerA, /* CreateListenerA */ + FreeRDP_WTSSetListenerSecurityW, /* SetListenerSecurityW */ + FreeRDP_WTSSetListenerSecurityA, /* SetListenerSecurityA */ + FreeRDP_WTSGetListenerSecurityW, /* GetListenerSecurityW */ + FreeRDP_WTSGetListenerSecurityA, /* GetListenerSecurityA */ + FreeRDP_WTSEnableChildSessions, /* EnableChildSessions */ + FreeRDP_WTSIsChildSessionsEnabled, /* IsChildSessionsEnabled */ + FreeRDP_WTSGetChildSessionId, /* GetChildSessionId */ + FreeRDP_WTSGetActiveConsoleSessionId /* GetActiveConsoleSessionId */ +}; + +PWtsApiFunctionTable FreeRDP_InitWtsApi(void) +{ + return &FreeRDP_WtsApiFunctionTable; +} diff --git a/libfreerdp/core/channel.h b/libfreerdp/core/channels.h similarity index 89% rename from libfreerdp/core/channel.h rename to libfreerdp/core/channels.h index e6a926830..0b0e5c95c 100644 --- a/libfreerdp/core/channel.h +++ b/libfreerdp/core/channels.h @@ -20,7 +20,9 @@ #ifndef __CHANNEL_H #define __CHANNEL_H -BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channel_id, BYTE* data, int size); +#include "client.h" + +BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, BYTE* data, int size); BOOL freerdp_channel_process(freerdp* instance, wStream* s, UINT16 channel_id); BOOL freerdp_channel_peer_process(freerdp_peer* client, wStream* s, UINT16 channel_id); diff --git a/channels/client/channels.c b/libfreerdp/core/client.c similarity index 65% rename from channels/client/channels.c rename to libfreerdp/core/client.c index 0241a17e8..c5dd47c29 100644 --- a/channels/client/channels.c +++ b/libfreerdp/core/client.c @@ -2,9 +2,7 @@ * FreeRDP: A Remote Desktop Protocol Implementation * Client Channels * - * Copyright 2009-2011 Jay Sorg - * Copyright 2010-2011 Vic Lee - * Copyright 2012 Marc-Andre Moreau + * Copyright 2014 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. @@ -23,55 +21,14 @@ #include "config.h" #endif -#include -#include -#include +#include "rdp.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include "client.h" -#include -#include -#include -#include -#include -#include +static void* g_pInterface; +static CHANNEL_INIT_DATA g_ChannelInitData; -#include "addin.h" -#include "init.h" -#include "open.h" - -#include "channels.h" - -/** - * MS compatible plugin interface - * reference: - * http://msdn.microsoft.com/en-us/library/aa383580.aspx - * - * Notes on threads: - * Many virtual channel plugins are built using threads. - * Non main threads may call MyVirtualChannelOpen, - * MyVirtualChannelClose, or MyVirtualChannelWrite. - * Since the plugin's VirtualChannelEntry function is called - * from the main thread, MyVirtualChannelInit has to be called - * from the main thread. - */ - -/** - * The current channel manager reference passes from VirtualChannelEntry to - * VirtualChannelInit for the pInitHandle. - */ - -void* g_pInterface; -CHANNEL_INIT_DATA g_ChannelInitData; - -static wArrayList* g_ChannelsList = NULL; +static wHashTable* g_OpenHandles = NULL; /* To generate unique sequence for all open handles */ int g_open_handle_sequence = 1; @@ -79,68 +36,7 @@ int g_open_handle_sequence = 1; /* For locking the global resources */ static CRITICAL_SECTION g_channels_lock; -rdpChannels* freerdp_channels_find_by_open_handle(int OpenHandle, int* pindex) -{ - int i, j; - BOOL found = FALSE; - rdpChannels* channels = NULL; - - ArrayList_Lock(g_ChannelsList); - - i = j = 0; - channels = (rdpChannels*) ArrayList_GetItem(g_ChannelsList, i++); - - while (channels) - { - for (j = 0; j < channels->openDataCount; j++) - { - if (channels->openDataList[j].OpenHandle == OpenHandle) - { - *pindex = j; - found = TRUE; - break; - } - } - - if (found) - break; - - channels = (rdpChannels*) ArrayList_GetItem(g_ChannelsList, i++); - } - - ArrayList_Unlock(g_ChannelsList); - - return (found) ? channels : NULL; -} - -rdpChannels* freerdp_channels_find_by_instance(freerdp* instance) -{ - int index; - BOOL found = FALSE; - rdpChannels* channels = NULL; - - ArrayList_Lock(g_ChannelsList); - - index = 0; - channels = (rdpChannels*) ArrayList_GetItem(g_ChannelsList, index++); - - while (channels) - { - if (channels->instance == instance) - { - found = TRUE; - break; - } - - channels = (rdpChannels*) ArrayList_GetItem(g_ChannelsList, index++); - } - - ArrayList_Unlock(g_ChannelsList); - - return (found) ? channels : NULL; -} - -CHANNEL_OPEN_DATA* freerdp_channels_find_channel_open_data_by_name(rdpChannels* channels, const char* channel_name) +CHANNEL_OPEN_DATA* freerdp_channels_find_channel_open_data_by_name(rdpChannels* channels, const char* name) { int index; CHANNEL_OPEN_DATA* pChannelOpenData; @@ -149,57 +45,26 @@ CHANNEL_OPEN_DATA* freerdp_channels_find_channel_open_data_by_name(rdpChannels* { pChannelOpenData = &channels->openDataList[index]; - if (strcmp(channel_name, pChannelOpenData->name) == 0) + if (strcmp(name, pChannelOpenData->name) == 0) return pChannelOpenData; } return NULL; } -/* returns rdpChannel for the channel id passed in */ -rdpChannel* freerdp_channels_find_channel_by_id(rdpChannels* channels, rdpSettings* settings, int channel_id, int* pindex) -{ - int index; - int count; - rdpChannel* channel; - - count = settings->ChannelCount; - - for (index = 0; index < count; index++) - { - channel = &settings->ChannelDefArray[index]; - - if (channel->ChannelId == channel_id) - { - if (pindex != 0) - *pindex = index; - - return channel; - } - } - - return NULL; -} - /* returns rdpChannel for the channel name passed in */ -rdpChannel* freerdp_channels_find_channel_by_name(rdpChannels* channels, - rdpSettings* settings, const char* channel_name, int* pindex) +rdpMcsChannel* freerdp_channels_find_channel_by_name(rdpRdp* rdp, const char* name) { int index; - int count; - rdpChannel* channel; + rdpMcsChannel* channel; + rdpMcs* mcs = rdp->mcs; - count = settings->ChannelCount; - - for (index = 0; index < count; index++) + for (index = 0; index < mcs->channelCount; index++) { - channel = &settings->ChannelDefArray[index]; + channel = &mcs->channels[index]; - if (strcmp(channel_name, channel->Name) == 0) + if (strcmp(name, channel->Name) == 0) { - if (pindex != 0) - *pindex = index; - return channel; } } @@ -207,116 +72,6 @@ rdpChannel* freerdp_channels_find_channel_by_name(rdpChannels* channels, return NULL; } -UINT32 FreeRDP_VirtualChannelWrite(UINT32 openHandle, void* pData, UINT32 dataLength, void* pUserData) -{ - int index; - rdpChannels* channels; - CHANNEL_OPEN_EVENT* item; - CHANNEL_OPEN_DATA* pChannelOpenData; - - channels = freerdp_channels_find_by_open_handle(openHandle, &index); - - if ((!channels) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) - { - DEBUG_CHANNELS("error bad channel handle"); - return CHANNEL_RC_BAD_CHANNEL_HANDLE; - } - - if (!channels->is_connected) - { - DEBUG_CHANNELS("error not connected"); - return CHANNEL_RC_NOT_CONNECTED; - } - - if (!pData) - { - DEBUG_CHANNELS("error bad pData"); - return CHANNEL_RC_NULL_DATA; - } - - if (!dataLength) - { - DEBUG_CHANNELS("error bad dataLength"); - return CHANNEL_RC_ZERO_LENGTH; - } - - pChannelOpenData = &channels->openDataList[index]; - - if (pChannelOpenData->flags != 2) - { - DEBUG_CHANNELS("error not open"); - return CHANNEL_RC_NOT_OPEN; - } - - if (!channels->is_connected) - { - DEBUG_CHANNELS("error not connected"); - return CHANNEL_RC_NOT_CONNECTED; - } - - item = (CHANNEL_OPEN_EVENT*) malloc(sizeof(CHANNEL_OPEN_EVENT)); - item->Data = pData; - item->DataLength = dataLength; - item->UserData = pUserData; - item->Index = index; - - MessageQueue_Post(channels->MsgPipe->Out, (void*) channels, 0, (void*) item, NULL); - - return CHANNEL_RC_OK; -} - -UINT32 FreeRDP_VirtualChannelEventPush(UINT32 openHandle, wMessage* event) -{ - int index; - rdpChannels* channels; - CHANNEL_OPEN_DATA* pChannelOpenData; - - channels = freerdp_channels_find_by_open_handle(openHandle, &index); - - if ((!channels) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) - { - DEBUG_CHANNELS("error bad channels handle"); - return CHANNEL_RC_BAD_CHANNEL_HANDLE; - } - - if (!channels->is_connected) - { - DEBUG_CHANNELS("error not connected"); - return CHANNEL_RC_NOT_CONNECTED; - } - - if (!event) - { - DEBUG_CHANNELS("error bad event"); - return CHANNEL_RC_NULL_DATA; - } - - pChannelOpenData = &channels->openDataList[index]; - - if (pChannelOpenData->flags != 2) - { - DEBUG_CHANNELS("error not open"); - return CHANNEL_RC_NOT_OPEN; - } - - if (!channels->is_connected) - { - DEBUG_CHANNELS("error not connected"); - return CHANNEL_RC_NOT_CONNECTED; - } - - /** - * We really intend to use the In queue for events, but we're pushing on both - * to wake up threads waiting on the out queue. Doing this cleanly would require - * breaking freerdp_pop_event() a bit too early in this refactoring. - */ - - MessageQueue_Post(channels->MsgPipe->In, (void*) channels, 1, (void*) event, NULL); - MessageQueue_Post(channels->MsgPipe->Out, (void*) channels, 1, (void*) event, NULL); - - return CHANNEL_RC_OK; -} - /** * this is called shortly after the application starts and * before any other function in the file @@ -324,27 +79,11 @@ UINT32 FreeRDP_VirtualChannelEventPush(UINT32 openHandle, wMessage* event) */ int freerdp_channels_global_init(void) { - if (!g_ChannelsList) - { - g_ChannelsList = ArrayList_New(TRUE); - InitializeCriticalSectionAndSpinCount(&g_channels_lock, 4000); - } - return 0; } int freerdp_channels_global_uninit(void) { - EnterCriticalSection(&g_channels_lock); - DeleteCriticalSection(&g_channels_lock); - - if (g_ChannelsList) - { - ArrayList_Lock(g_ChannelsList); - ArrayList_Free(g_ChannelsList); - g_ChannelsList = NULL; - } - return 0; } @@ -357,7 +96,11 @@ rdpChannels* freerdp_channels_new(void) channels->MsgPipe = MessagePipe_New(); - ArrayList_Add(g_ChannelsList, (void*) channels); + if (!g_OpenHandles) + { + g_OpenHandles = HashTable_New(TRUE); + InitializeCriticalSectionAndSpinCount(&g_channels_lock, 4000); + } return channels; } @@ -366,86 +109,9 @@ void freerdp_channels_free(rdpChannels* channels) { MessagePipe_Free(channels->MsgPipe); - ArrayList_Lock(g_ChannelsList); - ArrayList_Remove(g_ChannelsList, channels); - ArrayList_Unlock(g_ChannelsList); - free(channels); } -int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, void* entry, void* data) -{ - int status; - CHANNEL_ENTRY_POINTS_EX ep; - CHANNEL_CLIENT_DATA* pChannelClientData; - - if (channels->clientDataCount + 1 >= CHANNEL_MAX_COUNT) - { - fprintf(stderr, "error: too many channels\n"); - return 1; - } - - pChannelClientData = &channels->clientDataList[channels->clientDataCount]; - pChannelClientData->entry = (PVIRTUALCHANNELENTRY) entry; - - ep.cbSize = sizeof(ep); - ep.protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000; - ep.pVirtualChannelInit = FreeRDP_VirtualChannelInit; - ep.pVirtualChannelOpen = FreeRDP_VirtualChannelOpen; - ep.pVirtualChannelClose = FreeRDP_VirtualChannelClose; - ep.pVirtualChannelWrite = FreeRDP_VirtualChannelWrite; - - g_pInterface = NULL; - ep.MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER; - ep.ppInterface = &g_pInterface; - ep.pExtendedData = data; - ep.pVirtualChannelEventPush = FreeRDP_VirtualChannelEventPush; - - /* enable VirtualChannelInit */ - channels->can_call_init = TRUE; - channels->settings = settings; - - EnterCriticalSection(&g_channels_lock); - - g_ChannelInitData.channels = channels; - status = pChannelClientData->entry((PCHANNEL_ENTRY_POINTS) &ep); - - LeaveCriticalSection(&g_channels_lock); - - /* disable MyVirtualChannelInit */ - channels->settings = NULL; - channels->can_call_init = FALSE; - - if (!status) - { - fprintf(stderr, "error: channel export function call failed\n"); - return 1; - } - - return 0; -} - -/** - * this is called when processing the command line parameters - * called only from main thread - */ -int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, const char* name, void* data) -{ - void* entry; - - DEBUG_CHANNELS("%s", name); - - entry = (PVIRTUALCHANNELENTRY) freerdp_load_channel_addin_entry(name, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC); - - if (!entry) - { - DEBUG_CHANNELS("failed to find export function"); - return 1; - } - - return freerdp_channels_client_load(channels, settings, entry, data); -} - int freerdp_drdynvc_on_channel_connected(DrdynvcClientContext* context, const char* name, void* pInterface) { int status = 0; @@ -485,7 +151,6 @@ int freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance) int index; CHANNEL_CLIENT_DATA* pChannelClientData; - DEBUG_CHANNELS("enter"); channels->instance = instance; for (index = 0; index < channels->clientDataCount; index++) @@ -514,7 +179,7 @@ int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance) channels->is_connected = 1; hostname = instance->settings->ServerHostname; - hostnameLength = strlen(hostname); + hostnameLength = (int) strlen(hostname); for (index = 0; index < channels->clientDataCount; index++) { @@ -554,30 +219,35 @@ int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance) return 0; } -/** - * data coming from the server to the client - * called only from main thread - */ -int freerdp_channels_data(freerdp* instance, int channel_id, void* data, int data_size, int flags, int total_size) +int freerdp_channels_data(freerdp* instance, UINT16 channelId, BYTE* data, int dataSize, int flags, int totalSize) { int index; - rdpChannel* channel; + rdpMcs* mcs; rdpChannels* channels; + rdpMcsChannel* channel = NULL; CHANNEL_OPEN_DATA* pChannelOpenData; - channels = freerdp_channels_find_by_instance(instance); + mcs = instance->context->rdp->mcs; + channels = instance->context->channels; - if (!channels) + if (!channels || !mcs) { - DEBUG_CHANNELS("could not find channel manager"); return 1; } - channel = freerdp_channels_find_channel_by_id(channels, instance->settings, channel_id, &index); + for (index = 0; index < mcs->channelCount; index++) + { + channel = &mcs->channels[index]; + + if (mcs->channels[index].ChannelId == channelId) + { + channel = &mcs->channels[index]; + break; + } + } if (!channel) { - DEBUG_CHANNELS("could not find channel id"); return 1; } @@ -585,14 +255,13 @@ int freerdp_channels_data(freerdp* instance, int channel_id, void* data, int dat if (!pChannelOpenData) { - DEBUG_CHANNELS("could not find channel name"); return 1; } if (pChannelOpenData->pChannelOpenEventProc) { pChannelOpenData->pChannelOpenEventProc(pChannelOpenData->OpenHandle, - CHANNEL_EVENT_DATA_RECEIVED, data, data_size, total_size, flags); + CHANNEL_EVENT_DATA_RECEIVED, data, dataSize, totalSize, flags); } return 0; @@ -630,7 +299,6 @@ FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, wMessage* eve if (!name) { - DEBUG_CHANNELS("unknown event_class %d", GetMessageClass(event->id)); freerdp_event_free(event); return 1; } @@ -639,7 +307,6 @@ FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, wMessage* eve if (!pChannelOpenData) { - DEBUG_CHANNELS("could not find channel name %s", name); freerdp_event_free(event); return 1; } @@ -658,10 +325,10 @@ FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, wMessage* eve */ static int freerdp_channels_process_sync(rdpChannels* channels, freerdp* instance) { - int rc = TRUE; + int status = TRUE; wMessage message; wMessage* event; - rdpChannel* channel; + rdpMcsChannel* channel; CHANNEL_OPEN_EVENT* item; CHANNEL_OPEN_DATA* pChannelOpenData; @@ -669,7 +336,7 @@ static int freerdp_channels_process_sync(rdpChannels* channels, freerdp* instanc { if (message.id == WMQ_QUIT) { - rc = FALSE; + status = FALSE; break; } @@ -680,10 +347,9 @@ static int freerdp_channels_process_sync(rdpChannels* channels, freerdp* instanc if (!item) break; - pChannelOpenData = &channels->openDataList[item->Index]; + pChannelOpenData = item->pChannelOpenData; - channel = freerdp_channels_find_channel_by_name(channels, instance->settings, - pChannelOpenData->name, &item->Index); + channel = freerdp_channels_find_channel_by_name(instance->context->rdp, pChannelOpenData->name); if (channel) instance->SendChannelData(instance, channel->ChannelId, item->Data, item->DataLength); @@ -707,7 +373,7 @@ static int freerdp_channels_process_sync(rdpChannels* channels, freerdp* instanc } } - return rc; + return status; } /** @@ -803,8 +469,6 @@ void freerdp_channels_close(rdpChannels* channels, freerdp* instance) CHANNEL_OPEN_DATA* pChannelOpenData; CHANNEL_CLIENT_DATA* pChannelClientData; - DEBUG_CHANNELS("closing"); - channels->is_connected = 0; freerdp_channels_check_fds(channels, instance); @@ -835,3 +499,299 @@ void freerdp_channels_close(rdpChannels* channels, freerdp* instance) /* Emit a quit signal to the internal message pipe. */ MessagePipe_PostQuit(channels->MsgPipe, 0); } + +UINT VCAPITYPE FreeRDP_VirtualChannelInit(LPVOID* ppInitHandle, PCHANNEL_DEF pChannel, + INT channelCount, ULONG versionRequested, PCHANNEL_INIT_EVENT_FN pChannelInitEventProc) +{ + int index; + void* pInterface; + DWORD OpenHandle; + CHANNEL_DEF* channel; + rdpChannels* channels; + rdpSettings* settings; + PCHANNEL_DEF pChannelDef; + CHANNEL_INIT_DATA* pChannelInitData; + CHANNEL_OPEN_DATA* pChannelOpenData; + CHANNEL_CLIENT_DATA* pChannelClientData; + + if (!ppInitHandle) + return CHANNEL_RC_BAD_INIT_HANDLE; + + channels = g_ChannelInitData.channels; + pInterface = g_pInterface; + + pChannelInitData = &(channels->initDataList[channels->initDataCount]); + *ppInitHandle = pChannelInitData; + channels->initDataCount++; + + pChannelInitData->channels = channels; + pChannelInitData->pInterface = pInterface; + + if (!channels->can_call_init) + return CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY; + + if (channels->openDataCount + channelCount >= CHANNEL_MAX_COUNT) + return CHANNEL_RC_TOO_MANY_CHANNELS; + + if (!pChannel) + return CHANNEL_RC_BAD_CHANNEL; + + if (channels->is_connected) + return CHANNEL_RC_ALREADY_CONNECTED; + + if (versionRequested != VIRTUAL_CHANNEL_VERSION_WIN2000) + { + + } + + for (index = 0; index < channelCount; index++) + { + pChannelDef = &pChannel[index]; + + if (freerdp_channels_find_channel_open_data_by_name(channels, pChannelDef->name) != 0) + { + return CHANNEL_RC_BAD_CHANNEL; + } + } + + pChannelClientData = &channels->clientDataList[channels->clientDataCount]; + pChannelClientData->pChannelInitEventProc = pChannelInitEventProc; + pChannelClientData->pInitHandle = *ppInitHandle; + channels->clientDataCount++; + + settings = channels->settings; + + for (index = 0; index < channelCount; index++) + { + pChannelDef = &pChannel[index]; + pChannelOpenData = &channels->openDataList[channels->openDataCount]; + + OpenHandle = g_open_handle_sequence++; + + pChannelOpenData->OpenHandle = OpenHandle; + pChannelOpenData->channels = channels; + + HashTable_Add(g_OpenHandles, (void*) (UINT_PTR) OpenHandle, (void*) pChannelOpenData); + + pChannelOpenData->flags = 1; /* init */ + strncpy(pChannelOpenData->name, pChannelDef->name, CHANNEL_NAME_LEN); + pChannelOpenData->options = pChannelDef->options; + + if (settings->ChannelCount < CHANNEL_MAX_COUNT) + { + channel = &settings->ChannelDefArray[settings->ChannelCount]; + strncpy(channel->name, pChannelDef->name, 7); + channel->options = pChannelDef->options; + channels->settings->ChannelCount++; + } + + channels->openDataCount++; + } + + return CHANNEL_RC_OK; +} + +UINT VCAPITYPE FreeRDP_VirtualChannelOpen(LPVOID pInitHandle, LPDWORD pOpenHandle, + PCHAR pChannelName, PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc) +{ + void* pInterface; + rdpChannels* channels; + CHANNEL_INIT_DATA* pChannelInitData; + CHANNEL_OPEN_DATA* pChannelOpenData; + + pChannelInitData = (CHANNEL_INIT_DATA*) pInitHandle; + channels = pChannelInitData->channels; + pInterface = pChannelInitData->pInterface; + + if (!pOpenHandle) + return CHANNEL_RC_BAD_CHANNEL_HANDLE; + + if (!pChannelOpenEventProc) + return CHANNEL_RC_BAD_PROC; + + if (!channels->is_connected) + return CHANNEL_RC_NOT_CONNECTED; + + pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, pChannelName); + + if (!pChannelOpenData) + return CHANNEL_RC_UNKNOWN_CHANNEL_NAME; + + if (pChannelOpenData->flags == 2) + return CHANNEL_RC_ALREADY_OPEN; + + pChannelOpenData->flags = 2; /* open */ + pChannelOpenData->pInterface = pInterface; + pChannelOpenData->pChannelOpenEventProc = pChannelOpenEventProc; + *pOpenHandle = pChannelOpenData->OpenHandle; + + return CHANNEL_RC_OK; +} + +UINT VCAPITYPE FreeRDP_VirtualChannelClose(DWORD openHandle) +{ + CHANNEL_OPEN_DATA* pChannelOpenData; + + pChannelOpenData = HashTable_GetItemValue(g_OpenHandles, (void*) (UINT_PTR) openHandle); + + if (!pChannelOpenData) + return CHANNEL_RC_BAD_CHANNEL_HANDLE; + + if (pChannelOpenData->flags != 2) + return CHANNEL_RC_NOT_OPEN; + + pChannelOpenData->flags = 0; + + return CHANNEL_RC_OK; +} + +UINT VCAPITYPE FreeRDP_VirtualChannelWrite(DWORD openHandle, LPVOID pData, ULONG dataLength, LPVOID pUserData) +{ + rdpChannels* channels; + CHANNEL_OPEN_DATA* pChannelOpenData; + CHANNEL_OPEN_EVENT* pChannelOpenEvent; + + pChannelOpenData = HashTable_GetItemValue(g_OpenHandles, (void*) (UINT_PTR) openHandle); + + if (!pChannelOpenData) + return CHANNEL_RC_BAD_CHANNEL_HANDLE; + + channels = pChannelOpenData->channels; + + if (!channels) + return CHANNEL_RC_BAD_CHANNEL_HANDLE; + + if (!channels->is_connected) + return CHANNEL_RC_NOT_CONNECTED; + + if (!pData) + return CHANNEL_RC_NULL_DATA; + + if (!dataLength) + return CHANNEL_RC_ZERO_LENGTH; + + if (pChannelOpenData->flags != 2) + return CHANNEL_RC_NOT_OPEN; + + pChannelOpenEvent = (CHANNEL_OPEN_EVENT*) malloc(sizeof(CHANNEL_OPEN_EVENT)); + + if (!pChannelOpenEvent) + return CHANNEL_RC_NO_MEMORY; + + pChannelOpenEvent->Data = pData; + pChannelOpenEvent->DataLength = dataLength; + pChannelOpenEvent->UserData = pUserData; + pChannelOpenEvent->pChannelOpenData = pChannelOpenData; + + MessageQueue_Post(channels->MsgPipe->Out, (void*) channels, 0, (void*) pChannelOpenEvent, NULL); + + return CHANNEL_RC_OK; +} + +UINT FreeRDP_VirtualChannelEventPush(DWORD openHandle, wMessage* event) +{ + rdpChannels* channels; + CHANNEL_OPEN_DATA* pChannelOpenData; + + pChannelOpenData = HashTable_GetItemValue(g_OpenHandles, (void*) (UINT_PTR) openHandle); + + if (!pChannelOpenData) + return CHANNEL_RC_BAD_CHANNEL_HANDLE; + + channels = pChannelOpenData->channels; + + if (!channels) + return CHANNEL_RC_BAD_CHANNEL_HANDLE; + + if (!channels->is_connected) + return CHANNEL_RC_NOT_CONNECTED; + + if (!event) + return CHANNEL_RC_NULL_DATA; + + if (pChannelOpenData->flags != 2) + return CHANNEL_RC_NOT_OPEN; + + /** + * We really intend to use the In queue for events, but we're pushing on both + * to wake up threads waiting on the out queue. Doing this cleanly would require + * breaking freerdp_pop_event() a bit too early in this refactoring. + */ + + MessageQueue_Post(channels->MsgPipe->In, (void*) channels, 1, (void*) event, NULL); + MessageQueue_Post(channels->MsgPipe->Out, (void*) channels, 1, (void*) event, NULL); + + return CHANNEL_RC_OK; +} + +int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, void* entry, void* data) +{ + int status; + CHANNEL_ENTRY_POINTS_FREERDP EntryPoints; + CHANNEL_CLIENT_DATA* pChannelClientData; + + if (channels->clientDataCount + 1 >= CHANNEL_MAX_COUNT) + { + fprintf(stderr, "error: too many channels\n"); + return 1; + } + + pChannelClientData = &channels->clientDataList[channels->clientDataCount]; + pChannelClientData->entry = (PVIRTUALCHANNELENTRY) entry; + + ZeroMemory(&EntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP)); + + EntryPoints.cbSize = sizeof(EntryPoints); + EntryPoints.protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000; + EntryPoints.pVirtualChannelInit = FreeRDP_VirtualChannelInit; + EntryPoints.pVirtualChannelOpen = FreeRDP_VirtualChannelOpen; + EntryPoints.pVirtualChannelClose = FreeRDP_VirtualChannelClose; + EntryPoints.pVirtualChannelWrite = FreeRDP_VirtualChannelWrite; + + g_pInterface = NULL; + EntryPoints.MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER; + EntryPoints.ppInterface = &g_pInterface; + EntryPoints.pExtendedData = data; + EntryPoints.pVirtualChannelEventPush = FreeRDP_VirtualChannelEventPush; + + /* enable VirtualChannelInit */ + channels->can_call_init = TRUE; + channels->settings = settings; + + EnterCriticalSection(&g_channels_lock); + + g_ChannelInitData.channels = channels; + status = pChannelClientData->entry((PCHANNEL_ENTRY_POINTS) &EntryPoints); + + LeaveCriticalSection(&g_channels_lock); + + /* disable MyVirtualChannelInit */ + channels->settings = NULL; + channels->can_call_init = FALSE; + + if (!status) + { + fprintf(stderr, "error: channel export function call failed\n"); + return 1; + } + + return 0; +} + +/** + * this is called when processing the command line parameters + * called only from main thread + */ +int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, const char* name, void* data) +{ + void* entry; + + entry = (PVIRTUALCHANNELENTRY) freerdp_load_channel_addin_entry(name, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC); + + if (!entry) + { + return 1; + } + + return freerdp_channels_client_load(channels, settings, entry, data); +} diff --git a/channels/client/channels.h b/libfreerdp/core/client.h similarity index 77% rename from channels/client/channels.h rename to libfreerdp/core/client.h index 7e801e59b..532359033 100644 --- a/channels/client/channels.h +++ b/libfreerdp/core/client.h @@ -2,7 +2,7 @@ * FreeRDP: A Remote Desktop Protocol Implementation * Client Channels * - * Copyright 2013 Marc-Andre Moreau + * Copyright 2014 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. @@ -17,17 +17,17 @@ * limitations under the License. */ -#ifndef FREERDP_PRIVATE_CLIENT_CHANNELS -#define FREERDP_PRIVATE_CLIENT_CHANNELS +#ifndef FREERDP_CORE_CLIENT_H +#define FREERDP_CORE_CLIENT_H #include -#include -#include +#include #include #include #include +#include #include #include #include @@ -35,10 +35,6 @@ #include #include -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #define CHANNEL_MAX_COUNT 30 struct rdp_channel_client_data @@ -56,6 +52,7 @@ struct rdp_channel_open_data int options; int flags; void* pInterface; + rdpChannels* channels; PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc; }; typedef struct rdp_channel_open_data CHANNEL_OPEN_DATA; @@ -65,7 +62,7 @@ struct _CHANNEL_OPEN_EVENT void* Data; UINT32 DataLength; void* UserData; - int Index; + CHANNEL_OPEN_DATA* pChannelOpenData; }; typedef struct _CHANNEL_OPEN_EVENT CHANNEL_OPEN_EVENT; @@ -110,13 +107,4 @@ struct rdp_channels DrdynvcClientContext* drdynvc; }; -#ifdef WITH_DEBUG_CHANNELS -#define DEBUG_CHANNELS(fmt, ...) DEBUG_CLASS(CHANNELS, fmt, ## __VA_ARGS__) -#else -#define DEBUG_CHANNELS(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) -#endif - -rdpChannels* freerdp_channels_find_by_open_handle(int open_handle, int* pindex); -CHANNEL_OPEN_DATA* freerdp_channels_find_channel_open_data_by_name(rdpChannels* channels, const char* channel_name); - -#endif /* FREERDP_PRIVATE_CLIENT_CHANNELS */ +#endif /* FREERDP_CORE_CLIENT_H */ diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index bf2bae764..974a85bdb 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -23,6 +23,7 @@ #include "info.h" #include "input.h" +#include "rdp.h" #include "connection.h" #include "transport.h" @@ -338,7 +339,7 @@ BOOL rdp_client_redirect(rdpRdp* rdp) BOOL rdp_client_reconnect(rdpRdp* rdp) { - int i; + UINT32 i; transport_disconnect(rdp->transport); @@ -348,9 +349,9 @@ BOOL rdp_client_reconnect(rdpRdp* rdp) transport_free(rdp->transport); /* Reset virtual channel status */ - for (i = 0; i < rdp->settings->ChannelCount; i++) + for (i = 0; i < rdp->mcs->channelCount; i++) { - rdp->settings->ChannelDefArray[i].joined = FALSE; + rdp->mcs->channels[i].joined = FALSE; } rdp->transport = transport_new(rdp->settings); @@ -547,7 +548,7 @@ BOOL rdp_client_connect_mcs_attach_user_confirm(rdpRdp* rdp, wStream* s) if (!mcs_recv_attach_user_confirm(rdp->mcs, s)) return FALSE; - if (!mcs_send_channel_join_request(rdp->mcs, rdp->mcs->user_id)) + if (!mcs_send_channel_join_request(rdp->mcs, rdp->mcs->userId)) return FALSE; rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN); @@ -557,87 +558,89 @@ BOOL rdp_client_connect_mcs_attach_user_confirm(rdpRdp* rdp, wStream* s) BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s) { - int i; - UINT16 channel_id; - BOOL all_joined = TRUE; + UINT32 i; + UINT16 channelId; + BOOL allJoined = TRUE; + rdpMcs* mcs = rdp->mcs; - if (!mcs_recv_channel_join_confirm(rdp->mcs, s, &channel_id)) + if (!mcs_recv_channel_join_confirm(mcs, s, &channelId)) return FALSE; - if (!rdp->mcs->user_channel_joined) + if (!mcs->userChannelJoined) { - if (channel_id != rdp->mcs->user_id) + if (channelId != mcs->userId) return FALSE; - rdp->mcs->user_channel_joined = TRUE; + mcs->userChannelJoined = TRUE; - if (!mcs_send_channel_join_request(rdp->mcs, MCS_GLOBAL_CHANNEL_ID)) + if (!mcs_send_channel_join_request(mcs, MCS_GLOBAL_CHANNEL_ID)) return FALSE; } - else if (!rdp->mcs->global_channel_joined) + else if (!mcs->globalChannelJoined) { - if (channel_id != MCS_GLOBAL_CHANNEL_ID) + if (channelId != MCS_GLOBAL_CHANNEL_ID) return FALSE; - rdp->mcs->global_channel_joined = TRUE; + mcs->globalChannelJoined = TRUE; - if (rdp->mcs->message_channel_id != 0) + if (mcs->messageChannelId != 0) { - if (!mcs_send_channel_join_request(rdp->mcs, rdp->mcs->message_channel_id)) + if (!mcs_send_channel_join_request(mcs, mcs->messageChannelId)) return FALSE; - all_joined = FALSE; + allJoined = FALSE; } else { - if (rdp->settings->ChannelCount > 0) + if (mcs->channelCount > 0) { - if (!mcs_send_channel_join_request(rdp->mcs, rdp->settings->ChannelDefArray[0].ChannelId)) + if (!mcs_send_channel_join_request(mcs, mcs->channels[0].ChannelId)) return FALSE; - all_joined = FALSE; + allJoined = FALSE; } } } - else if ((rdp->mcs->message_channel_id != 0) && !rdp->mcs->message_channel_joined) + else if ((mcs->messageChannelId != 0) && !mcs->messageChannelJoined) { - if (channel_id != rdp->mcs->message_channel_id) + if (channelId != mcs->messageChannelId) return FALSE; - rdp->mcs->message_channel_joined = TRUE; + mcs->messageChannelJoined = TRUE; - if (rdp->settings->ChannelCount > 0) + if (mcs->channelCount > 0) { - if (!mcs_send_channel_join_request(rdp->mcs, rdp->settings->ChannelDefArray[0].ChannelId)) + if (!mcs_send_channel_join_request(mcs, mcs->channels[0].ChannelId)) return FALSE; - all_joined = FALSE; + allJoined = FALSE; } } else { - for (i = 0; i < rdp->settings->ChannelCount; i++) + for (i = 0; i < mcs->channelCount; i++) { - if (rdp->settings->ChannelDefArray[i].joined) + if (mcs->channels[i].joined) continue; - if (rdp->settings->ChannelDefArray[i].ChannelId != channel_id) + if (mcs->channels[i].ChannelId != channelId) return FALSE; - rdp->settings->ChannelDefArray[i].joined = TRUE; + mcs->channels[i].joined = TRUE; + break; } - if (i + 1 < rdp->settings->ChannelCount) + if (i + 1 < mcs->channelCount) { - if (!mcs_send_channel_join_request(rdp->mcs, rdp->settings->ChannelDefArray[i + 1].ChannelId)) + if (!mcs_send_channel_join_request(mcs, mcs->channels[i + 1].ChannelId)) return FALSE; - all_joined = FALSE; + allJoined = FALSE; } } - if (rdp->mcs->user_channel_joined && rdp->mcs->global_channel_joined && all_joined) + if (mcs->userChannelJoined && mcs->globalChannelJoined && allJoined) { if (!rdp_client_establish_keys(rdp)) return FALSE; @@ -658,14 +661,14 @@ BOOL rdp_client_connect_auto_detect(rdpRdp* rdp, wStream *s) UINT16 channelId; /* If the MCS message channel has been joined... */ - if (rdp->mcs->message_channel_id != 0) + if (rdp->mcs->messageChannelId != 0) { /* Process any MCS message channel PDUs. */ Stream_GetPointer(s, mark); if (rdp_read_header(rdp, s, &length, &channelId)) { - if (channelId == rdp->mcs->message_channel_id) + if (channelId == rdp->mcs->messageChannelId) { if (rdp_recv_message_channel_pdu(rdp, s) == 0) return TRUE; @@ -922,21 +925,22 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s) BOOL rdp_server_accept_mcs_connect_initial(rdpRdp* rdp, wStream* s) { - int i; + UINT32 i; + rdpMcs* mcs = rdp->mcs; - if (!mcs_recv_connect_initial(rdp->mcs, s)) + if (!mcs_recv_connect_initial(mcs, s)) return FALSE; fprintf(stderr, "Accepted client: %s\n", rdp->settings->ClientHostname); fprintf(stderr, "Accepted channels:"); - for (i = 0; i < rdp->settings->ChannelCount; i++) + for (i = 0; i < mcs->channelCount; i++) { - fprintf(stderr, " %s", rdp->settings->ChannelDefArray[i].Name); + fprintf(stderr, " %s", mcs->channels[i].Name); } fprintf(stderr, "\n"); - if (!mcs_send_connect_response(rdp->mcs)) + if (!mcs_send_connect_response(mcs)) return FALSE; rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_CONNECT); @@ -969,31 +973,32 @@ BOOL rdp_server_accept_mcs_attach_user_request(rdpRdp* rdp, wStream* s) BOOL rdp_server_accept_mcs_channel_join_request(rdpRdp* rdp, wStream* s) { - int i; - UINT16 channel_id; - BOOL all_joined = TRUE; + UINT32 i; + UINT16 channelId; + BOOL allJoined = TRUE; + rdpMcs* mcs = rdp->mcs; - if (!mcs_recv_channel_join_request(rdp->mcs, s, &channel_id)) + if (!mcs_recv_channel_join_request(mcs, s, &channelId)) return FALSE; - if (!mcs_send_channel_join_confirm(rdp->mcs, channel_id)) + if (!mcs_send_channel_join_confirm(mcs, channelId)) return FALSE; - if (channel_id == rdp->mcs->user_id) - rdp->mcs->user_channel_joined = TRUE; - else if (channel_id == MCS_GLOBAL_CHANNEL_ID) - rdp->mcs->global_channel_joined = TRUE; + if (channelId == mcs->userId) + mcs->userChannelJoined = TRUE; + else if (channelId == MCS_GLOBAL_CHANNEL_ID) + mcs->globalChannelJoined = TRUE; - for (i = 0; i < rdp->settings->ChannelCount; i++) + for (i = 0; i < mcs->channelCount; i++) { - if (rdp->settings->ChannelDefArray[i].ChannelId == channel_id) - rdp->settings->ChannelDefArray[i].joined = TRUE; + if (mcs->channels[i].ChannelId == channelId) + mcs->channels[i].joined = TRUE; - if (!rdp->settings->ChannelDefArray[i].joined) - all_joined = FALSE; + if (!mcs->channels[i].joined) + allJoined = FALSE; } - if ((rdp->mcs->user_channel_joined) && (rdp->mcs->global_channel_joined) && all_joined) + if ((mcs->userChannelJoined) && (mcs->globalChannelJoined) && allJoined) { rdp_server_transition_to_state(rdp, CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT); } diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index 6f402980c..31222771b 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -34,11 +34,13 @@ #include #include +#include #include #include #include #include +#include #include /* connectErrorCode is 'extern' in error.h. See comment there.*/ @@ -298,9 +300,9 @@ int freerdp_message_queue_process_pending_messages(freerdp* instance, DWORD id) return status; } -static int freerdp_send_channel_data(freerdp* instance, int channel_id, BYTE* data, int size) +static int freerdp_send_channel_data(freerdp* instance, UINT16 channelId, BYTE* data, int size) { - return rdp_send_channel_data(instance->context->rdp, channel_id, data, size); + return rdp_send_channel_data(instance->context->rdp, channelId, data, size); } BOOL freerdp_disconnect(freerdp* instance) @@ -476,6 +478,7 @@ freerdp* freerdp_new() ZeroMemory(instance, sizeof(freerdp)); instance->ContextSize = sizeof(rdpContext); instance->SendChannelData = freerdp_send_channel_data; + instance->ReceiveChannelData = freerdp_channels_data; } return instance; diff --git a/libfreerdp/core/gateway/ncacn_http.c b/libfreerdp/core/gateway/ncacn_http.c index 35525f5c7..83daaa33f 100644 --- a/libfreerdp/core/gateway/ncacn_http.c +++ b/libfreerdp/core/gateway/ncacn_http.c @@ -161,7 +161,6 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel) return 0; } - //ntlm_client_make_spn(ntlm, NULL, settings->GatewayHostname); if (!ntlm_client_make_spn(ntlm, _T("HTTP"), settings->GatewayHostname)) { return 0; diff --git a/libfreerdp/core/gateway/rpc.c b/libfreerdp/core/gateway/rpc.c index 5a3760f35..4df8c0da8 100644 --- a/libfreerdp/core/gateway/rpc.c +++ b/libfreerdp/core/gateway/rpc.c @@ -379,7 +379,7 @@ int rpc_write(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum) request_pdu->ptype = PTYPE_REQUEST; request_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; - request_pdu->auth_length = ntlm->ContextSizes.cbMaxSignature; + request_pdu->auth_length = (UINT16) ntlm->ContextSizes.cbMaxSignature; request_pdu->call_id = rpc->CallId++; request_pdu->alloc_hint = length; request_pdu->p_cont_id = 0x0000; diff --git a/libfreerdp/core/gateway/rpc_bind.c b/libfreerdp/core/gateway/rpc_bind.c index 108d7ff14..72a254381 100644 --- a/libfreerdp/core/gateway/rpc_bind.c +++ b/libfreerdp/core/gateway/rpc_bind.c @@ -142,7 +142,7 @@ int rpc_send_bind_pdu(rdpRpc* rpc) rpc_pdu_header_init(rpc, (rpcconn_hdr_t*) bind_pdu); - bind_pdu->auth_length = rpc->ntlm->outputBuffer[0].cbBuffer; + bind_pdu->auth_length = (UINT16) rpc->ntlm->outputBuffer[0].cbBuffer; bind_pdu->auth_verifier.auth_value = rpc->ntlm->outputBuffer[0].pvBuffer; bind_pdu->ptype = PTYPE_BIND; @@ -291,7 +291,7 @@ int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc) rpc_pdu_header_init(rpc, (rpcconn_hdr_t*) auth_3_pdu); - auth_3_pdu->auth_length = rpc->ntlm->outputBuffer[0].cbBuffer; + auth_3_pdu->auth_length = (UINT16) rpc->ntlm->outputBuffer[0].cbBuffer; auth_3_pdu->auth_verifier.auth_value = rpc->ntlm->outputBuffer[0].pvBuffer; auth_3_pdu->ptype = PTYPE_RPC_AUTH_3; diff --git a/libfreerdp/core/gcc.c b/libfreerdp/core/gcc.c index 4c7dd4376..ac6950ab2 100644 --- a/libfreerdp/core/gcc.c +++ b/libfreerdp/core/gcc.c @@ -137,7 +137,7 @@ BYTE h221_sc_key[4] = "McDn"; * @param settings rdp settings */ -BOOL gcc_read_conference_create_request(wStream* s, rdpSettings* settings) +BOOL gcc_read_conference_create_request(wStream* s, rdpMcs* mcs) { UINT16 length; BYTE choice; @@ -181,7 +181,7 @@ BOOL gcc_read_conference_create_request(wStream* s, rdpSettings* settings) return FALSE; if (Stream_GetRemainingLength(s) < length) return FALSE; - if (!gcc_read_client_data_blocks(s, settings, length)) + if (!gcc_read_client_data_blocks(s, mcs, length)) return FALSE; return TRUE; @@ -194,14 +194,14 @@ BOOL gcc_read_conference_create_request(wStream* s, rdpSettings* settings) * @param user_data client data blocks */ -void gcc_write_conference_create_request(wStream* s, wStream* user_data) +void gcc_write_conference_create_request(wStream* s, wStream* userData) { /* ConnectData */ per_write_choice(s, 0); /* From Key select object (0) of type OBJECT_IDENTIFIER */ per_write_object_identifier(s, t124_02_98_oid); /* ITU-T T.124 (02/98) OBJECT_IDENTIFIER */ /* ConnectData::connectPDU (OCTET_STRING) */ - per_write_length(s, Stream_GetPosition(user_data) + 14); /* connectPDU length */ + per_write_length(s, Stream_GetPosition(userData) + 14); /* connectPDU length */ /* ConnectGCCPDU */ per_write_choice(s, 0); /* From ConnectGCCPDU select conferenceCreateRequest (0) of type ConferenceCreateRequest */ @@ -219,10 +219,10 @@ void gcc_write_conference_create_request(wStream* s, wStream* user_data) per_write_octet_string(s, h221_cs_key, 4, 4); /* h221NonStandard, client-to-server H.221 key, "Duca" */ /* userData::value (OCTET_STRING) */ - per_write_octet_string(s, user_data->buffer, Stream_GetPosition(user_data), 0); /* array of client data blocks */ + per_write_octet_string(s, userData->buffer, Stream_GetPosition(userData), 0); /* array of client data blocks */ } -BOOL gcc_read_conference_create_response(wStream* s, rdpSettings* settings) +BOOL gcc_read_conference_create_response(wStream* s, rdpMcs* mcs) { UINT16 length; UINT32 tag; @@ -272,7 +272,7 @@ BOOL gcc_read_conference_create_response(wStream* s, rdpSettings* settings) if (!per_read_length(s, &length)) return FALSE; - if (!gcc_read_server_data_blocks(s, settings, length)) + if (!gcc_read_server_data_blocks(s, mcs, length)) { fprintf(stderr, "gcc_read_conference_create_response: gcc_read_server_data_blocks failed\n"); return FALSE; @@ -281,14 +281,14 @@ BOOL gcc_read_conference_create_response(wStream* s, rdpSettings* settings) return TRUE; } -void gcc_write_conference_create_response(wStream* s, wStream* user_data) +void gcc_write_conference_create_response(wStream* s, wStream* userData) { /* ConnectData */ per_write_choice(s, 0); per_write_object_identifier(s, t124_02_98_oid); /* ConnectData::connectPDU (OCTET_STRING) */ - per_write_length(s, Stream_GetPosition(user_data) + 2); + per_write_length(s, Stream_GetPosition(userData) + 2); /* ConnectGCCPDU */ per_write_choice(s, 0x14); @@ -312,10 +312,10 @@ void gcc_write_conference_create_response(wStream* s, wStream* user_data) per_write_octet_string(s, h221_sc_key, 4, 4); /* h221NonStandard, server-to-client H.221 key, "McDn" */ /* userData (OCTET_STRING) */ - per_write_octet_string(s, user_data->buffer, Stream_GetPosition(user_data), 0); /* array of server data blocks */ + per_write_octet_string(s, userData->buffer, Stream_GetPosition(userData), 0); /* array of server data blocks */ } -BOOL gcc_read_client_data_blocks(wStream* s, rdpSettings* settings, int length) +BOOL gcc_read_client_data_blocks(wStream* s, rdpMcs* mcs, int length) { UINT16 type; UINT16 blockLength; @@ -328,48 +328,48 @@ BOOL gcc_read_client_data_blocks(wStream* s, rdpSettings* settings, int length) if (!gcc_read_user_data_header(s, &type, &blockLength)) return FALSE; - if (Stream_GetRemainingLength(s) < (blockLength - 4)) + if (Stream_GetRemainingLength(s) < (size_t) (blockLength - 4)) return FALSE; switch (type) { case CS_CORE: - if (!gcc_read_client_core_data(s, settings, blockLength - 4)) + if (!gcc_read_client_core_data(s, mcs, blockLength - 4)) return FALSE; break; case CS_SECURITY: - if (!gcc_read_client_security_data(s, settings, blockLength - 4)) + if (!gcc_read_client_security_data(s, mcs, blockLength - 4)) return FALSE; break; case CS_NET: - if (!gcc_read_client_network_data(s, settings, blockLength - 4)) + if (!gcc_read_client_network_data(s, mcs, blockLength - 4)) return FALSE; break; case CS_CLUSTER: - if (!gcc_read_client_cluster_data(s, settings, blockLength - 4)) + if (!gcc_read_client_cluster_data(s, mcs, blockLength - 4)) return FALSE; break; case CS_MONITOR: - if (!gcc_read_client_monitor_data(s, settings, blockLength - 4)) + if (!gcc_read_client_monitor_data(s, mcs, blockLength - 4)) return FALSE; break; case CS_MCS_MSGCHANNEL: - if (!gcc_read_client_message_channel_data(s, settings, blockLength - 4)) + if (!gcc_read_client_message_channel_data(s, mcs, blockLength - 4)) return FALSE; break; case CS_MONITOR_EX: - if (!gcc_read_client_monitor_extended_data(s, settings, blockLength - 4)) + if (!gcc_read_client_monitor_extended_data(s, mcs, blockLength - 4)) return FALSE; break; case CS_MULTITRANSPORT: - if (!gcc_read_client_multitransport_channel_data(s, settings, blockLength - 4)) + if (!gcc_read_client_multitransport_channel_data(s, mcs, blockLength - 4)) return FALSE; break; @@ -394,12 +394,14 @@ BOOL gcc_read_client_data_blocks(wStream* s, rdpSettings* settings, int length) return TRUE; } -void gcc_write_client_data_blocks(wStream* s, rdpSettings* settings) +void gcc_write_client_data_blocks(wStream* s, rdpMcs* mcs) { - gcc_write_client_core_data(s, settings); - gcc_write_client_cluster_data(s, settings); - gcc_write_client_security_data(s, settings); - gcc_write_client_network_data(s, settings); + rdpSettings* settings = mcs->settings; + + gcc_write_client_core_data(s, mcs); + gcc_write_client_cluster_data(s, mcs); + gcc_write_client_security_data(s, mcs); + gcc_write_client_network_data(s, mcs); /* extended client data supported */ @@ -407,10 +409,10 @@ void gcc_write_client_data_blocks(wStream* s, rdpSettings* settings) { if (settings->SpanMonitors) { - gcc_write_client_monitor_data(s, settings); + gcc_write_client_monitor_data(s, mcs); } - gcc_write_client_message_channel_data(s, settings); - gcc_write_client_multitransport_channel_data(s, settings); + gcc_write_client_message_channel_data(s, mcs); + gcc_write_client_multitransport_channel_data(s, mcs); } else { @@ -421,7 +423,7 @@ void gcc_write_client_data_blocks(wStream* s, rdpSettings* settings) if (settings->ForceMultimon) { fprintf(stderr, "Sending multi monitor information anyway (may break connectivity!)\n"); - gcc_write_client_monitor_data(s, settings); + gcc_write_client_monitor_data(s, mcs); } else { @@ -431,7 +433,7 @@ void gcc_write_client_data_blocks(wStream* s, rdpSettings* settings) } } -BOOL gcc_read_server_data_blocks(wStream* s, rdpSettings* settings, int length) +BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length) { UINT16 type; UINT16 offset = 0; @@ -451,7 +453,7 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpSettings* settings, int length) switch (type) { case SC_CORE: - if (!gcc_read_server_core_data(s, settings)) + if (!gcc_read_server_core_data(s, mcs)) { fprintf(stderr, "gcc_read_server_data_blocks: gcc_read_server_core_data failed\n"); return FALSE; @@ -459,7 +461,7 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpSettings* settings, int length) break; case SC_SECURITY: - if (!gcc_read_server_security_data(s, settings)) + if (!gcc_read_server_security_data(s, mcs)) { fprintf(stderr, "gcc_read_server_data_blocks: gcc_read_server_security_data failed\n"); return FALSE; @@ -467,7 +469,7 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpSettings* settings, int length) break; case SC_NET: - if (!gcc_read_server_network_data(s, settings)) + if (!gcc_read_server_network_data(s, mcs)) { fprintf(stderr, "gcc_read_server_data_blocks: gcc_read_server_network_data failed\n"); return FALSE; @@ -475,7 +477,7 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpSettings* settings, int length) break; case SC_MCS_MSGCHANNEL: - if (!gcc_read_server_message_channel_data(s, settings)) + if (!gcc_read_server_message_channel_data(s, mcs)) { fprintf(stderr, "gcc_read_server_data_blocks: gcc_read_server_message_channel_data failed\n"); return FALSE; @@ -483,7 +485,7 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpSettings* settings, int length) break; case SC_MULTITRANSPORT: - if (!gcc_read_server_multitransport_channel_data(s, settings)) + if (!gcc_read_server_multitransport_channel_data(s, mcs)) { fprintf(stderr, "gcc_read_server_data_blocks: gcc_read_server_multitransport_channel_data failed\n"); return FALSE; @@ -501,11 +503,11 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpSettings* settings, int length) return TRUE; } -void gcc_write_server_data_blocks(wStream* s, rdpSettings* settings) +void gcc_write_server_data_blocks(wStream* s, rdpMcs* mcs) { - gcc_write_server_core_data(s, settings); /* serverCoreData */ - gcc_write_server_network_data(s, settings); /* serverNetworkData */ - gcc_write_server_security_data(s, settings); /* serverSecurityData */ + gcc_write_server_core_data(s, mcs); /* serverCoreData */ + gcc_write_server_network_data(s, mcs); /* serverNetworkData */ + gcc_write_server_security_data(s, mcs); /* serverSecurityData */ /* TODO: Send these GCC data blocks only when the client sent them */ //gcc_write_server_message_channel_data(s, settings); /* serverMessageChannelData */ @@ -520,7 +522,7 @@ BOOL gcc_read_user_data_header(wStream* s, UINT16* type, UINT16* length) Stream_Read_UINT16(s, *type); /* type */ Stream_Read_UINT16(s, *length); /* length */ - if (Stream_GetRemainingLength(s) < *length - 4) + if (Stream_GetRemainingLength(s) < (size_t) (*length - 4)) return FALSE; return TRUE; @@ -547,7 +549,7 @@ void gcc_write_user_data_header(wStream* s, UINT16 type, UINT16 length) * @param settings rdp settings */ -BOOL gcc_read_client_core_data(wStream* s, rdpSettings* settings, UINT16 blockLength) +BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) { char* str = NULL; UINT32 version; @@ -562,6 +564,7 @@ BOOL gcc_read_client_core_data(wStream* s, rdpSettings* settings, UINT16 blockLe UINT16 desktopOrientation = 0; UINT32 desktopScaleFactor = 0; UINT32 deviceScaleFactor = 0; + rdpSettings* settings = mcs->settings; /* Length of all required fields, until imeFileName */ if (blockLength < 128) @@ -747,7 +750,7 @@ BOOL gcc_read_client_core_data(wStream* s, rdpSettings* settings, UINT16 blockLe * @param settings rdp settings */ -void gcc_write_client_core_data(wStream* s, rdpSettings* settings) +void gcc_write_client_core_data(wStream* s, rdpMcs* mcs) { UINT32 version; WCHAR* clientName = NULL; @@ -758,6 +761,7 @@ void gcc_write_client_core_data(wStream* s, rdpSettings* settings) UINT16 earlyCapabilityFlags; WCHAR* clientDigProductId = NULL; int clientDigProductIdLength; + rdpSettings* settings = mcs->settings; gcc_write_user_data_header(s, CS_CORE, 216); @@ -851,11 +855,12 @@ void gcc_write_client_core_data(wStream* s, rdpSettings* settings) Stream_Write_UINT32(s, settings->SelectedProtocol); /* serverSelectedProtocol */ } -BOOL gcc_read_server_core_data(wStream* s, rdpSettings* settings) +BOOL gcc_read_server_core_data(wStream* s, rdpMcs* mcs) { UINT32 version; UINT32 clientRequestedProtocols; UINT32 earlyCapabilityFlags; + rdpSettings* settings = mcs->settings; if (Stream_GetRemainingLength(s) < 4) return FALSE; @@ -880,8 +885,10 @@ BOOL gcc_read_server_core_data(wStream* s, rdpSettings* settings) return TRUE; } -void gcc_write_server_core_data(wStream* s, rdpSettings* settings) +void gcc_write_server_core_data(wStream* s, rdpMcs* mcs) { + rdpSettings* settings = mcs->settings; + gcc_write_user_data_header(s, SC_CORE, 16); Stream_Write_UINT32(s, settings->RdpVersion == 4 ? RDP_VERSION_4 : RDP_VERSION_5_PLUS); @@ -896,8 +903,10 @@ void gcc_write_server_core_data(wStream* s, rdpSettings* settings) * @param settings rdp settings */ -BOOL gcc_read_client_security_data(wStream* s, rdpSettings* settings, UINT16 blockLength) +BOOL gcc_read_client_security_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) { + rdpSettings* settings = mcs->settings; + if (blockLength < 8) return FALSE; @@ -921,8 +930,10 @@ BOOL gcc_read_client_security_data(wStream* s, rdpSettings* settings, UINT16 blo * @param settings rdp settings */ -void gcc_write_client_security_data(wStream* s, rdpSettings* settings) +void gcc_write_client_security_data(wStream* s, rdpMcs* mcs) { + rdpSettings* settings = mcs->settings; + gcc_write_user_data_header(s, CS_SECURITY, 12); if (settings->DisableEncryption) @@ -938,13 +949,15 @@ void gcc_write_client_security_data(wStream* s, rdpSettings* settings) } } -BOOL gcc_read_server_security_data(wStream* s, rdpSettings* settings) +BOOL gcc_read_server_security_data(wStream* s, rdpMcs* mcs) { BYTE* data; UINT32 length; + rdpSettings* settings = mcs->settings; if (Stream_GetRemainingLength(s) < 8) return FALSE; + Stream_Read_UINT32(s, settings->EncryptionMethods); /* encryptionMethod */ Stream_Read_UINT32(s, settings->EncryptionLevel); /* encryptionLevel */ @@ -959,6 +972,7 @@ BOOL gcc_read_server_security_data(wStream* s, rdpSettings* settings) if (Stream_GetRemainingLength(s) < 8) return FALSE; + Stream_Read_UINT32(s, settings->ServerRandomLength); /* serverRandomLen */ Stream_Read_UINT32(s, settings->ServerCertificateLength); /* serverCertLen */ @@ -1044,7 +1058,7 @@ const BYTE tssk_exponent[] = 0x5b, 0x7b, 0x88, 0xc0 }; -void gcc_write_server_security_data(wStream* s, rdpSettings* settings) +void gcc_write_server_security_data(wStream* s, rdpMcs* mcs) { CryptoMd5 md5; BYTE* sigData; @@ -1052,6 +1066,7 @@ void gcc_write_server_security_data(wStream* s, rdpSettings* settings) BYTE encryptedSignature[TSSK_KEY_LENGTH]; BYTE signature[sizeof(initial_signature)]; UINT32 headerLen, serverRandomLen, serverCertLen, wPublicKeyBlobLen; + rdpSettings* settings = mcs->settings; if (!settings->DisableEncryption) { @@ -1173,26 +1188,28 @@ void gcc_write_server_security_data(wStream* s, rdpSettings* settings) * @param settings rdp settings */ -BOOL gcc_read_client_network_data(wStream* s, rdpSettings* settings, UINT16 blockLength) +BOOL gcc_read_client_network_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) { - int i; + UINT32 i; if (blockLength < 4) return FALSE; - Stream_Read_UINT32(s, settings->ChannelCount); /* channelCount */ - if (blockLength < 4 + settings->ChannelCount * 12) + Stream_Read_UINT32(s, mcs->channelCount); /* channelCount */ + + if (blockLength < 4 + mcs->channelCount * 12) return FALSE; - if (settings->ChannelCount > 16) + + if (mcs->channelCount > 16) return FALSE; /* channelDefArray */ - for (i = 0; i < settings->ChannelCount; i++) + for (i = 0; i < mcs->channelCount; i++) { /* CHANNEL_DEF */ - Stream_Read(s, settings->ChannelDefArray[i].Name, 8); /* name (8 bytes) */ - Stream_Read_UINT32(s, settings->ChannelDefArray[i].options); /* options (4 bytes) */ - settings->ChannelDefArray[i].ChannelId = MCS_GLOBAL_CHANNEL_ID + 1 + i; + Stream_Read(s, mcs->channels[i].Name, 8); /* name (8 bytes) */ + Stream_Read_UINT32(s, mcs->channels[i].options); /* options (4 bytes) */ + mcs->channels[i].ChannelId = MCS_GLOBAL_CHANNEL_ID + 1 + i; } return TRUE; @@ -1205,34 +1222,35 @@ BOOL gcc_read_client_network_data(wStream* s, rdpSettings* settings, UINT16 bloc * @param settings rdp settings */ -void gcc_write_client_network_data(wStream* s, rdpSettings* settings) +void gcc_write_client_network_data(wStream* s, rdpMcs* mcs) { - int i; + UINT32 i; UINT16 length; - if (settings->ChannelCount > 0) + if (mcs->channelCount > 0) { - length = settings->ChannelCount * 12 + 8; + length = mcs->channelCount * 12 + 8; gcc_write_user_data_header(s, CS_NET, length); - Stream_Write_UINT32(s, settings->ChannelCount); /* channelCount */ + Stream_Write_UINT32(s, mcs->channelCount); /* channelCount */ /* channelDefArray */ - for (i = 0; i < settings->ChannelCount; i++) + for (i = 0; i < mcs->channelCount; i++) { /* CHANNEL_DEF */ - Stream_Write(s, settings->ChannelDefArray[i].Name, 8); /* name (8 bytes) */ - Stream_Write_UINT32(s, settings->ChannelDefArray[i].options); /* options (4 bytes) */ + Stream_Write(s, mcs->channels[i].Name, 8); /* name (8 bytes) */ + Stream_Write_UINT32(s, mcs->channels[i].options); /* options (4 bytes) */ } } } -BOOL gcc_read_server_network_data(wStream* s, rdpSettings* settings) +BOOL gcc_read_server_network_data(wStream* s, rdpMcs* mcs) { int i; - UINT16 MCSChannelId; - UINT16 channelCount, channelsToTreat; UINT16 channelId; + UINT16 MCSChannelId; + UINT16 channelCount; + UINT16 parsedChannelCount; if (Stream_GetRemainingLength(s) < 4) return FALSE; @@ -1240,25 +1258,26 @@ BOOL gcc_read_server_network_data(wStream* s, rdpSettings* settings) Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */ Stream_Read_UINT16(s, channelCount); /* channelCount */ - channelsToTreat = channelCount; + parsedChannelCount = channelCount; - if (channelCount != settings->ChannelCount) + if (channelCount != mcs->channelCount) { fprintf(stderr, "requested %d channels, got %d instead\n", - settings->ChannelCount, channelCount); + mcs->channelCount, channelCount); /* we ensure that the response is not bigger than the request */ - if (channelCount > settings->ChannelCount) - channelsToTreat = settings->ChannelCount; + + if (channelCount > mcs->channelCount) + parsedChannelCount = mcs->channelCount; } - if (Stream_GetRemainingLength(s) < channelCount * 2) + if (Stream_GetRemainingLength(s) < (size_t) channelCount * 2) return FALSE; - for (i = 0; i < channelsToTreat; i++) + for (i = 0; i < parsedChannelCount; i++) { Stream_Read_UINT16(s, channelId); /* channelId */ - settings->ChannelDefArray[i].ChannelId = channelId; + mcs->channels[i].ChannelId = channelId; } if (channelCount % 2 == 1) @@ -1267,21 +1286,21 @@ BOOL gcc_read_server_network_data(wStream* s, rdpSettings* settings) return TRUE; } -void gcc_write_server_network_data(wStream* s, rdpSettings* settings) +void gcc_write_server_network_data(wStream* s, rdpMcs* mcs) { - int i; + UINT32 i; - gcc_write_user_data_header(s, SC_NET, 8 + settings->ChannelCount * 2 + (settings->ChannelCount % 2 == 1 ? 2 : 0)); + gcc_write_user_data_header(s, SC_NET, 8 + mcs->channelCount * 2 + (mcs->channelCount % 2 == 1 ? 2 : 0)); Stream_Write_UINT16(s, MCS_GLOBAL_CHANNEL_ID); /* MCSChannelId */ - Stream_Write_UINT16(s, settings->ChannelCount); /* channelCount */ + Stream_Write_UINT16(s, mcs->channelCount); /* channelCount */ - for (i = 0; i < settings->ChannelCount; i++) + for (i = 0; i < mcs->channelCount; i++) { - Stream_Write_UINT16(s, settings->ChannelDefArray[i].ChannelId); + Stream_Write_UINT16(s, mcs->channels[i].ChannelId); } - if (settings->ChannelCount % 2 == 1) + if (mcs->channelCount % 2 == 1) Stream_Write_UINT16(s, 0); } @@ -1292,10 +1311,11 @@ void gcc_write_server_network_data(wStream* s, rdpSettings* settings) * @param settings rdp settings */ -BOOL gcc_read_client_cluster_data(wStream* s, rdpSettings* settings, UINT16 blockLength) +BOOL gcc_read_client_cluster_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) { UINT32 flags; UINT32 redirectedSessionId; + rdpSettings* settings = mcs->settings; if (blockLength < 8) return FALSE; @@ -1316,9 +1336,10 @@ BOOL gcc_read_client_cluster_data(wStream* s, rdpSettings* settings, UINT16 bloc * @param settings rdp settings */ -void gcc_write_client_cluster_data(wStream* s, rdpSettings* settings) +void gcc_write_client_cluster_data(wStream* s, rdpMcs* mcs) { UINT32 flags; + rdpSettings* settings = mcs->settings; gcc_write_user_data_header(s, CS_CLUSTER, 12); @@ -1338,7 +1359,7 @@ void gcc_write_client_cluster_data(wStream* s, rdpSettings* settings) * @param settings rdp settings */ -BOOL gcc_read_client_monitor_data(wStream* s, rdpSettings* settings, UINT16 blockLength) +BOOL gcc_read_client_monitor_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) { UINT32 index; UINT32 flags; @@ -1378,11 +1399,12 @@ BOOL gcc_read_client_monitor_data(wStream* s, rdpSettings* settings, UINT16 bloc * @param settings rdp settings */ -void gcc_write_client_monitor_data(wStream* s, rdpSettings* settings) +void gcc_write_client_monitor_data(wStream* s, rdpMcs* mcs) { int i; UINT16 length; UINT32 left, top, right, bottom, flags; + rdpSettings* settings = mcs->settings; if (settings->MonitorCount > 1) { @@ -1409,7 +1431,7 @@ void gcc_write_client_monitor_data(wStream* s, rdpSettings* settings) } } -BOOL gcc_read_client_monitor_extended_data(wStream* s, rdpSettings* settings, UINT16 blockLength) +BOOL gcc_read_client_monitor_extended_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) { UINT32 index; UINT32 flags; @@ -1447,7 +1469,7 @@ BOOL gcc_read_client_monitor_extended_data(wStream* s, rdpSettings* settings, UI return TRUE; } -void gcc_write_client_monitor_extended_data(wStream* s, rdpSettings* settings) +void gcc_write_client_monitor_extended_data(wStream* s, rdpMcs* mcs) { } @@ -1459,7 +1481,7 @@ void gcc_write_client_monitor_extended_data(wStream* s, rdpSettings* settings) * @param settings rdp settings */ -BOOL gcc_read_client_message_channel_data(wStream* s, rdpSettings* settings, UINT16 blockLength) +BOOL gcc_read_client_message_channel_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) { UINT32 flags; @@ -1478,8 +1500,10 @@ BOOL gcc_read_client_message_channel_data(wStream* s, rdpSettings* settings, UIN * @param settings rdp settings */ -void gcc_write_client_message_channel_data(wStream* s, rdpSettings* settings) +void gcc_write_client_message_channel_data(wStream* s, rdpMcs* mcs) { + rdpSettings* settings = mcs->settings; + if (settings->NetworkAutoDetect || settings->SupportHeartbeatPdu || settings->SupportMultitransport) @@ -1490,9 +1514,8 @@ void gcc_write_client_message_channel_data(wStream* s, rdpSettings* settings) } } -BOOL gcc_read_server_message_channel_data(wStream* s, rdpSettings* settings) +BOOL gcc_read_server_message_channel_data(wStream* s, rdpMcs* mcs) { - freerdp* instance; UINT16 MCSChannelId; if (Stream_GetRemainingLength(s) < 2) @@ -1501,13 +1524,12 @@ BOOL gcc_read_server_message_channel_data(wStream* s, rdpSettings* settings) Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */ /* Save the MCS message channel id */ - instance = (freerdp*) settings->instance; - instance->context->rdp->mcs->message_channel_id = MCSChannelId; + mcs->messageChannelId = MCSChannelId; return TRUE; } -void gcc_write_server_message_channel_data(wStream* s, rdpSettings* settings) +void gcc_write_server_message_channel_data(wStream* s, rdpMcs* mcs) { UINT16 mcsChannelId = 0; @@ -1523,7 +1545,7 @@ void gcc_write_server_message_channel_data(wStream* s, rdpSettings* settings) * @param settings rdp settings */ -BOOL gcc_read_client_multitransport_channel_data(wStream* s, rdpSettings* settings, UINT16 blockLength) +BOOL gcc_read_client_multitransport_channel_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) { UINT32 flags; @@ -1542,8 +1564,10 @@ BOOL gcc_read_client_multitransport_channel_data(wStream* s, rdpSettings* settin * @param settings rdp settings */ -void gcc_write_client_multitransport_channel_data(wStream* s, rdpSettings* settings) +void gcc_write_client_multitransport_channel_data(wStream* s, rdpMcs* mcs) { + rdpSettings* settings = mcs->settings; + if (settings->MultitransportFlags != 0) { gcc_write_user_data_header(s, CS_MULTITRANSPORT, 8); @@ -1552,7 +1576,7 @@ void gcc_write_client_multitransport_channel_data(wStream* s, rdpSettings* setti } } -BOOL gcc_read_server_multitransport_channel_data(wStream* s, rdpSettings* settings) +BOOL gcc_read_server_multitransport_channel_data(wStream* s, rdpMcs* mcs) { UINT32 flags; @@ -1564,7 +1588,7 @@ BOOL gcc_read_server_multitransport_channel_data(wStream* s, rdpSettings* settin return TRUE; } -void gcc_write_server_multitransport_channel_data(wStream* s, rdpSettings* settings) +void gcc_write_server_multitransport_channel_data(wStream* s, rdpMcs* mcs) { UINT32 flags = 0; diff --git a/libfreerdp/core/gcc.h b/libfreerdp/core/gcc.h index 6c887817a..039fa44a0 100644 --- a/libfreerdp/core/gcc.h +++ b/libfreerdp/core/gcc.h @@ -29,41 +29,41 @@ #include -BOOL gcc_read_conference_create_request(wStream* s, rdpSettings* settings); -void gcc_write_conference_create_request(wStream* s, wStream* user_data); -BOOL gcc_read_conference_create_response(wStream* s, rdpSettings* settings); -void gcc_write_conference_create_response(wStream* s, wStream* user_data); -BOOL gcc_read_client_data_blocks(wStream* s, rdpSettings* settings, int length); -void gcc_write_client_data_blocks(wStream* s, rdpSettings* settings); -BOOL gcc_read_server_data_blocks(wStream* s, rdpSettings* settings, int length); -void gcc_write_server_data_blocks(wStream* s, rdpSettings* settings); +BOOL gcc_read_conference_create_request(wStream* s, rdpMcs* mcs); +void gcc_write_conference_create_request(wStream* s, wStream* userData); +BOOL gcc_read_conference_create_response(wStream* s, rdpMcs* mcs); +void gcc_write_conference_create_response(wStream* s, wStream* userData); +BOOL gcc_read_client_data_blocks(wStream* s, rdpMcs* mcs, int length); +void gcc_write_client_data_blocks(wStream* s, rdpMcs* mcs); +BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length); +void gcc_write_server_data_blocks(wStream* s, rdpMcs* mcs); BOOL gcc_read_user_data_header(wStream* s, UINT16* type, UINT16* length); void gcc_write_user_data_header(wStream* s, UINT16 type, UINT16 length); -BOOL gcc_read_client_core_data(wStream* s, rdpSettings* settings, UINT16 blockLength); -void gcc_write_client_core_data(wStream* s, rdpSettings* settings); -BOOL gcc_read_server_core_data(wStream* s, rdpSettings* settings); -void gcc_write_server_core_data(wStream* s, rdpSettings* settings); -BOOL gcc_read_client_security_data(wStream* s, rdpSettings* settings, UINT16 blockLength); -void gcc_write_client_security_data(wStream* s, rdpSettings* settings); -BOOL gcc_read_server_security_data(wStream* s, rdpSettings* settings); -void gcc_write_server_security_data(wStream* s, rdpSettings* settings); -BOOL gcc_read_client_network_data(wStream* s, rdpSettings* settings, UINT16 blockLength); -void gcc_write_client_network_data(wStream* s, rdpSettings* settings); -BOOL gcc_read_server_network_data(wStream* s, rdpSettings* settings); -void gcc_write_server_network_data(wStream* s, rdpSettings* settings); -BOOL gcc_read_client_cluster_data(wStream* s, rdpSettings* settings, UINT16 blockLength); -void gcc_write_client_cluster_data(wStream* s, rdpSettings* settings); -BOOL gcc_read_client_monitor_data(wStream* s, rdpSettings* settings, UINT16 blockLength); -void gcc_write_client_monitor_data(wStream* s, rdpSettings* settings); -BOOL gcc_read_client_monitor_extended_data(wStream* s, rdpSettings* settings, UINT16 blockLength); -void gcc_write_client_monitor_extended_data(wStream* s, rdpSettings* settings); -BOOL gcc_read_client_message_channel_data(wStream* s, rdpSettings* settings, UINT16 blockLength); -void gcc_write_client_message_channel_data(wStream* s, rdpSettings* settings); -BOOL gcc_read_server_message_channel_data(wStream* s, rdpSettings* settings); -void gcc_write_server_message_channel_data(wStream* s, rdpSettings* settings); -BOOL gcc_read_client_multitransport_channel_data(wStream* s, rdpSettings* settings, UINT16 blockLength); -void gcc_write_client_multitransport_channel_data(wStream* s, rdpSettings* settings); -BOOL gcc_read_server_multitransport_channel_data(wStream* s, rdpSettings* settings); -void gcc_write_server_multitransport_channel_data(wStream* s, rdpSettings* settings); +BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength); +void gcc_write_client_core_data(wStream* s, rdpMcs* mcs); +BOOL gcc_read_server_core_data(wStream* s, rdpMcs* mcs); +void gcc_write_server_core_data(wStream* s, rdpMcs* mcs); +BOOL gcc_read_client_security_data(wStream* s, rdpMcs* mcs, UINT16 blockLength); +void gcc_write_client_security_data(wStream* s, rdpMcs* mcs); +BOOL gcc_read_server_security_data(wStream* s, rdpMcs* mcs); +void gcc_write_server_security_data(wStream* s, rdpMcs* mcs); +BOOL gcc_read_client_network_data(wStream* s, rdpMcs* mcs, UINT16 blockLength); +void gcc_write_client_network_data(wStream* s, rdpMcs* mcs); +BOOL gcc_read_server_network_data(wStream* s, rdpMcs* mcs); +void gcc_write_server_network_data(wStream* s, rdpMcs* mcs); +BOOL gcc_read_client_cluster_data(wStream* s, rdpMcs* mcs, UINT16 blockLength); +void gcc_write_client_cluster_data(wStream* s, rdpMcs* mcs); +BOOL gcc_read_client_monitor_data(wStream* s, rdpMcs* mcs, UINT16 blockLength); +void gcc_write_client_monitor_data(wStream* s, rdpMcs* mcs); +BOOL gcc_read_client_monitor_extended_data(wStream* s, rdpMcs* mcs, UINT16 blockLength); +void gcc_write_client_monitor_extended_data(wStream* s, rdpMcs* mcs); +BOOL gcc_read_client_message_channel_data(wStream* s, rdpMcs* mcs, UINT16 blockLength); +void gcc_write_client_message_channel_data(wStream* s, rdpMcs* mcs); +BOOL gcc_read_server_message_channel_data(wStream* s, rdpMcs* mcs); +void gcc_write_server_message_channel_data(wStream* s, rdpMcs* mcs); +BOOL gcc_read_client_multitransport_channel_data(wStream* s, rdpMcs* mcs, UINT16 blockLength); +void gcc_write_client_multitransport_channel_data(wStream* s, rdpMcs* mcs); +BOOL gcc_read_server_multitransport_channel_data(wStream* s, rdpMcs* mcs); +void gcc_write_server_multitransport_channel_data(wStream* s, rdpMcs* mcs); #endif /* FREERDP_CORE_GCC_H */ diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c index 671840152..7ccc7eff7 100644 --- a/libfreerdp/core/info.c +++ b/libfreerdp/core/info.c @@ -314,7 +314,7 @@ BOOL rdp_read_info_packet(wStream* s, rdpSettings* settings) Stream_Read_UINT16(s, cbAlternateShell); /* cbAlternateShell */ Stream_Read_UINT16(s, cbWorkingDir); /* cbWorkingDir */ - if (Stream_GetRemainingLength(s) < cbDomain + 2) + if (Stream_GetRemainingLength(s) < (size_t) (cbDomain + 2)) return FALSE; if (cbDomain > 0) @@ -324,7 +324,7 @@ BOOL rdp_read_info_packet(wStream* s, rdpSettings* settings) } Stream_Seek(s, 2); - if (Stream_GetRemainingLength(s) < cbUserName + 2) + if (Stream_GetRemainingLength(s) < (size_t) (cbUserName + 2)) return FALSE; if (cbUserName > 0) @@ -334,7 +334,7 @@ BOOL rdp_read_info_packet(wStream* s, rdpSettings* settings) } Stream_Seek(s, 2); - if (Stream_GetRemainingLength(s) < cbPassword + 2) + if (Stream_GetRemainingLength(s) < (size_t) (cbPassword + 2)) return FALSE; if (cbPassword > 0) @@ -344,7 +344,7 @@ BOOL rdp_read_info_packet(wStream* s, rdpSettings* settings) } Stream_Seek(s, 2); - if (Stream_GetRemainingLength(s) < cbAlternateShell + 2) + if (Stream_GetRemainingLength(s) < (size_t) (cbAlternateShell + 2)) return FALSE; if (cbAlternateShell > 0) @@ -354,7 +354,7 @@ BOOL rdp_read_info_packet(wStream* s, rdpSettings* settings) } Stream_Seek(s, 2); - if (Stream_GetRemainingLength(s) < cbWorkingDir + 2) + if (Stream_GetRemainingLength(s) < (size_t) (cbWorkingDir + 2)) return FALSE; if (cbWorkingDir > 0) diff --git a/libfreerdp/core/input.c b/libfreerdp/core/input.c index c9ce3773d..546fc4c7c 100644 --- a/libfreerdp/core/input.c +++ b/libfreerdp/core/input.c @@ -52,7 +52,7 @@ wStream* rdp_client_input_pdu_init(rdpRdp* rdp, UINT16 type) void rdp_send_client_input_pdu(rdpRdp* rdp, wStream* s) { - rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_INPUT, rdp->mcs->user_id); + rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_INPUT, rdp->mcs->userId); } void input_write_synchronize_event(wStream* s, UINT32 flags) @@ -400,7 +400,7 @@ BOOL input_recv(rdpInput* input, wStream* s) Stream_Seek(s, 2); /* pad2Octets (2 bytes) */ /* Each input event uses 6 exactly bytes. */ - if (Stream_GetRemainingLength(s) < 6 * numberEvents) + if (Stream_GetRemainingLength(s) < (size_t) (6 * numberEvents)) return FALSE; for (i = 0; i < numberEvents; i++) diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c index 17e1520c7..78193f369 100644 --- a/libfreerdp/core/license.c +++ b/libfreerdp/core/license.c @@ -77,7 +77,7 @@ static const char* const state_transitions[] = "ST_RESEND_LAST_MESSAGE" }; -void license_print_product_info(PRODUCT_INFO* productInfo) +void license_print_product_info(LICENSE_PRODUCT_INFO* productInfo) { char* CompanyName = NULL; char* ProductId = NULL; @@ -473,7 +473,7 @@ void license_decrypt_platform_challenge(rdpLicense* license) * @param productInfo product information */ -BOOL license_read_product_info(wStream* s, PRODUCT_INFO* productInfo) +BOOL license_read_product_info(wStream* s, LICENSE_PRODUCT_INFO* productInfo) { if (Stream_GetRemainingLength(s) < 8) return FALSE; @@ -504,16 +504,16 @@ BOOL license_read_product_info(wStream* s, PRODUCT_INFO* productInfo) } /** - * Allocate New Product Information (PRODUCT_INFO).\n + * Allocate New Product Information (LICENSE_PRODUCT_INFO).\n * @msdn{cc241915} * @return new product information */ -PRODUCT_INFO* license_new_product_info() +LICENSE_PRODUCT_INFO* license_new_product_info() { - PRODUCT_INFO* productInfo; + LICENSE_PRODUCT_INFO* productInfo; - productInfo = (PRODUCT_INFO*) malloc(sizeof(PRODUCT_INFO)); + productInfo = (LICENSE_PRODUCT_INFO*) malloc(sizeof(LICENSE_PRODUCT_INFO)); productInfo->dwVersion = 0; productInfo->cbCompanyName = 0; @@ -525,12 +525,12 @@ PRODUCT_INFO* license_new_product_info() } /** - * Free Product Information (PRODUCT_INFO).\n + * Free Product Information (LICENSE_PRODUCT_INFO).\n * @msdn{cc241915} * @param productInfo product information */ -void license_free_product_info(PRODUCT_INFO* productInfo) +void license_free_product_info(LICENSE_PRODUCT_INFO* productInfo) { if (productInfo->pbCompanyName != NULL) free(productInfo->pbCompanyName); diff --git a/libfreerdp/core/license.h b/libfreerdp/core/license.h index 516604f81..38955e98d 100644 --- a/libfreerdp/core/license.h +++ b/libfreerdp/core/license.h @@ -148,7 +148,7 @@ typedef struct BYTE* pbCompanyName; UINT32 cbProductId; BYTE* pbProductId; -} PRODUCT_INFO; +} LICENSE_PRODUCT_INFO; typedef struct { @@ -187,7 +187,7 @@ struct rdp_license BYTE SessionKeyBlob[SESSION_KEY_BLOB_LENGTH]; BYTE MacSaltKey[MAC_SALT_KEY_LENGTH]; BYTE LicensingEncryptionKey[LICENSING_ENCRYPTION_KEY_LENGTH]; - PRODUCT_INFO* ProductInfo; + LICENSE_PRODUCT_INFO* ProductInfo; LICENSE_BLOB* ErrorInfo; LICENSE_BLOB* KeyExchangeList; LICENSE_BLOB* ServerCertificate; @@ -210,9 +210,9 @@ void license_generate_hwid(rdpLicense* license); void license_encrypt_premaster_secret(rdpLicense* license); void license_decrypt_platform_challenge(rdpLicense* license); -PRODUCT_INFO* license_new_product_info(void); -void license_free_product_info(PRODUCT_INFO* productInfo); -BOOL license_read_product_info(wStream* s, PRODUCT_INFO* productInfo); +LICENSE_PRODUCT_INFO* license_new_product_info(void); +void license_free_product_info(LICENSE_PRODUCT_INFO* productInfo); +BOOL license_read_product_info(wStream* s, LICENSE_PRODUCT_INFO* productInfo); LICENSE_BLOB* license_new_binary_blob(UINT16 type); void license_free_binary_blob(LICENSE_BLOB* blob); diff --git a/libfreerdp/core/listener.c b/libfreerdp/core/listener.c index e275ad404..e37c4c89f 100644 --- a/libfreerdp/core/listener.c +++ b/libfreerdp/core/listener.c @@ -27,6 +27,7 @@ #include #include +#include #ifndef _WIN32 #include @@ -45,7 +46,7 @@ #ifdef _WIN32 #if _WIN32_WINNT < 0x0600 -static const char *inet_ntop(int af, const void* src, char* dst, socklen_t cnt) +static const char* inet_ntop(int af, const void* src, char* dst, size_t cnt) { if (af == AF_INET) { @@ -64,7 +65,7 @@ static const char *inet_ntop(int af, const void* src, char* dst, socklen_t cnt) memset(&in, 0, sizeof(in)); in.sin6_family = AF_INET6; memcpy(&in.sin6_addr, src, sizeof(struct in_addr6)); - getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST); + getnameinfo((struct sockaddr*) &in, sizeof(struct sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST); return dst; } diff --git a/libfreerdp/core/mcs.c b/libfreerdp/core/mcs.c index 1fd38d86e..e6a914c3e 100644 --- a/libfreerdp/core/mcs.c +++ b/libfreerdp/core/mcs.c @@ -28,6 +28,7 @@ #include "mcs.h" #include "tpdu.h" #include "tpkt.h" +#include "client.h" /** * T.125 MCS is defined in: @@ -183,6 +184,25 @@ static const char* const mcs_result_enumerated[] = }; */ +int mcs_initialize_client_channels(rdpMcs* mcs, rdpSettings* settings) +{ + int index; + mcs->channelCount = settings->ChannelCount; + + if (mcs->channelCount > mcs->channelMaxCount) + mcs->channelCount = mcs->channelMaxCount; + + ZeroMemory(mcs->channels, sizeof(rdpMcsChannel) * mcs->channelMaxCount); + + for (index = 0; index < mcs->channelCount; index++) + { + CopyMemory(mcs->channels[index].Name, settings->ChannelDefArray[index].name, 8); + mcs->channels[index].options = settings->ChannelDefArray[index].options; + } + + return 0; +} + /** * Read a DomainMCSPDU header. * @param s stream @@ -320,6 +340,121 @@ void mcs_print_domain_parameters(DomainParameters* domainParameters) fprintf(stderr, "}\n"); } +/** + * Merge MCS Domain Parameters. + * @param domainParameters target parameters + * @param domainParameters minimum parameters + * @param domainParameters maximum parameters + * @param domainParameters output parameters + */ + +BOOL mcs_merge_domain_parameters(DomainParameters* targetParameters, DomainParameters* minimumParameters, + DomainParameters* maximumParameters, DomainParameters* pOutParameters) +{ + /* maxChannelIds */ + + if (targetParameters->maxChannelIds >= 4) + { + pOutParameters->maxChannelIds = targetParameters->maxChannelIds; + } + else if (maximumParameters->maxChannelIds >= 4) + { + pOutParameters->maxChannelIds = 4; + } + else + { + return FALSE; + } + + /* maxUserIds */ + + if (targetParameters->maxUserIds >= 3) + { + pOutParameters->maxUserIds = targetParameters->maxUserIds; + } + else if (maximumParameters->maxUserIds >= 3) + { + pOutParameters->maxUserIds = 3; + } + else + { + return FALSE; + } + + /* maxTokenIds */ + + pOutParameters->maxTokenIds = targetParameters->maxTokenIds; + + /* numPriorities */ + + if (minimumParameters->numPriorities <= 1) + { + pOutParameters->numPriorities = 1; + } + else + { + return FALSE; + } + + /* minThroughput */ + + pOutParameters->minThroughput = targetParameters->minThroughput; + + /* maxHeight */ + + if ((targetParameters->maxHeight == 1) || (minimumParameters->maxHeight <= 1)) + { + pOutParameters->maxHeight = 1; + } + else + { + return FALSE; + } + + /* maxMCSPDUsize */ + + if (targetParameters->maxMCSPDUsize >= 1024) + { + if (targetParameters->maxMCSPDUsize <= 65528) + { + pOutParameters->maxMCSPDUsize = targetParameters->maxMCSPDUsize; + } + else if ((minimumParameters->maxMCSPDUsize >= 124) && (minimumParameters->maxMCSPDUsize <= 65528)) + { + pOutParameters->maxMCSPDUsize = 65528; + } + else + { + return FALSE; + } + } + else + { + if (maximumParameters->maxMCSPDUsize >= 124) + { + pOutParameters->maxMCSPDUsize = maximumParameters->maxMCSPDUsize; + } + else + { + return FALSE; + } + } + + /* protocolVersion */ + + if ((targetParameters->protocolVersion == 2) || + ((minimumParameters->protocolVersion <= 2) && (maximumParameters->protocolVersion >= 2))) + { + pOutParameters->protocolVersion = 2; + } + else + { + return FALSE; + } + + return TRUE; +} + /** * Read an MCS Connect Initial PDU.\n * @msdn{cc240508} @@ -329,7 +464,7 @@ void mcs_print_domain_parameters(DomainParameters* domainParameters) BOOL mcs_recv_connect_initial(rdpMcs* mcs, wStream* s) { - UINT16 li; + UINT16 li; int length; BOOL upwardFlag; @@ -342,12 +477,12 @@ BOOL mcs_recv_connect_initial(rdpMcs* mcs, wStream* s) return FALSE; /* callingDomainSelector (OCTET_STRING) */ - if (!ber_read_octet_string_tag(s, &length) || Stream_GetRemainingLength(s) < length) + if (!ber_read_octet_string_tag(s, &length) || ((int) Stream_GetRemainingLength(s)) < length) return FALSE; Stream_Seek(s, length); /* calledDomainSelector (OCTET_STRING) */ - if (!ber_read_octet_string_tag(s, &length) || Stream_GetRemainingLength(s) < length) + if (!ber_read_octet_string_tag(s, &length) || ((int) Stream_GetRemainingLength(s)) < length) return FALSE; Stream_Seek(s, length); @@ -367,10 +502,14 @@ BOOL mcs_recv_connect_initial(rdpMcs* mcs, wStream* s) if (!mcs_read_domain_parameters(s, &mcs->maximumParameters)) return FALSE; - if (!ber_read_octet_string_tag(s, &length) || Stream_GetRemainingLength(s) < length) + if (!ber_read_octet_string_tag(s, &length) || ((int) Stream_GetRemainingLength(s)) < length) return FALSE; - if (!gcc_read_conference_create_request(s, mcs->transport->settings)) + if (!gcc_read_conference_create_request(s, mcs)) + return FALSE; + + if (!mcs_merge_domain_parameters(&mcs->targetParameters, &mcs->minimumParameters, + &mcs->maximumParameters, &mcs->domainParameters)) return FALSE; return TRUE; @@ -384,7 +523,7 @@ BOOL mcs_recv_connect_initial(rdpMcs* mcs, wStream* s) * @param user_data GCC Conference Create Request */ -void mcs_write_connect_initial(wStream* s, rdpMcs* mcs, wStream* user_data) +void mcs_write_connect_initial(wStream* s, rdpMcs* mcs, wStream* userData) { int length; wStream* tmps; @@ -410,7 +549,7 @@ void mcs_write_connect_initial(wStream* s, rdpMcs* mcs, wStream* user_data) mcs_write_domain_parameters(tmps, &mcs->maximumParameters); /* userData (OCTET_STRING) */ - ber_write_octet_string(tmps, user_data->buffer, Stream_GetPosition(user_data)); + ber_write_octet_string(tmps, userData->buffer, Stream_GetPosition(userData)); length = Stream_GetPosition(tmps); /* Connect-Initial (APPLICATION 101, IMPLICIT SEQUENCE) */ @@ -427,7 +566,7 @@ void mcs_write_connect_initial(wStream* s, rdpMcs* mcs, wStream* user_data) * @param user_data GCC Conference Create Response */ -void mcs_write_connect_response(wStream* s, rdpMcs* mcs, wStream* user_data) +void mcs_write_connect_response(wStream* s, rdpMcs* mcs, wStream* userData) { int length; wStream* tmps; @@ -435,10 +574,9 @@ void mcs_write_connect_response(wStream* s, rdpMcs* mcs, wStream* user_data) tmps = Stream_New(NULL, Stream_Capacity(s)); ber_write_enumerated(tmps, 0, MCS_Result_enum_length); ber_write_integer(tmps, 0); /* calledConnectId */ - mcs->domainParameters = mcs->targetParameters; mcs_write_domain_parameters(tmps, &(mcs->domainParameters)); /* userData (OCTET_STRING) */ - ber_write_octet_string(tmps, user_data->buffer, Stream_GetPosition(user_data)); + ber_write_octet_string(tmps, userData->buffer, Stream_GetPosition(userData)); length = Stream_GetPosition(tmps); ber_write_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, length); @@ -461,8 +599,10 @@ BOOL mcs_send_connect_initial(rdpMcs* mcs) wStream* gcc_CCrq; wStream* client_data; + mcs_initialize_client_channels(mcs, mcs->settings); + client_data = Stream_New(NULL, 512); - gcc_write_client_data_blocks(client_data, mcs->transport->settings); + gcc_write_client_data_blocks(client_data, mcs); gcc_CCrq = Stream_New(NULL, 1024); gcc_write_conference_create_request(gcc_CCrq, client_data); @@ -519,7 +659,7 @@ BOOL mcs_recv_connect_response(rdpMcs* mcs, wStream* s) return FALSE; } - if (!gcc_read_conference_create_response(s, mcs->transport->settings)) + if (!gcc_read_conference_create_response(s, mcs)) { fprintf(stderr, "mcs_recv_connect_response: gcc_read_conference_create_response failed\n"); return FALSE; @@ -544,7 +684,7 @@ BOOL mcs_send_connect_response(rdpMcs* mcs) wStream* server_data; server_data = Stream_New(NULL, 512); - gcc_write_server_data_blocks(server_data, mcs->transport->settings); + gcc_write_server_data_blocks(server_data, mcs); gcc_CCrsp = Stream_New(NULL, 512); gcc_write_conference_create_response(gcc_CCrsp, server_data); @@ -680,16 +820,18 @@ BOOL mcs_send_attach_user_request(rdpMcs* mcs) BOOL mcs_recv_attach_user_confirm(rdpMcs* mcs, wStream* s) { - UINT16 length; + BOOL status; BYTE result; + UINT16 length; enum DomainMCSPDU MCSPDU; MCSPDU = DomainMCSPDU_AttachUserConfirm; - return - mcs_read_domain_mcspdu_header(s, &MCSPDU, &length) && + status = mcs_read_domain_mcspdu_header(s, &MCSPDU, &length) && per_read_enumerated(s, &result, MCS_Result_enum_length) && /* result */ - per_read_integer16(s, &(mcs->user_id), MCS_BASE_CHANNEL_ID); /* initiator (UserId) */ + per_read_integer16(s, &(mcs->userId), MCS_BASE_CHANNEL_ID); /* initiator (UserId) */ + + return status; } /** @@ -703,14 +845,17 @@ BOOL mcs_send_attach_user_confirm(rdpMcs* mcs) wStream* s; int status; UINT16 length = 11; + rdpSettings* settings; s = Stream_New(NULL, length); + settings = mcs->transport->settings; + + mcs->userId = MCS_GLOBAL_CHANNEL_ID + 1 + settings->ChannelCount; mcs_write_domain_mcspdu_header(s, DomainMCSPDU_AttachUserConfirm, length, 2); per_write_enumerated(s, 0, MCS_Result_enum_length); /* result */ - mcs->user_id = MCS_GLOBAL_CHANNEL_ID + 1 + mcs->transport->settings->ChannelCount; - per_write_integer16(s, mcs->user_id, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */ + per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */ Stream_SealLength(s); @@ -728,19 +873,19 @@ BOOL mcs_send_attach_user_confirm(rdpMcs* mcs) * @param s stream */ -BOOL mcs_recv_channel_join_request(rdpMcs* mcs, wStream* s, UINT16* channel_id) +BOOL mcs_recv_channel_join_request(rdpMcs* mcs, wStream* s, UINT16* channelId) { UINT16 length; + UINT16 userId; enum DomainMCSPDU MCSPDU; - UINT16 user_id; MCSPDU = DomainMCSPDU_ChannelJoinRequest; return mcs_read_domain_mcspdu_header(s, &MCSPDU, &length) && - per_read_integer16(s, &user_id, MCS_BASE_CHANNEL_ID) && - (user_id == mcs->user_id) && - per_read_integer16(s, channel_id, 0); + per_read_integer16(s, &userId, MCS_BASE_CHANNEL_ID) && + (userId == mcs->userId) && + per_read_integer16(s, channelId, 0); } /** @@ -750,7 +895,7 @@ BOOL mcs_recv_channel_join_request(rdpMcs* mcs, wStream* s, UINT16* channel_id) * @param channel_id channel id */ -BOOL mcs_send_channel_join_request(rdpMcs* mcs, UINT16 channel_id) +BOOL mcs_send_channel_join_request(rdpMcs* mcs, UINT16 channelId) { wStream* s; int status; @@ -760,8 +905,8 @@ BOOL mcs_send_channel_join_request(rdpMcs* mcs, UINT16 channel_id) mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinRequest, length, 0); - per_write_integer16(s, mcs->user_id, MCS_BASE_CHANNEL_ID); - per_write_integer16(s, channel_id, 0); + per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID); + per_write_integer16(s, channelId, 0); Stream_SealLength(s); @@ -778,7 +923,7 @@ BOOL mcs_send_channel_join_request(rdpMcs* mcs, UINT16 channel_id) * @param mcs mcs module */ -BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs, wStream* s, UINT16* channel_id) +BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs, wStream* s, UINT16* channelId) { BOOL status; UINT16 length; @@ -794,7 +939,7 @@ BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs, wStream* s, UINT16* channel_id) status &= per_read_enumerated(s, &result, MCS_Result_enum_length); /* result */ status &= per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */ status &= per_read_integer16(s, &requested, 0); /* requested (ChannelId) */ - status &= per_read_integer16(s, channel_id, 0); /* channelId */ + status &= per_read_integer16(s, channelId, 0); /* channelId */ return status; } @@ -805,7 +950,7 @@ BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs, wStream* s, UINT16* channel_id) * @param mcs mcs module */ -BOOL mcs_send_channel_join_confirm(rdpMcs* mcs, UINT16 channel_id) +BOOL mcs_send_channel_join_confirm(rdpMcs* mcs, UINT16 channelId) { wStream* s; int status; @@ -816,9 +961,9 @@ BOOL mcs_send_channel_join_confirm(rdpMcs* mcs, UINT16 channel_id) mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinConfirm, length, 2); per_write_enumerated(s, 0, MCS_Result_enum_length); /* result */ - per_write_integer16(s, mcs->user_id, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */ - per_write_integer16(s, channel_id, 0); /* requested (ChannelId) */ - per_write_integer16(s, channel_id, 0); /* channelId */ + per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */ + per_write_integer16(s, channelId, 0); /* requested (ChannelId) */ + per_write_integer16(s, channelId, 0); /* channelId */ Stream_SealLength(s); @@ -913,14 +1058,21 @@ rdpMcs* mcs_new(rdpTransport* transport) mcs = (rdpMcs*) malloc(sizeof(rdpMcs)); - if (mcs != NULL) + if (mcs) { ZeroMemory(mcs, sizeof(rdpMcs)); mcs->transport = transport; + mcs->settings = transport->settings; + mcs_init_domain_parameters(&mcs->targetParameters, 34, 2, 0, 0xFFFF); mcs_init_domain_parameters(&mcs->minimumParameters, 1, 1, 1, 0x420); mcs_init_domain_parameters(&mcs->maximumParameters, 0xFFFF, 0xFC17, 0xFFFF, 0xFFFF); + mcs_init_domain_parameters(&mcs->domainParameters, 0, 0, 0, 0xFFFF); + + mcs->channelCount = 0; + mcs->channelMaxCount = CHANNEL_MAX_COUNT; + mcs->channels = (rdpMcsChannel*) calloc(mcs->channelMaxCount, sizeof(rdpMcsChannel)); } return mcs; @@ -933,7 +1085,7 @@ rdpMcs* mcs_new(rdpTransport* transport) void mcs_free(rdpMcs* mcs) { - if (mcs != NULL) + if (mcs) { free(mcs); } diff --git a/libfreerdp/core/mcs.h b/libfreerdp/core/mcs.h index 870b746e4..7438b0b1d 100644 --- a/libfreerdp/core/mcs.h +++ b/libfreerdp/core/mcs.h @@ -123,21 +123,36 @@ typedef struct UINT32 protocolVersion; } DomainParameters; +struct rdp_mcs_channel +{ + char Name[8]; + UINT32 options; + int ChannelId; + BOOL joined; + void* handle; +}; +typedef struct rdp_mcs_channel rdpMcsChannel; + struct rdp_mcs { rdpTransport* transport; + rdpSettings* settings; - UINT16 user_id; - UINT16 message_channel_id; + UINT16 userId; + UINT16 messageChannelId; DomainParameters domainParameters; DomainParameters targetParameters; DomainParameters minimumParameters; DomainParameters maximumParameters; - BOOL user_channel_joined; - BOOL global_channel_joined; - BOOL message_channel_joined; + BOOL userChannelJoined; + BOOL globalChannelJoined; + BOOL messageChannelJoined; + + UINT32 channelCount; + UINT32 channelMaxCount; + rdpMcsChannel* channels; }; #define MCS_SEND_DATA_HEADER_MAX_LENGTH 8 @@ -145,8 +160,11 @@ struct rdp_mcs #define MCS_TYPE_CONNECT_INITIAL 0x65 #define MCS_TYPE_CONNECT_RESPONSE 0x66 -void mcs_write_connect_initial(wStream* s, rdpMcs* mcs, wStream* user_data); -void mcs_write_connect_response(wStream* s, rdpMcs* mcs, wStream* user_data); +BOOL mcs_merge_domain_parameters(DomainParameters* targetParameters, DomainParameters* minimumParameters, + DomainParameters* maximumParameters, DomainParameters* pOutParameters); + +void mcs_write_connect_initial(wStream* s, rdpMcs* mcs, wStream* userData); +void mcs_write_connect_response(wStream* s, rdpMcs* mcs, wStream* userData); BOOL mcs_recv_connect_initial(rdpMcs* mcs, wStream* s); BOOL mcs_send_connect_initial(rdpMcs* mcs); @@ -158,10 +176,10 @@ BOOL mcs_recv_attach_user_request(rdpMcs* mcs, wStream* s); BOOL mcs_send_attach_user_request(rdpMcs* mcs); BOOL mcs_recv_attach_user_confirm(rdpMcs* mcs, wStream* s); BOOL mcs_send_attach_user_confirm(rdpMcs* mcs); -BOOL mcs_recv_channel_join_request(rdpMcs* mcs, wStream* s, UINT16* channel_id); -BOOL mcs_send_channel_join_request(rdpMcs* mcs, UINT16 channel_id); -BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs, wStream* s, UINT16* channel_id); -BOOL mcs_send_channel_join_confirm(rdpMcs* mcs, UINT16 channel_id); +BOOL mcs_recv_channel_join_request(rdpMcs* mcs, wStream* s, UINT16* channelId); +BOOL mcs_send_channel_join_request(rdpMcs* mcs, UINT16 channelId); +BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs, wStream* s, UINT16* channelId); +BOOL mcs_send_channel_join_confirm(rdpMcs* mcs, UINT16 channelId); BOOL mcs_recv_disconnect_provider_ultimatum(rdpMcs* mcs, wStream* s, int* reason); BOOL mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs); BOOL mcs_read_domain_mcspdu_header(wStream* s, enum DomainMCSPDU* domainMCSPDU, UINT16* length); diff --git a/libfreerdp/core/message.c b/libfreerdp/core/message.c index 5d6083f22..10e2bd637 100644 --- a/libfreerdp/core/message.c +++ b/libfreerdp/core/message.c @@ -77,7 +77,7 @@ static void update_message_DesktopResize(rdpContext* context) static void update_message_BitmapUpdate(rdpContext* context, BITMAP_UPDATE* bitmap) { - int index; + UINT32 index; BITMAP_UPDATE* wParam; wParam = (BITMAP_UPDATE*) malloc(sizeof(BITMAP_UPDATE)); @@ -998,7 +998,7 @@ static int update_message_free_update_class(wMessage* msg, int type) case Update_BitmapUpdate: { - int index; + UINT32 index; BITMAP_UPDATE* wParam = (BITMAP_UPDATE*) msg->wParam; for (index = 0; index < wParam->number; index++) diff --git a/libfreerdp/core/nla.c b/libfreerdp/core/nla.c index 301590acb..970652d4f 100644 --- a/libfreerdp/core/nla.c +++ b/libfreerdp/core/nla.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -122,6 +123,9 @@ int credssp_ntlm_client_init(rdpCredssp* credssp) settings = credssp->settings; instance = (freerdp*) settings->instance; + if (settings->RestrictedAdminModeRequired) + settings->DisableCredentialsDelegation = TRUE; + if ((!settings->Password) || (!settings->Username) || (!strlen(settings->Password)) || (!strlen(settings->Username))) { @@ -997,7 +1001,7 @@ void credssp_encode_ts_credentials(rdpCredssp* credssp) UserLength = credssp->identity.UserLength; PasswordLength = credssp->identity.PasswordLength; - if (credssp->settings->RestrictedAdminModeRequired) + if (credssp->settings->DisableCredentialsDelegation) { credssp->identity.DomainLength = 0; credssp->identity.UserLength = 0; @@ -1007,10 +1011,10 @@ void credssp_encode_ts_credentials(rdpCredssp* credssp) length = ber_sizeof_sequence(credssp_sizeof_ts_credentials(credssp)); sspi_SecBufferAlloc(&credssp->ts_credentials, length); - s = Stream_New(credssp->ts_credentials.pvBuffer, length); + s = Stream_New((BYTE*) credssp->ts_credentials.pvBuffer, length); credssp_write_ts_credentials(credssp, s); - if (credssp->settings->RestrictedAdminModeRequired) + if (credssp->settings->DisableCredentialsDelegation) { credssp->identity.DomainLength = DomainLength; credssp->identity.UserLength = UserLength; @@ -1244,7 +1248,7 @@ int credssp_recv(rdpCredssp* credssp) !ber_read_sequence_tag(s, &length) || /* NegoDataItem */ !ber_read_contextual_tag(s, 0, &length, TRUE) || /* [0] negoToken */ !ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ - Stream_GetRemainingLength(s) < length) + ((int) Stream_GetRemainingLength(s)) < length) { Stream_Free(s, TRUE); return -1; @@ -1257,8 +1261,8 @@ int credssp_recv(rdpCredssp* credssp) /* [2] authInfo (OCTET STRING) */ if (ber_read_contextual_tag(s, 2, &length, TRUE) != FALSE) { - if(!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ - Stream_GetRemainingLength(s) < length) + if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ + ((int) Stream_GetRemainingLength(s)) < length) { Stream_Free(s, TRUE); return -1; @@ -1271,8 +1275,8 @@ int credssp_recv(rdpCredssp* credssp) /* [3] pubKeyAuth (OCTET STRING) */ if (ber_read_contextual_tag(s, 3, &length, TRUE) != FALSE) { - if(!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ - Stream_GetRemainingLength(s) < length) + if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ + ((int) Stream_GetRemainingLength(s)) < length) { Stream_Free(s, TRUE); return -1; @@ -1315,6 +1319,59 @@ void credssp_buffer_free(rdpCredssp* credssp) sspi_SecBufferFree(&credssp->authInfo); } +LPTSTR credssp_make_spn(const char* ServiceClass, const char* hostname) +{ + DWORD status; + DWORD SpnLength; + LPTSTR hostnameX = NULL; + LPTSTR ServiceClassX = NULL; + LPTSTR ServicePrincipalName = NULL; + +#ifdef UNICODE + ConvertToUnicode(CP_UTF8, 0, hostname, -1, &hostnameX, 0); + ConvertToUnicode(CP_UTF8, 0, ServiceClass, -1, &ServiceClassX, 0); +#else + hostnameX = _strdup(hostname); + ServiceClassX = _strdup(ServiceClass); +#endif + + if (!ServiceClass) + { + ServicePrincipalName = (LPTSTR) _tcsdup(hostnameX); + free(ServiceClassX); + free(hostnameX); + + return ServicePrincipalName; + } + + SpnLength = 0; + status = DsMakeSpn(ServiceClassX, hostnameX, NULL, 0, NULL, &SpnLength, NULL); + + if (status != ERROR_BUFFER_OVERFLOW) + { + free(ServiceClassX); + free(hostnameX); + return NULL; + } + + ServicePrincipalName = (LPTSTR) malloc(SpnLength * sizeof(TCHAR)); + + status = DsMakeSpn(ServiceClassX, hostnameX, NULL, 0, NULL, &SpnLength, ServicePrincipalName); + + if (status != ERROR_SUCCESS) + { + free(ServicePrincipalName); + free(ServiceClassX); + free(hostnameX); + return NULL; + } + + free(ServiceClassX); + free(hostnameX); + + return ServicePrincipalName; +} + /** * Create new CredSSP state machine. * @param transport @@ -1326,15 +1383,16 @@ rdpCredssp* credssp_new(freerdp* instance, rdpTransport* transport, rdpSettings* rdpCredssp* credssp; credssp = (rdpCredssp*) malloc(sizeof(rdpCredssp)); - ZeroMemory(credssp, sizeof(rdpCredssp)); - if (credssp != NULL) + if (credssp) { HKEY hKey; LONG status; DWORD dwType; DWORD dwSize; + ZeroMemory(credssp, sizeof(rdpCredssp)); + credssp->instance = instance; credssp->settings = settings; credssp->server = settings->ServerMode; @@ -1382,7 +1440,7 @@ rdpCredssp* credssp_new(freerdp* instance, rdpTransport* transport, rdpSettings* void credssp_free(rdpCredssp* credssp) { - if (credssp != NULL) + if (credssp) { if (credssp->table) credssp->table->DeleteSecurityContext(&credssp->context); diff --git a/libfreerdp/core/nla.h b/libfreerdp/core/nla.h index 5a4baa299..24eeb8d4b 100644 --- a/libfreerdp/core/nla.h +++ b/libfreerdp/core/nla.h @@ -58,6 +58,7 @@ struct rdp_credssp }; int credssp_authenticate(rdpCredssp* credssp); +LPTSTR credssp_make_spn(const char* ServiceClass, const char* hostname); rdpCredssp* credssp_new(freerdp* instance, rdpTransport* transport, rdpSettings* settings); void credssp_free(rdpCredssp* credssp); diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c index 5836da631..b48ba1a39 100644 --- a/libfreerdp/core/orders.c +++ b/libfreerdp/core/orders.c @@ -651,7 +651,7 @@ static INLINE BOOL update_read_delta_rects(wStream* s, DELTA_RECT* rectangles, i int i; BYTE flags = 0; BYTE* zeroBits; - int zeroBitsSize; + UINT32 zeroBitsSize; if (number > 45) number = 45; @@ -711,7 +711,7 @@ static INLINE BOOL update_read_delta_points(wStream* s, DELTA_POINT* points, int int i; BYTE flags = 0; BYTE* zeroBits; - int zeroBitsSize; + UINT32 zeroBitsSize; zeroBitsSize = ((number + 3) / 4); @@ -2464,7 +2464,7 @@ BOOL update_read_cache_brush_order(wStream* s, CACHE_BRUSH_ORDER* cache_brush, U else { /* uncompressed brush */ - int scanline = (cache_brush->bpp / 8) * 8; + UINT32 scanline = (cache_brush->bpp / 8) * 8; if (Stream_GetRemainingLength(s) < scanline * 8) return FALSE; diff --git a/libfreerdp/core/peer.c b/libfreerdp/core/peer.c index d0c05af6b..24bc3cf5e 100644 --- a/libfreerdp/core/peer.c +++ b/libfreerdp/core/peer.c @@ -394,7 +394,7 @@ static void freerdp_peer_disconnect(freerdp_peer* client) transport_disconnect(client->context->rdp->transport); } -static int freerdp_peer_send_channel_data(freerdp_peer* client, int channelId, BYTE* data, int size) +static int freerdp_peer_send_channel_data(freerdp_peer* client, UINT16 channelId, BYTE* data, int size) { return rdp_send_channel_data(client->context->rdp, channelId, data, size); } diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index a874ff183..2b1e871eb 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -109,7 +109,7 @@ BOOL rdp_read_share_control_header(wStream* s, UINT16* length, UINT16* type, UIN /* Share Control Header */ Stream_Read_UINT16(s, *length); /* totalLength */ - if (*length - 2 > Stream_GetRemainingLength(s)) + if (((size_t) *length - 2) > Stream_GetRemainingLength(s)) return FALSE; Stream_Read_UINT16(s, *type); /* pduType */ @@ -279,7 +279,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId) return FALSE; } - if (*length - 8 > Stream_GetRemainingLength(s)) + if ((size_t) (*length - 8) > Stream_GetRemainingLength(s)) return FALSE; if (MCSPDU == DomainMCSPDU_DisconnectProviderUltimatum) @@ -361,7 +361,7 @@ void rdp_write_header(rdpRdp* rdp, wStream* s, UINT16 length, UINT16 channelId) } mcs_write_domain_mcspdu_header(s, MCSPDU, length, 0); - per_write_integer16(s, rdp->mcs->user_id, MCS_BASE_CHANNEL_ID); /* initiator */ + per_write_integer16(s, rdp->mcs->userId, MCS_BASE_CHANNEL_ID); /* initiator */ per_write_integer16(s, channelId, 0); /* channelId */ Stream_Write_UINT8(s, 0x70); /* dataPriority + segmentation */ /* @@ -555,7 +555,7 @@ BOOL rdp_send_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 sec_flags) length = Stream_GetPosition(s); Stream_SetPosition(s, 0); - rdp_write_header(rdp, s, length, rdp->mcs->message_channel_id); + rdp_write_header(rdp, s, length, rdp->mcs->messageChannelId); sec_bytes = rdp_get_sec_bytes(rdp); sec_hold = Stream_GetPosition(s); @@ -648,7 +648,7 @@ BOOL rdp_recv_server_status_info_pdu(rdpRdp* rdp, wStream* s) BOOL rdp_recv_monitor_layout_pdu(rdpRdp* rdp, wStream* s) { - int index; + UINT32 index; UINT32 monitorCount; MONITOR_DEF* monitor; MONITOR_DEF* monitorDefArray; @@ -682,7 +682,7 @@ BOOL rdp_recv_monitor_layout_pdu(rdpRdp* rdp, wStream* s) BOOL rdp_write_monitor_layout_pdu(wStream* s, UINT32 monitorCount, MONITOR_DEF* monitorDefArray) { - int index; + UINT32 index; MONITOR_DEF* monitor; Stream_EnsureRemainingCapacity(s, 4 + (monitorCount * 20)); @@ -722,7 +722,7 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s) if (compressed_type & PACKET_COMPRESSED) { - if (Stream_GetRemainingLength(s) < compressed_len - 18) + if (Stream_GetRemainingLength(s) < (size_t) (compressed_len - 18)) { fprintf(stderr, "decompress_rdp: not enough bytes for compressed_len=%d\n", compressed_len); return -1; @@ -1050,7 +1050,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s) Stream_SetPosition(s, nextPosition); } } - else if (channelId == rdp->mcs->message_channel_id) + else if (channelId == rdp->mcs->messageChannelId) { return rdp_recv_message_channel_pdu(rdp, s); } @@ -1161,9 +1161,9 @@ static int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra) return status; } -int rdp_send_channel_data(rdpRdp* rdp, int channel_id, BYTE* data, int size) +int rdp_send_channel_data(rdpRdp* rdp, UINT16 channelId, BYTE* data, int size) { - return freerdp_channel_send(rdp, channel_id, data, size); + return freerdp_channel_send(rdp, channelId, data, size); } /** diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h index fbd73e45c..e0764c5ba 100644 --- a/libfreerdp/core/rdp.h +++ b/libfreerdp/core/rdp.h @@ -42,7 +42,7 @@ #include "connection.h" #include "redirection.h" #include "capabilities.h" -#include "channel.h" +#include "channels.h" #include #include @@ -198,9 +198,9 @@ wStream* rdp_data_pdu_init(rdpRdp* rdp); BOOL rdp_send_data_pdu(rdpRdp* rdp, wStream* s, BYTE type, UINT16 channel_id); int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s); -BOOL rdp_send(rdpRdp* rdp, wStream* s, UINT16 channel_id); +BOOL rdp_send(rdpRdp* rdp, wStream* s, UINT16 channelId); -int rdp_send_channel_data(rdpRdp* rdp, int channel_id, BYTE* data, int size); +int rdp_send_channel_data(rdpRdp* rdp, UINT16 channelId, BYTE* data, int size); wStream* rdp_message_channel_pdu_init(rdpRdp* rdp); BOOL rdp_send_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 sec_flags); diff --git a/libfreerdp/core/redirection.c b/libfreerdp/core/redirection.c index 6dbdd9e6b..d7f7e9ec0 100644 --- a/libfreerdp/core/redirection.c +++ b/libfreerdp/core/redirection.c @@ -152,7 +152,7 @@ int rdp_redirection_apply_settings(rdpRdp* rdp) if (settings->RedirectionFlags & LB_TARGET_NET_ADDRESSES) { - int i; + UINT32 i; freerdp_target_net_addresses_free(settings); diff --git a/libfreerdp/core/server.c b/libfreerdp/core/server.c new file mode 100644 index 000000000..7758510a1 --- /dev/null +++ b/libfreerdp/core/server.c @@ -0,0 +1,1232 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Server Channels + * + * Copyright 2014 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 + +#include +#include + +#include "rdp.h" + +#include "server.h" + +#ifdef WITH_DEBUG_DVC +#define DEBUG_DVC(fmt, ...) DEBUG_CLASS(DVC, fmt, ## __VA_ARGS__) +#else +#define DEBUG_DVC(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) +#endif + +static DWORD g_SessionId = 1; +static wHashTable* g_ServerHandles = NULL; + +static rdpPeerChannel* wts_get_dvc_channel_by_id(WTSVirtualChannelManager* vcm, UINT32 ChannelId) +{ + int index; + int count; + BOOL found = FALSE; + rdpPeerChannel* channel = NULL; + + ArrayList_Lock(vcm->dynamicVirtualChannels); + + count = ArrayList_Count(vcm->dynamicVirtualChannels); + + for (index = 0; index < count; index++) + { + channel = (rdpPeerChannel*) ArrayList_GetItem(vcm->dynamicVirtualChannels, index); + + if (channel->channelId == ChannelId) + { + found = TRUE; + break; + } + } + + ArrayList_Unlock(vcm->dynamicVirtualChannels); + + return found ? channel : NULL; +} + +static void wts_queue_receive_data(rdpPeerChannel* channel, const BYTE* Buffer, UINT32 Length) +{ + BYTE* buffer; + UINT32 length; + UINT16 channelId; + + length = Length; + buffer = (BYTE*) malloc(length); + CopyMemory(buffer, Buffer, length); + channelId = channel->channelId; + + MessageQueue_Post(channel->queue, (void*) (UINT_PTR) channelId, 0, (void*) buffer, (void*) (UINT_PTR) length); +} + +static void wts_queue_send_item(rdpPeerChannel* channel, BYTE* Buffer, UINT32 Length) +{ + BYTE* buffer; + UINT32 length; + UINT16 channelId; + + buffer = Buffer; + length = Length; + channelId = channel->channelId; + + MessageQueue_Post(channel->vcm->queue, (void*) (UINT_PTR) channelId, 0, (void*) buffer, (void*) (UINT_PTR) length); +} + +static int wts_read_variable_uint(wStream* s, int cbLen, UINT32* val) +{ + switch (cbLen) + { + case 0: + if (Stream_GetRemainingLength(s) < 1) + return 0; + Stream_Read_UINT8(s, *val); + return 1; + + case 1: + if (Stream_GetRemainingLength(s) < 2) + return 0; + Stream_Read_UINT16(s, *val); + return 2; + + default: + if (Stream_GetRemainingLength(s) < 4) + return 0; + Stream_Read_UINT32(s, *val); + return 4; + } +} + +static void wts_read_drdynvc_capabilities_response(rdpPeerChannel* channel, UINT32 length) +{ + UINT16 Version; + + if (length < 3) + return; + + Stream_Seek_UINT8(channel->receiveData); /* Pad (1 byte) */ + Stream_Read_UINT16(channel->receiveData, Version); + + DEBUG_DVC("Version: %d", Version); + + channel->vcm->drdynvc_state = DRDYNVC_STATE_READY; +} + +static void wts_read_drdynvc_create_response(rdpPeerChannel* channel, wStream* s, UINT32 length) +{ + UINT32 CreationStatus; + + if (length < 4) + return; + + Stream_Read_UINT32(s, CreationStatus); + + if ((INT32) CreationStatus < 0) + { + DEBUG_DVC("ChannelId %d creation failed (%d)", channel->channelId, (INT32) CreationStatus); + channel->dvc_open_state = DVC_OPEN_STATE_FAILED; + } + else + { + DEBUG_DVC("ChannelId %d creation succeeded", channel->channelId); + channel->dvc_open_state = DVC_OPEN_STATE_SUCCEEDED; + } +} + +static void wts_read_drdynvc_data_first(rdpPeerChannel* channel, wStream* s, int cbLen, UINT32 length) +{ + int value; + + value = wts_read_variable_uint(s, cbLen, &channel->dvc_total_length); + + if (value == 0) + return; + + length -= value; + + if (length > channel->dvc_total_length) + return; + + Stream_SetPosition(channel->receiveData, 0); + Stream_EnsureRemainingCapacity(channel->receiveData, (int) channel->dvc_total_length); + Stream_Write(channel->receiveData, Stream_Pointer(s), length); +} + +static void wts_read_drdynvc_data(rdpPeerChannel* channel, wStream* s, UINT32 length) +{ + if (channel->dvc_total_length > 0) + { + if (Stream_GetPosition(channel->receiveData) + length > channel->dvc_total_length) + { + channel->dvc_total_length = 0; + fprintf(stderr, "wts_read_drdynvc_data: incorrect fragment data, discarded.\n"); + return; + } + + Stream_Write(channel->receiveData, Stream_Pointer(s), length); + + if (Stream_GetPosition(channel->receiveData) >= (int) channel->dvc_total_length) + { + wts_queue_receive_data(channel, Stream_Buffer(channel->receiveData), channel->dvc_total_length); + channel->dvc_total_length = 0; + } + } + else + { + wts_queue_receive_data(channel, Stream_Pointer(s), length); + } +} + +static void wts_read_drdynvc_close_response(rdpPeerChannel* channel) +{ + DEBUG_DVC("ChannelId %d close response", channel->channelId); + channel->dvc_open_state = DVC_OPEN_STATE_CLOSED; +} + +static void wts_read_drdynvc_pdu(rdpPeerChannel* channel) +{ + UINT32 length; + int value; + int Cmd; + int Sp; + int cbChId; + UINT32 ChannelId; + rdpPeerChannel* dvc; + + length = Stream_GetPosition(channel->receiveData); + + if (length < 1) + return; + + Stream_SetPosition(channel->receiveData, 0); + Stream_Read_UINT8(channel->receiveData, value); + + length--; + Cmd = (value & 0xf0) >> 4; + Sp = (value & 0x0c) >> 2; + cbChId = (value & 0x03) >> 0; + + if (Cmd == CAPABILITY_REQUEST_PDU) + { + wts_read_drdynvc_capabilities_response(channel, length); + } + else if (channel->vcm->drdynvc_state == DRDYNVC_STATE_READY) + { + value = wts_read_variable_uint(channel->receiveData, cbChId, &ChannelId); + + if (value == 0) + return; + + length -= value; + + DEBUG_DVC("Cmd %d ChannelId %d length %d", Cmd, ChannelId, length); + dvc = wts_get_dvc_channel_by_id(channel->vcm, ChannelId); + + if (dvc) + { + switch (Cmd) + { + case CREATE_REQUEST_PDU: + wts_read_drdynvc_create_response(dvc, channel->receiveData, length); + break; + + case DATA_FIRST_PDU: + wts_read_drdynvc_data_first(dvc, channel->receiveData, Sp, length); + break; + + case DATA_PDU: + wts_read_drdynvc_data(dvc, channel->receiveData, length); + break; + + case CLOSE_REQUEST_PDU: + wts_read_drdynvc_close_response(dvc); + break; + + default: + fprintf(stderr, "wts_read_drdynvc_pdu: Cmd %d not recognized.\n", Cmd); + break; + } + } + else + { + DEBUG_DVC("ChannelId %d not exists.", ChannelId); + } + } + else + { + fprintf(stderr, "wts_read_drdynvc_pdu: received Cmd %d but channel is not ready.\n", Cmd); + } +} + +static int wts_write_variable_uint(wStream* stream, UINT32 val) +{ + int cb; + + if (val <= 0xFF) + { + cb = 0; + Stream_Write_UINT8(stream, val); + } + else if (val <= 0xFFFF) + { + cb = 1; + Stream_Write_UINT16(stream, val); + } + else + { + cb = 3; + Stream_Write_UINT32(stream, val); + } + + return cb; +} + +static void wts_write_drdynvc_header(wStream *s, BYTE Cmd, UINT32 ChannelId) +{ + BYTE* bm; + int cbChId; + + Stream_GetPointer(s, bm); + Stream_Seek_UINT8(s); + cbChId = wts_write_variable_uint(s, ChannelId); + *bm = ((Cmd & 0x0F) << 4) | cbChId; +} + +static void wts_write_drdynvc_create_request(wStream *s, UINT32 ChannelId, const char *ChannelName) +{ + UINT32 len; + + wts_write_drdynvc_header(s, CREATE_REQUEST_PDU, ChannelId); + len = strlen(ChannelName) + 1; + Stream_EnsureRemainingCapacity(s, (int) len); + Stream_Write(s, ChannelName, len); +} + +static void WTSProcessChannelData(rdpPeerChannel* channel, UINT16 channelId, BYTE* data, int size, int flags, int totalSize) +{ + if (flags & CHANNEL_FLAG_FIRST) + { + Stream_SetPosition(channel->receiveData, 0); + } + + Stream_EnsureRemainingCapacity(channel->receiveData, size); + Stream_Write(channel->receiveData, data, size); + + if (flags & CHANNEL_FLAG_LAST) + { + if (Stream_GetPosition(channel->receiveData) != totalSize) + { + fprintf(stderr, "WTSProcessChannelData: read error\n"); + } + if (channel == channel->vcm->drdynvc_channel) + { + wts_read_drdynvc_pdu(channel); + } + else + { + wts_queue_receive_data(channel, Stream_Buffer(channel->receiveData), Stream_GetPosition(channel->receiveData)); + } + Stream_SetPosition(channel->receiveData, 0); + } +} + +static int WTSReceiveChannelData(freerdp_peer* client, UINT16 channelId, BYTE* data, int size, int flags, int totalSize) +{ + int i; + BOOL status = FALSE; + rdpPeerChannel* channel; + rdpMcs* mcs = client->context->rdp->mcs; + + for (i = 0; i < mcs->channelCount; i++) + { + if (mcs->channels[i].ChannelId == channelId) + break; + } + + if (i < mcs->channelCount) + { + channel = (rdpPeerChannel*) mcs->channels[i].handle; + + if (channel) + { + WTSProcessChannelData(channel, channelId, data, size, flags, totalSize); + status = TRUE; + } + } + + return status; +} + +void WTSVirtualChannelManagerGetFileDescriptor(HANDLE hServer, void** fds, int* fds_count) +{ + void* fd; + WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*) hServer; + + fd = GetEventWaitObject(MessageQueue_Event(vcm->queue)); + + if (fd) + { + fds[*fds_count] = fd; + (*fds_count)++; + } + +#if 0 + if (vcm->drdynvc_channel) + { + fd = GetEventWaitObject(vcm->drdynvc_channel->receiveEvent); + + if (fd) + { + fds[*fds_count] = fd; + (*fds_count)++; + } + } +#endif +} + +BOOL WTSVirtualChannelManagerCheckFileDescriptor(HANDLE hServer) +{ + wMessage message; + BOOL status = TRUE; + rdpPeerChannel* channel; + UINT32 dynvc_caps; + WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*) hServer; + + if ((vcm->drdynvc_state == DRDYNVC_STATE_NONE) && vcm->client->activated) + { + /* Initialize drdynvc channel once and only once. */ + vcm->drdynvc_state = DRDYNVC_STATE_INITIALIZED; + + channel = (rdpPeerChannel*) WTSVirtualChannelOpen((HANDLE) vcm, WTS_CURRENT_SESSION, "drdynvc"); + + if (channel) + { + vcm->drdynvc_channel = channel; + dynvc_caps = 0x00010050; /* DYNVC_CAPS_VERSION1 (4 bytes) */ + WTSVirtualChannelWrite(channel, (PCHAR) &dynvc_caps, sizeof(dynvc_caps), NULL); + } + } + + while (MessageQueue_Peek(vcm->queue, &message, TRUE)) + { + BYTE* buffer; + UINT32 length; + UINT16 channelId; + + channelId = (UINT16) (UINT_PTR) message.context; + buffer = (BYTE*) message.wParam; + length = (UINT32) (UINT_PTR) message.lParam; + + if (vcm->client->SendChannelData(vcm->client, channelId, buffer, length) == FALSE) + { + status = FALSE; + } + + free(buffer); + + if (!status) + break; + } + + return status; +} + +HANDLE WTSVirtualChannelManagerGetEventHandle(HANDLE hServer) +{ + WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*) hServer; + return MessageQueue_Event(vcm->queue); +} + +BOOL WTSVirtualChannelManagerIsChannelJoined(HANDLE hServer, const char* name) +{ + rdpMcs* mcs; + UINT32 index; + BOOL joined = FALSE; + WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*) hServer; + + mcs = vcm->rdp->mcs; + + for (index = 0; index < mcs->channelCount; index++) + { + if (mcs->channels[index].joined) + { + if (strncmp(mcs->channels[index].Name, name, strlen(name)) == 0) + { + joined = TRUE; + } + } + } + + return joined; +} + +BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionW(LPWSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionA(LPSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSStopRemoteControlSession(ULONG LogonId) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSConnectSessionW(ULONG LogonId, ULONG TargetLogonId, PWSTR pPassword, BOOL bWait) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSConnectSessionA(ULONG LogonId, ULONG TargetLogonId, PSTR pPassword, BOOL bWait) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSEnumerateServersW(LPWSTR pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOW* ppServerInfo, DWORD* pCount) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSEnumerateServersA(LPSTR pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOA* ppServerInfo, DWORD* pCount) +{ + return FALSE; +} + +HANDLE WINAPI FreeRDP_WTSOpenServerW(LPWSTR pServerName) +{ + return INVALID_HANDLE_VALUE; +} + +HANDLE WINAPI FreeRDP_WTSOpenServerA(LPSTR pServerName) +{ + rdpContext* context; + freerdp_peer* client; + WTSVirtualChannelManager* vcm; + HANDLE hServer = INVALID_HANDLE_VALUE; + + context = (rdpContext*) pServerName; + + if (!context) + return INVALID_HANDLE_VALUE; + + client = context->peer; + + if (!client) + return INVALID_HANDLE_VALUE; + + vcm = (WTSVirtualChannelManager*) calloc(1, sizeof(WTSVirtualChannelManager)); + + if (vcm) + { + vcm->client = client; + vcm->rdp = context->rdp; + + vcm->SessionId = g_SessionId++; + + if (!g_ServerHandles) + g_ServerHandles = HashTable_New(TRUE); + + HashTable_Add(g_ServerHandles, (void*) (UINT_PTR) vcm->SessionId, (void*) vcm); + + vcm->queue = MessageQueue_New(NULL); + + vcm->dvc_channel_id_seq = 1; + vcm->dynamicVirtualChannels = ArrayList_New(TRUE); + + client->ReceiveChannelData = WTSReceiveChannelData; + + hServer = (HANDLE) vcm; + } + + return hServer; +} + +HANDLE WINAPI FreeRDP_WTSOpenServerExW(LPWSTR pServerName) +{ + return INVALID_HANDLE_VALUE; +} + +HANDLE WINAPI FreeRDP_WTSOpenServerExA(LPSTR pServerName) +{ + return FreeRDP_WTSOpenServerA(pServerName); +} + +VOID WINAPI FreeRDP_WTSCloseServer(HANDLE hServer) +{ + int index; + int count; + rdpPeerChannel* channel; + WTSVirtualChannelManager* vcm; + + vcm = (WTSVirtualChannelManager*) hServer; + + if (vcm) + { + HashTable_Remove(g_ServerHandles, (void*) (UINT_PTR) vcm->SessionId); + + ArrayList_Lock(vcm->dynamicVirtualChannels); + + count = ArrayList_Count(vcm->dynamicVirtualChannels); + + for (index = 0; index < count; index++) + { + channel = (rdpPeerChannel*) ArrayList_GetItem(vcm->dynamicVirtualChannels, index); + WTSVirtualChannelClose(channel); + } + + ArrayList_Unlock(vcm->dynamicVirtualChannels); + + ArrayList_Free(vcm->dynamicVirtualChannels); + + if (vcm->drdynvc_channel) + { + WTSVirtualChannelClose(vcm->drdynvc_channel); + vcm->drdynvc_channel = NULL; + } + + MessageQueue_Free(vcm->queue); + + free(vcm); + } +} + +BOOL WINAPI FreeRDP_WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOW* ppSessionInfo, DWORD* pCount) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSEnumerateSessionsA(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOA* ppSessionInfo, DWORD* pCount) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSEnumerateSessionsExW(HANDLE hServer, DWORD* pLevel, DWORD Filter, PWTS_SESSION_INFO_1W* ppSessionInfo, DWORD* pCount) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSEnumerateSessionsExA(HANDLE hServer, DWORD* pLevel, DWORD Filter, PWTS_SESSION_INFO_1A* ppSessionInfo, DWORD* pCount) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOA* ppProcessInfo, DWORD* pCount) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSTerminateProcess(HANDLE hServer, DWORD ProcessId, DWORD ExitCode) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSQuerySessionInformationW(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPWSTR* ppBuffer, DWORD* pBytesReturned) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSQuerySessionInformationA(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPSTR* ppBuffer, DWORD* pBytesReturned) +{ + DWORD BytesReturned; + WTSVirtualChannelManager* vcm; + + vcm = (WTSVirtualChannelManager*) hServer; + + if (!vcm) + return FALSE; + + if (WTSInfoClass == WTSSessionId) + { + ULONG* pBuffer; + + BytesReturned = sizeof(ULONG); + pBuffer = (ULONG*) malloc(sizeof(BytesReturned)); + + *pBuffer = vcm->SessionId; + + *ppBuffer = (LPSTR) pBuffer; + *pBytesReturned = BytesReturned; + + return TRUE; + } + + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSQueryUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR* ppBuffer, DWORD* pBytesReturned) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSQueryUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR* ppBuffer, DWORD* pBytesReturned) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSSetUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR pBuffer, DWORD DataLength) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSSetUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR pBuffer, DWORD DataLength) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSSendMessageW(HANDLE hServer, DWORD SessionId, LPWSTR pTitle, DWORD TitleLength, + LPWSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSSendMessageA(HANDLE hServer, DWORD SessionId, LPSTR pTitle, DWORD TitleLength, + LPSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSDisconnectSession(HANDLE hServer, DWORD SessionId, BOOL bWait) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSLogoffSession(HANDLE hServer, DWORD SessionId, BOOL bWait) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSShutdownSystem(HANDLE hServer, DWORD ShutdownFlag) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags) +{ + return FALSE; +} + +HANDLE WINAPI FreeRDP_WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName) +{ + int index; + int length; + rdpMcs* mcs; + BOOL joined = FALSE; + freerdp_peer* client; + rdpPeerChannel* channel; + WTSVirtualChannelManager* vcm; + HANDLE hChannelHandle = NULL; + + vcm = (WTSVirtualChannelManager*) hServer; + + if (!vcm) + return NULL; + + client = vcm->client; + mcs = client->context->rdp->mcs; + + length = strlen(pVirtualName); + + if (length > 8) + { + SetLastError(ERROR_NOT_FOUND); + return NULL; + } + + for (index = 0; index < mcs->channelCount; index++) + { + if (mcs->channels[index].joined && (strncmp(mcs->channels[index].Name, pVirtualName, length) == 0)) + { + joined = TRUE; + break; + } + } + + if (!joined) + { + SetLastError(ERROR_NOT_FOUND); + return NULL; + } + + channel = (rdpPeerChannel*) mcs->channels[index].handle; + + if (!channel) + { + channel = (rdpPeerChannel*) calloc(1, sizeof(rdpPeerChannel)); + + channel->vcm = vcm; + channel->client = client; + channel->channelId = mcs->channels[index].ChannelId; + channel->index = index; + channel->channelType = RDP_PEER_CHANNEL_TYPE_SVC; + channel->receiveData = Stream_New(NULL, client->settings->VirtualChannelChunkSize); + channel->queue = MessageQueue_New(NULL); + + mcs->channels[index].handle = channel; + } + + hChannelHandle = (HANDLE) channel; + + return hChannelHandle; +} + +HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags) +{ + int index; + wStream* s; + rdpMcs* mcs; + BOOL joined = FALSE; + freerdp_peer* client; + rdpPeerChannel* channel; + WTSVirtualChannelManager* vcm; + + if (SessionId == WTS_CURRENT_SESSION) + return NULL; + + vcm = (WTSVirtualChannelManager*) HashTable_GetItemValue(g_ServerHandles, (void*) (UINT_PTR) SessionId); + + if (!vcm) + return NULL; + + if (!(flags & WTS_CHANNEL_OPTION_DYNAMIC)) + { + return FreeRDP_WTSVirtualChannelOpen((HANDLE) vcm, SessionId, pVirtualName); + } + + client = vcm->client; + mcs = client->context->rdp->mcs; + + for (index = 0; index < mcs->channelCount; index++) + { + if (mcs->channels[index].joined && (strncmp(mcs->channels[index].Name, "drdynvc", 7) == 0)) + { + joined = TRUE; + break; + } + } + + if (!joined) + { + SetLastError(ERROR_NOT_FOUND); + return NULL; + } + + if (!vcm->drdynvc_channel || (vcm->drdynvc_state != DRDYNVC_STATE_READY)) + { + SetLastError(ERROR_NOT_READY); + return NULL; + } + + channel = (rdpPeerChannel*) calloc(1, sizeof(rdpPeerChannel)); + + channel->vcm = vcm; + channel->client = client; + channel->channelType = RDP_PEER_CHANNEL_TYPE_DVC; + channel->receiveData = Stream_New(NULL, client->settings->VirtualChannelChunkSize); + channel->queue = MessageQueue_New(NULL); + + channel->channelId = vcm->dvc_channel_id_seq++; + ArrayList_Add(vcm->dynamicVirtualChannels, channel); + + s = Stream_New(NULL, 64); + wts_write_drdynvc_create_request(s, channel->channelId, pVirtualName); + WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL); + Stream_Free(s, TRUE); + + return NULL; +} + +BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle) +{ + wStream* s; + rdpMcs* mcs; + WTSVirtualChannelManager* vcm; + rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; + + if (channel) + { + vcm = channel->vcm; + mcs = vcm->client->context->rdp->mcs; + + if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC) + { + if (channel->index < mcs->channelCount) + mcs->channels[channel->index].handle = NULL; + } + else + { + ArrayList_Remove(vcm->dynamicVirtualChannels, channel); + + if (channel->dvc_open_state == DVC_OPEN_STATE_SUCCEEDED) + { + s = Stream_New(NULL, 8); + wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channelId); + WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL); + Stream_Free(s, TRUE); + } + } + + if (channel->receiveData) + Stream_Free(channel->receiveData, TRUE); + + if (channel->queue) + { + MessageQueue_Free(channel->queue); + channel->queue = NULL; + } + + free(channel); + } + + return TRUE; +} + +BOOL WINAPI FreeRDP_WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead) +{ + BYTE* buffer; + UINT32 length; + UINT16 channelId; + wMessage message; + rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; + + if (!MessageQueue_Peek(channel->queue, &message, TRUE)) + { + *pBytesRead = 0; + return TRUE; + } + + channelId = (UINT16) (UINT_PTR) message.context; + buffer = (BYTE*) message.wParam; + length = (UINT32) (UINT_PTR) message.lParam; + + *pBytesRead = length; + + if (length > BufferSize) + return FALSE; + + CopyMemory(Buffer, buffer, length); + free(buffer); + + return TRUE; +} + +BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten) +{ + wStream* s; + int cbLen; + int cbChId; + int first; + BYTE* buffer; + UINT32 length; + UINT32 written; + rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; + + if (!channel) + return FALSE; + + if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC) + { + length = Length; + buffer = (BYTE*) malloc(length); + CopyMemory(buffer, Buffer, length); + + wts_queue_send_item(channel, buffer, length); + } + else if (!channel->vcm->drdynvc_channel || (channel->vcm->drdynvc_state != DRDYNVC_STATE_READY)) + { + DEBUG_DVC("drdynvc not ready"); + return FALSE; + } + else + { + first = TRUE; + + while (Length > 0) + { + s = Stream_New(NULL, channel->client->settings->VirtualChannelChunkSize); + buffer = Stream_Buffer(s); + + Stream_Seek_UINT8(s); + cbChId = wts_write_variable_uint(s, channel->channelId); + + if (first && (Length > (UINT32) Stream_GetRemainingLength(s))) + { + cbLen = wts_write_variable_uint(s, Length); + buffer[0] = (DATA_FIRST_PDU << 4) | (cbLen << 2) | cbChId; + } + else + { + buffer[0] = (DATA_PDU << 4) | cbChId; + } + + first = FALSE; + written = Stream_GetRemainingLength(s); + + if (written > Length) + written = Length; + + Stream_Write(s, Buffer, written); + length = Stream_GetPosition(s); + Stream_Free(s, FALSE); + + Length -= written; + Buffer += written; + + wts_queue_send_item(channel->vcm->drdynvc_channel, buffer, length); + } + } + + if (pBytesWritten) + *pBytesWritten = Length; + + return TRUE; +} + +BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeInput(HANDLE hChannelHandle) +{ + return TRUE; +} + +BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle) +{ + return TRUE; +} + +BOOL WINAPI FreeRDP_WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned) +{ + void* pfd; + BOOL bval; + void* fds[10]; + HANDLE hEvent; + int fds_count = 0; + BOOL status = FALSE; + rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; + ZeroMemory(fds, sizeof(fds)); + + hEvent = MessageQueue_Event(channel->queue); + + switch ((UINT32) WtsVirtualClass) + { + case WTSVirtualFileHandle: + + pfd = GetEventWaitObject(hEvent); + + if (pfd) + { + fds[fds_count] = pfd; + (fds_count)++; + } + + *ppBuffer = malloc(sizeof(void*)); + CopyMemory(*ppBuffer, &fds[0], sizeof(void*)); + *pBytesReturned = sizeof(void*); + status = TRUE; + break; + + case WTSVirtualEventHandle: + *ppBuffer = malloc(sizeof(HANDLE)); + CopyMemory(*ppBuffer, &(hEvent), sizeof(HANDLE)); + *pBytesReturned = sizeof(void*); + status = TRUE; + break; + + case WTSVirtualChannelReady: + if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC) + { + bval = TRUE; + status = TRUE; + } + else + { + switch (channel->dvc_open_state) + { + case DVC_OPEN_STATE_NONE: + bval = FALSE; + status = TRUE; + break; + + case DVC_OPEN_STATE_SUCCEEDED: + bval = TRUE; + status = TRUE; + break; + + default: + bval = FALSE; + status = FALSE; + break; + } + } + + *ppBuffer = malloc(sizeof(BOOL)); + CopyMemory(*ppBuffer, &bval, sizeof(BOOL)); + *pBytesReturned = sizeof(BOOL); + break; + + default: + break; + } + return status; +} + +VOID WINAPI FreeRDP_WTSFreeMemory(PVOID pMemory) +{ + free(pMemory); +} + +BOOL WINAPI FreeRDP_WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotification(HWND hWnd) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd, DWORD dwFlags) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSQueryUserToken(ULONG SessionId, PHANDLE phToken) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSEnumerateProcessesExW(HANDLE hServer, DWORD* pLevel, DWORD SessionId, LPWSTR* ppProcessInfo, DWORD* pCount) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSEnumerateProcessesExA(HANDLE hServer, DWORD* pLevel, DWORD SessionId, LPSTR* ppProcessInfo, DWORD* pCount) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSEnumerateListenersW(HANDLE hServer, PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEW pListeners, DWORD* pCount) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSEnumerateListenersA(HANDLE hServer, PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEA pListeners, DWORD* pCount) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSQueryListenerConfigW(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSQueryListenerConfigA(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSCreateListenerW(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer, DWORD flag) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSCreateListenerA(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer, DWORD flag) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSSetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPWSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSSetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSGetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPWSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSGetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded) +{ + return FALSE; +} + +BOOL CDECL FreeRDP_WTSEnableChildSessions(BOOL bEnable) +{ + return FALSE; +} + +BOOL CDECL FreeRDP_WTSIsChildSessionsEnabled(PBOOL pbEnabled) +{ + return FALSE; +} + +BOOL CDECL FreeRDP_WTSGetChildSessionId(PULONG pSessionId) +{ + return FALSE; +} + +DWORD WINAPI FreeRDP_WTSGetActiveConsoleSessionId(void) +{ + return 0xFFFFFFFF; +} diff --git a/libfreerdp/core/server.h b/libfreerdp/core/server.h new file mode 100644 index 000000000..1e0e2ccd5 --- /dev/null +++ b/libfreerdp/core/server.h @@ -0,0 +1,174 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Server Channels + * + * Copyright 2014 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_CORE_SERVER_H +#define FREERDP_CORE_SERVER_H + +#include +#include +#include +#include + +#include +#include +#include + +typedef struct WTSVirtualChannelManager WTSVirtualChannelManager; + +#include "rdp.h" + +#define CREATE_REQUEST_PDU 0x01 +#define DATA_FIRST_PDU 0x02 +#define DATA_PDU 0x03 +#define CLOSE_REQUEST_PDU 0x04 +#define CAPABILITY_REQUEST_PDU 0x05 + +enum +{ + RDP_PEER_CHANNEL_TYPE_SVC = 0, + RDP_PEER_CHANNEL_TYPE_DVC = 1 +}; + +enum +{ + DRDYNVC_STATE_NONE = 0, + DRDYNVC_STATE_INITIALIZED = 1, + DRDYNVC_STATE_READY = 2 +}; + +enum +{ + DVC_OPEN_STATE_NONE = 0, + DVC_OPEN_STATE_SUCCEEDED = 1, + DVC_OPEN_STATE_FAILED = 2, + DVC_OPEN_STATE_CLOSED = 3 +}; + +typedef struct rdp_peer_channel rdpPeerChannel; + +struct rdp_peer_channel +{ + WTSVirtualChannelManager* vcm; + freerdp_peer* client; + + UINT32 channelId; + UINT16 channelType; + UINT16 index; + + wStream* receiveData; + wMessageQueue* queue; + + BYTE dvc_open_state; + UINT32 dvc_total_length; +}; + +struct WTSVirtualChannelManager +{ + rdpRdp* rdp; + freerdp_peer* client; + + DWORD SessionId; + wMessageQueue* queue; + + rdpPeerChannel* drdynvc_channel; + BYTE drdynvc_state; + UINT32 dvc_channel_id_seq; + + wArrayList* dynamicVirtualChannels; +}; + +BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionW(LPWSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers); +BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionA(LPSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers); +BOOL WINAPI FreeRDP_WTSStopRemoteControlSession(ULONG LogonId); +BOOL WINAPI FreeRDP_WTSConnectSessionW(ULONG LogonId, ULONG TargetLogonId, PWSTR pPassword, BOOL bWait); +BOOL WINAPI FreeRDP_WTSConnectSessionA(ULONG LogonId, ULONG TargetLogonId, PSTR pPassword, BOOL bWait); +BOOL WINAPI FreeRDP_WTSEnumerateServersW(LPWSTR pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOW* ppServerInfo, DWORD* pCount); +BOOL WINAPI FreeRDP_WTSEnumerateServersA(LPSTR pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOA* ppServerInfo, DWORD* pCount); +HANDLE WINAPI FreeRDP_WTSOpenServerW(LPWSTR pServerName); +HANDLE WINAPI FreeRDP_WTSOpenServerA(LPSTR pServerName); +HANDLE WINAPI FreeRDP_WTSOpenServerExW(LPWSTR pServerName); +HANDLE WINAPI FreeRDP_WTSOpenServerExA(LPSTR pServerName); +VOID WINAPI FreeRDP_WTSCloseServer(HANDLE hServer); +BOOL WINAPI FreeRDP_WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOW* ppSessionInfo, DWORD* pCount); +BOOL WINAPI FreeRDP_WTSEnumerateSessionsA(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOA* ppSessionInfo, DWORD* pCount); +BOOL WINAPI FreeRDP_WTSEnumerateSessionsExW(HANDLE hServer, DWORD* pLevel, DWORD Filter, PWTS_SESSION_INFO_1W* ppSessionInfo, DWORD* pCount); +BOOL WINAPI FreeRDP_WTSEnumerateSessionsExA(HANDLE hServer, DWORD* pLevel, DWORD Filter, PWTS_SESSION_INFO_1A* ppSessionInfo, DWORD* pCount); +BOOL WINAPI FreeRDP_WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount); +BOOL WINAPI FreeRDP_WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOA* ppProcessInfo, DWORD* pCount); +BOOL WINAPI FreeRDP_WTSTerminateProcess(HANDLE hServer, DWORD ProcessId, DWORD ExitCode); +BOOL WINAPI FreeRDP_WTSQuerySessionInformationW(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPWSTR* ppBuffer, DWORD* pBytesReturned); +BOOL WINAPI FreeRDP_WTSQuerySessionInformationA(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPSTR* ppBuffer, DWORD* pBytesReturned); +BOOL WINAPI FreeRDP_WTSQueryUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR* ppBuffer, DWORD* pBytesReturned); +BOOL WINAPI FreeRDP_WTSQueryUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR* ppBuffer, DWORD* pBytesReturned); +BOOL WINAPI FreeRDP_WTSSetUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR pBuffer, DWORD DataLength); +BOOL WINAPI FreeRDP_WTSSetUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR pBuffer, DWORD DataLength); +BOOL WINAPI FreeRDP_WTSSendMessageW(HANDLE hServer, DWORD SessionId, LPWSTR pTitle, DWORD TitleLength, + LPWSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait); +BOOL WINAPI FreeRDP_WTSSendMessageA(HANDLE hServer, DWORD SessionId, LPSTR pTitle, DWORD TitleLength, + LPSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait); +BOOL WINAPI FreeRDP_WTSDisconnectSession(HANDLE hServer, DWORD SessionId, BOOL bWait); +BOOL WINAPI FreeRDP_WTSLogoffSession(HANDLE hServer, DWORD SessionId, BOOL bWait); +BOOL WINAPI FreeRDP_WTSShutdownSystem(HANDLE hServer, DWORD ShutdownFlag); +BOOL WINAPI FreeRDP_WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags); +HANDLE WINAPI FreeRDP_WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName); +HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags); +BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle); +BOOL WINAPI FreeRDP_WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead); +BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten); +BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeInput(HANDLE hChannelHandle); +BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle); +BOOL WINAPI FreeRDP_WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned); +VOID WINAPI FreeRDP_WTSFreeMemory(PVOID pMemory); +BOOL WINAPI FreeRDP_WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries); +BOOL WINAPI FreeRDP_WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries); +BOOL WINAPI FreeRDP_WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags); +BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotification(HWND hWnd); +BOOL WINAPI FreeRDP_WTSRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd, DWORD dwFlags); +BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd); +BOOL WINAPI FreeRDP_WTSQueryUserToken(ULONG SessionId, PHANDLE phToken); +BOOL WINAPI FreeRDP_WTSEnumerateProcessesExW(HANDLE hServer, DWORD* pLevel, DWORD SessionId, LPWSTR* ppProcessInfo, DWORD* pCount); +BOOL WINAPI FreeRDP_WTSEnumerateProcessesExA(HANDLE hServer, DWORD* pLevel, DWORD SessionId, LPSTR* ppProcessInfo, DWORD* pCount); +BOOL WINAPI FreeRDP_WTSEnumerateListenersW(HANDLE hServer, PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEW pListeners, DWORD* pCount); +BOOL WINAPI FreeRDP_WTSEnumerateListenersA(HANDLE hServer, PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEA pListeners, DWORD* pCount); +BOOL WINAPI FreeRDP_WTSQueryListenerConfigW(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer); +BOOL WINAPI FreeRDP_WTSQueryListenerConfigA(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer); +BOOL WINAPI FreeRDP_WTSCreateListenerW(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer, DWORD flag); +BOOL WINAPI FreeRDP_WTSCreateListenerA(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer, DWORD flag); +BOOL WINAPI FreeRDP_WTSSetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPWSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor); +BOOL WINAPI FreeRDP_WTSSetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor); +BOOL WINAPI FreeRDP_WTSGetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPWSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded); +BOOL WINAPI FreeRDP_WTSGetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded); + +BOOL CDECL FreeRDP_WTSEnableChildSessions(BOOL bEnable); +BOOL CDECL FreeRDP_WTSIsChildSessionsEnabled(PBOOL pbEnabled); +BOOL CDECL FreeRDP_WTSGetChildSessionId(PULONG pSessionId); + +DWORD WINAPI FreeRDP_WTSGetActiveConsoleSessionId(void); + +#endif /* FREERDP_CORE_SERVER_H */ diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c index b9ad028c8..38e7e27d5 100644 --- a/libfreerdp/core/settings.c +++ b/libfreerdp/core/settings.c @@ -234,6 +234,7 @@ rdpSettings* freerdp_settings_new(DWORD flags) settings->DisableEncryption = FALSE; settings->SaltedChecksum = TRUE; settings->ServerPort = 3389; + settings->GatewayPort = 443; settings->DesktopResize = TRUE; settings->ToggleFullscreen = TRUE; settings->DesktopPosX = 0; @@ -257,8 +258,8 @@ rdpSettings* freerdp_settings_new(DWORD flags) settings->ChannelCount = 0; settings->ChannelDefArraySize = 32; - settings->ChannelDefArray = (rdpChannel*) malloc(sizeof(rdpChannel) * settings->ChannelDefArraySize); - ZeroMemory(settings->ChannelDefArray, sizeof(rdpChannel) * settings->ChannelDefArraySize); + settings->ChannelDefArray = (CHANNEL_DEF*) malloc(sizeof(CHANNEL_DEF) * settings->ChannelDefArraySize); + ZeroMemory(settings->ChannelDefArray, sizeof(CHANNEL_DEF) * settings->ChannelDefArraySize); settings->MonitorCount = 0; settings->MonitorDefArraySize = 32; @@ -386,7 +387,7 @@ rdpSettings* freerdp_settings_new(DWORD flags) settings->FrameAcknowledge = 2; settings->MouseMotion = TRUE; - settings->AutoReconnectionEnabled = TRUE; + settings->AutoReconnectionEnabled = FALSE; settings->AutoReconnectMaxRetries = 20; settings->ClientAutoReconnectCookie = (ARC_CS_PRIVATE_PACKET*) malloc(sizeof(ARC_CS_PRIVATE_PACKET)); @@ -425,7 +426,7 @@ rdpSettings* freerdp_settings_new(DWORD flags) rdpSettings* freerdp_settings_clone(rdpSettings* settings) { - int index; + UINT32 index; rdpSettings* _settings; _settings = (rdpSettings*) malloc(sizeof(rdpSettings)); @@ -452,6 +453,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings) _settings->ClientAddress = _strdup(settings->ClientAddress); /* 769 */ _settings->ClientDir = _strdup(settings->ClientDir); /* 770 */ _settings->DynamicDSTTimeZoneKeyName = _strdup(settings->DynamicDSTTimeZoneKeyName); /* 897 */ + _settings->AuthenticationServiceClass = _strdup(settings->AuthenticationServiceClass); /* 1098 */ _settings->PreconnectionBlob = _strdup(settings->PreconnectionBlob); /* 1155 */ _settings->KerberosKdc = _strdup(settings->KerberosKdc); /* 1344 */ _settings->KerberosRealm = _strdup(settings->KerberosRealm); /* 1345 */ @@ -616,6 +618,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings) _settings->Authentication = settings->Authentication; /* 1092 */ _settings->NegotiateSecurityLayer = settings->NegotiateSecurityLayer; /* 1096 */ _settings->RestrictedAdminModeRequired = settings->RestrictedAdminModeRequired; /* 1097 */ + _settings->DisableCredentialsDelegation = settings->DisableCredentialsDelegation; /* 1099 */ _settings->MstscCookieMode = settings->MstscCookieMode; /* 1152 */ _settings->SendPreconnectionPdu = settings->SendPreconnectionPdu; /* 1156 */ _settings->IgnoreCertificate = settings->IgnoreCertificate; /* 1408 */ @@ -691,8 +694,8 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings) _settings->ChannelCount = settings->ChannelCount; _settings->ChannelDefArraySize = settings->ChannelDefArraySize; - _settings->ChannelDefArray = (rdpChannel*) malloc(sizeof(rdpChannel) * settings->ChannelDefArraySize); - CopyMemory(_settings->ChannelDefArray, settings->ChannelDefArray, sizeof(rdpChannel) * settings->ChannelDefArraySize); + _settings->ChannelDefArray = (CHANNEL_DEF*) malloc(sizeof(CHANNEL_DEF) * settings->ChannelDefArraySize); + CopyMemory(_settings->ChannelDefArray, settings->ChannelDefArray, sizeof(CHANNEL_DEF) * settings->ChannelDefArraySize); _settings->MonitorCount = settings->MonitorCount; _settings->MonitorDefArraySize = settings->MonitorDefArraySize; @@ -819,6 +822,7 @@ void freerdp_settings_free(rdpSettings* settings) free(settings->RedirectionDomain); free(settings->RedirectionPassword); free(settings->RedirectionTsvUrl); + free(settings->AuthenticationServiceClass); freerdp_target_net_addresses_free(settings); freerdp_device_collection_free(settings); freerdp_static_channel_collection_free(settings); diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index 567fc169e..f0fe28d50 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -29,10 +29,10 @@ #include #include #include +#include #include #include -#include #include #include @@ -292,8 +292,16 @@ BOOL transport_connect_nla(rdpTransport* transport) return TRUE; if (!transport->credssp) + { transport->credssp = credssp_new(instance, transport, settings); + if (settings->AuthenticationServiceClass) + { + transport->credssp->ServicePrincipalName = + credssp_make_spn(settings->AuthenticationServiceClass, settings->ServerHostname); + } + } + if (credssp_authenticate(transport->credssp) < 0) { if (!connectErrorCode) @@ -365,10 +373,10 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por transport->layer = TRANSPORT_LAYER_TSG; transport->TcpOut = tcp_new(settings); - status = tcp_connect(transport->TcpIn, settings->GatewayHostname, 443); + status = tcp_connect(transport->TcpIn, settings->GatewayHostname, settings->GatewayPort); if (status) - status = tcp_connect(transport->TcpOut, settings->GatewayHostname, 443); + status = tcp_connect(transport->TcpOut, settings->GatewayHostname, settings->GatewayPort); if (status) status = transport_tsg_connect(transport, hostname, port); diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c index 97e5fa789..b322fe753 100644 --- a/libfreerdp/core/update.c +++ b/libfreerdp/core/update.c @@ -749,7 +749,7 @@ static void update_send_refresh_rect(rdpContext* context, BYTE count, RECTANGLE_ s = rdp_data_pdu_init(rdp); update_write_refresh_rect(s, count, areas); - rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_REFRESH_RECT, rdp->mcs->user_id); + rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_REFRESH_RECT, rdp->mcs->userId); Stream_Release(s); } } @@ -778,7 +778,7 @@ static void update_send_suppress_output(rdpContext* context, BYTE allow, RECTANG s = rdp_data_pdu_init(rdp); update_write_suppress_output(s, allow, area); - rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SUPPRESS_OUTPUT, rdp->mcs->user_id); + rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SUPPRESS_OUTPUT, rdp->mcs->userId); Stream_Release(s); } } @@ -838,7 +838,7 @@ static void update_send_frame_acknowledge(rdpContext* context, UINT32 frameId) { s = rdp_data_pdu_init(rdp); Stream_Write_UINT32(s, frameId); - rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FRAME_ACKNOWLEDGE, rdp->mcs->user_id); + rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FRAME_ACKNOWLEDGE, rdp->mcs->userId); Stream_Release(s); } } @@ -1460,7 +1460,7 @@ BOOL update_read_refresh_rect(rdpUpdate* update, wStream* s) Stream_Read_UINT8(s, numberOfAreas); Stream_Seek(s, 3); /* pad3Octects */ - if (Stream_GetRemainingLength(s) < numberOfAreas * 4 * 2) + if (Stream_GetRemainingLength(s) < ((size_t) numberOfAreas * 4 * 2)) return FALSE; areas = (RECTANGLE_16*) malloc(sizeof(RECTANGLE_16) * numberOfAreas); diff --git a/libfreerdp/crypto/ber.c b/libfreerdp/crypto/ber.c index 38d98f411..74ce23190 100644 --- a/libfreerdp/crypto/ber.c +++ b/libfreerdp/crypto/ber.c @@ -369,7 +369,7 @@ BOOL ber_read_integer(wStream* s, UINT32* value) if (!ber_read_universal_tag(s, BER_TAG_INTEGER, FALSE) || !ber_read_length(s, &length) || - Stream_GetRemainingLength(s) < length) + ((int) Stream_GetRemainingLength(s)) < length) return FALSE; if (value == NULL) diff --git a/libfreerdp/crypto/per.c b/libfreerdp/crypto/per.c index ab6a409ad..788266860 100644 --- a/libfreerdp/crypto/per.c +++ b/libfreerdp/crypto/per.c @@ -160,7 +160,7 @@ void per_write_number_of_sets(wStream* s, BYTE number) BOOL per_read_padding(wStream* s, int length) { - if (Stream_GetRemainingLength(s) < length) + if (((int) Stream_GetRemainingLength(s)) < length) return FALSE; Stream_Seek(s, length); @@ -399,7 +399,7 @@ BOOL per_read_octet_string(wStream* s, BYTE* oct_str, int length, int min) if (mlength + min != length) return FALSE; - if (Stream_GetRemainingLength(s) < length) + if (((int) Stream_GetRemainingLength(s)) < length) return FALSE; a_oct_str = Stream_Pointer(s); @@ -453,7 +453,7 @@ BOOL per_read_numeric_string(wStream* s, int min) length = (mlength + min + 1) / 2; - if (Stream_GetRemainingLength(s) < length) + if (((int) Stream_GetRemainingLength(s)) < length) return FALSE; Stream_Seek(s, length); diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index 4fe93ee94..d2168b39e 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -594,10 +594,11 @@ BOOL tls_match_hostname(char *pattern, int pattern_length, char *hostname) return TRUE; } - if (pattern_length > 2 && pattern[0] == '*' && pattern[1] == '.' && strlen(hostname) >= pattern_length) + if ((pattern_length > 2) && (pattern[0] == '*') && (pattern[1] == '.') && (((int) strlen(hostname)) >= pattern_length)) { - char *check_hostname = &hostname[ strlen(hostname) - pattern_length+1 ]; - if (memcmp((void*) check_hostname, (void*) &pattern[1], pattern_length - 1) == 0 ) + char* check_hostname = &hostname[strlen(hostname) - pattern_length + 1]; + + if (memcmp((void*) check_hostname, (void*) &pattern[1], pattern_length - 1) == 0) { return TRUE; } @@ -865,8 +866,7 @@ void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name int index; assert(NULL != hostname); - assert(NULL != common_name); - + fprintf(stderr, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); fprintf(stderr, "@ WARNING: CERTIFICATE NAME MISMATCH! @\n"); fprintf(stderr, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); @@ -874,17 +874,14 @@ void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name fprintf(stderr, "does not match %s given in the certificate:\n", alt_names_count < 1 ? "the name" : "any of the names"); fprintf(stderr, "Common Name (CN):\n"); fprintf(stderr, "\t%s\n", common_name ? common_name : "no CN found in certificate"); - if (alt_names_count > 1) + if (alt_names_count > 0) { assert(NULL != alt_names); fprintf(stderr, "Alternative names:\n"); - if (alt_names_count > 1) + for (index = 0; index < alt_names_count; index++) { - for (index = 0; index < alt_names_count; index++) - { - assert(alt_names[index]); - fprintf(stderr, "\t %s\n", alt_names[index]); - } + assert(alt_names[index]); + fprintf(stderr, "\t %s\n", alt_names[index]); } } fprintf(stderr, "A valid certificate for the wrong name should NOT be trusted!\n"); diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c index baa503edb..2bc0091b4 100644 --- a/libfreerdp/gdi/gdi.c +++ b/libfreerdp/gdi/gdi.c @@ -313,7 +313,8 @@ static const UINT32 rop3_code_table[] = }; /* Hatch Patterns as monochrome data */ -static BYTE GDI_BS_HACHTED_PATTERNS[] = { +static BYTE GDI_BS_HATCHED_PATTERNS[] = +{ 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, /* HS_HORIZONTAL */ 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, /* HS_VERTICAL */ 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F, /* HS_FDIAGONAL */ @@ -437,7 +438,7 @@ gdiBitmap* gdi_bitmap_new_ex(rdpGdi* gdi, int width, int height, int bpp, BYTE* void gdi_bitmap_free_ex(gdiBitmap* bitmap) { - if (bitmap != NULL) + if (bitmap) { gdi_SelectObject(bitmap->hdc, (HGDIOBJECT) bitmap->org_bitmap); gdi_DeleteObject((HGDIOBJECT) bitmap->bitmap); @@ -456,7 +457,7 @@ void gdi_set_bounds(rdpContext* context, rdpBounds* bounds) { rdpGdi* gdi = context->gdi; - if (bounds != NULL) + if (bounds) { gdi_SetClipRgn(gdi->drawing->hdc, bounds->left, bounds->top, bounds->right - bounds->left + 1, bounds->bottom - bounds->top + 1); @@ -479,18 +480,24 @@ void gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { BYTE* data; rdpBrush* brush; + UINT32 foreColor; + UINT32 backColor; + GDI_COLOR originalColor; HGDI_BRUSH originalBrush; rdpGdi* gdi = context->gdi; brush = &patblt->brush; + foreColor = freerdp_color_convert_rgb(patblt->foreColor, gdi->srcBpp, 24, gdi->clrconv); + backColor = freerdp_color_convert_rgb(patblt->backColor, gdi->srcBpp, 24, gdi->clrconv); + + originalColor = gdi_SetTextColor(gdi->drawing->hdc, foreColor); + if (brush->style == GDI_BS_SOLID) { - UINT32 color; originalBrush = gdi->drawing->hdc->brush; - color = freerdp_color_convert_rgb(patblt->foreColor, gdi->srcBpp, 32, gdi->clrconv); - gdi->drawing->hdc->brush = gdi_CreateSolidBrush(color); + gdi->drawing->hdc->brush = gdi_CreateSolidBrush(foreColor); gdi_PatBlt(gdi->drawing->hdc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight, gdi_rop3_code(patblt->bRop)); @@ -502,7 +509,7 @@ void gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { HGDI_BITMAP hBmp; - data = freerdp_mono_image_convert(GDI_BS_HACHTED_PATTERNS + 8 * brush->hatch, 8, 8, 1, + data = freerdp_mono_image_convert(GDI_BS_HATCHED_PATTERNS + 8 * brush->hatch, 8, 8, 1, gdi->dstBpp, patblt->backColor, patblt->foreColor, gdi->clrconv); hBmp = gdi_CreateBitmap(8, 8, gdi->drawing->hdc->bitsPerPixel, data); @@ -545,6 +552,8 @@ void gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { fprintf(stderr, "unimplemented brush style:%d\n", brush->style); } + + gdi_SetTextColor(gdi->drawing->hdc, originalColor); } void gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt) @@ -561,7 +570,7 @@ void gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect) GDI_RECT rect; HGDI_BRUSH hBrush; UINT32 brush_color; - rdpGdi *gdi = context->gdi; + rdpGdi* gdi = context->gdi; gdi_CRgnToRect(opaque_rect->nLeftRect, opaque_rect->nTopRect, opaque_rect->nWidth, opaque_rect->nHeight, &rect); @@ -581,7 +590,7 @@ void gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* multi_o HGDI_BRUSH hBrush; UINT32 brush_color; DELTA_RECT* rectangle; - rdpGdi *gdi = context->gdi; + rdpGdi* gdi = context->gdi; for (i = 1; i < (int) multi_opaque_rect->numRectangles + 1; i++) { @@ -599,19 +608,19 @@ void gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* multi_o } } -void gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to) +void gdi_line_to(rdpContext* context, LINE_TO_ORDER* lineTo) { UINT32 color; HGDI_PEN hPen; - rdpGdi *gdi = context->gdi; + rdpGdi* gdi = context->gdi; - color = freerdp_color_convert_rgb(line_to->penColor, gdi->srcBpp, 32, gdi->clrconv); - hPen = gdi_CreatePen(line_to->penStyle, line_to->penWidth, (GDI_COLOR) color); + color = freerdp_color_convert_rgb(lineTo->penColor, gdi->srcBpp, 32, gdi->clrconv); + hPen = gdi_CreatePen(lineTo->penStyle, lineTo->penWidth, (GDI_COLOR) color); gdi_SelectObject(gdi->drawing->hdc, (HGDIOBJECT) hPen); - gdi_SetROP2(gdi->drawing->hdc, line_to->bRop2); + gdi_SetROP2(gdi->drawing->hdc, lineTo->bRop2); - gdi_MoveToEx(gdi->drawing->hdc, line_to->nXStart, line_to->nYStart, NULL); - gdi_LineTo(gdi->drawing->hdc, line_to->nXEnd, line_to->nYEnd); + gdi_MoveToEx(gdi->drawing->hdc, lineTo->nXStart, lineTo->nYStart, NULL); + gdi_LineTo(gdi->drawing->hdc, lineTo->nXEnd, lineTo->nYEnd); gdi_DeleteObject((HGDIOBJECT) hPen); } @@ -619,12 +628,12 @@ void gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to) void gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline) { int i; + INT32 x; + INT32 y; UINT32 color; HGDI_PEN hPen; DELTA_POINT* points; rdpGdi* gdi = context->gdi; - INT32 x; - INT32 y; color = freerdp_color_convert_rgb(polyline->penColor, gdi->srcBpp, 32, gdi->clrconv); hPen = gdi_CreatePen(GDI_PS_SOLID, 1, (GDI_COLOR) color); @@ -666,14 +675,17 @@ void gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt) UINT32 foreColor; UINT32 backColor; gdiBitmap* bitmap; + GDI_COLOR originalColor; HGDI_BRUSH originalBrush; rdpGdi* gdi = context->gdi; brush = &mem3blt->brush; bitmap = (gdiBitmap*) mem3blt->bitmap; - foreColor = freerdp_color_convert_rgb(mem3blt->foreColor, gdi->srcBpp, 32, gdi->clrconv); - backColor = freerdp_color_convert_rgb(mem3blt->backColor, gdi->srcBpp, 32, gdi->clrconv); + foreColor = freerdp_color_convert_rgb(mem3blt->foreColor, gdi->srcBpp, 24, gdi->clrconv); + backColor = freerdp_color_convert_rgb(mem3blt->backColor, gdi->srcBpp, 24, gdi->clrconv); + + originalColor = gdi_SetTextColor(gdi->drawing->hdc, foreColor); if (brush->style == GDI_BS_SOLID) { @@ -717,6 +729,8 @@ void gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt) { fprintf(stderr, "Mem3Blt unimplemented brush style:%d\n", brush->style); } + + gdi_SetTextColor(gdi->drawing->hdc, originalColor); } void gdi_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc) diff --git a/libfreerdp/gdi/graphics.c b/libfreerdp/gdi/graphics.c index 2be36a50a..084c1b17c 100644 --- a/libfreerdp/gdi/graphics.c +++ b/libfreerdp/gdi/graphics.c @@ -96,36 +96,37 @@ void gdi_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap) void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, BYTE* data, int width, int height, int bpp, int length, - BOOL compressed, int codec_id) + BOOL compressed, int codecId) { + BOOL status; UINT16 size; - RFX_MESSAGE* msg; BYTE* src; BYTE* dst; int yindex; int xindex; rdpGdi* gdi; - BOOL status; + RFX_MESSAGE* msg; size = width * height * ((bpp + 7) / 8); - if (bitmap->data == NULL) + if (!bitmap->data) bitmap->data = (BYTE*) malloc(size); else bitmap->data = (BYTE*) realloc(bitmap->data, size); - switch (codec_id) + switch (codecId) { case RDP_CODEC_ID_NSCODEC: gdi = context->gdi; nsc_process_message(gdi->nsc_context, bpp, width, height, data, length); - freerdp_image_flip(((NSC_CONTEXT*)gdi->nsc_context)->BitmapData, bitmap->data, width, height, bpp); + freerdp_image_flip(((NSC_CONTEXT*) gdi->nsc_context)->BitmapData, bitmap->data, width, height, bpp); break; + case RDP_CODEC_ID_REMOTEFX: gdi = context->gdi; rfx_context_set_pixel_format(gdi->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8); msg = rfx_process_message(gdi->rfx_context, data, length); - if (msg == NULL) + if (!msg) { fprintf(stderr, "gdi_Bitmap_Decompress: rfx Decompression Failed\n"); } @@ -159,7 +160,7 @@ void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, { status = bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp); - if (status == FALSE) + if (!status) { fprintf(stderr, "gdi_Bitmap_Decompress: Bitmap Decompression Failed\n"); } @@ -268,8 +269,11 @@ void gdi_register_graphics(rdpGraphics* graphics) rdpBitmap* bitmap; rdpGlyph* glyph; - bitmap = (rdpBitmap*) malloc(sizeof(rdpBitmap)); - ZeroMemory(bitmap, sizeof(rdpBitmap)); + bitmap = (rdpBitmap*) calloc(1, sizeof(rdpBitmap)); + + if (!bitmap) + return; + bitmap->size = sizeof(gdiBitmap); bitmap->New = gdi_Bitmap_New; @@ -281,8 +285,11 @@ void gdi_register_graphics(rdpGraphics* graphics) graphics_register_bitmap(graphics, bitmap); free(bitmap); - glyph = (rdpGlyph*) malloc(sizeof(rdpGlyph)); - ZeroMemory(glyph, sizeof(rdpGlyph)); + glyph = (rdpGlyph*) calloc(1, sizeof(rdpGlyph)); + + if (!glyph) + return; + glyph->size = sizeof(gdiGlyph); glyph->New = gdi_Glyph_New; diff --git a/libfreerdp/gdi/include/line.c b/libfreerdp/gdi/include/line.c index d8a56b7ea..8088d797d 100644 --- a/libfreerdp/gdi/include/line.c +++ b/libfreerdp/gdi/include/line.c @@ -70,6 +70,8 @@ int LINE_TO(HGDI_DC hdc, int nXEnd, int nYEnd) by1 = MAX(by1, 0); bx2 = MIN(bx2, bmp->width - 1); by2 = MIN(by2, bmp->height - 1); + + gdi_InvalidateRegion(hdc, bx1, by1, bx2 - bx1 + 1, by2 - by1 + 1); pen = GDI_GET_PEN_COLOR(hdc->pen); diff --git a/libfreerdp/gdi/test/TestGdiBitBlt.c b/libfreerdp/gdi/test/TestGdiBitBlt.c index b164bc61f..1738a1164 100644 --- a/libfreerdp/gdi/test/TestGdiBitBlt.c +++ b/libfreerdp/gdi/test/TestGdiBitBlt.c @@ -407,6 +407,7 @@ BYTE bmp_PATINVERT[256] = int CompareBitmaps(HGDI_BITMAP hBmp1, HGDI_BITMAP hBmp2) { + int bpp; int x, y; BYTE *p1, *p2; @@ -417,7 +418,7 @@ int CompareBitmaps(HGDI_BITMAP hBmp1, HGDI_BITMAP hBmp2) { p1 = hBmp1->data; p2 = hBmp2->data; - int bpp = hBmp1->bitsPerPixel; + bpp = hBmp1->bitsPerPixel; if (bpp == 32) { diff --git a/libfreerdp/utils/stopwatch.c b/libfreerdp/utils/stopwatch.c index fb1c5c161..a45ee9a73 100644 --- a/libfreerdp/utils/stopwatch.c +++ b/libfreerdp/utils/stopwatch.c @@ -92,7 +92,7 @@ double stopwatch_get_elapsed_time_in_seconds(STOPWATCH* stopwatch) void stopwatch_get_elapsed_time_in_useconds(STOPWATCH* stopwatch, UINT32* sec, UINT32* usec) { - *sec = stopwatch->elapsed / 1000000; - *usec = stopwatch->elapsed % 1000000; + *sec = (UINT32) stopwatch->elapsed / 1000000; + *usec = (UINT32) stopwatch->elapsed % 1000000; } diff --git a/libfreerdp/utils/svc_plugin.c b/libfreerdp/utils/svc_plugin.c index 884b6c237..b6411025f 100644 --- a/libfreerdp/utils/svc_plugin.c +++ b/libfreerdp/utils/svc_plugin.c @@ -132,7 +132,7 @@ static void svc_plugin_process_event(rdpSvcPlugin* plugin, wMessage* event_in) MessageQueue_Post(plugin->MsgPipe->In, NULL, 1, (void*) event_in, NULL); } -static void svc_plugin_open_event(UINT32 openHandle, UINT32 event, void* pData, UINT32 dataLength, +static VOID VCAPITYPE svc_plugin_open_event(DWORD openHandle, UINT event, LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { rdpSvcPlugin* plugin; @@ -207,7 +207,7 @@ static void* svc_plugin_thread_func(void* arg) return 0; } -static void svc_plugin_process_connected(rdpSvcPlugin* plugin, void* pData, UINT32 dataLength) +static void svc_plugin_process_connected(rdpSvcPlugin* plugin, LPVOID pData, UINT32 dataLength) { UINT32 status; @@ -249,7 +249,7 @@ static void svc_plugin_process_terminated(rdpSvcPlugin* plugin) svc_plugin_remove_init_handle_data(plugin->InitHandle); } -static void svc_plugin_init_event(void* pInitHandle, UINT32 event, void* pData, UINT32 dataLength) +static VOID VCAPITYPE svc_plugin_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength) { rdpSvcPlugin* plugin; @@ -285,7 +285,7 @@ void svc_plugin_init(rdpSvcPlugin* plugin, CHANNEL_ENTRY_POINTS* pEntryPoints) * VirtualChannelInit at a time. So this should be safe. */ - CopyMemory(&(plugin->channel_entry_points), pEntryPoints, pEntryPoints->cbSize); + CopyMemory(&(plugin->channel_entry_points), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP)); plugin->channel_entry_points.pVirtualChannelInit(&(plugin->InitHandle), &(plugin->channel_def), 1, VIRTUAL_CHANNEL_VERSION_WIN2000, svc_plugin_init_event); diff --git a/server/Mac/mf_interface.h b/server/Mac/mf_interface.h index a59951f4f..80c10172f 100644 --- a/server/Mac/mf_interface.h +++ b/server/Mac/mf_interface.h @@ -59,7 +59,7 @@ struct mf_peer_context NSC_CONTEXT* nsc_context; //#ifdef WITH_SERVER_CHANNELS - WTSVirtualChannelManager* vcm; + HANDLE vcm; //#endif //#ifdef CHANNEL_AUDIN_SERVER audin_server_context* audin; diff --git a/server/Mac/mf_peer.c b/server/Mac/mf_peer.c index 0d059cf49..93ab74e6e 100644 --- a/server/Mac/mf_peer.c +++ b/server/Mac/mf_peer.c @@ -186,16 +186,13 @@ int mf_peer_context_new(freerdp_peer* client, mfPeerContext* context) context->s = Stream_New(NULL, 0xFFFF); - //#ifdef WITH_SERVER_CHANNELS - context->vcm = WTSCreateVirtualChannelManager(client); - //#endif + context->vcm = WTSOpenServerA((LPSTR) client->context); mf_info_peer_register(context->info, context); return 0; } - /* Called after a peer disconnects */ void mf_peer_context_free(freerdp_peer* client, mfPeerContext* context) { @@ -221,9 +218,7 @@ void mf_peer_context_free(freerdp_peer* client, mfPeerContext* context) rdpsnd_server_context_free(context->rdpsnd); //#endif - //#ifdef WITH_SERVER_CHANNELS - WTSDestroyVirtualChannelManager(context->vcm); - //#endif + WTSCloseServer(context->vcm); } } @@ -253,7 +248,6 @@ void mf_peer_init(freerdp_peer* client) } } - BOOL mf_peer_post_connect(freerdp_peer* client) { mfPeerContext* context = (mfPeerContext*) client->context; @@ -294,25 +288,12 @@ BOOL mf_peer_post_connect(freerdp_peer* client) mfi->mouse_down_right = FALSE; mfi->mouse_down_other = FALSE; - - //#ifdef WITH_SERVER_CHANNELS - /* Iterate all channel names requested by the client and activate those supported by the server */ - int i; - for (i = 0; i < client->settings->ChannelCount; i++) + if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, "rdpsnd")) { - if (client->settings->ChannelDefArray[i].joined) - { - //#ifdef CHANNEL_RDPSND_SERVER - if (strncmp(client->settings->ChannelDefArray[i].Name, "rdpsnd", 6) == 0) - { - mf_peer_rdpsnd_init(context); /* Audio Output */ - } - //#endif - } + mf_peer_rdpsnd_init(context); /* Audio Output */ } /* Dynamic Virtual Channels */ - //#endif #ifdef CHANNEL_AUDIN_SERVER mf_peer_audin_init(context); /* Audio Input */ @@ -321,7 +302,6 @@ BOOL mf_peer_post_connect(freerdp_peer* client) return TRUE; } - BOOL mf_peer_activate(freerdp_peer* client) { mfPeerContext* context = (mfPeerContext*) client->context; @@ -332,21 +312,6 @@ BOOL mf_peer_activate(freerdp_peer* client) return TRUE; } -/*BOOL wf_peer_logon(freerdp_peer* client, SEC_WINNT_AUTH_IDENTITY* identity, BOOL automatic) - { - fprintf(stderr, "PeerLogon\n"); - - if (automatic) - { - _tprintf(_T("Logon: User:%s Domain:%s Password:%s\n"), - identity->User, identity->Domain, identity->Password); - } - - - wfreerdp_server_peer_callback_event(((rdpContext*) client->context)->peer->pId, WF_SRV_CALLBACK_EVENT_AUTH); - return TRUE; - }*/ - void mf_peer_synchronize_event(rdpInput* input, UINT32 flags) { fprintf(stderr, "Client sent a synchronize event (flags:0x%08X)\n", flags); @@ -421,70 +386,6 @@ void mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client) pthread_detach(th); } -/*DWORD WINAPI wf_peer_socket_listener(LPVOID lpParam) - { - int i, fds; - int rcount; - int max_fds; - void* rfds[32]; - fd_set rfds_set; - wfPeerContext* context; - freerdp_peer* client = (freerdp_peer*) lpParam; - - ZeroMemory(rfds, sizeof(rfds)); - context = (wfPeerContext*) client->context; - - fprintf(stderr, "PeerSocketListener\n"); - - while (1) - { - rcount = 0; - - if (client->GetFileDescriptor(client, rfds, &rcount) != TRUE) - { - fprintf(stderr, "Failed to get peer file descriptor\n"); - break; - } - - max_fds = 0; - FD_ZERO(&rfds_set); - - for (i = 0; i < rcount; i++) - { - fds = (int)(long)(rfds[i]); - - if (fds > max_fds) - max_fds = fds; - - FD_SET(fds, &rfds_set); - } - - if (max_fds == 0) - break; - - select(max_fds + 1, &rfds_set, NULL, NULL, NULL); - - SetEvent(context->socketEvent); - WaitForSingleObject(context->socketSemaphore, INFINITE); - - if (context->socketClose) - break; - } - - fprintf(stderr, "Exiting Peer Socket Listener Thread\n"); - - return 0; - } - - void wf_peer_read_settings(freerdp_peer* client) - { - if (!wf_settings_read_string_ascii(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), _T("CertificateFile"), &(client->settings->CertificateFile))) - client->settings->CertificateFile = _strdup("server.crt"); - - if (!wf_settings_read_string_ascii(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), _T("PrivateKeyFile"), &(client->settings->PrivateKeyFile))) - client->settings->PrivateKeyFile = _strdup("server.key"); - }*/ - void* mf_peer_main_loop(void* arg) { int i; @@ -541,9 +442,7 @@ void* mf_peer_main_loop(void* arg) break; } - //#ifdef WITH_SERVER_CHANNELS WTSVirtualChannelManagerGetFileDescriptor(context->vcm, rfds, &rcount); - //#endif max_fds = 0; FD_ZERO(&rfds_set); @@ -579,18 +478,17 @@ void* mf_peer_main_loop(void* arg) fprintf(stderr, "Failed to check freerdp file descriptor\n"); break; } + if ((mf_peer_check_fds(client)) != TRUE) { fprintf(stderr, "Failed to check mfreerdp file descriptor\n"); break; } - - //#ifdef WITH_SERVER_CHANNELS if (WTSVirtualChannelManagerCheckFileDescriptor(context->vcm) != TRUE) + { break; - //#endif - + } } fprintf(stderr, "Client %s disconnected.\n", client->local ? "(local)" : client->hostname); diff --git a/server/Mac/mfreerdp.c b/server/Mac/mfreerdp.c index e1679d36a..2ac3122a2 100644 --- a/server/Mac/mfreerdp.c +++ b/server/Mac/mfreerdp.c @@ -33,10 +33,12 @@ #include #include +#include +#include #include -//#include -//#include +#include +#include #include "mfreerdp.h" #include "mf_peer.h" @@ -107,6 +109,8 @@ int main(int argc, char* argv[]) signal(SIGPIPE, SIG_IGN); + WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi()); + instance = freerdp_listener_new(); instance->PeerAccepted = mf_peer_accepted; diff --git a/server/Sample/sfreerdp.c b/server/Sample/sfreerdp.c index c98d4e05e..7948db0f9 100644 --- a/server/Sample/sfreerdp.c +++ b/server/Sample/sfreerdp.c @@ -63,7 +63,7 @@ void test_peer_context_new(freerdp_peer* client, testPeerContext* context) context->icon_x = -1; context->icon_y = -1; - context->vcm = WTSCreateVirtualChannelManager(client); + context->vcm = WTSOpenServerA((LPSTR) client->context); } void test_peer_context_free(freerdp_peer* client, testPeerContext* context) @@ -93,7 +93,7 @@ void test_peer_context_free(freerdp_peer* client, testPeerContext* context) if (context->rdpsnd) rdpsnd_server_context_free(context->rdpsnd); - WTSDestroyVirtualChannelManager(context->vcm); + WTSCloseServer((HANDLE) context->vcm); } } @@ -490,33 +490,26 @@ BOOL tf_peer_post_connect(freerdp_peer* client) /* A real server should tag the peer as activated here and start sending updates in main loop. */ test_peer_load_icon(client); - /* Iterate all channel names requested by the client and activate those supported by the server */ - - for (i = 0; i < client->settings->ChannelCount; i++) + if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, "rdpdbg")) { - if (client->settings->ChannelDefArray[i].joined) + context->debug_channel = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpdbg", 0); + + if (context->debug_channel != NULL) { - if (strncmp(client->settings->ChannelDefArray[i].Name, "rdpdbg", 6) == 0) - { - context->debug_channel = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpdbg", 0); + printf("Open channel rdpdbg.\n"); - if (context->debug_channel != NULL) - { - printf("Open channel rdpdbg.\n"); + context->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - context->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - - context->debug_channel_thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) tf_debug_channel_thread_func, (void*) context, 0, NULL); - } - } - else if (strncmp(client->settings->ChannelDefArray[i].Name, "rdpsnd", 6) == 0) - { - sf_peer_rdpsnd_init(context); /* Audio Output */ - } + context->debug_channel_thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) tf_debug_channel_thread_func, (void*) context, 0, NULL); } } + if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, "rdpsnd")) + { + sf_peer_rdpsnd_init(context); /* Audio Output */ + } + /* Dynamic Virtual Channels */ sf_peer_audin_init(context); /* Audio Input */ diff --git a/server/Windows/cli/wfreerdp.c b/server/Windows/cli/wfreerdp.c index 43e4e3ef1..0e28c4398 100644 --- a/server/Windows/cli/wfreerdp.c +++ b/server/Windows/cli/wfreerdp.c @@ -36,14 +36,9 @@ int IDcount = 0; BOOL CALLBACK moncb(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { - printf("%d\t(%d, %d), (%d, %d)\n", - IDcount, - lprcMonitor->left, - lprcMonitor->top, - lprcMonitor->right, - lprcMonitor->bottom); - + IDcount, lprcMonitor->left, lprcMonitor->top, + lprcMonitor->right, lprcMonitor->bottom); IDcount++; @@ -121,7 +116,6 @@ int main(int argc, char* argv[]) index++; } - if (index == argc - 1) { server->port = (DWORD) atoi(argv[index]); @@ -160,7 +154,6 @@ int main(int argc, char* argv[]) } } - printf("Starting server\n"); wfreerdp_server_start(server); diff --git a/server/Windows/wf_info.c b/server/Windows/wf_info.c index 57c03e8bf..c49d352df 100644 --- a/server/Windows/wf_info.c +++ b/server/Windows/wf_info.c @@ -88,7 +88,6 @@ int wf_info_try_lock(wfInfo* wfi, DWORD dwMilliseconds) int wf_info_unlock(wfInfo* wfi) { - if (ReleaseMutex(wfi->mutex) == 0) { printf("wf_info_unlock failed with 0x%08X\n", GetLastError()); @@ -102,12 +101,6 @@ wfInfo* wf_info_init() { wfInfo* wfi; - /* - OSVERSIONINFOEX osvi; - SYSTEM_INFO si; - BOOL bOsVersionInfoEx; - */ - wfi = (wfInfo*) malloc(sizeof(wfInfo)); ZeroMemory(wfi, sizeof(wfInfo)); @@ -126,9 +119,6 @@ wfInfo* wf_info_init() _tprintf(_T("CreateMutex error: %d\n"), GetLastError()); } - //wfi->updateEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - //printf("updateEvent created\n"); - wfi->updateSemaphore = CreateSemaphore(NULL, 0, 32, NULL); wfi->updateThread = CreateThread(NULL, 0, wf_update_thread, wfi, CREATE_SUSPENDED, NULL); @@ -165,29 +155,6 @@ wfInfo* wf_info_init() } } RegCloseKey(hKey); - - //detect windows version - /* - ZeroMemory(&si, sizeof(SYSTEM_INFO)); - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*) &osvi); - - wfi->win8 = FALSE; - if(bOsVersionInfoEx != 0 ) - { - if ( VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && - osvi.dwMajorVersion > 4 ) - { - if ( osvi.dwMajorVersion == 6 && - osvi.dwMinorVersion == 2) - { - wfi->win8 = TRUE; - } - } - } - */ } return wfi; diff --git a/server/Windows/wf_interface.c b/server/Windows/wf_interface.c index 724f74c2a..ea0e98d46 100644 --- a/server/Windows/wf_interface.c +++ b/server/Windows/wf_interface.c @@ -22,11 +22,15 @@ #include "config.h" #endif - #include #include + +#include +#include +#include #include -#include +#include +#include #include "wf_peer.h" #include "wf_settings.h" @@ -180,6 +184,8 @@ wfServer* wfreerdp_server_new() server->port = 3389; } + WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi()); + cbEvent = NULL; return server; @@ -229,7 +235,6 @@ FREERDP_API UINT32 wfreerdp_server_get_peer_hostname(int pId, wchar_t * dstStr) wfi = wf_info_get_instance(); peer = wfi->peers[pId]; - if (peer) { UINT32 sLen; @@ -243,7 +248,6 @@ FREERDP_API UINT32 wfreerdp_server_get_peer_hostname(int pId, wchar_t * dstStr) printf("nonexistent peer id=%d\n", pId); return 0; } - } FREERDP_API BOOL wfreerdp_server_peer_is_local(int pId) @@ -254,7 +258,6 @@ FREERDP_API BOOL wfreerdp_server_peer_is_local(int pId) wfi = wf_info_get_instance(); peer = wfi->peers[pId]; - if (peer) { return peer->local; @@ -264,6 +267,7 @@ FREERDP_API BOOL wfreerdp_server_peer_is_local(int pId) return FALSE; } } + FREERDP_API BOOL wfreerdp_server_peer_is_connected(int pId) { wfInfo* wfi; @@ -290,7 +294,6 @@ FREERDP_API BOOL wfreerdp_server_peer_is_activated(int pId) wfi = wf_info_get_instance(); peer = wfi->peers[pId]; - if (peer) { @@ -310,7 +313,6 @@ FREERDP_API BOOL wfreerdp_server_peer_is_authenticated(int pId) wfi = wf_info_get_instance(); peer = wfi->peers[pId]; - if (peer) { return peer->authenticated; diff --git a/server/Windows/wf_interface.h b/server/Windows/wf_interface.h index 4108448b9..dc3af1c7f 100644 --- a/server/Windows/wf_interface.h +++ b/server/Windows/wf_interface.h @@ -99,7 +99,7 @@ struct wf_peer_context HANDLE socketThread; HANDLE socketSemaphore; - WTSVirtualChannelManager* vcm; + HANDLE vcm; RdpsndServerContext* rdpsnd; }; diff --git a/server/Windows/wf_peer.c b/server/Windows/wf_peer.c index f06ea3ec0..e214a007d 100644 --- a/server/Windows/wf_peer.c +++ b/server/Windows/wf_peer.c @@ -23,11 +23,11 @@ #endif #include +#include #include #include #include -#include #include "wf_info.h" #include "wf_input.h" @@ -41,7 +41,7 @@ void wf_peer_context_new(freerdp_peer* client, wfPeerContext* context) { context->info = wf_info_get_instance(); - context->vcm = WTSCreateVirtualChannelManager(client); + context->vcm = WTSOpenServerA((LPSTR) client->context); wf_info_peer_register(context->info, context); } @@ -57,7 +57,7 @@ void wf_peer_context_free(freerdp_peer* client, wfPeerContext* context) wf_rdpsnd_unlock(); } - WTSDestroyVirtualChannelManager(context->vcm); + WTSCloseServer(context->vcm); } void wf_peer_init(freerdp_peer* client) @@ -79,7 +79,7 @@ BOOL wf_peer_post_connect(freerdp_peer* client) wfi = context->info; settings = client->settings; - if ( (get_screen_info(wfi->screenID, NULL, &wfi->servscreen_width, &wfi->servscreen_height, &wfi->bitsPerPixel) == 0) || + if ((get_screen_info(wfi->screenID, NULL, &wfi->servscreen_width, &wfi->servscreen_height, &wfi->bitsPerPixel) == 0) || (wfi->servscreen_width == 0) || (wfi->servscreen_height == 0) || (wfi->bitsPerPixel == 0) ) @@ -103,15 +103,9 @@ BOOL wf_peer_post_connect(freerdp_peer* client) client->update->DesktopResize(client->update->context); } - for (i = 0; i < client->settings->ChannelCount; i++) + if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, "rdpsnd")) { - if (client->settings->ChannelDefArray[i].joined) - { - if (strncmp(client->settings->ChannelDefArray[i].Name, "rdpsnd", 6) == 0) - { - wf_peer_rdpsnd_init(context); /* Audio Output */ - } - } + wf_peer_rdpsnd_init(context); /* Audio Output */ } return TRUE; @@ -260,7 +254,7 @@ DWORD WINAPI wf_peer_main_loop(LPVOID lpParam) wfi = context->info; - if (wfi->input_disabled == TRUE) + if (wfi->input_disabled) { printf("client input is disabled\n"); client->input->KeyboardEvent = wf_peer_keyboard_event_dummy; @@ -315,7 +309,7 @@ DWORD WINAPI wf_peer_main_loop(LPVOID lpParam) } //force disconnect - if(wfi->force_all_disconnect == TRUE) + if (wfi->force_all_disconnect == TRUE) { printf("Forcing Disconnect -> "); break; diff --git a/server/Windows/wf_update.c b/server/Windows/wf_update.c index 0332316be..a8488557f 100644 --- a/server/Windows/wf_update.c +++ b/server/Windows/wf_update.c @@ -108,10 +108,8 @@ DWORD WINAPI wf_update_thread(LPVOID lpParam) return 0; } - void wf_update_encode(wfInfo* wfi) { - RFX_RECT rect; long height, width; BYTE* pDataBits = NULL; @@ -135,6 +133,7 @@ void wf_update_encode(wfInfo* wfi) //printf("x:%d y:%d w:%d h:%d\n", wfi->invalid.left, wfi->invalid.top, width, height); Stream_Clear(wfi->s); + rfx_compose_message(wfi->rfx_context, wfi->s, &rect, 1, pDataBits, width, height, stride); diff --git a/server/Windows/wf_wasapi.c b/server/Windows/wf_wasapi.c index 7530ca76e..f2cb18cbc 100644 --- a/server/Windows/wf_wasapi.c +++ b/server/Windows/wf_wasapi.c @@ -33,14 +33,13 @@ int wf_rdpsnd_set_latest_peer(wfPeerContext* peer) return 0; } - int wf_wasapi_activate(RdpsndServerContext* context) { wchar_t * pattern = L"Stereo Mix"; wf_wasapi_get_device_string(pattern, &devStr); - if(devStr == NULL) + if (devStr == NULL) { _tprintf(_T("Failed to match for output device! Disabling rdpsnd.\n")); return 1; @@ -99,7 +98,6 @@ int wf_wasapi_get_device_string(LPWSTR pattern, LPWSTR * deviceStr) exit(1); } - hr = pEndpoint->lpVtbl->GetId(pEndpoint, &pwszID); if ( FAILED(hr) ) { @@ -107,8 +105,6 @@ int wf_wasapi_get_device_string(LPWSTR pattern, LPWSTR * deviceStr) exit(1); } - - hr = pEndpoint->lpVtbl->OpenPropertyStore(pEndpoint, STGM_READ, &pProps); if ( FAILED(hr) ) { @@ -116,7 +112,6 @@ int wf_wasapi_get_device_string(LPWSTR pattern, LPWSTR * deviceStr) exit(1); } - hr = pProps->lpVtbl->GetValue(pProps, &PKEY_Device_FriendlyName, &nameVar); if ( FAILED(hr) ) { @@ -158,7 +153,6 @@ int wf_wasapi_get_device_string(LPWSTR pattern, LPWSTR * deviceStr) return 0; } - DWORD WINAPI wf_rdpsnd_wasapi_thread(LPVOID lpParam) { IMMDeviceEnumerator *pEnumerator = NULL; @@ -210,7 +204,6 @@ DWORD WINAPI wf_rdpsnd_wasapi_thread(LPVOID lpParam) exit(1); } - pwfx->wFormatTag = wfi->agreed_format->wFormatTag; pwfx->nChannels = wfi->agreed_format->nChannels; pwfx->nSamplesPerSec = wfi->agreed_format->nSamplesPerSec; @@ -220,13 +213,9 @@ DWORD WINAPI wf_rdpsnd_wasapi_thread(LPVOID lpParam) pwfx->cbSize = wfi->agreed_format->cbSize; hr = pAudioClient->lpVtbl->Initialize( - pAudioClient, - AUDCLNT_SHAREMODE_SHARED, - 0, - hnsRequestedDuration, - 0, - pwfx, - NULL); + pAudioClient, AUDCLNT_SHAREMODE_SHARED, 0, + hnsRequestedDuration, 0, pwfx, NULL); + if (FAILED(hr)) { _tprintf(_T("Failed to initialize the audio client\n")); @@ -247,7 +236,6 @@ DWORD WINAPI wf_rdpsnd_wasapi_thread(LPVOID lpParam) exit(1); } - hnsActualDuration = (UINT32)REFTIMES_PER_SEC * bufferFrameCount / pwfx->nSamplesPerSec; hr = pAudioClient->lpVtbl->Start(pAudioClient); @@ -262,7 +250,6 @@ DWORD WINAPI wf_rdpsnd_wasapi_thread(LPVOID lpParam) { DWORD flags; - Sleep(hnsActualDuration/REFTIMES_PER_MILLISEC/2); hr = pCaptureClient->lpVtbl->GetNextPacketSize(pCaptureClient, &packetLength); @@ -272,7 +259,7 @@ DWORD WINAPI wf_rdpsnd_wasapi_thread(LPVOID lpParam) exit(1); } - while(packetLength != 0) + while (packetLength != 0) { hr = pCaptureClient->lpVtbl->GetBuffer(pCaptureClient, &pData, &numFramesAvailable, &flags, NULL, NULL); if (FAILED(hr)) diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt index c20a307c6..22ad623da 100644 --- a/winpr/CMakeLists.txt +++ b/winpr/CMakeLists.txt @@ -22,7 +22,7 @@ project(WinPR C) set(CMAKE_COLOR_MAKEFILE ON) if(FREERDP_VERSION) - set(FREERDP_BUILD) + set(FREERDP_BUILD 1) endif() # Include cmake modules @@ -37,12 +37,13 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/) # Check for cmake compatibility (enable/disable features) include(CheckCmakeCompat) - include(FindFeature) +include(ComplexLibrary) include(AutoVersioning) include(ConfigOptions) include(CheckCCompilerFlag) include(GNUInstallDirsWrapper) +include(CMakePackageConfigHelpers) # Soname versioning set(WINPR_VERSION_MAJOR "1") @@ -61,6 +62,8 @@ if(NOT DEFINED BUILD_SHARED_LIBS) set(BUILD_SHARED_LIBS ON) endif() +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWINPR_EXPORTS") + if(FREERDP_BUILD) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE) include_directories(${CMAKE_CURRENT_BINARY_DIR}/include PARENT_SCOPE) @@ -91,8 +94,6 @@ if(${CMAKE_VERSION} VERSION_GREATER "2.8.10") set(WINPR_INCLUDE_DIR "include") set(WINPR_MONOLITHIC_BUILD ${MONOLITHIC_BUILD}) - message(STATUS "WINPR_VERSION: ${WINPR_VERSION}") - configure_package_config_file(WinPRConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/WinPRConfig.cmake INSTALL_DESTINATION ${WINPR_CMAKE_INSTALL_DIR} PATH_VARS WINPR_INCLUDE_DIR WINPR_MONOLITHIC_BUILD) diff --git a/winpr/include/winpr/cmdline.h b/winpr/include/winpr/cmdline.h index e38f8fec4..6c5f605db 100644 --- a/winpr/include/winpr/cmdline.h +++ b/winpr/include/winpr/cmdline.h @@ -93,7 +93,7 @@ struct _COMMAND_LINE_ARGUMENT_A LPCSTR Name; DWORD Flags; LPCSTR Format; - LPSTR Default; + LPCSTR Default; LPSTR Value; LONG Index; LPCSTR Alias; diff --git a/winpr/include/winpr/collections.h b/winpr/include/winpr/collections.h index f37c4e5da..6e7568dbe 100644 --- a/winpr/include/winpr/collections.h +++ b/winpr/include/winpr/collections.h @@ -257,12 +257,15 @@ WINPR_API void LinkedList_Free(wLinkedList* list); /* System.Collections.Generic.KeyValuePair */ +typedef struct _wKeyValuePair wKeyValuePair; + struct _wKeyValuePair { void* key; void* value; + + wKeyValuePair* next; }; -typedef struct _wKeyValuePair wKeyValuePair; /* Reference Table */ @@ -315,6 +318,40 @@ WINPR_API void CountdownEvent_Reset(wCountdownEvent* countdown, DWORD count); WINPR_API wCountdownEvent* CountdownEvent_New(DWORD initialCount); WINPR_API void CountdownEvent_Free(wCountdownEvent* countdown); +/* Hash Table */ + +struct _wHashTable +{ + BOOL synchronized; + CRITICAL_SECTION lock; + + long numOfBuckets; + long numOfElements; + float idealRatio; + float lowerRehashThreshold; + float upperRehashThreshold; + wKeyValuePair** bucketArray; + int (*keycmp)(void* key1, void* key2); + int (*valuecmp)(void* value1, void* value2); + unsigned long (*hashFunction)(void* key); + void (*keyDeallocator)(void* key); + void (*valueDeallocator)(void* value); +}; +typedef struct _wHashTable wHashTable; + +WINPR_API int HashTable_Count(wHashTable* table); +WINPR_API int HashTable_Add(wHashTable* table, void* key, void* value); +WINPR_API BOOL HashTable_Remove(wHashTable* table, void* key); +WINPR_API void HashTable_Clear(wHashTable* table); +WINPR_API BOOL HashTable_Contains(wHashTable* table, void* key); +WINPR_API BOOL HashTable_ContainsKey(wHashTable* table, void* key); +WINPR_API BOOL HashTable_ContainsValue(wHashTable* table, void* value); +WINPR_API void* HashTable_GetItemValue(wHashTable* table, void* key); +WINPR_API BOOL HashTable_SetItemValue(wHashTable* table, void* key, void* value); + +WINPR_API wHashTable* HashTable_New(BOOL synchronized); +WINPR_API void HashTable_Free(wHashTable* table); + /* BufferPool */ struct _wBufferPoolItem diff --git a/winpr/include/winpr/crt.h b/winpr/include/winpr/crt.h index 70ea058e5..326b13b9a 100644 --- a/winpr/include/winpr/crt.h +++ b/winpr/include/winpr/crt.h @@ -26,24 +26,34 @@ #include +#include #include -#include - -/* Data Alignment */ +#include #ifndef _WIN32 +#define CopyMemory(Destination, Source, Length) memcpy((Destination), (Source), (Length)) +#define MoveMemory(Destination, Source, Length) memmove((Destination), (Source), (Length)) +#define FillMemory(Destination, Length, Fill) memset((Destination), (Fill), (Length)) +#define ZeroMemory(Destination, Length) memset((Destination), 0, (Length)) + +#ifdef __cplusplus +extern "C" { +#endif + +WINPR_API PVOID SecureZeroMemory(PVOID ptr, SIZE_T cnt); + +#ifdef __cplusplus +} +#endif + +/* Data Alignment */ + #ifndef _ERRNO_T_DEFINED #define _ERRNO_T_DEFINED typedef int errno_t; #endif -#define RTL_NUMBER_OF_V1(A) (sizeof(A) / sizeof((A)[0])) -#define RTL_NUMBER_OF_V2(A) RTL_NUMBER_OF_V1(A) - -#define ARRAYSIZE(A) RTL_NUMBER_OF_V2(A) -#define _ARRAYSIZE(A) RTL_NUMBER_OF_V1(A) - #ifdef __cplusplus extern "C" { #endif diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index 27f1fd33f..75488865a 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -23,12 +23,24 @@ #include #include +#include + #ifdef _WIN32 #include #else +/* ncrypt.h */ + +typedef ULONG_PTR NCRYPT_HANDLE; +typedef ULONG_PTR NCRYPT_PROV_HANDLE; +typedef ULONG_PTR NCRYPT_KEY_HANDLE; +typedef ULONG_PTR NCRYPT_HASH_HANDLE; +typedef ULONG_PTR NCRYPT_SECRET_HANDLE; + +/* wincrypt.h */ + #define GET_ALG_CLASS(x) (x & (7 << 13)) #define GET_ALG_TYPE(x) (x & (15 << 9)) #define GET_ALG_SID(x) (x & (511)) @@ -492,6 +504,94 @@ DWORD CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType, #define CertGetNameString CertGetNameStringA #endif +/** + * Data Protection API (DPAPI) + */ + +#define CRYPTPROTECTMEMORY_BLOCK_SIZE 16 + +#define CRYPTPROTECTMEMORY_SAME_PROCESS 0x00000000 +#define CRYPTPROTECTMEMORY_CROSS_PROCESS 0x00000001 +#define CRYPTPROTECTMEMORY_SAME_LOGON 0x00000002 + +#define CRYPTPROTECT_PROMPT_ON_UNPROTECT 0x00000001 +#define CRYPTPROTECT_PROMPT_ON_PROTECT 0x00000002 +#define CRYPTPROTECT_PROMPT_RESERVED 0x00000004 +#define CRYPTPROTECT_PROMPT_STRONG 0x00000008 +#define CRYPTPROTECT_PROMPT_REQUIRE_STRONG 0x00000010 + +#define CRYPTPROTECT_UI_FORBIDDEN 0x1 +#define CRYPTPROTECT_LOCAL_MACHINE 0x4 +#define CRYPTPROTECT_CRED_SYNC 0x8 +#define CRYPTPROTECT_AUDIT 0x10 +#define CRYPTPROTECT_NO_RECOVERY 0x20 +#define CRYPTPROTECT_VERIFY_PROTECTION 0x40 +#define CRYPTPROTECT_CRED_REGENERATE 0x80 + +#define CRYPTPROTECT_FIRST_RESERVED_FLAGVAL 0x0FFFFFFF +#define CRYPTPROTECT_LAST_RESERVED_FLAGVAL 0xFFFFFFFF + +typedef struct _CRYPTPROTECT_PROMPTSTRUCT +{ + DWORD cbSize; + DWORD dwPromptFlags; + HWND hwndApp; + LPCWSTR szPrompt; +} CRYPTPROTECT_PROMPTSTRUCT, *PCRYPTPROTECT_PROMPTSTRUCT; + +#define CRYPTPROTECT_DEFAULT_PROVIDER { 0xdf9d8cd0, 0x1501, 0x11d1, { 0x8c, 0x7a, 0x00, 0xc0, 0x4f, 0xc2, 0x97, 0xeb } } + +#ifdef __cplusplus +extern "C" { +#endif + +WINPR_API BOOL CryptProtectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags); +WINPR_API BOOL CryptUnprotectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags); + +WINPR_API BOOL CryptProtectData(DATA_BLOB* pDataIn, LPCWSTR szDataDescr, DATA_BLOB* pOptionalEntropy, + PVOID pvReserved, CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, DWORD dwFlags, DATA_BLOB* pDataOut); +WINPR_API BOOL CryptUnprotectData(DATA_BLOB* pDataIn, LPWSTR* ppszDataDescr, DATA_BLOB* pOptionalEntropy, + PVOID pvReserved, CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, DWORD dwFlags, DATA_BLOB* pDataOut); + +#ifdef __cplusplus +} +#endif + +#define CRYPT_STRING_BASE64HEADER 0x00000000 +#define CRYPT_STRING_BASE64 0x00000001 +#define CRYPT_STRING_BINARY 0x00000002 +#define CRYPT_STRING_BASE64REQUESTHEADER 0x00000003 +#define CRYPT_STRING_HEX 0x00000004 +#define CRYPT_STRING_HEXASCII 0x00000005 +#define CRYPT_STRING_BASE64_ANY 0x00000006 +#define CRYPT_STRING_ANY 0x00000007 +#define CRYPT_STRING_HEX_ANY 0x00000008 +#define CRYPT_STRING_BASE64X509CRLHEADER 0x00000009 +#define CRYPT_STRING_HEXADDR 0x0000000A +#define CRYPT_STRING_HEXASCIIADDR 0x0000000B +#define CRYPT_STRING_HEXRAW 0x0000000C + +#define CRYPT_STRING_HASHDATA 0x10000000 +#define CRYPT_STRING_STRICT 0x20000000 +#define CRYPT_STRING_NOCRLF 0x40000000 +#define CRYPT_STRING_NOCR 0x80000000 + +BOOL CryptStringToBinaryW(LPCWSTR pszString, DWORD cchString, DWORD dwFlags, BYTE* pbBinary, + DWORD* pcbBinary, DWORD* pdwSkip, DWORD* pdwFlags); +BOOL CryptStringToBinaryA(LPCSTR pszString, DWORD cchString, DWORD dwFlags, BYTE* pbBinary, + DWORD* pcbBinary, DWORD* pdwSkip, DWORD* pdwFlags); + +BOOL CryptBinaryToStringW(CONST BYTE* pbBinary, DWORD cbBinary, DWORD dwFlags, LPWSTR pszString, DWORD* pcchString); +BOOL CryptBinaryToStringA(CONST BYTE* pbBinary, DWORD cbBinary, DWORD dwFlags, LPSTR pszString, DWORD* pcchString); + +#ifdef UNICODE +#define CryptStringToBinary CryptStringToBinaryW +#define CryptBinaryToString CryptBinaryToStringW +#else +#define CryptStringToBinary CryptStringToBinaryA +#define CryptBinaryToString CryptBinaryToStringA +#endif + #endif #endif /* WINPR_CRYPTO_H */ diff --git a/winpr/include/winpr/error.h b/winpr/include/winpr/error.h index 077d2ca14..6f59e4884 100644 --- a/winpr/include/winpr/error.h +++ b/winpr/include/winpr/error.h @@ -37,6 +37,60 @@ extern "C" { #define NO_ERROR 0 #endif +#define E_UNEXPECTED 0x8000FFFF +#define E_NOTIMPL 0x80004001 +#define E_OUTOFMEMORY 0x8007000E +#define E_INVALIDARG 0x80070057 +#define E_NOINTERFACE 0x80004002 +#define E_POINTER 0x80004003 +#define E_HANDLE 0x80070006 +#define E_ABORT 0x80004004 +#define E_FAIL 0x80004005 +#define E_ACCESSDENIED 0x80070005 + +#define CO_E_INIT_TLS 0x80004006 +#define CO_E_INIT_SHARED_ALLOCATOR 0x80004007 +#define CO_E_INIT_MEMORY_ALLOCATOR 0x80004008 +#define CO_E_INIT_CLASS_CACHE 0x80004009 +#define CO_E_INIT_RPC_CHANNEL 0x8000400A +#define CO_E_INIT_TLS_SET_CHANNEL_CONTROL 0x8000400B +#define CO_E_INIT_TLS_CHANNEL_CONTROL 0x8000400C +#define CO_E_INIT_UNACCEPTED_USER_ALLOCATOR 0x8000400D +#define CO_E_INIT_SCM_MUTEX_EXISTS 0x8000400E +#define CO_E_INIT_SCM_FILE_MAPPING_EXISTS 0x8000400F +#define CO_E_INIT_SCM_MAP_VIEW_OF_FILE 0x80004010 +#define CO_E_INIT_SCM_EXEC_FAILURE 0x80004011 +#define CO_E_INIT_ONLY_SINGLE_THREADED 0x80004012 +#define CO_E_CANT_REMOTE 0x80004013 +#define CO_E_BAD_SERVER_NAME 0x80004014 +#define CO_E_WRONG_SERVER_IDENTITY 0x80004015 +#define CO_E_OLE1DDE_DISABLED 0x80004016 +#define CO_E_RUNAS_SYNTAX 0x80004017 +#define CO_E_CREATEPROCESS_FAILURE 0x80004018 +#define CO_E_RUNAS_CREATEPROCESS_FAILURE 0x80004019 +#define CO_E_RUNAS_LOGON_FAILURE 0x8000401A +#define CO_E_LAUNCH_PERMSSION_DENIED 0x8000401B +#define CO_E_START_SERVICE_FAILURE 0x8000401C +#define CO_E_REMOTE_COMMUNICATION_FAILURE 0x8000401D +#define CO_E_SERVER_START_TIMEOUT 0x8000401E +#define CO_E_CLSREG_INCONSISTENT 0x8000401F +#define CO_E_IIDREG_INCONSISTENT 0x80004020 +#define CO_E_NOT_SUPPORTED 0x80004021 +#define CO_E_RELOAD_DLL 0x80004022 +#define CO_E_MSI_ERROR 0x80004023 +#define CO_E_ATTEMPT_TO_CREATE_OUTSIDE_CLIENT_CONTEXT 0x80004024 +#define CO_E_SERVER_PAUSED 0x80004025 +#define CO_E_SERVER_NOT_PAUSED 0x80004026 +#define CO_E_CLASS_DISABLED 0x80004027 +#define CO_E_CLRNOTAVAILABLE 0x80004028 +#define CO_E_ASYNC_WORK_REJECTED 0x80004029 +#define CO_E_SERVER_INIT_TIMEOUT 0x8000402A +#define CO_E_NO_SECCTX_IN_ACTIVATE 0x8000402B +#define CO_E_TRACKER_CONFIG 0x80004030 +#define CO_E_THREADPOOL_CONFIG 0x80004031 +#define CO_E_SXS_CONFIG 0x80004032 +#define CO_E_MALFORMED_SPN 0x80004033 + #define FACILITY_WINDOWSUPDATE 36 #define FACILITY_WINDOWS_CE 24 #define FACILITY_WINDOWS 8 @@ -2879,6 +2933,47 @@ extern "C" { #define ERROR_STATE_CONTAINER_NAME_SIZE_LIMIT_EXCEEDED 0x00003DCA #define ERROR_API_UNAVAILABLE 0x00003DE1 +#ifndef FACILITY_WEBSERVICES +#define FACILITY_WEBSERVICES 61 +#define WS_S_ASYNC 0x003D0000 +#define WS_S_END 0x003D0001 +#define WS_E_INVALID_FORMAT 0x803D0000 +#define WS_E_OBJECT_FAULTED 0x803D0001 +#define WS_E_NUMERIC_OVERFLOW 0x803D0002 +#define WS_E_INVALID_OPERATION 0x803D0003 +#define WS_E_OPERATION_ABORTED 0x803D0004 +#define WS_E_ENDPOINT_ACCESS_DENIED 0x803D0005 +#define WS_E_OPERATION_TIMED_OUT 0x803D0006 +#define WS_E_OPERATION_ABANDONED 0x803D0007 +#define WS_E_QUOTA_EXCEEDED 0x803D0008 +#define WS_E_NO_TRANSLATION_AVAILABLE 0x803D0009 +#define WS_E_SECURITY_VERIFICATION_FAILURE 0x803D000A +#define WS_E_ADDRESS_IN_USE 0x803D000B +#define WS_E_ADDRESS_NOT_AVAILABLE 0x803D000C +#define WS_E_ENDPOINT_NOT_FOUND 0x803D000D +#define WS_E_ENDPOINT_NOT_AVAILABLE 0x803D000E +#define WS_E_ENDPOINT_FAILURE 0x803D000F +#define WS_E_ENDPOINT_UNREACHABLE 0x803D0010 +#define WS_E_ENDPOINT_ACTION_NOT_SUPPORTED 0x803D0011 +#define WS_E_ENDPOINT_TOO_BUSY 0x803D0012 +#define WS_E_ENDPOINT_FAULT_RECEIVED 0x803D0013 +#define WS_E_ENDPOINT_DISCONNECTED 0x803D0014 +#define WS_E_PROXY_FAILURE 0x803D0015 +#define WS_E_PROXY_ACCESS_DENIED 0x803D0016 +#define WS_E_NOT_SUPPORTED 0x803D0017 +#define WS_E_PROXY_REQUIRES_BASIC_AUTH 0x803D0018 +#define WS_E_PROXY_REQUIRES_DIGEST_AUTH 0x803D0019 +#define WS_E_PROXY_REQUIRES_NTLM_AUTH 0x803D001A +#define WS_E_PROXY_REQUIRES_NEGOTIATE_AUTH 0x803D001B +#define WS_E_SERVER_REQUIRES_BASIC_AUTH 0x803D001C +#define WS_E_SERVER_REQUIRES_DIGEST_AUTH 0x803D001D +#define WS_E_SERVER_REQUIRES_NTLM_AUTH 0x803D001E +#define WS_E_SERVER_REQUIRES_NEGOTIATE_AUTH 0x803D001F +#define WS_E_INVALID_ENDPOINT_URL 0x803D0020 +#define WS_E_OTHER 0x803D0021 +#define WS_E_SECURITY_TOKEN_EXPIRED 0x803D0022 +#define WS_E_SECURITY_SYSTEM_FAILURE 0x803D0023 +#endif #define EXCEPTION_MAXIMUM_PARAMETERS 15 diff --git a/winpr/include/winpr/file.h b/winpr/include/winpr/file.h index 12208dae4..69e4eceed 100644 --- a/winpr/include/winpr/file.h +++ b/winpr/include/winpr/file.h @@ -102,6 +102,56 @@ #define FILE_FLAG_OPEN_NO_RECALL 0x00100000 #define FILE_FLAG_FIRST_PIPE_INSTANCE 0x00080000 +#define PAGE_NOACCESS 0x00000001 +#define PAGE_READONLY 0x00000002 +#define PAGE_READWRITE 0x00000004 +#define PAGE_WRITECOPY 0x00000008 +#define PAGE_EXECUTE 0x00000010 +#define PAGE_EXECUTE_READ 0x00000020 +#define PAGE_EXECUTE_READWRITE 0x00000040 +#define PAGE_EXECUTE_WRITECOPY 0x00000080 +#define PAGE_GUARD 0x00000100 +#define PAGE_NOCACHE 0x00000200 +#define PAGE_WRITECOMBINE 0x00000400 + +#define MEM_COMMIT 0x00001000 +#define MEM_RESERVE 0x00002000 +#define MEM_DECOMMIT 0x00004000 +#define MEM_RELEASE 0x00008000 +#define MEM_FREE 0x00010000 +#define MEM_PRIVATE 0x00020000 +#define MEM_MAPPED 0x00040000 +#define MEM_RESET 0x00080000 +#define MEM_TOP_DOWN 0x00100000 +#define MEM_WRITE_WATCH 0x00200000 +#define MEM_PHYSICAL 0x00400000 +#define MEM_4MB_PAGES 0x80000000 +#define MEM_IMAGE SEC_IMAGE + +#define SEC_NO_CHANGE 0x00400000 +#define SEC_FILE 0x00800000 +#define SEC_IMAGE 0x01000000 +#define SEC_VLM 0x02000000 +#define SEC_RESERVE 0x04000000 +#define SEC_COMMIT 0x08000000 +#define SEC_NOCACHE 0x10000000 +#define SEC_WRITECOMBINE 0x40000000 +#define SEC_LARGE_PAGES 0x80000000 + +#define SECTION_MAP_EXECUTE_EXPLICIT 0x00020 +#define SECTION_EXTEND_SIZE 0x00010 +#define SECTION_MAP_READ 0x00004 +#define SECTION_MAP_WRITE 0x00002 +#define SECTION_QUERY 0x00001 +#define SECTION_MAP_EXECUTE 0x00008 +#define SECTION_ALL_ACCESS 0xF001F + +#define FILE_MAP_COPY SECTION_QUERY +#define FILE_MAP_WRITE SECTION_MAP_WRITE +#define FILE_MAP_READ SECTION_MAP_READ +#define FILE_MAP_ALL_ACCESS SECTION_ALL_ACCESS +#define FILE_MAP_EXECUTE SECTION_MAP_EXECUTE_EXPLICIT + #define CREATE_NEW 1 #define CREATE_ALWAYS 2 #define OPEN_EXISTING 3 diff --git a/winpr/include/winpr/locale.h b/winpr/include/winpr/locale.h new file mode 100644 index 000000000..b63b421bd --- /dev/null +++ b/winpr/include/winpr/locale.h @@ -0,0 +1,495 @@ +/** + * WinPR: Windows Portable Runtime + * Localization Functions + * + * Copyright 2014 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_LOCALE_H +#define WINPR_LOCALE_H + +#include +#include + +#ifndef _WIN32 + +#define LANG_NEUTRAL 0x00 +#define LANG_INVARIANT 0x7f + +#define LANG_AFRIKAANS 0x36 +#define LANG_ALBANIAN 0x1c +#define LANG_ALSATIAN 0x84 +#define LANG_AMHARIC 0x5e +#define LANG_ARABIC 0x01 +#define LANG_ARMENIAN 0x2b +#define LANG_ASSAMESE 0x4d +#define LANG_AZERI 0x2c +#define LANG_AZERBAIJANI 0x2c +#define LANG_BANGLA 0x45 +#define LANG_BASHKIR 0x6d +#define LANG_BASQUE 0x2d +#define LANG_BELARUSIAN 0x23 +#define LANG_BENGALI 0x45 +#define LANG_BRETON 0x7e +#define LANG_BOSNIAN 0x1a +#define LANG_BOSNIAN_NEUTRAL 0x781a +#define LANG_BULGARIAN 0x02 +#define LANG_CATALAN 0x03 +#define LANG_CENTRAL_KURDISH 0x92 +#define LANG_CHEROKEE 0x5c +#define LANG_CHINESE 0x04 +#define LANG_CHINESE_SIMPLIFIED 0x04 +#define LANG_CHINESE_TRADITIONAL 0x7c04 +#define LANG_CORSICAN 0x83 +#define LANG_CROATIAN 0x1a +#define LANG_CZECH 0x05 +#define LANG_DANISH 0x06 +#define LANG_DARI 0x8c +#define LANG_DIVEHI 0x65 +#define LANG_DUTCH 0x13 +#define LANG_ENGLISH 0x09 +#define LANG_ESTONIAN 0x25 +#define LANG_FAEROESE 0x38 +#define LANG_FARSI 0x29 +#define LANG_FILIPINO 0x64 +#define LANG_FINNISH 0x0b +#define LANG_FRENCH 0x0c +#define LANG_FRISIAN 0x62 +#define LANG_FULAH 0x67 +#define LANG_GALICIAN 0x56 +#define LANG_GEORGIAN 0x37 +#define LANG_GERMAN 0x07 +#define LANG_GREEK 0x08 +#define LANG_GREENLANDIC 0x6f +#define LANG_GUJARATI 0x47 +#define LANG_HAUSA 0x68 +#define LANG_HAWAIIAN 0x75 +#define LANG_HEBREW 0x0d +#define LANG_HINDI 0x39 +#define LANG_HUNGARIAN 0x0e +#define LANG_ICELANDIC 0x0f +#define LANG_IGBO 0x70 +#define LANG_INDONESIAN 0x21 +#define LANG_INUKTITUT 0x5d +#define LANG_IRISH 0x3c +#define LANG_ITALIAN 0x10 +#define LANG_JAPANESE 0x11 +#define LANG_KANNADA 0x4b +#define LANG_KASHMIRI 0x60 +#define LANG_KAZAK 0x3f +#define LANG_KHMER 0x53 +#define LANG_KICHE 0x86 +#define LANG_KINYARWANDA 0x87 +#define LANG_KONKANI 0x57 +#define LANG_KOREAN 0x12 +#define LANG_KYRGYZ 0x40 +#define LANG_LAO 0x54 +#define LANG_LATVIAN 0x26 +#define LANG_LITHUANIAN 0x27 +#define LANG_LOWER_SORBIAN 0x2e +#define LANG_LUXEMBOURGISH 0x6e +#define LANG_MACEDONIAN 0x2f +#define LANG_MALAY 0x3e +#define LANG_MALAYALAM 0x4c +#define LANG_MALTESE 0x3a +#define LANG_MANIPURI 0x58 +#define LANG_MAORI 0x81 +#define LANG_MAPUDUNGUN 0x7a +#define LANG_MARATHI 0x4e +#define LANG_MOHAWK 0x7c +#define LANG_MONGOLIAN 0x50 +#define LANG_NEPALI 0x61 +#define LANG_NORWEGIAN 0x14 +#define LANG_OCCITAN 0x82 +#define LANG_ODIA 0x48 +#define LANG_ORIYA 0x48 +#define LANG_PASHTO 0x63 +#define LANG_PERSIAN 0x29 +#define LANG_POLISH 0x15 +#define LANG_PORTUGUESE 0x16 +#define LANG_PULAR 0x67 +#define LANG_PUNJABI 0x46 +#define LANG_QUECHUA 0x6b +#define LANG_ROMANIAN 0x18 +#define LANG_ROMANSH 0x17 +#define LANG_RUSSIAN 0x19 +#define LANG_SAKHA 0x85 +#define LANG_SAMI 0x3b +#define LANG_SANSKRIT 0x4f +#define LANG_SCOTTISH_GAELIC 0x91 +#define LANG_SERBIAN 0x1a +#define LANG_SERBIAN_NEUTRAL 0x7c1a +#define LANG_SINDHI 0x59 +#define LANG_SINHALESE 0x5b +#define LANG_SLOVAK 0x1b +#define LANG_SLOVENIAN 0x24 +#define LANG_SOTHO 0x6c +#define LANG_SPANISH 0x0a +#define LANG_SWAHILI 0x41 +#define LANG_SWEDISH 0x1d +#define LANG_SYRIAC 0x5a +#define LANG_TAJIK 0x28 +#define LANG_TAMAZIGHT 0x5f +#define LANG_TAMIL 0x49 +#define LANG_TATAR 0x44 +#define LANG_TELUGU 0x4a +#define LANG_THAI 0x1e +#define LANG_TIBETAN 0x51 +#define LANG_TIGRIGNA 0x73 +#define LANG_TIGRINYA 0x73 +#define LANG_TSWANA 0x32 +#define LANG_TURKISH 0x1f +#define LANG_TURKMEN 0x42 +#define LANG_UIGHUR 0x80 +#define LANG_UKRAINIAN 0x22 +#define LANG_UPPER_SORBIAN 0x2e +#define LANG_URDU 0x20 +#define LANG_UZBEK 0x43 +#define LANG_VALENCIAN 0x03 +#define LANG_VIETNAMESE 0x2a +#define LANG_WELSH 0x52 +#define LANG_WOLOF 0x88 +#define LANG_XHOSA 0x34 +#define LANG_YAKUT 0x85 +#define LANG_YI 0x78 +#define LANG_YORUBA 0x6a +#define LANG_ZULU 0x35 + +#define SUBLANG_NEUTRAL 0x00 +#define SUBLANG_DEFAULT 0x01 +#define SUBLANG_SYS_DEFAULT 0x02 +#define SUBLANG_CUSTOM_DEFAULT 0x03 +#define SUBLANG_CUSTOM_UNSPECIFIED 0x04 +#define SUBLANG_UI_CUSTOM_DEFAULT 0x05 + +#define SUBLANG_AFRIKAANS_SOUTH_AFRICA 0x01 +#define SUBLANG_ALBANIAN_ALBANIA 0x01 +#define SUBLANG_ALSATIAN_FRANCE 0x01 +#define SUBLANG_AMHARIC_ETHIOPIA 0x01 +#define SUBLANG_ARABIC_SAUDI_ARABIA 0x01 +#define SUBLANG_ARABIC_IRAQ 0x02 +#define SUBLANG_ARABIC_EGYPT 0x03 +#define SUBLANG_ARABIC_LIBYA 0x04 +#define SUBLANG_ARABIC_ALGERIA 0x05 +#define SUBLANG_ARABIC_MOROCCO 0x06 +#define SUBLANG_ARABIC_TUNISIA 0x07 +#define SUBLANG_ARABIC_OMAN 0x08 +#define SUBLANG_ARABIC_YEMEN 0x09 +#define SUBLANG_ARABIC_SYRIA 0x0a +#define SUBLANG_ARABIC_JORDAN 0x0b +#define SUBLANG_ARABIC_LEBANON 0x0c +#define SUBLANG_ARABIC_KUWAIT 0x0d +#define SUBLANG_ARABIC_UAE 0x0e +#define SUBLANG_ARABIC_BAHRAIN 0x0f +#define SUBLANG_ARABIC_QATAR 0x10 +#define SUBLANG_ARMENIAN_ARMENIA 0x01 +#define SUBLANG_ASSAMESE_INDIA 0x01 +#define SUBLANG_AZERI_LATIN 0x01 +#define SUBLANG_AZERI_CYRILLIC 0x02 +#define SUBLANG_AZERBAIJANI_AZERBAIJAN_LATIN 0x01 +#define SUBLANG_AZERBAIJANI_AZERBAIJAN_CYRILLIC 0x02 +#define SUBLANG_BANGLA_INDIA 0x01 +#define SUBLANG_BANGLA_BANGLADESH 0x02 +#define SUBLANG_BASHKIR_RUSSIA 0x01 +#define SUBLANG_BASQUE_BASQUE 0x01 +#define SUBLANG_BELARUSIAN_BELARUS 0x01 +#define SUBLANG_BENGALI_INDIA 0x01 +#define SUBLANG_BENGALI_BANGLADESH 0x02 +#define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN 0x05 +#define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x08 +#define SUBLANG_BRETON_FRANCE 0x01 +#define SUBLANG_BULGARIAN_BULGARIA 0x01 +#define SUBLANG_CATALAN_CATALAN 0x01 +#define SUBLANG_CENTRAL_KURDISH_IRAQ 0x01 +#define SUBLANG_CHEROKEE_CHEROKEE 0x01 +#define SUBLANG_CHINESE_TRADITIONAL 0x01 +#define SUBLANG_CHINESE_SIMPLIFIED 0x02 +#define SUBLANG_CHINESE_HONGKONG 0x03 +#define SUBLANG_CHINESE_SINGAPORE 0x04 +#define SUBLANG_CHINESE_MACAU 0x05 +#define SUBLANG_CORSICAN_FRANCE 0x01 +#define SUBLANG_CZECH_CZECH_REPUBLIC 0x01 +#define SUBLANG_CROATIAN_CROATIA 0x01 +#define SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN 0x04 +#define SUBLANG_DANISH_DENMARK 0x01 +#define SUBLANG_DARI_AFGHANISTAN 0x01 +#define SUBLANG_DIVEHI_MALDIVES 0x01 +#define SUBLANG_DUTCH 0x01 +#define SUBLANG_DUTCH_BELGIAN 0x02 +#define SUBLANG_ENGLISH_US 0x01 +#define SUBLANG_ENGLISH_UK 0x02 +#define SUBLANG_ENGLISH_AUS 0x03 +#define SUBLANG_ENGLISH_CAN 0x04 +#define SUBLANG_ENGLISH_NZ 0x05 +#define SUBLANG_ENGLISH_EIRE 0x06 +#define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07 +#define SUBLANG_ENGLISH_JAMAICA 0x08 +#define SUBLANG_ENGLISH_CARIBBEAN 0x09 +#define SUBLANG_ENGLISH_BELIZE 0x0a +#define SUBLANG_ENGLISH_TRINIDAD 0x0b +#define SUBLANG_ENGLISH_ZIMBABWE 0x0c +#define SUBLANG_ENGLISH_PHILIPPINES 0x0d +#define SUBLANG_ENGLISH_INDIA 0x10 +#define SUBLANG_ENGLISH_MALAYSIA 0x11 +#define SUBLANG_ENGLISH_SINGAPORE 0x12 +#define SUBLANG_ESTONIAN_ESTONIA 0x01 +#define SUBLANG_FAEROESE_FAROE_ISLANDS 0x01 +#define SUBLANG_FILIPINO_PHILIPPINES 0x01 +#define SUBLANG_FINNISH_FINLAND 0x01 +#define SUBLANG_FRENCH 0x01 +#define SUBLANG_FRENCH_BELGIAN 0x02 +#define SUBLANG_FRENCH_CANADIAN 0x03 +#define SUBLANG_FRENCH_SWISS 0x04 +#define SUBLANG_FRENCH_LUXEMBOURG 0x05 +#define SUBLANG_FRENCH_MONACO 0x06 +#define SUBLANG_FRISIAN_NETHERLANDS 0x01 +#define SUBLANG_FULAH_SENEGAL 0x02 +#define SUBLANG_GALICIAN_GALICIAN 0x01 +#define SUBLANG_GEORGIAN_GEORGIA 0x01 +#define SUBLANG_GERMAN 0x01 +#define SUBLANG_GERMAN_SWISS 0x02 +#define SUBLANG_GERMAN_AUSTRIAN 0x03 +#define SUBLANG_GERMAN_LUXEMBOURG 0x04 +#define SUBLANG_GERMAN_LIECHTENSTEIN 0x05 +#define SUBLANG_GREEK_GREECE 0x01 +#define SUBLANG_GREENLANDIC_GREENLAND 0x01 +#define SUBLANG_GUJARATI_INDIA 0x01 +#define SUBLANG_HAUSA_NIGERIA_LATIN 0x01 +#define SUBLANG_HAWAIIAN_US 0x01 +#define SUBLANG_HEBREW_ISRAEL 0x01 +#define SUBLANG_HINDI_INDIA 0x01 +#define SUBLANG_HUNGARIAN_HUNGARY 0x01 +#define SUBLANG_ICELANDIC_ICELAND 0x01 +#define SUBLANG_IGBO_NIGERIA 0x01 +#define SUBLANG_INDONESIAN_INDONESIA 0x01 +#define SUBLANG_INUKTITUT_CANADA 0x01 +#define SUBLANG_INUKTITUT_CANADA_LATIN 0x02 +#define SUBLANG_IRISH_IRELAND 0x02 +#define SUBLANG_ITALIAN 0x01 +#define SUBLANG_ITALIAN_SWISS 0x02 +#define SUBLANG_JAPANESE_JAPAN 0x01 +#define SUBLANG_KANNADA_INDIA 0x01 +#define SUBLANG_KASHMIRI_SASIA 0x02 +#define SUBLANG_KASHMIRI_INDIA 0x02 +#define SUBLANG_KAZAK_KAZAKHSTAN 0x01 +#define SUBLANG_KHMER_CAMBODIA 0x01 +#define SUBLANG_KICHE_GUATEMALA 0x01 +#define SUBLANG_KINYARWANDA_RWANDA 0x01 +#define SUBLANG_KONKANI_INDIA 0x01 +#define SUBLANG_KOREAN 0x01 +#define SUBLANG_KYRGYZ_KYRGYZSTAN 0x01 +#define SUBLANG_LAO_LAO 0x01 +#define SUBLANG_LATVIAN_LATVIA 0x01 +#define SUBLANG_LITHUANIAN 0x01 +#define SUBLANG_LOWER_SORBIAN_GERMANY 0x02 +#define SUBLANG_LUXEMBOURGISH_LUXEMBOURG 0x01 +#define SUBLANG_MACEDONIAN_MACEDONIA 0x01 +#define SUBLANG_MALAY_MALAYSIA 0x01 +#define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02 +#define SUBLANG_MALAYALAM_INDIA 0x01 +#define SUBLANG_MALTESE_MALTA 0x01 +#define SUBLANG_MAORI_NEW_ZEALAND 0x01 +#define SUBLANG_MAPUDUNGUN_CHILE 0x01 +#define SUBLANG_MARATHI_INDIA 0x01 +#define SUBLANG_MOHAWK_MOHAWK 0x01 +#define SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA 0x01 +#define SUBLANG_MONGOLIAN_PRC 0x02 +#define SUBLANG_NEPALI_INDIA 0x02 +#define SUBLANG_NEPALI_NEPAL 0x01 +#define SUBLANG_NORWEGIAN_BOKMAL 0x01 +#define SUBLANG_NORWEGIAN_NYNORSK 0x02 +#define SUBLANG_OCCITAN_FRANCE 0x01 +#define SUBLANG_ODIA_INDIA 0x01 +#define SUBLANG_ORIYA_INDIA 0x01 +#define SUBLANG_PASHTO_AFGHANISTAN 0x01 +#define SUBLANG_PERSIAN_IRAN 0x01 +#define SUBLANG_POLISH_POLAND 0x01 +#define SUBLANG_PORTUGUESE 0x02 +#define SUBLANG_PORTUGUESE_BRAZILIAN 0x01 +#define SUBLANG_PULAR_SENEGAL 0x02 +#define SUBLANG_PUNJABI_INDIA 0x01 +#define SUBLANG_PUNJABI_PAKISTAN 0x02 +#define SUBLANG_QUECHUA_BOLIVIA 0x01 +#define SUBLANG_QUECHUA_ECUADOR 0x02 +#define SUBLANG_QUECHUA_PERU 0x03 +#define SUBLANG_ROMANIAN_ROMANIA 0x01 +#define SUBLANG_ROMANSH_SWITZERLAND 0x01 +#define SUBLANG_RUSSIAN_RUSSIA 0x01 +#define SUBLANG_SAKHA_RUSSIA 0x01 +#define SUBLANG_SAMI_NORTHERN_NORWAY 0x01 +#define SUBLANG_SAMI_NORTHERN_SWEDEN 0x02 +#define SUBLANG_SAMI_NORTHERN_FINLAND 0x03 +#define SUBLANG_SAMI_LULE_NORWAY 0x04 +#define SUBLANG_SAMI_LULE_SWEDEN 0x05 +#define SUBLANG_SAMI_SOUTHERN_NORWAY 0x06 +#define SUBLANG_SAMI_SOUTHERN_SWEDEN 0x07 +#define SUBLANG_SAMI_SKOLT_FINLAND 0x08 +#define SUBLANG_SAMI_INARI_FINLAND 0x09 +#define SUBLANG_SANSKRIT_INDIA 0x01 +#define SUBLANG_SCOTTISH_GAELIC 0x01 +#define SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_LATIN 0x06 +#define SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x07 +#define SUBLANG_SERBIAN_MONTENEGRO_LATIN 0x0b +#define SUBLANG_SERBIAN_MONTENEGRO_CYRILLIC 0x0c +#define SUBLANG_SERBIAN_SERBIA_LATIN 0x09 +#define SUBLANG_SERBIAN_SERBIA_CYRILLIC 0x0a +#define SUBLANG_SERBIAN_CROATIA 0x01 +#define SUBLANG_SERBIAN_LATIN 0x02 +#define SUBLANG_SERBIAN_CYRILLIC 0x03 +#define SUBLANG_SINDHI_INDIA 0x01 +#define SUBLANG_SINDHI_PAKISTAN 0x02 +#define SUBLANG_SINDHI_AFGHANISTAN 0x02 +#define SUBLANG_SINHALESE_SRI_LANKA 0x01 +#define SUBLANG_SOTHO_NORTHERN_SOUTH_AFRICA 0x01 +#define SUBLANG_SLOVAK_SLOVAKIA 0x01 +#define SUBLANG_SLOVENIAN_SLOVENIA 0x01 +#define SUBLANG_SPANISH 0x01 +#define SUBLANG_SPANISH_MEXICAN 0x02 +#define SUBLANG_SPANISH_MODERN 0x03 +#define SUBLANG_SPANISH_GUATEMALA 0x04 +#define SUBLANG_SPANISH_COSTA_RICA 0x05 +#define SUBLANG_SPANISH_PANAMA 0x06 +#define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07 +#define SUBLANG_SPANISH_VENEZUELA 0x08 +#define SUBLANG_SPANISH_COLOMBIA 0x09 +#define SUBLANG_SPANISH_PERU 0x0a +#define SUBLANG_SPANISH_ARGENTINA 0x0b +#define SUBLANG_SPANISH_ECUADOR 0x0c +#define SUBLANG_SPANISH_CHILE 0x0d +#define SUBLANG_SPANISH_URUGUAY 0x0e +#define SUBLANG_SPANISH_PARAGUAY 0x0f +#define SUBLANG_SPANISH_BOLIVIA 0x10 +#define SUBLANG_SPANISH_EL_SALVADOR 0x11 +#define SUBLANG_SPANISH_HONDURAS 0x12 +#define SUBLANG_SPANISH_NICARAGUA 0x13 +#define SUBLANG_SPANISH_PUERTO_RICO 0x14 +#define SUBLANG_SPANISH_US 0x15 +#define SUBLANG_SWAHILI_KENYA 0x01 +#define SUBLANG_SWEDISH 0x01 +#define SUBLANG_SWEDISH_FINLAND 0x02 +#define SUBLANG_SYRIAC_SYRIA 0x01 +#define SUBLANG_TAJIK_TAJIKISTAN 0x01 +#define SUBLANG_TAMAZIGHT_ALGERIA_LATIN 0x02 +#define SUBLANG_TAMAZIGHT_MOROCCO_TIFINAGH 0x04 +#define SUBLANG_TAMIL_INDIA 0x01 +#define SUBLANG_TAMIL_SRI_LANKA 0x02 +#define SUBLANG_TATAR_RUSSIA 0x01 +#define SUBLANG_TELUGU_INDIA 0x01 +#define SUBLANG_THAI_THAILAND 0x01 +#define SUBLANG_TIBETAN_PRC 0x01 +#define SUBLANG_TIGRIGNA_ERITREA 0x02 +#define SUBLANG_TIGRINYA_ERITREA 0x02 +#define SUBLANG_TIGRINYA_ETHIOPIA 0x01 +#define SUBLANG_TSWANA_BOTSWANA 0x02 +#define SUBLANG_TSWANA_SOUTH_AFRICA 0x01 +#define SUBLANG_TURKISH_TURKEY 0x01 +#define SUBLANG_TURKMEN_TURKMENISTAN 0x01 +#define SUBLANG_UIGHUR_PRC 0x01 +#define SUBLANG_UKRAINIAN_UKRAINE 0x01 +#define SUBLANG_UPPER_SORBIAN_GERMANY 0x01 +#define SUBLANG_URDU_PAKISTAN 0x01 +#define SUBLANG_URDU_INDIA 0x02 +#define SUBLANG_UZBEK_LATIN 0x01 +#define SUBLANG_UZBEK_CYRILLIC 0x02 +#define SUBLANG_VALENCIAN_VALENCIA 0x02 +#define SUBLANG_VIETNAMESE_VIETNAM 0x01 +#define SUBLANG_WELSH_UNITED_KINGDOM 0x01 +#define SUBLANG_WOLOF_SENEGAL 0x01 +#define SUBLANG_XHOSA_SOUTH_AFRICA 0x01 +#define SUBLANG_YAKUT_RUSSIA 0x01 +#define SUBLANG_YI_PRC 0x01 +#define SUBLANG_YORUBA_NIGERIA 0x01 +#define SUBLANG_ZULU_SOUTH_AFRICA 0x01 + +#define SORT_DEFAULT 0x0 + +#define SORT_INVARIANT_MATH 0x1 + +#define SORT_JAPANESE_XJIS 0x0 +#define SORT_JAPANESE_UNICODE 0x1 +#define SORT_JAPANESE_RADICALSTROKE 0x4 + +#define SORT_CHINESE_BIG5 0x0 +#define SORT_CHINESE_PRCP 0x0 +#define SORT_CHINESE_UNICODE 0x1 +#define SORT_CHINESE_PRC 0x2 +#define SORT_CHINESE_BOPOMOFO 0x3 +#define SORT_CHINESE_RADICALSTROKE 0x4 + +#define SORT_KOREAN_KSC 0x0 +#define SORT_KOREAN_UNICODE 0x1 + +#define SORT_GERMAN_PHONE_BOOK 0x1 + +#define SORT_HUNGARIAN_DEFAULT 0x0 +#define SORT_HUNGARIAN_TECHNICAL 0x1 + +#define SORT_GEORGIAN_TRADITIONAL 0x0 +#define SORT_GEORGIAN_MODERN 0x1 + +#define MAKELANGID(p, s) ((((WORD)(s)) << 10) | (WORD)(p)) +#define PRIMARYLANGID(lgid) ((WORD)(lgid) & 0x3FF) +#define SUBLANGID(lgid) ((WORD)(lgid) >> 10) + +#define NLS_VALID_LOCALE_MASK 0x000FFFFF + +#define MAKELCID(lgid, srtid) ((DWORD)((((DWORD)((WORD)(srtid))) << 16) | ((DWORD)((WORD)(lgid))))) + +#define MAKESORTLCID(lgid, srtid, ver) \ + ((DWORD)((MAKELCID(lgid, srtid)) | (((DWORD)((WORD)(ver))) << 20))) + +#define LANGIDFROMLCID(lcid) ((WORD)(lcid)) +#define SORTIDFROMLCID(lcid) ((WORD)((((DWORD)(lcid)) >> 16) & 0xF)) + +#define SORTVERSIONFROMLCID(lcid) ((WORD)((((DWORD)(lcid)) >> 20) & 0xF)) + +#define LOCALE_NAME_MAX_LENGTH 85 + + +#define LANG_SYSTEM_DEFAULT (MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT)) +#define LANG_USER_DEFAULT (MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)) + +#define LOCALE_SYSTEM_DEFAULT (MAKELCID(LANG_SYSTEM_DEFAULT, SORT_DEFAULT)) +#define LOCALE_USER_DEFAULT (MAKELCID(LANG_USER_DEFAULT, SORT_DEFAULT)) + +#define LOCALE_CUSTOM_DEFAULT \ + (MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_DEFAULT), SORT_DEFAULT)) + +#define LOCALE_CUSTOM_UNSPECIFIED \ + (MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_UNSPECIFIED), SORT_DEFAULT)) + +#define LOCALE_CUSTOM_UI_DEFAULT \ + (MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_UI_CUSTOM_DEFAULT), SORT_DEFAULT)) + +#define LOCALE_NEUTRAL \ + (MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), SORT_DEFAULT)) + +#define LOCALE_INVARIANT \ + (MAKELCID(MAKELANGID(LANG_INVARIANT, SUBLANG_NEUTRAL), SORT_DEFAULT)) + +#ifdef __cplusplus +extern "C" { +#endif + + + +#ifdef __cplusplus +} +#endif + +#endif + +#endif /* WINPR_LOCALE_H */ + diff --git a/winpr/include/winpr/memory.h b/winpr/include/winpr/memory.h index 3a99685a8..28e740fc4 100644 --- a/winpr/include/winpr/memory.h +++ b/winpr/include/winpr/memory.h @@ -17,27 +17,57 @@ * limitations under the License. */ -#ifndef WINPR_CRT_MEMORY_H -#define WINPR_CRT_MEMORY_H +#ifndef WINPR_MEMORY_H +#define WINPR_MEMORY_H #include #include #include + #include #include +#include +#include +#include + #ifndef _WIN32 -#define CopyMemory(Destination, Source, Length) memcpy((Destination), (Source), (Length)) -#define MoveMemory(Destination, Source, Length) memmove((Destination), (Source), (Length)) -#define FillMemory(Destination, Length, Fill) memset((Destination), (Fill), (Length)) -#define ZeroMemory(Destination, Length) memset((Destination), 0, (Length)) +#ifdef __cplusplus +extern "C" { +#endif -WINPR_API PVOID SecureZeroMemory(PVOID ptr, SIZE_T cnt); +WINPR_API HANDLE CreateFileMappingA(HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes, DWORD flProtect, + DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCSTR lpName); +WINPR_API HANDLE CreateFileMappingW(HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes, DWORD flProtect, + DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCWSTR lpName); + +WINPR_API HANDLE OpenFileMappingA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName); +WINPR_API HANDLE OpenFileMappingW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName); + +WINPR_API LPVOID MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, + DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap); + +WINPR_API LPVOID MapViewOfFileEx(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, + DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, LPVOID lpBaseAddress); + +WINPR_API BOOL FlushViewOfFile(LPCVOID lpBaseAddress, SIZE_T dwNumberOfBytesToFlush); + +WINPR_API BOOL UnmapViewOfFile(LPCVOID lpBaseAddress); + +#ifdef __cplusplus +} +#endif + +#ifdef UNICODE +#define CreateFileMapping CreateFileMappingW +#define OpenFileMapping OpenFileMappingW +#else +#define CreateFileMapping CreateFileMappingA +#define OpenFileMapping OpenFileMappingA +#endif #endif -#include - -#endif /* WINPR_CRT_MEMORY_H */ +#endif /* WINPR_MEMORY_H */ diff --git a/winpr/include/winpr/registry.h b/winpr/include/winpr/registry.h index e6f9757f4..229bc6f13 100644 --- a/winpr/include/winpr/registry.h +++ b/winpr/include/winpr/registry.h @@ -102,8 +102,6 @@ extern "C" { #define REG_QWORD 11 #define REG_QWORD_LITTLE_ENDIAN 11 -#define WINAPI WINPR_API - typedef HANDLE HKEY; typedef HANDLE* PHKEY; diff --git a/winpr/include/winpr/security.h b/winpr/include/winpr/security.h index 4ad7d4d4f..f36099f89 100644 --- a/winpr/include/winpr/security.h +++ b/winpr/include/winpr/security.h @@ -371,6 +371,38 @@ typedef struct _TOKEN_APPCONTAINER_INFORMATION PSID TokenAppContainer; } TOKEN_APPCONTAINER_INFORMATION, *PTOKEN_APPCONTAINER_INFORMATION; +#ifdef __cplusplus +extern "C" { +#endif + +WINPR_API BOOL InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision); +WINPR_API DWORD GetSecurityDescriptorLength(PSECURITY_DESCRIPTOR pSecurityDescriptor); +WINPR_API BOOL IsValidSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor); + +WINPR_API BOOL GetSecurityDescriptorControl(PSECURITY_DESCRIPTOR pSecurityDescriptor, + PSECURITY_DESCRIPTOR_CONTROL pControl, LPDWORD lpdwRevision); +WINPR_API BOOL SetSecurityDescriptorControl(PSECURITY_DESCRIPTOR pSecurityDescriptor, + SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet); + +WINPR_API BOOL GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbDaclPresent, PACL* pDacl, LPBOOL lpbDaclDefaulted); +WINPR_API BOOL SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl, BOOL bDaclDefaulted); + +WINPR_API BOOL GetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID* pGroup, LPBOOL lpbGroupDefaulted); +WINPR_API BOOL SetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pGroup, BOOL bGroupDefaulted); + +WINPR_API BOOL GetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID* pOwner, LPBOOL lpbOwnerDefaulted); +WINPR_API BOOL SetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pOwner, BOOL bOwnerDefaulted); + +WINPR_API DWORD GetSecurityDescriptorRMControl(PSECURITY_DESCRIPTOR SecurityDescriptor, PUCHAR RMControl); +WINPR_API DWORD SetSecurityDescriptorRMControl(PSECURITY_DESCRIPTOR SecurityDescriptor, PUCHAR RMControl); + +WINPR_API BOOL GetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbSaclPresent, PACL* pSacl, LPBOOL lpbSaclDefaulted); +WINPR_API BOOL SetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bSaclPresent, PACL pSacl, BOOL bSaclDefaulted); + +#ifdef __cplusplus +} +#endif + #endif #endif /* WINPR_SECURITY_H */ diff --git a/winpr/include/winpr/spec.h b/winpr/include/winpr/spec.h index 917e8af82..9dbf394db 100644 --- a/winpr/include/winpr/spec.h +++ b/winpr/include/winpr/spec.h @@ -28,6 +28,29 @@ #else +#define DUMMYUNIONNAME u +#define DUMMYUNIONNAME1 u1 +#define DUMMYUNIONNAME2 u2 +#define DUMMYUNIONNAME3 u3 +#define DUMMYUNIONNAME4 u4 +#define DUMMYUNIONNAME5 u5 +#define DUMMYUNIONNAME6 u6 +#define DUMMYUNIONNAME7 u7 +#define DUMMYUNIONNAME8 u8 + +#define DUMMYSTRUCTNAME s +#define DUMMYSTRUCTNAME1 s1 +#define DUMMYSTRUCTNAME2 s2 +#define DUMMYSTRUCTNAME3 s3 +#define DUMMYSTRUCTNAME4 s4 +#define DUMMYSTRUCTNAME5 s5 + +#if (defined(_M_AMD64) || defined(_M_ARM)) && !defined(_WIN32) +#define _UNALIGNED __unaligned +#else +#define _UNALIGNED +#endif + #ifndef DECLSPEC_ALIGN #if defined(_MSC_VER) && (_MSC_VER >= 1300) && !defined(MIDL_PASS) #define DECLSPEC_ALIGN(x) __declspec(align(x)) @@ -44,14 +67,30 @@ #define MEMORY_ALLOCATION_ALIGNMENT 8 #endif -#define DUMMYSTRUCTNAME s - #ifdef __GNUC__ #ifndef __declspec #define __declspec(e) __attribute__((e)) #endif #endif +#if defined(_WIN32) || defined(__CYGWIN__) + #ifdef __GNUC__ + #define DECLSPEC_EXPORT __attribute__((dllexport)) + #define DECLSPEC_IMPORT __attribute__((dllimport)) + #else + #define DECLSPEC_EXPORT __declspec(dllexport) + #define DECLSPEC_IMPORT __declspec(dllimport) + #endif +#else + #if defined(__GNUC__) && __GNUC__ >= 4 + #define DECLSPEC_EXPORT __attribute__ ((visibility("default"))) + #define DECLSPEC_IMPORT + #else + #define DECLSPEC_EXPORT + #define DECLSPEC_IMPORT + #endif +#endif + #ifndef DECLSPEC_NORETURN #if (defined(__GNUC__) || defined(_MSC_VER) || defined(__clang__)) #define DECLSPEC_NORETURN __declspec(noreturn) @@ -60,6 +99,876 @@ #endif #endif /* DECLSPEC_NORETURN */ +/** + * Header Annotations: + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa383701/ + */ + +#define __field_bcount(size) __notnull __byte_writableTo(size) +#define __field_ecount(size) __notnull __elem_writableTo(size) +#define __post_invalid _Post_ __notvalid + +#define __deref_in +#define __deref_in_ecount(size) +#define __deref_in_bcount(size) +#define __deref_in_opt +#define __deref_in_ecount_opt(size) +#define __deref_in_bcount_opt(size) +#define __deref_opt_in +#define __deref_opt_in_ecount(size) +#define __deref_opt_in_bcount(size) +#define __deref_opt_in_opt +#define __deref_opt_in_ecount_opt(size) +#define __deref_opt_in_bcount_opt(size) +#define __out_awcount(expr,size) +#define __in_awcount(expr,size) +#define __nullnullterminated +#define __in_data_source(src_sym) +#define __kernel_entry +#define __out_data_source(src_sym) +#define __analysis_noreturn +#define _Check_return_opt_ +#define _Check_return_wat_ + +#define __inner_exceptthat +#define __inner_typefix(ctype) +#define _Always_(annos) +#define _Analysis_noreturn_ +#define _Analysis_assume_(expr) +#define _At_(target, annos) +#define _At_buffer_(target, iter, bound, annos) +#define _Check_return_ +#define _COM_Outptr_ +#define _COM_Outptr_opt_ +#define _COM_Outptr_opt_result_maybenull_ +#define _COM_Outptr_result_maybenull_ +#define _Const_ +#define _Deref_in_bound_ +#define _Deref_in_range_(lb,ub) +#define _Deref_inout_bound_ +#define _Deref_inout_z_ +#define _Deref_inout_z_bytecap_c_(size) +#define _Deref_inout_z_cap_c_(size) +#define _Deref_opt_out_ +#define _Deref_opt_out_opt_ +#define _Deref_opt_out_opt_z_ +#define _Deref_opt_out_z_ +#define _Deref_out_ +#define _Deref_out_bound_ +#define _Deref_out_opt_ +#define _Deref_out_opt_z_ +#define _Deref_out_range_(lb,ub) +#define _Deref_out_z_ +#define _Deref_out_z_bytecap_c_(size) +#define _Deref_out_z_cap_c_(size) +#define _Deref_post_bytecap_(size) +#define _Deref_post_bytecap_c_(size) +#define _Deref_post_bytecap_x_(size) +#define _Deref_post_bytecount_(size) +#define _Deref_post_bytecount_c_(size) +#define _Deref_post_bytecount_x_(size) +#define _Deref_post_cap_(size) +#define _Deref_post_cap_c_(size) +#define _Deref_post_cap_x_(size) +#define _Deref_post_count_(size) +#define _Deref_post_count_c_(size) +#define _Deref_post_count_x_(size) +#define _Deref_post_maybenull_ +#define _Deref_post_notnull_ +#define _Deref_post_null_ +#define _Deref_post_opt_bytecap_(size) +#define _Deref_post_opt_bytecap_c_(size) +#define _Deref_post_opt_bytecap_x_(size) +#define _Deref_post_opt_bytecount_(size) +#define _Deref_post_opt_bytecount_c_(size) +#define _Deref_post_opt_bytecount_x_(size) +#define _Deref_post_opt_cap_(size) +#define _Deref_post_opt_cap_c_(size) +#define _Deref_post_opt_cap_x_(size) +#define _Deref_post_opt_count_(size) +#define _Deref_post_opt_count_c_(size) +#define _Deref_post_opt_count_x_(size) +#define _Deref_post_opt_valid_ +#define _Deref_post_opt_valid_bytecap_(size) +#define _Deref_post_opt_valid_bytecap_c_(size) +#define _Deref_post_opt_valid_bytecap_x_(size) +#define _Deref_post_opt_valid_cap_(size) +#define _Deref_post_opt_valid_cap_c_(size) +#define _Deref_post_opt_valid_cap_x_(size) +#define _Deref_post_opt_z_ +#define _Deref_post_opt_z_bytecap_(size) +#define _Deref_post_opt_z_bytecap_c_(size) +#define _Deref_post_opt_z_bytecap_x_(size) +#define _Deref_post_opt_z_cap_(size) +#define _Deref_post_opt_z_cap_c_(size) +#define _Deref_post_opt_z_cap_x_(size) +#define _Deref_post_valid_ +#define _Deref_post_valid_bytecap_(size) +#define _Deref_post_valid_bytecap_c_(size) +#define _Deref_post_valid_bytecap_x_(size) +#define _Deref_post_valid_cap_(size) +#define _Deref_post_valid_cap_c_(size) +#define _Deref_post_valid_cap_x_(size) +#define _Deref_post_z_ +#define _Deref_post_z_bytecap_(size) +#define _Deref_post_z_bytecap_c_(size) +#define _Deref_post_z_bytecap_x_(size) +#define _Deref_post_z_cap_(size) +#define _Deref_post_z_cap_c_(size) +#define _Deref_post_z_cap_x_(size) +#define _Deref_pre_bytecap_(size) +#define _Deref_pre_bytecap_c_(size) +#define _Deref_pre_bytecap_x_(size) +#define _Deref_pre_bytecount_(size) +#define _Deref_pre_bytecount_c_(size) +#define _Deref_pre_bytecount_x_(size) +#define _Deref_pre_cap_(size) +#define _Deref_pre_cap_c_(size) +#define _Deref_pre_cap_x_(size) +#define _Deref_pre_count_(size) +#define _Deref_pre_count_c_(size) +#define _Deref_pre_count_x_(size) +#define _Deref_pre_invalid_ +#define _Deref_pre_maybenull_ +#define _Deref_pre_notnull_ +#define _Deref_pre_null_ +#define _Deref_pre_opt_bytecap_(size) +#define _Deref_pre_opt_bytecap_c_(size) +#define _Deref_pre_opt_bytecap_x_(size) +#define _Deref_pre_opt_bytecount_(size) +#define _Deref_pre_opt_bytecount_c_(size) +#define _Deref_pre_opt_bytecount_x_(size) +#define _Deref_pre_opt_cap_(size) +#define _Deref_pre_opt_cap_c_(size) +#define _Deref_pre_opt_cap_x_(size) +#define _Deref_pre_opt_count_(size) +#define _Deref_pre_opt_count_c_(size) +#define _Deref_pre_opt_count_x_(size) +#define _Deref_pre_opt_valid_ +#define _Deref_pre_opt_valid_bytecap_(size) +#define _Deref_pre_opt_valid_bytecap_c_(size) +#define _Deref_pre_opt_valid_bytecap_x_(size) +#define _Deref_pre_opt_valid_cap_(size) +#define _Deref_pre_opt_valid_cap_c_(size) +#define _Deref_pre_opt_valid_cap_x_(size) +#define _Deref_pre_opt_z_ +#define _Deref_pre_opt_z_bytecap_(size) +#define _Deref_pre_opt_z_bytecap_c_(size) +#define _Deref_pre_opt_z_bytecap_x_(size) +#define _Deref_pre_opt_z_cap_(size) +#define _Deref_pre_opt_z_cap_c_(size) +#define _Deref_pre_opt_z_cap_x_(size) +#define _Deref_pre_readonly_ +#define _Deref_pre_valid_ +#define _Deref_pre_valid_bytecap_(size) +#define _Deref_pre_valid_bytecap_c_(size) +#define _Deref_pre_valid_bytecap_x_(size) +#define _Deref_pre_valid_cap_(size) +#define _Deref_pre_valid_cap_c_(size) +#define _Deref_pre_valid_cap_x_(size) +#define _Deref_pre_writeonly_ +#define _Deref_pre_z_ +#define _Deref_pre_z_bytecap_(size) +#define _Deref_pre_z_bytecap_c_(size) +#define _Deref_pre_z_bytecap_x_(size) +#define _Deref_pre_z_cap_(size) +#define _Deref_pre_z_cap_c_(size) +#define _Deref_pre_z_cap_x_(size) +#define _Deref_prepost_bytecap_(size) +#define _Deref_prepost_bytecap_x_(size) +#define _Deref_prepost_bytecount_(size) +#define _Deref_prepost_bytecount_x_(size) +#define _Deref_prepost_cap_(size) +#define _Deref_prepost_cap_x_(size) +#define _Deref_prepost_count_(size) +#define _Deref_prepost_count_x_(size) +#define _Deref_prepost_opt_bytecap_(size) +#define _Deref_prepost_opt_bytecap_x_(size) +#define _Deref_prepost_opt_bytecount_(size) +#define _Deref_prepost_opt_bytecount_x_(size) +#define _Deref_prepost_opt_cap_(size) +#define _Deref_prepost_opt_cap_x_(size) +#define _Deref_prepost_opt_count_(size) +#define _Deref_prepost_opt_count_x_(size) +#define _Deref_prepost_opt_valid_ +#define _Deref_prepost_opt_valid_bytecap_(size) +#define _Deref_prepost_opt_valid_bytecap_x_(size) +#define _Deref_prepost_opt_valid_cap_(size) +#define _Deref_prepost_opt_valid_cap_x_(size) +#define _Deref_prepost_opt_z_ +#define _Deref_prepost_opt_z_bytecap_(size) +#define _Deref_prepost_opt_z_cap_(size) +#define _Deref_prepost_valid_ +#define _Deref_prepost_valid_bytecap_(size) +#define _Deref_prepost_valid_bytecap_x_(size) +#define _Deref_prepost_valid_cap_(size) +#define _Deref_prepost_valid_cap_x_(size) +#define _Deref_prepost_z_ +#define _Deref_prepost_z_bytecap_(size) +#define _Deref_prepost_z_cap_(size) +#define _Deref_ret_bound_ +#define _Deref_ret_opt_z_ +#define _Deref_ret_range_(lb,ub) +#define _Deref_ret_z_ +#define _Deref2_pre_readonly_ +#define _Field_range_(min,max) +#define _Field_size_(size) +#define _Field_size_bytes_(size) +#define _Field_size_bytes_full_(size) +#define _Field_size_bytes_full_opt_(size) +#define _Field_size_bytes_opt_(size) +#define _Field_size_bytes_part_(size, count) +#define _Field_size_bytes_part_opt_(size, count) +#define _Field_size_full_(size) +#define _Field_size_full_opt_(size) +#define _Field_size_opt_(size) +#define _Field_size_part_(size, count) +#define _Field_size_part_opt_(size, count) +#define _Field_z_ +#define _Function_class_(x) +#define _Group_(annos) +#define _In_ +#define _In_bound_ +#define _In_bytecount_(size) +#define _In_bytecount_c_(size) +#define _In_bytecount_x_(size) +#define _In_count_(size) +#define _In_count_c_(size) +#define _In_count_x_(size) +#define _In_defensive_(annotes) +#define _In_opt_ +#define _In_opt_bytecount_(size) +#define _In_opt_bytecount_c_(size) +#define _In_opt_bytecount_x_(size) +#define _In_opt_count_(size) +#define _In_opt_count_c_(size) +#define _In_opt_count_x_(size) +#define _In_opt_ptrdiff_count_(size) +#define _In_opt_z_ +#define _In_opt_z_bytecount_(size) +#define _In_opt_z_bytecount_c_(size) +#define _In_opt_z_count_(size) +#define _In_opt_z_count_c_(size) +#define _In_ptrdiff_count_(size) +#define _In_range_(lb,ub) +#define _In_reads_(size) +#define _In_reads_bytes_(size) +#define _In_reads_bytes_opt_(size) +#define _In_reads_opt_(size) +#define _In_reads_opt_z_(size) +#define _In_reads_or_z_(size) +#define _In_reads_to_ptr_(ptr) +#define _In_reads_to_ptr_opt_(ptr) +#define _In_reads_to_ptr_opt_z_(ptr) +#define _In_reads_to_ptr_z_(ptr) +#define _In_reads_z_(size) +#define _In_z_ +#define _In_z_bytecount_(size) +#define _In_z_bytecount_c_(size) +#define _In_z_count_(size) +#define _In_z_count_c_(size) +#define _Inout_ +#define _Inout_bytecap_(size) +#define _Inout_bytecap_c_(size) +#define _Inout_bytecap_x_(size) +#define _Inout_bytecount_(size) +#define _Inout_bytecount_c_(size) +#define _Inout_bytecount_x_(size) +#define _Inout_cap_(size) +#define _Inout_cap_c_(size) +#define _Inout_cap_x_(size) +#define _Inout_count_(size) +#define _Inout_count_c_(size) +#define _Inout_count_x_(size) +#define _Inout_defensive_(annotes) +#define _Inout_opt_ +#define _Inout_opt_bytecap_(size) +#define _Inout_opt_bytecap_c_(size) +#define _Inout_opt_bytecap_x_(size) +#define _Inout_opt_bytecount_(size) +#define _Inout_opt_bytecount_c_(size) +#define _Inout_opt_bytecount_x_(size) +#define _Inout_opt_cap_(size) +#define _Inout_opt_cap_c_(size) +#define _Inout_opt_cap_x_(size) +#define _Inout_opt_count_(size) +#define _Inout_opt_count_c_(size) +#define _Inout_opt_count_x_(size) +#define _Inout_opt_ptrdiff_count_(size) +#define _Inout_opt_z_ +#define _Inout_opt_z_bytecap_(size) +#define _Inout_opt_z_bytecap_c_(size) +#define _Inout_opt_z_bytecap_x_(size) +#define _Inout_opt_z_bytecount_(size) +#define _Inout_opt_z_bytecount_c_(size) +#define _Inout_opt_z_cap_(size) +#define _Inout_opt_z_cap_c_(size) +#define _Inout_opt_z_cap_x_(size) +#define _Inout_opt_z_count_(size) +#define _Inout_opt_z_count_c_(size) +#define _Inout_ptrdiff_count_(size) +#define _Inout_updates_(size) +#define _Inout_updates_all_(size) +#define _Inout_updates_all_opt_(size) +#define _Inout_updates_bytes_(size) +#define _Inout_updates_bytes_all_(size) +#define _Inout_updates_bytes_all_opt_(size) +#define _Inout_updates_bytes_opt_(size) +#define _Inout_updates_bytes_to_(size,count) +#define _Inout_updates_bytes_to_opt_(size,count) +#define _Inout_updates_opt_(size) +#define _Inout_updates_opt_z_(size) +#define _Inout_updates_to_(size,count) +#define _Inout_updates_to_opt_(size,count) +#define _Inout_updates_z_(size) +#define _Inout_z_ +#define _Inout_z_bytecap_(size) +#define _Inout_z_bytecap_c_(size) +#define _Inout_z_bytecap_x_(size) +#define _Inout_z_bytecount_(size) +#define _Inout_z_bytecount_c_(size) +#define _Inout_z_cap_(size) +#define _Inout_z_cap_c_(size) +#define _Inout_z_cap_x_(size) +#define _Inout_z_count_(size) +#define _Inout_z_count_c_(size) +#define _Interlocked_operand_ +#define _Literal_ +#define _Maybenull_ +#define _Maybevalid_ +#define _Maybe_raises_SEH_exception +#define _Must_inspect_result_ +#define _Notliteral_ +#define _Notnull_ +#define _Notref_ +#define _Notvalid_ +#define _Null_ +#define _Null_terminated_ +#define _NullNull_terminated_ +#define _On_failure_(annos) +#define _Out_ +#define _Out_bound_ +#define _Out_bytecap_(size) +#define _Out_bytecap_c_(size) +#define _Out_bytecap_post_bytecount_(cap,count) +#define _Out_bytecap_x_(size) +#define _Out_bytecapcount_(capcount) +#define _Out_bytecapcount_x_(capcount) +#define _Out_cap_(size) +#define _Out_cap_c_(size) +#define _Out_cap_m_(mult,size) +#define _Out_cap_post_count_(cap,count) +#define _Out_cap_x_(size) +#define _Out_capcount_(capcount) +#define _Out_capcount_x_(capcount) +#define _Out_defensive_(annotes) +#define _Out_opt_ +#define _Out_opt_bytecap_(size) +#define _Out_opt_bytecap_c_(size) +#define _Out_opt_bytecap_post_bytecount_(cap,count) +#define _Out_opt_bytecap_x_(size) +#define _Out_opt_bytecapcount_(capcount) +#define _Out_opt_bytecapcount_x_(capcount) +#define _Out_opt_cap_(size) +#define _Out_opt_cap_c_(size) +#define _Out_opt_cap_m_(mult,size) +#define _Out_opt_cap_post_count_(cap,count) +#define _Out_opt_cap_x_(size) +#define _Out_opt_capcount_(capcount) +#define _Out_opt_capcount_x_(capcount) +#define _Out_opt_ptrdiff_cap_(size) +#define _Out_opt_z_bytecap_(size) +#define _Out_opt_z_bytecap_c_(size) +#define _Out_opt_z_bytecap_post_bytecount_(cap,count) +#define _Out_opt_z_bytecap_x_(size) +#define _Out_opt_z_bytecapcount_(capcount) +#define _Out_opt_z_cap_(size) +#define _Out_opt_z_cap_c_(size) +#define _Out_opt_z_cap_m_(mult,size) +#define _Out_opt_z_cap_post_count_(cap,count) +#define _Out_opt_z_cap_x_(size) +#define _Out_opt_z_capcount_(capcount) +#define _Out_ptrdiff_cap_(size) +#define _Out_range_(lb,ub) +#define _Out_writes_(size) +#define _Out_writes_all_(size) +#define _Out_writes_all_opt_(size) +#define _Out_writes_bytes_(size) +#define _Out_writes_bytes_all_(size) +#define _Out_writes_bytes_all_opt_(size) +#define _Out_writes_bytes_opt_(size) +#define _Out_writes_bytes_to_(size,count) +#define _Out_writes_bytes_to_opt_(size,count) +#define _Out_writes_opt_(size) +#define _Out_writes_opt_z_(size) +#define _Out_writes_to_(size,count) +#define _Out_writes_to_opt_(size,count) +#define _Out_writes_to_ptr_(ptr) +#define _Out_writes_to_ptr_opt_(ptr) +#define _Out_writes_to_ptr_opt_z_(ptr) +#define _Out_writes_to_ptr_z_(ptr) +#define _Out_writes_z_(size) +#define _Out_z_bytecap_(size) +#define _Out_z_bytecap_c_(size) +#define _Out_z_bytecap_post_bytecount_(cap,count) +#define _Out_z_bytecap_x_(size) +#define _Out_z_bytecapcount_(capcount) +#define _Out_z_cap_(size) +#define _Out_z_cap_c_(size) +#define _Out_z_cap_m_(mult,size) +#define _Out_z_cap_post_count_(cap,count) +#define _Out_z_cap_x_(size) +#define _Out_z_capcount_(capcount) +#define _Outptr_ +#define _Outptr_opt_ +#define _Outptr_opt_result_buffer_(size) +#define _Outptr_opt_result_buffer_all_(size) +#define _Outptr_opt_result_buffer_all_maybenull_(size) +#define _Outptr_opt_result_buffer_maybenull_(size) +#define _Outptr_opt_result_buffer_to_(size, count) +#define _Outptr_opt_result_buffer_to_maybenull_(size, count) +#define _Outptr_opt_result_bytebuffer_(size) +#define _Outptr_opt_result_bytebuffer_all_(size) +#define _Outptr_opt_result_bytebuffer_all_maybenull_(size) +#define _Outptr_opt_result_bytebuffer_maybenull_(size) +#define _Outptr_opt_result_bytebuffer_to_(size, count) +#define _Outptr_opt_result_bytebuffer_to_maybenull_(size, count) +#define _Outptr_opt_result_maybenull_ +#define _Outptr_opt_result_maybenull_z_ +#define _Outptr_opt_result_nullonfailure_ +#define _Outptr_opt_result_z_ +#define _Outptr_result_buffer_(size) +#define _Outptr_result_buffer_all_(size) +#define _Outptr_result_buffer_all_maybenull_(size) +#define _Outptr_result_buffer_maybenull_(size) +#define _Outptr_result_buffer_to_(size, count) +#define _Outptr_result_buffer_to_maybenull_(size, count) +#define _Outptr_result_bytebuffer_(size) +#define _Outptr_result_bytebuffer_all_(size) +#define _Outptr_result_bytebuffer_all_maybenull_(size) +#define _Outptr_result_bytebuffer_maybenull_(size) +#define _Outptr_result_bytebuffer_to_(size, count) +#define _Outptr_result_bytebuffer_to_maybenull_(size, count) +#define _Outptr_result_maybenull_ +#define _Outptr_result_maybenull_z_ +#define _Outptr_result_nullonfailure_ +#define _Outptr_result_z_ +#define _Outref_ +#define _Outref_result_buffer_(size) +#define _Outref_result_buffer_all_(size) +#define _Outref_result_buffer_all_maybenull_(size) +#define _Outref_result_buffer_maybenull_(size) +#define _Outref_result_buffer_to_(size, count) +#define _Outref_result_buffer_to_maybenull_(size, count) +#define _Outref_result_bytebuffer_(size) +#define _Outref_result_bytebuffer_all_(size) +#define _Outref_result_bytebuffer_all_maybenull_(size) +#define _Outref_result_bytebuffer_maybenull_(size) +#define _Outref_result_bytebuffer_to_(size, count) +#define _Outref_result_bytebuffer_to_maybenull_(size, count) +#define _Outref_result_maybenull_ +#define _Outref_result_nullonfailure_ +#define _Points_to_data_ +#define _Post_ +#define _Post_bytecap_(size) +#define _Post_bytecount_(size) +#define _Post_bytecount_c_(size) +#define _Post_bytecount_x_(size) +#define _Post_cap_(size) +#define _Post_count_(size) +#define _Post_count_c_(size) +#define _Post_count_x_(size) +#define _Post_defensive_ +#define _Post_equal_to_(expr) +#define _Post_invalid_ +#define _Post_maybenull_ +#define _Post_maybez_ +#define _Post_notnull_ +#define _Post_null_ +#define _Post_ptr_invalid_ +#define _Post_readable_byte_size_(size) +#define _Post_readable_size_(size) +#define _Post_satisfies_(cond) +#define _Post_valid_ +#define _Post_writable_byte_size_(size) +#define _Post_writable_size_(size) +#define _Post_z_ +#define _Post_z_bytecount_(size) +#define _Post_z_bytecount_c_(size) +#define _Post_z_bytecount_x_(size) +#define _Post_z_count_(size) +#define _Post_z_count_c_(size) +#define _Post_z_count_x_(size) +#define _Pre_ +#define _Pre_bytecap_(size) +#define _Pre_bytecap_c_(size) +#define _Pre_bytecap_x_(size) +#define _Pre_bytecount_(size) +#define _Pre_bytecount_c_(size) +#define _Pre_bytecount_x_(size) +#define _Pre_cap_(size) +#define _Pre_cap_c_(size) +#define _Pre_cap_c_one_ +#define _Pre_cap_for_(param) +#define _Pre_cap_m_(mult,size) +#define _Pre_cap_x_(size) +#define _Pre_count_(size) +#define _Pre_count_c_(size) +#define _Pre_count_x_(size) +#define _Pre_defensive_ +#define _Pre_equal_to_(expr) +#define _Pre_invalid_ +#define _Pre_maybenull_ +#define _Pre_notnull_ +#define _Pre_null_ +#define _Pre_opt_bytecap_(size) +#define _Pre_opt_bytecap_c_(size) +#define _Pre_opt_bytecap_x_(size) +#define _Pre_opt_bytecount_(size) +#define _Pre_opt_bytecount_c_(size) +#define _Pre_opt_bytecount_x_(size) +#define _Pre_opt_cap_(size) +#define _Pre_opt_cap_c_(size) +#define _Pre_opt_cap_c_one_ +#define _Pre_opt_cap_for_(param) +#define _Pre_opt_cap_m_(mult,size) +#define _Pre_opt_cap_x_(size) +#define _Pre_opt_count_(size) +#define _Pre_opt_count_c_(size) +#define _Pre_opt_count_x_(size) +#define _Pre_opt_ptrdiff_cap_(ptr) +#define _Pre_opt_ptrdiff_count_(ptr) +#define _Pre_opt_valid_ +#define _Pre_opt_valid_bytecap_(size) +#define _Pre_opt_valid_bytecap_c_(size) +#define _Pre_opt_valid_bytecap_x_(size) +#define _Pre_opt_valid_cap_(size) +#define _Pre_opt_valid_cap_c_(size) +#define _Pre_opt_valid_cap_x_(size) +#define _Pre_opt_z_ +#define _Pre_opt_z_bytecap_(size) +#define _Pre_opt_z_bytecap_c_(size) +#define _Pre_opt_z_bytecap_x_(size) +#define _Pre_opt_z_cap_(size) +#define _Pre_opt_z_cap_c_(size) +#define _Pre_opt_z_cap_x_(size) +#define _Pre_ptrdiff_cap_(ptr) +#define _Pre_ptrdiff_count_(ptr) +#define _Pre_readable_byte_size_(size) +#define _Pre_readable_size_(size) +#define _Pre_readonly_ +#define _Pre_satisfies_(cond) +#define _Pre_unknown_ +#define _Pre_valid_ +#define _Pre_valid_bytecap_(size) +#define _Pre_valid_bytecap_c_(size) +#define _Pre_valid_bytecap_x_(size) +#define _Pre_valid_cap_(size) +#define _Pre_valid_cap_c_(size) +#define _Pre_valid_cap_x_(size) +#define _Pre_writable_byte_size_(size) +#define _Pre_writable_size_(size) +#define _Pre_writeonly_ +#define _Pre_z_ +#define _Pre_z_bytecap_(size) +#define _Pre_z_bytecap_c_(size) +#define _Pre_z_bytecap_x_(size) +#define _Pre_z_cap_(size) +#define _Pre_z_cap_c_(size) +#define _Pre_z_cap_x_(size) +#define _Prepost_bytecount_(size) +#define _Prepost_bytecount_c_(size) +#define _Prepost_bytecount_x_(size) +#define _Prepost_count_(size) +#define _Prepost_count_c_(size) +#define _Prepost_count_x_(size) +#define _Prepost_opt_bytecount_(size) +#define _Prepost_opt_bytecount_c_(size) +#define _Prepost_opt_bytecount_x_(size) +#define _Prepost_opt_count_(size) +#define _Prepost_opt_count_c_(size) +#define _Prepost_opt_count_x_(size) +#define _Prepost_opt_valid_ +#define _Prepost_opt_z_ +#define _Prepost_valid_ +#define _Prepost_z_ +#define _Printf_format_string_ +#define _Raises_SEH_exception_ +#define _Maybe_raises_SEH_exception_ +#define _Readable_bytes_(size) +#define _Readable_elements_(size) +#define _Reserved_ +#define _Result_nullonfailure_ +#define _Result_zeroonfailure_ +#define __inner_callback +#define _Ret_ +#define _Ret_bound_ +#define _Ret_bytecap_(size) +#define _Ret_bytecap_c_(size) +#define _Ret_bytecap_x_(size) +#define _Ret_bytecount_(size) +#define _Ret_bytecount_c_(size) +#define _Ret_bytecount_x_(size) +#define _Ret_cap_(size) +#define _Ret_cap_c_(size) +#define _Ret_cap_x_(size) +#define _Ret_count_(size) +#define _Ret_count_c_(size) +#define _Ret_count_x_(size) +#define _Ret_maybenull_ +#define _Ret_maybenull_z_ +#define _Ret_notnull_ +#define _Ret_null_ +#define _Ret_opt_ +#define _Ret_opt_bytecap_(size) +#define _Ret_opt_bytecap_c_(size) +#define _Ret_opt_bytecap_x_(size) +#define _Ret_opt_bytecount_(size) +#define _Ret_opt_bytecount_c_(size) +#define _Ret_opt_bytecount_x_(size) +#define _Ret_opt_cap_(size) +#define _Ret_opt_cap_c_(size) +#define _Ret_opt_cap_x_(size) +#define _Ret_opt_count_(size) +#define _Ret_opt_count_c_(size) +#define _Ret_opt_count_x_(size) +#define _Ret_opt_valid_ +#define _Ret_opt_z_ +#define _Ret_opt_z_bytecap_(size) +#define _Ret_opt_z_bytecount_(size) +#define _Ret_opt_z_cap_(size) +#define _Ret_opt_z_count_(size) +#define _Ret_range_(lb,ub) +#define _Ret_valid_ +#define _Ret_writes_(size) +#define _Ret_writes_bytes_(size) +#define _Ret_writes_bytes_maybenull_(size) +#define _Ret_writes_bytes_to_(size,count) +#define _Ret_writes_bytes_to_maybenull_(size,count) +#define _Ret_writes_maybenull_(size) +#define _Ret_writes_maybenull_z_(size) +#define _Ret_writes_to_(size,count) +#define _Ret_writes_to_maybenull_(size,count) +#define _Ret_writes_z_(size) +#define _Ret_z_ +#define _Ret_z_bytecap_(size) +#define _Ret_z_bytecount_(size) +#define _Ret_z_cap_(size) +#define _Ret_z_count_(size) +#define _Return_type_success_(expr) +#define _Scanf_format_string_ +#define _Scanf_s_format_string_ +#define _Struct_size_bytes_(size) +#define _Success_(expr) +#define _Unchanged_(e) +#define _Use_decl_annotations_ +#define _Valid_ +#define _When_(expr, annos) +#define _Writable_bytes_(size) +#define _Writable_elements_(size) + + +#define __bcount(size) +#define __bcount_opt(size) +#define __deref_bcount(size) +#define __deref_bcount_opt(size) +#define __deref_ecount(size) +#define __deref_ecount_opt(size) +#define __deref_in +#define __deref_in_bcount(size) +#define __deref_in_bcount_opt(size) +#define __deref_in_ecount(size) +#define __deref_in_ecount_opt(size) +#define __deref_in_opt +#define __deref_inout +#define __deref_inout_bcount(size) +#define __deref_inout_bcount_full(size) +#define __deref_inout_bcount_full_opt(size) +#define __deref_inout_bcount_opt(size) +#define __deref_inout_bcount_part(size,length) +#define __deref_inout_bcount_part_opt(size,length) +#define __deref_inout_ecount(size) +#define __deref_inout_ecount_full(size) +#define __deref_inout_ecount_full_opt(size) +#define __deref_inout_ecount_opt(size) +#define __deref_inout_ecount_part(size,length) +#define __deref_inout_ecount_part_opt(size,length) +#define __deref_inout_opt +#define __deref_opt_bcount(size) +#define __deref_opt_bcount_opt(size) +#define __deref_opt_ecount(size) +#define __deref_opt_ecount_opt(size) +#define __deref_opt_in +#define __deref_opt_in_bcount(size) +#define __deref_opt_in_bcount_opt(size) +#define __deref_opt_in_ecount(size) +#define __deref_opt_in_ecount_opt(size) +#define __deref_opt_in_opt +#define __deref_opt_inout +#define __deref_opt_inout_bcount(size) +#define __deref_opt_inout_bcount_full(size) +#define __deref_opt_inout_bcount_full_opt(size) +#define __deref_opt_inout_bcount_opt(size) +#define __deref_opt_inout_bcount_part(size,length) +#define __deref_opt_inout_bcount_part_opt(size,length) +#define __deref_opt_inout_ecount(size) +#define __deref_opt_inout_ecount_full(size) +#define __deref_opt_inout_ecount_full_opt(size) +#define __deref_opt_inout_ecount_opt(size) +#define __deref_opt_inout_ecount_part(size,length) +#define __deref_opt_inout_ecount_part_opt(size,length) +#define __deref_opt_inout_opt +#define __deref_opt_out +#define __deref_opt_out_bcount(size) +#define __deref_opt_out_bcount_full(size) +#define __deref_opt_out_bcount_full_opt(size) +#define __deref_opt_out_bcount_opt(size) +#define __deref_opt_out_bcount_part(size,length) +#define __deref_opt_out_bcount_part_opt(size,length) +#define __deref_opt_out_ecount(size) +#define __deref_opt_out_ecount_full(size) +#define __deref_opt_out_ecount_full_opt(size) +#define __deref_opt_out_ecount_opt(size) +#define __deref_opt_out_ecount_part(size,length) +#define __deref_opt_out_ecount_part_opt(size,length) +#define __deref_opt_out_opt +#define __deref_out +#define __deref_out_bcount(size) +#define __deref_out_bcount_full(size) +#define __deref_out_bcount_full_opt(size) +#define __deref_out_bcount_opt(size) +#define __deref_out_bcount_part(size,length) +#define __deref_out_bcount_part_opt(size,length) +#define __deref_out_ecount(size) +#define __deref_out_ecount_full(size) +#define __deref_out_ecount_full_opt(size) +#define __deref_out_ecount_opt(size) +#define __deref_out_ecount_part(size,length) +#define __deref_out_ecount_part_opt(size,length) +#define __deref_out_opt +#define __ecount(size) +#define __ecount_opt(size) +//#define __in /* Conflicts with libstdc++ header macros */ +#define __in_bcount(size) +#define __in_bcount_opt(size) +#define __in_ecount(size) +#define __in_ecount_opt(size) +#define __in_opt +#define __inout +#define __inout_bcount(size) +#define __inout_bcount_full(size) +#define __inout_bcount_full_opt(size) +#define __inout_bcount_opt(size) +#define __inout_bcount_part(size,length) +#define __inout_bcount_part_opt(size,length) +#define __inout_ecount(size) +#define __inout_ecount_full(size) +#define __inout_ecount_full_opt(size) +#define __inout_ecount_opt(size) +#define __inout_ecount_part(size,length) +#define __inout_ecount_part_opt(size,length) +#define __inout_opt +//#define __out /* Conflicts with libstdc++ header macros */ +#define __out_bcount(size) +#define __out_bcount_full(size) +#define __out_bcount_full_opt(size) +#define __out_bcount_opt(size) +#define __out_bcount_part(size,length) +#define __out_bcount_part_opt(size,length) +#define __out_ecount(size) +#define __out_ecount_full(size) +#define __out_ecount_full_opt(size) +#define __out_ecount_opt(size) +#define __out_ecount_part(size,length) +#define __out_ecount_part_opt(size,length) +#define __out_opt + +#define __blocksOn(resource) +#define __callback +#define __checkReturn +#define __format_string +#define __in_awcount(expr,size) +#define __nullnullterminated +#define __nullterminated +#define __out_awcount(expr,size) +#define __override +//#define __reserved /* Conflicts with header included by CarbonCore.h on OS X */ +#define __success(expr) +#define __typefix(ctype) + +#ifndef _countof +#ifndef __cplusplus +#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0])) +#else +extern "C++" { +template +char (*__countof_helper(_CountofType (&_Array)[_SizeOfArray]))[_SizeOfArray]; +#define _countof(_Array) sizeof(*__countof_helper(_Array)) +} +#endif +#endif + +/** + * RTL Definitions + */ + +#define MINCHAR 0x80 +#define MAXCHAR 0x7F + +#ifndef MINSHORT +#define MINSHORT 0x8000 +#endif + +#ifndef MAXSHORT +#define MAXSHORT 0x7FFF +#endif + +#define MINLONG 0x80000000 +#define MAXLONG 0x7FFFFFFF +#define MAXBYTE 0xFF +#define MAXWORD 0xFFFF +#define MAXDWORD 0xFFFFFFFF + +#define FIELD_OFFSET(type, field) ((LONG)(LONG_PTR)&(((type *)0)->field)) + +#define RTL_FIELD_SIZE(type, field) (sizeof(((type *)0)->field)) + +#define RTL_SIZEOF_THROUGH_FIELD(type, field) \ + (FIELD_OFFSET(type, field) + RTL_FIELD_SIZE(type, field)) + +#define RTL_CONTAINS_FIELD(Struct, Size, Field) \ + ((((PCHAR)(&(Struct)->Field)) + sizeof((Struct)->Field)) <= (((PCHAR)(Struct))+(Size))) + +#define RTL_NUMBER_OF_V1(A) (sizeof(A) / sizeof((A)[0])) +#define RTL_NUMBER_OF_V2(A) RTL_NUMBER_OF_V1(A) + +#define RTL_NUMBER_OF(A) RTL_NUMBER_OF_V1(A) + +#define ARRAYSIZE(A) RTL_NUMBER_OF_V2(A) +#define _ARRAYSIZE(A) RTL_NUMBER_OF_V1(A) + +#define RTL_FIELD_TYPE(type, field) (((type*)0)->field) + +#define RTL_NUMBER_OF_FIELD(type, field) (RTL_NUMBER_OF(RTL_FIELD_TYPE(type, field))) + +#define RTL_PADDING_BETWEEN_FIELDS(T, F1, F2) \ + ((FIELD_OFFSET(T, F2) > FIELD_OFFSET(T, F1)) \ + ? (FIELD_OFFSET(T, F2) - FIELD_OFFSET(T, F1) - RTL_FIELD_SIZE(T, F1)) \ + : (FIELD_OFFSET(T, F1) - FIELD_OFFSET(T, F2) - RTL_FIELD_SIZE(T, F2))) + +#if defined(__cplusplus) +#define RTL_CONST_CAST(type) const_cast +#else +#define RTL_CONST_CAST(type) (type) +#endif + +#define RTL_BITS_OF(sizeOfArg) (sizeof(sizeOfArg) * 8) + +#define RTL_BITS_OF_FIELD(type, field) (RTL_BITS_OF(RTL_FIELD_TYPE(type, field))) + +#define CONTAINING_RECORD(address, type, field) \ + ((type *)((PCHAR)(address) - (ULONG_PTR)(&((type *)0)->field))) + #endif #endif /* WINPR_SPEC_H */ diff --git a/winpr/include/winpr/sspi.h b/winpr/include/winpr/sspi.h index f2adcd2bb..817a13477 100644 --- a/winpr/include/winpr/sspi.h +++ b/winpr/include/winpr/sspi.h @@ -1012,7 +1012,7 @@ extern "C" { WINPR_API void sspi_GlobalInit(void); WINPR_API void sspi_GlobalFinish(void); -WINPR_API void sspi_SecBufferAlloc(PSecBuffer SecBuffer, size_t size); +WINPR_API void sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size); WINPR_API void sspi_SecBufferFree(PSecBuffer SecBuffer); WINPR_API void sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, char* user, char* domain, char* password); diff --git a/winpr/include/winpr/synch.h b/winpr/include/winpr/synch.h index 10647ff30..181b6f490 100644 --- a/winpr/include/winpr/synch.h +++ b/winpr/include/winpr/synch.h @@ -297,7 +297,7 @@ WINPR_API BOOL DeleteTimerQueueTimer(HANDLE TimerQueue, HANDLE Timer, HANDLE Com #endif -#if ((_WIN32) && (_WIN32_WINNT < 0x0600)) +#if ((_WIN32) && (_WIN32_WINNT < 0x0403)) WINPR_API BOOL InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD Flags); diff --git a/winpr/include/winpr/winsock.h b/winpr/include/winpr/winsock.h index 647f6bc2c..f25ba9997 100644 --- a/winpr/include/winpr/winsock.h +++ b/winpr/include/winpr/winsock.h @@ -34,10 +34,92 @@ PCSTR inet_ntop(INT Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize); #else /* _WIN32 */ +#include +#include +#include +#include #include +#include +#include +#include +#include +#include + +typedef UINT_PTR SOCKET; typedef struct sockaddr_storage SOCKADDR_STORAGE; +#define WSADESCRIPTION_LEN 256 +#define WSASYS_STATUS_LEN 128 + +typedef struct WSAData +{ + WORD wVersion; + WORD wHighVersion; +#ifdef _M_AMD64 + unsigned short iMaxSockets; + unsigned short iMaxUdpDg; + char* lpVendorInfo; + char szDescription[WSADESCRIPTION_LEN+1]; + char szSystemStatus[WSASYS_STATUS_LEN+1]; +#else + char szDescription[WSADESCRIPTION_LEN+1]; + char szSystemStatus[WSASYS_STATUS_LEN+1]; + unsigned short iMaxSockets; + unsigned short iMaxUdpDg; + char* lpVendorInfo; +#endif +} WSADATA, *LPWSADATA; + +#ifndef MAKEWORD +#define MAKEWORD(a,b) ((WORD)(((BYTE)((DWORD_PTR)(a) & 0xFF)) | (((WORD)((BYTE)((DWORD_PTR)(b) & 0xFF))) << 8))) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +WINPR_API int WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData); +WINPR_API int WSACleanup(void); + +WINPR_API void WSASetLastError(int iError); +WINPR_API int WSAGetLastError(void); + +WINPR_API SOCKET _accept(SOCKET s, struct sockaddr* addr, int* addrlen); +WINPR_API int _bind(SOCKET s, const struct sockaddr* addr, int namelen); +WINPR_API int closesocket(SOCKET s); +WINPR_API int _connect(SOCKET s, const struct sockaddr* name, int namelen); +WINPR_API int _ioctlsocket(SOCKET s, long cmd, u_long* argp); +WINPR_API int _getpeername(SOCKET s, struct sockaddr* name, int* namelen); +WINPR_API int _getsockname(SOCKET s, struct sockaddr* name, int* namelen); +WINPR_API int _getsockopt(SOCKET s, int level, int optname, char* optval, int* optlen); +WINPR_API u_long _htonl(u_long hostlong); +WINPR_API u_short _htons(u_short hostshort); +WINPR_API unsigned long _inet_addr(const char* cp); +WINPR_API char* _inet_ntoa(struct in_addr in); +WINPR_API int _listen(SOCKET s, int backlog); +WINPR_API u_long _ntohl(u_long netlong); +WINPR_API u_short _ntohs(u_short netshort); +WINPR_API int _recv(SOCKET s, char* buf, int len, int flags); +WINPR_API int _recvfrom(SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int* fromlen); +WINPR_API int _select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, const struct timeval* timeout); +WINPR_API int _send(SOCKET s, const char* buf, int len, int flags); +WINPR_API int _sendto(SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen); +WINPR_API int _setsockopt(SOCKET s, int level, int optname, const char* optval, int optlen); +WINPR_API int _shutdown(SOCKET s, int how); +WINPR_API SOCKET _socket(int af, int type, int protocol); +WINPR_API struct hostent* _gethostbyaddr(const char* addr, int len, int type); +WINPR_API struct hostent* _gethostbyname(const char* name); +WINPR_API int _gethostname(char* name, int namelen); +WINPR_API struct servent* _getservbyport(int port, const char* proto); +WINPR_API struct servent* _getservbyname(const char* name, const char* proto); +WINPR_API struct protoent* _getprotobynumber(int number); +WINPR_API struct protoent* _getprotobyname(const char* name); + +#ifdef __cplusplus +} +#endif + #endif /* _WIN32 */ #endif /* WINPR_WINSOCK_H */ diff --git a/winpr/include/winpr/wlog.h b/winpr/include/winpr/wlog.h index 87b79c8a2..eda5e60a3 100644 --- a/winpr/include/winpr/wlog.h +++ b/winpr/include/winpr/wlog.h @@ -48,6 +48,7 @@ typedef struct _wLogAppender wLogAppender; #define WLOG_ERROR 4 #define WLOG_FATAL 5 #define WLOG_OFF 6 +#define WLOG_LEVEL_INHERIT 0xFFFF /** * Log Message @@ -198,7 +199,7 @@ struct _wLog WINPR_API void WLog_PrintMessage(wLog* log, wLogMessage* message, ...); #define WLog_Print(_log, _log_level, _fmt, ...) \ - if (_log_level >= _log->Level) { \ + if (_log_level >= WLog_GetLogLevel(_log)) { \ wLogMessage _log_message; \ _log_message.Type = WLOG_MESSAGE_TEXT; \ _log_message.Level = _log_level; \ @@ -210,7 +211,7 @@ WINPR_API void WLog_PrintMessage(wLog* log, wLogMessage* message, ...); } #define WLog_Data(_log, _log_level, ...) \ - if (_log_level >= _log->Level) { \ + if (_log_level >= WLog_GetLogLevel(_log)) { \ wLogMessage _log_message; \ _log_message.Type = WLOG_MESSAGE_DATA; \ _log_message.Level = _log_level; \ @@ -222,7 +223,7 @@ WINPR_API void WLog_PrintMessage(wLog* log, wLogMessage* message, ...); } #define WLog_Image(_log, _log_level, ...) \ - if (_log_level >= _log->Level) { \ + if (_log_level >= WLog_GetLogLevel(_log)) { \ wLogMessage _log_message; \ _log_message.Type = WLOG_MESSAGE_IMAGE; \ _log_message.Level = _log_level; \ @@ -234,7 +235,7 @@ WINPR_API void WLog_PrintMessage(wLog* log, wLogMessage* message, ...); } #define WLog_Packet(_log, _log_level, ...) \ - if (_log_level >= _log->Level) { \ + if (_log_level >= WLog_GetLogLevel(_log)) { \ wLogMessage _log_message; \ _log_message.Type = WLOG_MESSAGE_PACKET; \ _log_message.Level = _log_level; \ diff --git a/winpr/include/winpr/wtsapi.h b/winpr/include/winpr/wtsapi.h index 42f2b0101..b8c61cfd0 100644 --- a/winpr/include/winpr/wtsapi.h +++ b/winpr/include/winpr/wtsapi.h @@ -25,10 +25,20 @@ #include -#ifndef _WIN32 +#ifdef _WIN32 + +#define CurrentTime _CurrentTime /* Workaround for X11 "CurrentTime" header conflict */ + +#endif + +#ifdef _WIN32 + +#include + +#else /** - * Virtual Channel Protocol (Common) + * Virtual Channel Protocol (pchannel.h) */ #define CHANNEL_CHUNK_LENGTH 1600 @@ -41,11 +51,6 @@ #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 @@ -76,8 +81,29 @@ typedef struct tagCHANNEL_PDU_HEADER UINT32 flags; } CHANNEL_PDU_HEADER, *PCHANNEL_PDU_HEADER; +#endif + /** - * Virtual Channel Client API + * These channel flags are defined in some versions of pchannel.h only + */ + +#ifndef CHANNEL_FLAG_SHOW_PROTOCOL +#define CHANNEL_FLAG_SHOW_PROTOCOL 0x10 +#endif +#ifndef CHANNEL_FLAG_SUSPEND +#define CHANNEL_FLAG_SUSPEND 0x20 +#endif +#ifndef CHANNEL_FLAG_RESUME +#define CHANNEL_FLAG_RESUME 0x40 +#endif +#ifndef CHANNEL_FLAG_SHADOW_PERSISTENT +#define CHANNEL_FLAG_SHADOW_PERSISTENT 0x80 +#endif + +#if !defined(_WIN32) || !defined(H_CCHANNEL) + +/** + * Virtual Channel Client API (cchannel.h) */ #ifdef _WIN32 @@ -211,8 +237,12 @@ typedef VIRTUALCHANNELENTRYEX *PVIRTUALCHANNELENTRYEX; typedef HRESULT (VCAPITYPE *PFNVCAPIGETINSTANCE)(REFIID refiid, PULONG pNumObjs, PVOID* ppObjArray); +#endif + +#if !defined(_WIN32) || !defined(_INC_WTSAPI) + /** - * Windows Terminal Services API (WtsApi) + * Windows Terminal Services API (wtsapi32.h) */ #define WTS_CURRENT_SERVER ((HANDLE)NULL) @@ -433,12 +463,12 @@ typedef struct _WTSINFOW DWORD OutgoingCompressedBytes; WCHAR WinStationName[WINSTATIONNAME_LENGTH]; WCHAR Domain[DOMAIN_LENGTH]; - WCHAR UserName[USERNAME_LENGTH+1]; + WCHAR UserName[USERNAME_LENGTH + 1]; LARGE_INTEGER ConnectTime; LARGE_INTEGER DisconnectTime; LARGE_INTEGER LastInputTime; LARGE_INTEGER LogonTime; - LARGE_INTEGER CurrentTime; + LARGE_INTEGER _CurrentTime; /* Conflicts with X11 headers */ } WTSINFOW, *PWTSINFOW; typedef struct _WTSINFOA @@ -458,7 +488,7 @@ typedef struct _WTSINFOA LARGE_INTEGER DisconnectTime; LARGE_INTEGER LastInputTime; LARGE_INTEGER LogonTime; - LARGE_INTEGER CurrentTime; + LARGE_INTEGER _CurrentTime; /* Conflicts with X11 headers */ } WTSINFOA, *PWTSINFOA; #define WTS_SESSIONSTATE_UNKNOWN 0xFFFFFFFF @@ -477,7 +507,7 @@ typedef struct _WTSINFOEX_LEVEL1_W LARGE_INTEGER ConnectTime; LARGE_INTEGER DisconnectTime; LARGE_INTEGER LastInputTime; - LARGE_INTEGER CurrentTime; + LARGE_INTEGER _CurrentTime; /* Conflicts with X11 headers */ DWORD IncomingBytes; DWORD OutgoingBytes; DWORD IncomingFrames; @@ -498,7 +528,7 @@ typedef struct _WTSINFOEX_LEVEL1_A LARGE_INTEGER ConnectTime; LARGE_INTEGER DisconnectTime; LARGE_INTEGER LastInputTime; - LARGE_INTEGER CurrentTime; + LARGE_INTEGER _CurrentTime; /* Conflicts with X11 headers */ DWORD IncomingBytes; DWORD OutgoingBytes; DWORD IncomingFrames; @@ -707,7 +737,7 @@ typedef struct _WTSUSERCONFIGW #define WTS_EVENT_LOGOFF 0x00000040 #define WTS_EVENT_STATECHANGE 0x00000080 #define WTS_EVENT_LICENSE 0x00000100 -#define WTS_EVENT_ALL 0x7fffffff +#define WTS_EVENT_ALL 0x7FFFFFFF #define WTS_EVENT_FLUSH 0x80000000 #define REMOTECONTROL_KBDSHIFT_HOTKEY 0x1 @@ -925,122 +955,128 @@ typedef struct _WTSLISTENERCONFIGA extern "C" { #endif -WINPR_API BOOL WTSStopRemoteControlSession(ULONG LogonId); +WINPR_API BOOL WINAPI 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 WINAPI WTSStartRemoteControlSessionW(LPWSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers); +WINPR_API BOOL WINAPI 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 WINAPI WTSConnectSessionW(ULONG LogonId, ULONG TargetLogonId, PWSTR pPassword, BOOL bWait); +WINPR_API BOOL WINAPI 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 BOOL WINAPI WTSEnumerateServersW(LPWSTR pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOW* ppServerInfo, DWORD* pCount); +WINPR_API BOOL WINAPI 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 WINAPI WTSOpenServerW(LPWSTR pServerName); +WINPR_API HANDLE WINAPI WTSOpenServerA(LPSTR pServerName); -WINPR_API HANDLE WTSOpenServerExW(LPWSTR pServerName); -WINPR_API HANDLE WTSOpenServerExA(LPSTR pServerName); +WINPR_API HANDLE WINAPI WTSOpenServerExW(LPWSTR pServerName); +WINPR_API HANDLE WINAPI WTSOpenServerExA(LPSTR pServerName); -WINPR_API VOID WTSCloseServer(HANDLE hServer); +WINPR_API VOID WINAPI 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 WINAPI WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOW* ppSessionInfo, DWORD* pCount); +WINPR_API BOOL WINAPI 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 WINAPI WTSEnumerateSessionsExW(HANDLE hServer, DWORD* pLevel, DWORD Filter, PWTS_SESSION_INFO_1W* ppSessionInfo, DWORD* pCount); +WINPR_API BOOL WINAPI 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 WINAPI WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount); +WINPR_API BOOL WINAPI 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 WINAPI 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 WINAPI WTSQuerySessionInformationW(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPWSTR* ppBuffer, DWORD* pBytesReturned); +WINPR_API BOOL WINAPI 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 WINAPI WTSQueryUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR* ppBuffer, DWORD* pBytesReturned); +WINPR_API BOOL WINAPI 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 WINAPI WTSSetUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR pBuffer, DWORD DataLength); +WINPR_API BOOL WINAPI 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, +WINPR_API BOOL WINAPI 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, +WINPR_API BOOL WINAPI 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 WINAPI WTSDisconnectSession(HANDLE hServer, DWORD SessionId, BOOL bWait); -WINPR_API BOOL WTSLogoffSession(HANDLE hServer, DWORD SessionId, BOOL bWait); +WINPR_API BOOL WINAPI WTSLogoffSession(HANDLE hServer, DWORD SessionId, BOOL bWait); -WINPR_API BOOL WTSShutdownSystem(HANDLE hServer, DWORD ShutdownFlag); +WINPR_API BOOL WINAPI WTSShutdownSystem(HANDLE hServer, DWORD ShutdownFlag); -WINPR_API BOOL WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags); +WINPR_API BOOL WINAPI WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags); -WINPR_API HANDLE WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName); +WINPR_API HANDLE WINAPI WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName); -WINPR_API HANDLE WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags); +WINPR_API HANDLE WINAPI WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags); -WINPR_API BOOL WTSVirtualChannelClose(HANDLE hChannelHandle); +WINPR_API BOOL WINAPI WTSVirtualChannelClose(HANDLE hChannelHandle); -WINPR_API BOOL WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead); +WINPR_API BOOL WINAPI 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 WINAPI WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten); -WINPR_API BOOL WTSVirtualChannelPurgeInput(HANDLE hChannelHandle); +WINPR_API BOOL WINAPI WTSVirtualChannelPurgeInput(HANDLE hChannelHandle); -WINPR_API BOOL WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle); +WINPR_API BOOL WINAPI WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle); -WINPR_API BOOL WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned); +WINPR_API BOOL WINAPI WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned); -WINPR_API VOID WTSFreeMemory(PVOID pMemory); +WINPR_API VOID WINAPI WTSFreeMemory(PVOID pMemory); -WINPR_API BOOL WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags); +WINPR_API BOOL WINAPI WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags); -WINPR_API BOOL WTSUnRegisterSessionNotification(HWND hWnd); +WINPR_API BOOL WINAPI WTSUnRegisterSessionNotification(HWND hWnd); -WINPR_API BOOL WTSRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd, DWORD dwFlags); +WINPR_API BOOL WINAPI WTSRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd, DWORD dwFlags); -WINPR_API BOOL WTSUnRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd); +WINPR_API BOOL WINAPI WTSUnRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd); -WINPR_API BOOL WTSQueryUserToken(ULONG SessionId, PHANDLE phToken); +WINPR_API BOOL WINAPI 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 WINAPI WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries); +WINPR_API BOOL WINAPI 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 WINAPI WTSEnumerateProcessesExW(HANDLE hServer, DWORD* pLevel, DWORD SessionId, LPWSTR* ppProcessInfo, DWORD* pCount); +WINPR_API BOOL WINAPI 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 WINAPI WTSEnumerateListenersW(HANDLE hServer, PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEW pListeners, DWORD* pCount); +WINPR_API BOOL WINAPI 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 WINAPI WTSQueryListenerConfigW(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer); +WINPR_API BOOL WINAPI WTSQueryListenerConfigA(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer); -WINPR_API BOOL WTSCreateListenerW(HANDLE hServer, PVOID pReserved, DWORD Reserved, +WINPR_API BOOL WINAPI WTSCreateListenerW(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer, DWORD flag); -WINPR_API BOOL WTSCreateListenerA(HANDLE hServer, PVOID pReserved, DWORD Reserved, +WINPR_API BOOL WINAPI WTSCreateListenerA(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer, DWORD flag); -WINPR_API BOOL WTSSetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved, +WINPR_API BOOL WINAPI 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, +WINPR_API BOOL WINAPI 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, +WINPR_API BOOL WINAPI 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, +WINPR_API BOOL WINAPI 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); +/** + * WTSEnableChildSessions, WTSIsChildSessionsEnabled and WTSGetChildSessionId + * are not explicitly declared as WINAPI like other WTSAPI functions. + * Since they are declared as extern "C", we explicitly declare them as CDECL. + */ -WINPR_API BOOL WTSIsChildSessionsEnabled(PBOOL pbEnabled); +WINPR_API BOOL CDECL WTSEnableChildSessions(BOOL bEnable); -WINPR_API BOOL WTSGetChildSessionId(PULONG pSessionId); +WINPR_API BOOL CDECL WTSIsChildSessionsEnabled(PBOOL pbEnabled); + +WINPR_API BOOL CDECL WTSGetChildSessionId(PULONG pSessionId); #ifdef __cplusplus } @@ -1090,5 +1126,241 @@ WINPR_API BOOL WTSGetChildSessionId(PULONG pSessionId); #endif +#ifndef _WIN32 + +/** + * WTSGetActiveConsoleSessionId is declared in WinBase.h + * and exported by kernel32.dll, so we have to treat it separately. + */ + +WINPR_API DWORD WINAPI WTSGetActiveConsoleSessionId(void); + +#endif + +typedef BOOL (WINAPI * WTS_STOP_REMOTE_CONTROL_SESSION_FN)(ULONG LogonId); + +typedef BOOL (WINAPI * WTS_START_REMOTE_CONTROL_SESSION_FN_W)(LPWSTR pTargetServerName, + ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers); +typedef BOOL (WINAPI * WTS_START_REMOTE_CONTROL_SESSION_FN_A)(LPSTR pTargetServerName, + ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers); + +typedef BOOL (WINAPI * WTS_CONNECT_SESSION_FN_W)(ULONG LogonId, ULONG TargetLogonId, PWSTR pPassword, BOOL bWait); +typedef BOOL (WINAPI * WTS_CONNECT_SESSION_FN_A)(ULONG LogonId, ULONG TargetLogonId, PSTR pPassword, BOOL bWait); + +typedef BOOL (WINAPI * WTS_ENUMERATE_SERVERS_FN_W)(LPWSTR pDomainName, + DWORD Reserved, DWORD Version, PWTS_SERVER_INFOW* ppServerInfo, DWORD* pCount); +typedef BOOL (WINAPI * WTS_ENUMERATE_SERVERS_FN_A)(LPSTR pDomainName, + DWORD Reserved, DWORD Version, PWTS_SERVER_INFOA* ppServerInfo, DWORD* pCount); + +typedef HANDLE (WINAPI * WTS_OPEN_SERVER_FN_W)(LPWSTR pServerName); +typedef HANDLE (WINAPI * WTS_OPEN_SERVER_FN_A)(LPSTR pServerName); + +typedef HANDLE (WINAPI * WTS_OPEN_SERVER_EX_FN_W)(LPWSTR pServerName); +typedef HANDLE (WINAPI * WTS_OPEN_SERVER_EX_FN_A)(LPSTR pServerName); + +typedef VOID (WINAPI * WTS_CLOSE_SERVER_FN)(HANDLE hServer); + +typedef BOOL (WINAPI * WTS_ENUMERATE_SESSIONS_FN_W)(HANDLE hServer, + DWORD Reserved, DWORD Version, PWTS_SESSION_INFOW* ppSessionInfo, DWORD* pCount); +typedef BOOL (WINAPI * WTS_ENUMERATE_SESSIONS_FN_A)(HANDLE hServer, + DWORD Reserved, DWORD Version, PWTS_SESSION_INFOA* ppSessionInfo, DWORD* pCount); + +typedef BOOL (WINAPI * WTS_ENUMERATE_SESSIONS_EX_FN_W)(HANDLE hServer, + DWORD* pLevel, DWORD Filter, PWTS_SESSION_INFO_1W* ppSessionInfo, DWORD* pCount); +typedef BOOL (WINAPI * WTS_ENUMERATE_SESSIONS_EX_FN_A)(HANDLE hServer, + DWORD* pLevel, DWORD Filter, PWTS_SESSION_INFO_1A* ppSessionInfo, DWORD* pCount); + +typedef BOOL (WINAPI * WTS_ENUMERATE_PROCESSES_FN_W)(HANDLE hServer, + DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount); +typedef BOOL (WINAPI * WTS_ENUMERATE_PROCESSES_FN_A)(HANDLE hServer, + DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOA* ppProcessInfo, DWORD* pCount); + +typedef BOOL (WINAPI * WTS_TERMINATE_PROCESS_FN)(HANDLE hServer, DWORD ProcessId, DWORD ExitCode); + +typedef BOOL (WINAPI * WTS_QUERY_SESSION_INFORMATION_FN_W)(HANDLE hServer, + DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPWSTR* ppBuffer, DWORD* pBytesReturned); +typedef BOOL (WINAPI * WTS_QUERY_SESSION_INFORMATION_FN_A)(HANDLE hServer, + DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPSTR* ppBuffer, DWORD* pBytesReturned); + +typedef BOOL (WINAPI * WTS_QUERY_USER_CONFIG_FN_W)(LPWSTR pServerName, + LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR* ppBuffer, DWORD* pBytesReturned); +typedef BOOL (WINAPI * WTS_QUERY_USER_CONFIG_FN_A)(LPSTR pServerName, + LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR* ppBuffer, DWORD* pBytesReturned); + +typedef BOOL (WINAPI * WTS_SET_USER_CONFIG_FN_W)(LPWSTR pServerName, + LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR pBuffer, DWORD DataLength); +typedef BOOL (WINAPI * WTS_SET_USER_CONFIG_FN_A)(LPSTR pServerName, + LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR pBuffer, DWORD DataLength); + +typedef BOOL (WINAPI * WTS_SEND_MESSAGE_FN_W)(HANDLE hServer, DWORD SessionId, LPWSTR pTitle, DWORD TitleLength, + LPWSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait); +typedef BOOL (WINAPI * WTS_SEND_MESSAGE_FN_A)(HANDLE hServer, DWORD SessionId, LPSTR pTitle, DWORD TitleLength, + LPSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait); + +typedef BOOL (WINAPI * WTS_DISCONNECT_SESSION_FN)(HANDLE hServer, DWORD SessionId, BOOL bWait); + +typedef BOOL (WINAPI * WTS_LOGOFF_SESSION_FN)(HANDLE hServer, DWORD SessionId, BOOL bWait); + +typedef BOOL (WINAPI * WTS_SHUTDOWN_SYSTEM_FN)(HANDLE hServer, DWORD ShutdownFlag); + +typedef BOOL (WINAPI * WTS_WAIT_SYSTEM_EVENT_FN)(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags); + +typedef HANDLE (WINAPI * WTS_VIRTUAL_CHANNEL_OPEN_FN)(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName); + +typedef HANDLE (WINAPI * WTS_VIRTUAL_CHANNEL_OPEN_EX_FN)(DWORD SessionId, LPSTR pVirtualName, DWORD flags); + +typedef BOOL (WINAPI * WTS_VIRTUAL_CHANNEL_CLOSE_FN)(HANDLE hChannelHandle); + +typedef BOOL (WINAPI * WTS_VIRTUAL_CHANNEL_READ_FN)(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead); + +typedef BOOL (WINAPI * WTS_VIRTUAL_CHANNEL_WRITE_FN)(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten); + +typedef BOOL (WINAPI * WTS_VIRTUAL_CHANNEL_PURGE_INPUT_FN)(HANDLE hChannelHandle); + +typedef BOOL (WINAPI * WTS_VIRTUAL_CHANNEL_PURGE_OUTPUT_FN)(HANDLE hChannelHandle); + +typedef BOOL (WINAPI * WTS_VIRTUAL_CHANNEL_QUERY_FN)(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned); + +typedef VOID (WINAPI * WTS_FREE_MEMORY_FN)(PVOID pMemory); + +typedef BOOL (WINAPI * WTS_REGISTER_SESSION_NOTIFICATION_FN)(HWND hWnd, DWORD dwFlags); + +typedef BOOL (WINAPI * WTS_UNREGISTER_SESSION_NOTIFICATION_FN)(HWND hWnd); + +typedef BOOL (WINAPI * WTS_REGISTER_SESSION_NOTIFICATION_EX_FN)(HANDLE hServer, HWND hWnd, DWORD dwFlags); + +typedef BOOL (WINAPI * WTS_UNREGISTER_SESSION_NOTIFICATION_EX_FN)(HANDLE hServer, HWND hWnd); + +typedef BOOL (WINAPI * WTS_QUERY_USER_TOKEN_FN)(ULONG SessionId, PHANDLE phToken); + +typedef BOOL (WINAPI * WTS_FREE_MEMORY_EX_FN_W)(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries); +typedef BOOL (WINAPI * WTS_FREE_MEMORY_EX_FN_A)(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries); + +typedef BOOL (WINAPI * WTS_ENUMERATE_PROCESSES_EX_FN_W)(HANDLE hServer, + DWORD* pLevel, DWORD SessionId, LPWSTR* ppProcessInfo, DWORD* pCount); +typedef BOOL (WINAPI * WTS_ENUMERATE_PROCESSES_EX_FN_A)(HANDLE hServer, + DWORD* pLevel, DWORD SessionId, LPSTR* ppProcessInfo, DWORD* pCount); + +typedef BOOL (WINAPI * WTS_ENUMERATE_LISTENERS_FN_W)(HANDLE hServer, + PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEW pListeners, DWORD* pCount); +typedef BOOL (WINAPI * WTS_ENUMERATE_LISTENERS_FN_A)(HANDLE hServer, + PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEA pListeners, DWORD* pCount); + +typedef BOOL (WINAPI * WTS_QUERY_LISTENER_CONFIG_FN_W)(HANDLE hServer, + PVOID pReserved, DWORD Reserved, LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer); +typedef BOOL (WINAPI * WTS_QUERY_LISTENER_CONFIG_FN_A)(HANDLE hServer, + PVOID pReserved, DWORD Reserved, LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer); + +typedef BOOL (WINAPI * WTS_CREATE_LISTENER_FN_W)(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer, DWORD flag); +typedef BOOL (WINAPI * WTS_CREATE_LISTENER_FN_A)(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer, DWORD flag); + +typedef BOOL (WINAPI * WTS_SET_LISTENER_SECURITY_FN_W)(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPWSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor); +typedef BOOL (WINAPI * WTS_SET_LISTENER_SECURITY_FN_A)(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor); + +typedef BOOL (WINAPI * WTS_GET_LISTENER_SECURITY_FN_W)(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPWSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded); +typedef BOOL (WINAPI * WTS_GET_LISTENER_SECURITY_FN_A)(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded); + +typedef BOOL (CDECL * WTS_ENABLE_CHILD_SESSIONS_FN)(BOOL bEnable); + +typedef BOOL (CDECL * WTS_IS_CHILD_SESSIONS_ENABLED_FN)(PBOOL pbEnabled); + +typedef BOOL (CDECL * WTS_GET_CHILD_SESSION_ID_FN)(PULONG pSessionId); + +typedef DWORD (WINAPI * WTS_GET_ACTIVE_CONSOLE_SESSION_ID_FN)(void); + +struct _WtsApiFunctionTable +{ + DWORD dwVersion; + DWORD dwFlags; + + WTS_STOP_REMOTE_CONTROL_SESSION_FN pStopRemoteControlSession; + WTS_START_REMOTE_CONTROL_SESSION_FN_W pStartRemoteControlSessionW; + WTS_START_REMOTE_CONTROL_SESSION_FN_A pStartRemoteControlSessionA; + WTS_CONNECT_SESSION_FN_W pConnectSessionW; + WTS_CONNECT_SESSION_FN_A pConnectSessionA; + WTS_ENUMERATE_SERVERS_FN_W pEnumerateServersW; + WTS_ENUMERATE_SERVERS_FN_A pEnumerateServersA; + WTS_OPEN_SERVER_FN_W pOpenServerW; + WTS_OPEN_SERVER_FN_A pOpenServerA; + WTS_OPEN_SERVER_EX_FN_W pOpenServerExW; + WTS_OPEN_SERVER_EX_FN_A pOpenServerExA; + WTS_CLOSE_SERVER_FN pCloseServer; + WTS_ENUMERATE_SESSIONS_FN_W pEnumerateSessionsW; + WTS_ENUMERATE_SESSIONS_FN_A pEnumerateSessionsA; + WTS_ENUMERATE_SESSIONS_EX_FN_W pEnumerateSessionsExW; + WTS_ENUMERATE_SESSIONS_EX_FN_A pEnumerateSessionsExA; + WTS_ENUMERATE_PROCESSES_FN_W pEnumerateProcessesW; + WTS_ENUMERATE_PROCESSES_FN_A pEnumerateProcessesA; + WTS_TERMINATE_PROCESS_FN pTerminateProcess; + WTS_QUERY_SESSION_INFORMATION_FN_W pQuerySessionInformationW; + WTS_QUERY_SESSION_INFORMATION_FN_A pQuerySessionInformationA; + WTS_QUERY_USER_CONFIG_FN_W pQueryUserConfigW; + WTS_QUERY_USER_CONFIG_FN_A pQueryUserConfigA; + WTS_SET_USER_CONFIG_FN_W pSetUserConfigW; + WTS_SET_USER_CONFIG_FN_A pSetUserConfigA; + WTS_SEND_MESSAGE_FN_W pSendMessageW; + WTS_SEND_MESSAGE_FN_A pSendMessageA; + WTS_DISCONNECT_SESSION_FN pDisconnectSession; + WTS_LOGOFF_SESSION_FN pLogoffSession; + WTS_SHUTDOWN_SYSTEM_FN pShutdownSystem; + WTS_WAIT_SYSTEM_EVENT_FN pWaitSystemEvent; + WTS_VIRTUAL_CHANNEL_OPEN_FN pVirtualChannelOpen; + WTS_VIRTUAL_CHANNEL_OPEN_EX_FN pVirtualChannelOpenEx; + WTS_VIRTUAL_CHANNEL_CLOSE_FN pVirtualChannelClose; + WTS_VIRTUAL_CHANNEL_READ_FN pVirtualChannelRead; + WTS_VIRTUAL_CHANNEL_WRITE_FN pVirtualChannelWrite; + WTS_VIRTUAL_CHANNEL_PURGE_INPUT_FN pVirtualChannelPurgeInput; + WTS_VIRTUAL_CHANNEL_PURGE_OUTPUT_FN pVirtualChannelPurgeOutput; + WTS_VIRTUAL_CHANNEL_QUERY_FN pVirtualChannelQuery; + WTS_FREE_MEMORY_FN pFreeMemory; + WTS_REGISTER_SESSION_NOTIFICATION_FN pRegisterSessionNotification; + WTS_UNREGISTER_SESSION_NOTIFICATION_FN pUnRegisterSessionNotification; + WTS_REGISTER_SESSION_NOTIFICATION_EX_FN pRegisterSessionNotificationEx; + WTS_UNREGISTER_SESSION_NOTIFICATION_EX_FN pUnRegisterSessionNotificationEx; + WTS_QUERY_USER_TOKEN_FN pQueryUserToken; + WTS_FREE_MEMORY_EX_FN_W pFreeMemoryExW; + WTS_FREE_MEMORY_EX_FN_A pFreeMemoryExA; + WTS_ENUMERATE_PROCESSES_EX_FN_W pEnumerateProcessesExW; + WTS_ENUMERATE_PROCESSES_EX_FN_A pEnumerateProcessesExA; + WTS_ENUMERATE_LISTENERS_FN_W pEnumerateListenersW; + WTS_ENUMERATE_LISTENERS_FN_A pEnumerateListenersA; + WTS_QUERY_LISTENER_CONFIG_FN_W pQueryListenerConfigW; + WTS_QUERY_LISTENER_CONFIG_FN_A pQueryListenerConfigA; + WTS_CREATE_LISTENER_FN_W pCreateListenerW; + WTS_CREATE_LISTENER_FN_A pCreateListenerA; + WTS_SET_LISTENER_SECURITY_FN_W pSetListenerSecurityW; + WTS_SET_LISTENER_SECURITY_FN_A pSetListenerSecurityA; + WTS_GET_LISTENER_SECURITY_FN_W pGetListenerSecurityW; + WTS_GET_LISTENER_SECURITY_FN_A pGetListenerSecurityA; + WTS_ENABLE_CHILD_SESSIONS_FN pEnableChildSessions; + WTS_IS_CHILD_SESSIONS_ENABLED_FN pIsChildSessionsEnabled; + WTS_GET_CHILD_SESSION_ID_FN pGetChildSessionId; + WTS_GET_ACTIVE_CONSOLE_SESSION_ID_FN pGetActiveConsoleSessionId; +}; +typedef struct _WtsApiFunctionTable WtsApiFunctionTable; +typedef WtsApiFunctionTable* PWtsApiFunctionTable; + +typedef PWtsApiFunctionTable (CDECL * INIT_WTSAPI_FN)(void); + +#ifdef __cplusplus +extern "C" { +#endif + +WINPR_API BOOL WTSRegisterWtsApiFunctionTable(PWtsApiFunctionTable table); + +#ifdef __cplusplus +} +#endif + #endif /* WINPR_WTSAPI_H */ diff --git a/winpr/include/winpr/wtypes.h b/winpr/include/winpr/wtypes.h index 83458f531..26299ed3d 100644 --- a/winpr/include/winpr/wtypes.h +++ b/winpr/include/winpr/wtypes.h @@ -26,12 +26,21 @@ #include #include +#include + +#ifdef _WIN32 +#include +#endif + #if defined(__OBJC__) && defined(__APPLE__) #include #endif #ifndef _WIN32 +#define WINAPI +#define CDECL + #define __int8 char #define __int16 short #define __int32 int @@ -268,6 +277,8 @@ typedef struct _SECURITY_DESCRIPTOR PACL Dacl; } SECURITY_DESCRIPTOR, *PSECURITY_DESCRIPTOR; +typedef WORD SECURITY_DESCRIPTOR_CONTROL, *PSECURITY_DESCRIPTOR_CONTROL; + typedef struct _SECURITY_ATTRIBUTES { DWORD nLength; @@ -303,4 +314,38 @@ typedef LONG NTSTATUS; typedef NTSTATUS *PNTSTATUS; #endif +#ifndef _WIN32 + +typedef struct tagDEC +{ + USHORT wReserved; + union { + struct { + BYTE scale; + BYTE sign; + } DUMMYSTRUCTNAME; + USHORT signscale; + } DUMMYUNIONNAME; + ULONG Hi32; + union { + struct { + ULONG Lo32; + ULONG Mid32; + } DUMMYSTRUCTNAME2; + ULONGLONG Lo64; + } DUMMYUNIONNAME2; +} DECIMAL; + +typedef DECIMAL *LPDECIMAL; + +#define DECIMAL_NEG ((BYTE) 0x80) +#define DECIMAL_SETZERO(dec) { (dec).Lo64 = 0; (dec).Hi32 = 0; (dec).signscale = 0; } + +typedef char CCHAR; +typedef DWORD LCID; +typedef PDWORD PLCID; +typedef WORD LANGID; + +#endif + #endif /* WINPR_WTYPES_H */ diff --git a/winpr/libwinpr/credui/CMakeLists.txt b/winpr/libwinpr/credui/CMakeLists.txt index 2f59aa252..de9e71b8e 100644 --- a/winpr/libwinpr/credui/CMakeLists.txt +++ b/winpr/libwinpr/credui/CMakeLists.txt @@ -35,6 +35,11 @@ if(WIN32) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} credui) endif() +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL + MODULE winpr + MODULES winpr-crt winpr-utils) + if(MONOLITHIC_BUILD) set(WINPR_LIBS ${WINPR_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE) else() diff --git a/winpr/libwinpr/crt/casing.c b/winpr/libwinpr/crt/casing.c new file mode 100644 index 000000000..9f0988f4f --- /dev/null +++ b/winpr/libwinpr/crt/casing.c @@ -0,0 +1,1041 @@ +/** + * Unicode case mappings + * + * This code is generated by wine's make_unicode script + * which downloads data from unicode.org and produces + * readily usable conversion tables. + * + * After asking permission from Alexandre Julliard in May 2011, + * it was clarified that no copyright was claimed by the wine + * project on the script's generated output. + */ + +#define WINPR_TOLOWERW(_wch) \ + (_wch + winpr_casemap_lower[winpr_casemap_lower[_wch >> 8] + (_wch & 0xFF)]); + +#define WINPR_TOUPPERW(_wch) \ + (_wch + winpr_casemap_upper[winpr_casemap_upper[_wch >> 8] + (_wch & 0xFF)]); + +const WCHAR winpr_casemap_lower[3807] = +{ + /* index */ + 0x01bf, 0x02bf, 0x03bf, 0x044f, 0x054f, 0x064f, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x06af, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x07af, 0x08ae, + 0x0100, 0x09ab, 0x0100, 0x0100, 0x0a2f, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0b2f, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0c22, 0x0d00, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0ddf, + /* defaults */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x0041 .. 0x00ff */ + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x0100 .. 0x01ff */ + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0xff39, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0xff87, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, + 0x0000, 0x00d2, 0x0001, 0x0000, 0x0001, 0x0000, 0x00ce, 0x0001, + 0x0000, 0x00cd, 0x00cd, 0x0001, 0x0000, 0x0000, 0x004f, 0x00ca, + 0x00cb, 0x0001, 0x0000, 0x00cd, 0x00cf, 0x0000, 0x00d3, 0x00d1, + 0x0001, 0x0000, 0x0000, 0x0000, 0x00d3, 0x00d5, 0x0000, 0x00d6, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x00da, 0x0001, + 0x0000, 0x00da, 0x0000, 0x0000, 0x0001, 0x0000, 0x00da, 0x0001, + 0x0000, 0x00d9, 0x00d9, 0x0001, 0x0000, 0x0001, 0x0000, 0x00db, + 0x0001, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0001, 0x0000, 0x0002, + 0x0001, 0x0000, 0x0002, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0000, 0x0002, 0x0001, 0x0000, 0x0001, 0x0000, 0xff9f, 0xffc8, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + /* 0x0200 .. 0x02ff */ + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0xff7e, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x2a2b, 0x0001, 0x0000, 0xff5d, 0x2a28, 0x0000, + 0x0000, 0x0001, 0x0000, 0xff3d, 0x0045, 0x0047, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x0370 .. 0x03ff */ + 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0026, 0x0000, + 0x0025, 0x0025, 0x0025, 0x0000, 0x0040, 0x0000, 0x003f, 0x003f, + 0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffc4, 0x0000, 0x0000, 0x0001, + 0x0000, 0xfff9, 0x0001, 0x0000, 0x0000, 0xff7e, 0xff7e, 0xff7e, + /* 0x0400 .. 0x04ff */ + 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, + 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x000f, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + /* 0x0500 .. 0x05ff */ + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x10a0 .. 0x10ff */ + 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, + 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, + 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, + 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, + 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x0000, 0x1c60, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1c60, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x1e00 .. 0x1eff */ + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe241, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + /* 0x1f01 .. 0x1fff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xfff8, 0x0000, 0xfff8, 0x0000, 0xfff8, 0x0000, 0xfff8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xffb6, 0xffb6, 0xfff7, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffaa, + 0xffaa, 0xffaa, 0xffaa, 0xfff7, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xff9c, 0xff9c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xff90, 0xff90, 0xfff9, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xff80, + 0xff80, 0xff82, 0xff82, 0xfff7, 0x0000, 0x0000, 0x0000, + /* 0x2103 .. 0x21ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xe2a3, 0x0000, 0x0000, 0x0000, 0xdf41, + 0xdfba, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x001c, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x247c .. 0x24ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, + 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, + 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, + 0x001a, 0x001a, 0x001a, 0x001a, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x2c00 .. 0x2cff */ + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0000, 0xd609, 0xf11a, 0xd619, 0x0000, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0xd5e4, 0xd603, 0xd5e1, + 0xd5e2, 0x0000, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd5c1, 0xd5c1, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0xa60d .. 0xa6ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + /* 0xa722 .. 0xa7ff */ + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x75fc, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0001, 0x0000, 0x5ad8, 0x0000, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x5abc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0xff21 .. 0xffff */ + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; +const WCHAR winpr_casemap_upper[3994] = +{ + /* index */ + 0x019f, 0x029f, 0x039f, 0x045a, 0x0556, 0x0656, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x06dd, 0x07dc, 0x08dc, + 0x0100, 0x09d0, 0x0100, 0x0100, 0x0a55, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0b3f, 0x0c3f, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0cfe, 0x0ddb, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0e9a, + /* defaults */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x0061 .. 0x00ff */ + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x02e7, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0x0000, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0x0079, + /* 0x0100 .. 0x01ff */ + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xff18, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0xfed4, + 0x00c3, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, + 0xffff, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0061, 0x0000, 0x0000, + 0x0000, 0xffff, 0x00a3, 0x0000, 0x0000, 0x0000, 0x0082, 0x0000, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, + 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, + 0xffff, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0038, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xfffe, 0x0000, + 0xffff, 0xfffe, 0x0000, 0xffff, 0xfffe, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0xffb1, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0x0000, 0xffff, 0xfffe, 0x0000, 0xffff, 0x0000, 0x0000, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + /* 0x0200 .. 0x02ff */ + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x2a3f, + 0x2a3f, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x2a1f, 0x2a1c, 0x2a1e, 0xff2e, 0xff32, 0x0000, 0xff33, 0xff33, + 0x0000, 0xff36, 0x0000, 0xff35, 0x0000, 0x0000, 0x0000, 0x0000, + 0xff33, 0x0000, 0x0000, 0xff31, 0x0000, 0xa528, 0xa544, 0x0000, + 0xff2f, 0xff2d, 0x0000, 0x29f7, 0x0000, 0x0000, 0x0000, 0xff2d, + 0x0000, 0x29fd, 0xff2b, 0x0000, 0x0000, 0xff2a, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x29e7, 0x0000, 0x0000, + 0xff26, 0x0000, 0x0000, 0xff26, 0x0000, 0x0000, 0x0000, 0x0000, + 0xff26, 0xffbb, 0xff27, 0xff27, 0xffb9, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xff25, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x0345 .. 0x03ff */ + 0x0054, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0082, 0x0082, + 0x0082, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffda, + 0xffdb, 0xffdb, 0xffdb, 0x0000, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe1, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffc0, + 0xffc1, 0xffc1, 0x0000, 0xffc2, 0xffc7, 0x0000, 0x0000, 0x0000, + 0xffd1, 0xffca, 0xfff8, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0xffaa, 0xffb0, 0x0007, 0x0000, 0x0000, + 0xffa0, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0xffff, 0x0000, + 0x0000, 0x0000, 0x0000, + /* 0x0404 .. 0x04ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, + 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, + 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0xfff1, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, + /* 0x0500 .. 0x05ff */ + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x1d79 .. 0x1dff */ + 0x8a04, 0x0000, 0x0000, 0x0000, 0x0ee6, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x1e01 .. 0x1eff */ + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xffc5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + /* 0x1f00 .. 0x1fff */ + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0008, 0x0000, 0x0008, 0x0000, 0x0008, 0x0000, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x004a, 0x004a, 0x0056, 0x0056, 0x0056, 0x0056, 0x0064, 0x0064, + 0x0080, 0x0080, 0x0070, 0x0070, 0x007e, 0x007e, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0000, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3db, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0007, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x210c .. 0x21ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xffe4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xfff0, 0xfff0, 0xfff0, 0xfff0, + 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0xfff0, + 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x247b .. 0x24ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffe6, 0xffe6, 0xffe6, + 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, + 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, + 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x2c16 .. 0x2cff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0xd5d5, + 0xd5d8, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, + 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, + /* 0x2d00 .. 0x2dff */ + 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, + 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, + 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, + 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, + 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0x0000, 0xe3a0, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3a0, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0xa641 .. 0xa6ff */ + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0xa723 .. 0xa7ff */ + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, + 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0xff41 .. 0xffff */ + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; + diff --git a/winpr/libwinpr/crt/string.c b/winpr/libwinpr/crt/string.c index ed7c84a44..0ecdc6a42 100644 --- a/winpr/libwinpr/crt/string.c +++ b/winpr/libwinpr/crt/string.c @@ -30,6 +30,8 @@ #ifndef _WIN32 +#include "casing.c" + char* _strdup(const char* strSource) { char* strDestination; @@ -213,25 +215,10 @@ DWORD CharUpperBuffA(LPSTR lpsz, DWORD cchLength) DWORD CharUpperBuffW(LPWSTR lpsz, DWORD cchLength) { DWORD i; - unsigned char* p; - unsigned int wc, uwc; - - p = (unsigned char*) lpsz; for (i = 0; i < cchLength; i++) { - wc = (unsigned int) (*p); - wc += (unsigned int) (*(p + 1)) << 8; - - uwc = towupper(wc); - - if (uwc != wc) - { - *p = uwc & 0xFF; - *(p + 1) = (uwc >> 8) & 0xFF; - } - - p += 2; + lpsz[i] = WINPR_TOUPPERW(lpsz[i]); } return cchLength; @@ -297,25 +284,10 @@ DWORD CharLowerBuffA(LPSTR lpsz, DWORD cchLength) DWORD CharLowerBuffW(LPWSTR lpsz, DWORD cchLength) { DWORD i; - unsigned char* p; - unsigned int wc, uwc; - - p = (unsigned char*) lpsz; for (i = 0; i < cchLength; i++) { - wc = (unsigned int) (*p); - wc += (unsigned int) (*(p + 1)) << 8; - - uwc = towlower(wc); - - if (uwc != wc) - { - *p = uwc & 0xFF; - *(p + 1) = (uwc >> 8) & 0xFF; - } - - p += 2; + lpsz[i] = WINPR_TOLOWERW(lpsz[i]); } return cchLength; diff --git a/winpr/libwinpr/crt/test/TestUnicodeConversion.c b/winpr/libwinpr/crt/test/TestUnicodeConversion.c index 67f05e535..594f58877 100644 --- a/winpr/libwinpr/crt/test/TestUnicodeConversion.c +++ b/winpr/libwinpr/crt/test/TestUnicodeConversion.c @@ -78,6 +78,14 @@ static BYTE ch_HowAreYou_UTF16[] = "\x60\x4F\x7D\x59\x17\x54\x00\x00"; static int ch_HowAreYou_cchWideChar = 4; static int ch_HowAreYou_cbMultiByte = 10; +/* Uppercasing */ + +static BYTE ru_Administrator_lower[] = + "\xd0\x90\xd0\xb4\xd0\xbc\xd0\xb8\xd0\xbd\xd0\xb8\xd1\x81\xd1\x82\xd1\x80\xd0\xb0\xd1\x82\xd0\xbe\xd1\x80\x00"; + +static BYTE ru_Administrator_upper[] = + "\xd0\x90\xd0\x94\xd0\x9c\xd0\x98\xd0\x9d\xd0\x98\xd0\xa1\xd0\xa2\xd0\xa0\xd0\x90\xd0\xa2\xd0\x9e\xd0\xa0\x00"; + void string_hexdump(BYTE* data, int length) { BYTE* p = data; @@ -242,6 +250,35 @@ int convert_utf16_to_utf8(BYTE* lpWideCharStr, BYTE* expected_lpMultiByteStr, in return length; } +int test_unicode_uppercasing(BYTE* lower, BYTE* upper) +{ + WCHAR* lowerW = NULL; + int lowerLength; + WCHAR* upperW = NULL; + int upperLength; + + lowerLength = ConvertToUnicode(CP_UTF8, 0, (LPSTR) lower, -1, &lowerW, 0); + upperLength = ConvertToUnicode(CP_UTF8, 0, (LPSTR) upper, -1, &upperW, 0); + + CharUpperBuffW(lowerW, lowerLength); + + if (_wcscmp(lowerW, upperW) != 0) + { + printf("Lowercase String:\n"); + string_hexdump((BYTE*) lowerW, lowerLength * 2); + + printf("Uppercase String:\n"); + string_hexdump((BYTE*) upperW, upperLength * 2); + + return -1; + } + + free(lowerW); + free(upperW); + + return 0; +} + int TestUnicodeConversion(int argc, char* argv[]) { /* Letters */ @@ -324,5 +361,11 @@ int TestUnicodeConversion(int argc, char* argv[]) if (convert_utf16_to_utf8(ch_HowAreYou_UTF16, ch_HowAreYou_UTF8, ch_HowAreYou_cbMultiByte) < 1) return -1; + /* Uppercasing */ + + printf("Uppercasing\n"); + + test_unicode_uppercasing(ru_Administrator_lower, ru_Administrator_upper); + return 0; } diff --git a/winpr/libwinpr/crypto/CMakeLists.txt b/winpr/libwinpr/crypto/CMakeLists.txt index c1c5e822c..e8fc30bda 100644 --- a/winpr/libwinpr/crypto/CMakeLists.txt +++ b/winpr/libwinpr/crypto/CMakeLists.txt @@ -30,15 +30,27 @@ endif() add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT" MONOLITHIC ${MONOLITHIC_BUILD} SOURCES ${${MODULE_PREFIX}_SRCS}) + +include_directories(${ZLIB_INCLUDE_DIRS}) +include_directories(${OPENSSL_INCLUDE_DIR}) set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SOVERSION ${WINPR_VERSION} PREFIX "lib") +set(${MODULE_PREFIX}_LIBS + ${ZLIB_LIBRARIES} + ${OPENSSL_LIBRARIES}) + +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL + MODULE winpr + MODULES winpr-crt winpr-utils) + if(WIN32) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} crypt32) endif() if(MONOLITHIC_BUILD) - + set(WINPR_LIBS ${WINPR_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE) else() install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT WinPRTargets) endif() diff --git a/winpr/libwinpr/crypto/crypto.c b/winpr/libwinpr/crypto/crypto.c index 8556121e9..96a53d107 100644 --- a/winpr/libwinpr/crypto/crypto.c +++ b/winpr/libwinpr/crypto/crypto.c @@ -89,8 +89,6 @@ * CryptMsgUpdate * CryptMsgVerifyCountersignatureEncoded * CryptMsgVerifyCountersignatureEncodedEx - * CryptProtectData - * CryptProtectMemory * CryptQueryObject * CryptRegisterDefaultOIDFunction * CryptRegisterOIDFunction @@ -115,11 +113,7 @@ * CryptSIPRetrieveSubjectGuid * CryptSIPRetrieveSubjectGuidForCatalogFile * CryptSIPVerifyIndirectData - * CryptStringToBinaryA - * CryptStringToBinaryW * CryptUninstallDefaultContext - * CryptUnprotectData - * CryptUnprotectMemory * CryptUnregisterDefaultOIDFunction * CryptUnregisterOIDFunction * CryptUnregisterOIDInfo @@ -146,4 +140,140 @@ #include "crypto.h" +#include +#include + +static wListDictionary* g_ProtectedMemoryBlocks = NULL; + +BOOL CryptProtectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) +{ + BYTE* pCipherText; + int cbOut, cbFinal; + BYTE randomKey[256]; + WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock; + + if (dwFlags != CRYPTPROTECTMEMORY_SAME_PROCESS) + return FALSE; + + if (!g_ProtectedMemoryBlocks) + g_ProtectedMemoryBlocks = ListDictionary_New(TRUE); + + pMemBlock = (WINPR_PROTECTED_MEMORY_BLOCK*) malloc(sizeof(WINPR_PROTECTED_MEMORY_BLOCK)); + ZeroMemory(pMemBlock, sizeof(WINPR_PROTECTED_MEMORY_BLOCK)); + + pMemBlock->pData = pData; + pMemBlock->cbData = cbData; + pMemBlock->dwFlags = dwFlags; + + /* AES Initialization */ + + RAND_bytes(pMemBlock->salt, 8); + RAND_bytes(randomKey, sizeof(randomKey)); + + EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), + pMemBlock->salt, + randomKey, sizeof(randomKey), + 4, pMemBlock->key, pMemBlock->iv); + + SecureZeroMemory(randomKey, sizeof(randomKey)); + + EVP_CIPHER_CTX_init(&(pMemBlock->enc)); + EVP_EncryptInit_ex(&(pMemBlock->enc), EVP_aes_256_cbc(), NULL, pMemBlock->key, pMemBlock->iv); + + EVP_CIPHER_CTX_init(&(pMemBlock->dec)); + EVP_DecryptInit_ex(&(pMemBlock->dec), EVP_aes_256_cbc(), NULL, pMemBlock->key, pMemBlock->iv); + + /* AES Encryption */ + + cbOut = pMemBlock->cbData + AES_BLOCK_SIZE - 1; + pCipherText = (BYTE*) malloc(cbOut); + + EVP_EncryptInit_ex(&(pMemBlock->enc), NULL, NULL, NULL, NULL); + EVP_EncryptUpdate(&(pMemBlock->enc), pCipherText, &cbOut, pMemBlock->pData, pMemBlock->cbData); + EVP_EncryptFinal_ex(&(pMemBlock->enc), pCipherText + cbOut, &cbFinal); + + CopyMemory(pMemBlock->pData, pCipherText, pMemBlock->cbData); + free(pCipherText); + + ListDictionary_Add(g_ProtectedMemoryBlocks, pData, pMemBlock); + + return TRUE; +} + +BOOL CryptUnprotectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) +{ + BYTE* pPlainText; + int cbOut, cbFinal; + WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock; + + if (dwFlags != CRYPTPROTECTMEMORY_SAME_PROCESS) + return FALSE; + + if (!g_ProtectedMemoryBlocks) + return FALSE; + + pMemBlock = (WINPR_PROTECTED_MEMORY_BLOCK*) ListDictionary_GetItemValue(g_ProtectedMemoryBlocks, pData); + + if (!pMemBlock) + return FALSE; + + /* AES Decryption */ + + cbOut = pMemBlock->cbData + AES_BLOCK_SIZE - 1; + pPlainText = (BYTE*) malloc(cbOut); + + EVP_DecryptInit_ex(&(pMemBlock->dec), NULL, NULL, NULL, NULL); + EVP_DecryptUpdate(&(pMemBlock->dec), pPlainText, &cbOut, pMemBlock->pData, pMemBlock->cbData); + EVP_DecryptFinal_ex(&(pMemBlock->dec), pPlainText + cbOut, &cbFinal); + + CopyMemory(pMemBlock->pData, pPlainText, pMemBlock->cbData); + SecureZeroMemory(pPlainText, pMemBlock->cbData); + free(pPlainText); + + ListDictionary_Remove(g_ProtectedMemoryBlocks, pData); + + /* AES Cleanup */ + + EVP_CIPHER_CTX_cleanup(&(pMemBlock->enc)); + EVP_CIPHER_CTX_cleanup(&(pMemBlock->dec)); + + free(pMemBlock); + + return TRUE; +} + +BOOL CryptProtectData(DATA_BLOB* pDataIn, LPCWSTR szDataDescr, DATA_BLOB* pOptionalEntropy, + PVOID pvReserved, CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, DWORD dwFlags, DATA_BLOB* pDataOut) +{ + return TRUE; +} + +BOOL CryptUnprotectData(DATA_BLOB* pDataIn, LPWSTR* ppszDataDescr, DATA_BLOB* pOptionalEntropy, + PVOID pvReserved, CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, DWORD dwFlags, DATA_BLOB* pDataOut) +{ + return TRUE; +} + +BOOL CryptStringToBinaryW(LPCWSTR pszString, DWORD cchString, DWORD dwFlags, BYTE* pbBinary, + DWORD* pcbBinary, DWORD* pdwSkip, DWORD* pdwFlags) +{ + return TRUE; +} + +BOOL CryptStringToBinaryA(LPCSTR pszString, DWORD cchString, DWORD dwFlags, BYTE* pbBinary, + DWORD* pcbBinary, DWORD* pdwSkip, DWORD* pdwFlags) +{ + return TRUE; +} + +BOOL CryptBinaryToStringW(CONST BYTE* pbBinary, DWORD cbBinary, DWORD dwFlags, LPWSTR pszString, DWORD* pcchString) +{ + return TRUE; +} + +BOOL CryptBinaryToStringA(CONST BYTE* pbBinary, DWORD cbBinary, DWORD dwFlags, LPSTR pszString, DWORD* pcchString) +{ + return TRUE; +} + #endif diff --git a/winpr/libwinpr/crypto/crypto.h b/winpr/libwinpr/crypto/crypto.h index cd4fcdad5..5fbc74083 100644 --- a/winpr/libwinpr/crypto/crypto.h +++ b/winpr/libwinpr/crypto/crypto.h @@ -22,6 +22,10 @@ #ifndef _WIN32 +#include +#include +#include + struct _WINPR_CERTSTORE { LPCSTR lpszStoreProvider; @@ -29,6 +33,19 @@ struct _WINPR_CERTSTORE }; typedef struct _WINPR_CERTSTORE WINPR_CERTSTORE; +struct _WINPR_PROTECTED_MEMORY_BLOCK +{ + BYTE* pData; + DWORD cbData; + DWORD dwFlags; + BYTE key[32]; + BYTE iv[32]; + BYTE salt[8]; + EVP_CIPHER_CTX enc; + EVP_CIPHER_CTX dec; +}; +typedef struct _WINPR_PROTECTED_MEMORY_BLOCK WINPR_PROTECTED_MEMORY_BLOCK; + #endif #endif /* WINPR_CRYPTO_PRIVATE_H */ diff --git a/winpr/libwinpr/crypto/test/CMakeLists.txt b/winpr/libwinpr/crypto/test/CMakeLists.txt index 398cb9c8e..58a29cdb7 100644 --- a/winpr/libwinpr/crypto/test/CMakeLists.txt +++ b/winpr/libwinpr/crypto/test/CMakeLists.txt @@ -5,7 +5,9 @@ set(MODULE_PREFIX "TEST_CRYPTO") set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) set(${MODULE_PREFIX}_TESTS - TestCertEnumCertificatesInStore.c) + TestCryptoProtectData.c + TestCryptoProtectMemory.c + TestCryptoCertEnumCertificatesInStore.c) create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} diff --git a/winpr/libwinpr/crypto/test/TestCertEnumCertificatesInStore.c b/winpr/libwinpr/crypto/test/TestCryptoCertEnumCertificatesInStore.c similarity index 95% rename from winpr/libwinpr/crypto/test/TestCertEnumCertificatesInStore.c rename to winpr/libwinpr/crypto/test/TestCryptoCertEnumCertificatesInStore.c index d4a909e5a..d0eb67516 100644 --- a/winpr/libwinpr/crypto/test/TestCertEnumCertificatesInStore.c +++ b/winpr/libwinpr/crypto/test/TestCryptoCertEnumCertificatesInStore.c @@ -12,7 +12,7 @@ #include #endif -int TestCertEnumCertificatesInStore(int argc, char* argv[]) +int TestCryptoCertEnumCertificatesInStore(int argc, char* argv[]) { int index; DWORD status; diff --git a/winpr/libwinpr/crypto/test/TestCryptoProtectData.c b/winpr/libwinpr/crypto/test/TestCryptoProtectData.c new file mode 100644 index 000000000..faa24d3c5 --- /dev/null +++ b/winpr/libwinpr/crypto/test/TestCryptoProtectData.c @@ -0,0 +1,11 @@ + + +#include +#include +#include + +int TestCryptoProtectData(int argc, char* argv[]) +{ + return 0; +} + diff --git a/winpr/libwinpr/crypto/test/TestCryptoProtectMemory.c b/winpr/libwinpr/crypto/test/TestCryptoProtectMemory.c new file mode 100644 index 000000000..75b461adb --- /dev/null +++ b/winpr/libwinpr/crypto/test/TestCryptoProtectMemory.c @@ -0,0 +1,47 @@ + +#include +#include +#include + +static const char* SECRET_PASSWORD_TEST = "MySecretPassword123!"; + +int TestCryptoProtectMemory(int argc, char* argv[]) +{ + int cbPlainText; + int cbCipherText; + char* pPlainText; + BYTE* pCipherText; + + pPlainText = (char*) SECRET_PASSWORD_TEST; + cbPlainText = strlen(pPlainText) + 1; + + cbCipherText = cbPlainText + (CRYPTPROTECTMEMORY_BLOCK_SIZE - (cbPlainText % CRYPTPROTECTMEMORY_BLOCK_SIZE)); + printf("cbPlainText: %d cbCipherText: %d\n", cbPlainText, cbCipherText); + + pCipherText = (BYTE*) malloc(cbCipherText); + CopyMemory(pCipherText, pPlainText, cbPlainText); + ZeroMemory(&pCipherText[cbPlainText], (cbCipherText - cbPlainText)); + + if (!CryptProtectMemory(pCipherText, cbCipherText, CRYPTPROTECTMEMORY_SAME_PROCESS)) + { + printf("CryptProtectMemory failure\n"); + return -1; + } + + printf("PlainText: %s (cbPlainText = %d, cbCipherText = %d)\n", pPlainText, cbPlainText, cbCipherText); + + winpr_HexDump(pCipherText, cbCipherText); + + if (!CryptUnprotectMemory(pCipherText, cbCipherText, CRYPTPROTECTMEMORY_SAME_PROCESS)) + { + printf("CryptUnprotectMemory failure\n"); + return -1; + } + + printf("Decrypted CipherText: %s\n", pCipherText); + + SecureZeroMemory(pCipherText, cbCipherText); + free(pCipherText); + + return 0; +} diff --git a/winpr/libwinpr/environment/environment.c b/winpr/libwinpr/environment/environment.c index 7e998e998..e56c0b1e2 100644 --- a/winpr/libwinpr/environment/environment.c +++ b/winpr/libwinpr/environment/environment.c @@ -165,48 +165,57 @@ DWORD GetEnvironmentVariableA(LPCSTR lpName, LPSTR lpBuffer, DWORD nSize) DWORD GetEnvironmentVariableEBA(LPCSTR envBlock, LPCSTR lpName, LPSTR lpBuffer, DWORD nSize) { - int length; + int vLength = 0; char* env = NULL; const char * penvb = envBlock; char *foundEquals; + int nLength, fLength, lpNameLength; + + if (!lpName || NULL == envBlock) + return 0; + + lpNameLength = strlen(lpName); + if (0 == lpNameLength) + return 0; while (*penvb && *(penvb+1)) { - length = strlen(penvb); + fLength = strlen(penvb); foundEquals = strstr(penvb,"="); - if (foundEquals == NULL) { + if (foundEquals == NULL) + { + /* if no = sign is found the envBlock is broken */ + return 0; + } + nLength = foundEquals - penvb; + if (nLength != lpNameLength) + { + penvb += (fLength +1); continue; } #ifdef _WIN32 - if (strnicmp(penvb,lpName,foundEquals - penvb) == 0) { + if (strnicmp(penvb,lpName,nLength) == 0) #else - if (strncmp(penvb,lpName,foundEquals - penvb) == 0) { + if (strncmp(penvb,lpName,nLength) == 0) #endif - if (*(penvb + (foundEquals - penvb)) == '=') { - // found variable ... - if (foundEquals == NULL) { - return 0; - } else { - env = foundEquals + 1; - break; - } - } + { + env = foundEquals + 1; + break; } - penvb += (length +1); + penvb += (fLength +1); } - if (!env) return 0; - length = strlen(env); + vLength = strlen(env); - if ((length + 1 > nSize) || (!lpBuffer)) - return length + 1; + if ((vLength + 1 > nSize) || (!lpBuffer)) + return vLength + 1; - CopyMemory(lpBuffer, env, length + 1); + CopyMemory(lpBuffer, env, vLength + 1); - return length; + return vLength; } @@ -252,33 +261,23 @@ BOOL SetEnvironmentVariableEBA(LPSTR * envBlock,LPCSTR lpName, LPCSTR lpValue) if (lpValue) { - - length = strlen(lpName) + strlen(lpValue) + 1; - envstr = (char*) malloc(length + 1); - sprintf_s(envstr, length + 1, "%s=%s", lpName, lpValue); - envstr[length] = '\0'; - - newEB = MergeEnvironmentStrings((LPCSTR)*envBlock,envstr); - free(envstr); - if (*envBlock != NULL) - free(*envBlock); - *envBlock = newEB; - return TRUE; + length = strlen(lpName) + strlen(lpValue) + 2; /* +2 because of = and \0 */ + envstr = (char*) malloc(length + 1); /* +1 because of closing \0 */ + sprintf_s(envstr, length, "%s=%s", lpName, lpValue); } else { - length = strlen(lpName) + 1; - envstr = (char*) malloc(length + 1); - sprintf_s(envstr, length + 1, "%s=", lpName); - envstr[length] = '\0'; - - newEB = MergeEnvironmentStrings((LPCSTR)*envBlock,envstr); - free(envstr); - if (*envBlock != NULL) - free(*envBlock); - *envBlock = newEB; - return TRUE; + length = strlen(lpName) + 2; /* +2 because of = and \0 */ + envstr = (char*) malloc(length + 1); /* +1 because of closing \0 */ + sprintf_s(envstr, length, "%s=", lpName); } + envstr[length] = '\0'; + newEB = MergeEnvironmentStrings((LPCSTR)*envBlock,envstr); + free(envstr); + if (*envBlock != NULL) + free(*envBlock); + *envBlock = newEB; + return TRUE; } @@ -364,6 +363,7 @@ LPCH MergeEnvironmentStrings(PCSTR original, PCSTR merge) // first build an char ** of the merge env strings mergeStrings = (LPCSTR*) malloc(mergeArraySize * sizeof(char *)); + ZeroMemory(mergeStrings,mergeArraySize * sizeof(char *)); mergeStringLenth = 0; cp = merge; diff --git a/winpr/libwinpr/environment/test/TestEnvironmentGetSetEB.c b/winpr/libwinpr/environment/test/TestEnvironmentGetSetEB.c index dbf248a6a..4e27f8e41 100644 --- a/winpr/libwinpr/environment/test/TestEnvironmentGetSetEB.c +++ b/winpr/libwinpr/environment/test/TestEnvironmentGetSetEB.c @@ -13,8 +13,12 @@ int TestEnvironmentGetSetEB(int argc, char* argv[]) LPTCH lpszEnvironmentBlock = "SHELL=123\0test=1\0test1=2\0DISPLAY=WINPR_TEST_VALUE\0\0"; LPTCH lpszEnvironmentBlockNew = NULL; + /* Get length of an variable */ length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"DISPLAY", NULL, 0); + if (0 == length) + return -1; + /* Get the variable itself */ p = (LPSTR) malloc(length); length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"DISPLAY", p, length); @@ -22,14 +26,47 @@ int TestEnvironmentGetSetEB(int argc, char* argv[]) if (strcmp(p, "WINPR_TEST_VALUE") != 0) { + free(p); return -1; } free(p); - lpszEnvironmentBlockNew = (LPTCH) malloc(1024); - memcpy(lpszEnvironmentBlockNew,lpszEnvironmentBlock,56); + /* Get length of an non-existing variable */ + length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"BLA", NULL, 0); + if (0 != length) + { + printf("Unset variable returned\n"); + return -1; + } + /* Get length of an similar called variables */ + length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"XDISPLAY", NULL, 0); + if (0 != length) + { + printf("Similar named variable returned (XDISPLAY, length %d)\n", length); + return -1; + } + length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"DISPLAYX", NULL, 0); + if (0 != length) + { + printf("Similar named variable returned (DISPLAYX, length %d)\n", length); + return -1; + } + length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"DISPLA", NULL, 0); + if (0 != length) + { + printf("Similar named variable returned (DISPLA, length %d)\n", length); + return -1; + } + length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"ISPLAY", NULL, 0); + if (0 != length) + { + printf("Similar named variable returned (ISPLAY, length %d)\n", length); + return -1; + } + + /* Set variable in empty environment block */ if (SetEnvironmentVariableEBA(&lpszEnvironmentBlockNew, "test", "5")) { if (GetEnvironmentVariableEBA(lpszEnvironmentBlockNew,"test", test, 1023)) @@ -44,13 +81,12 @@ int TestEnvironmentGetSetEB(int argc, char* argv[]) return -1; } } - - //free(lpszEnvironmentBlockNew); - + /* Clear variable */ if (SetEnvironmentVariableEBA(&lpszEnvironmentBlockNew, "test", NULL)) { if (GetEnvironmentVariableEBA(lpszEnvironmentBlockNew,"test", test, 1023)) { + free(lpszEnvironmentBlockNew); return -1; } else @@ -58,6 +94,34 @@ int TestEnvironmentGetSetEB(int argc, char* argv[]) // not found .. this is expected } } + free(lpszEnvironmentBlockNew); + + lpszEnvironmentBlockNew = (LPTCH) malloc(1024); + memcpy(lpszEnvironmentBlockNew,lpszEnvironmentBlock,56); + + /* Set variable in empty environment block */ + if (SetEnvironmentVariableEBA(&lpszEnvironmentBlockNew, "test", "5")) + { + if (0 != GetEnvironmentVariableEBA(lpszEnvironmentBlockNew,"testr", test, 1023)) + { + printf("GetEnvironmentVariableEBA returned unset variable\n"); + free(lpszEnvironmentBlockNew); + return -1; + } + if (GetEnvironmentVariableEBA(lpszEnvironmentBlockNew,"test", test, 1023)) + { + if (strcmp(test,"5") != 0) + { + free(lpszEnvironmentBlockNew); + return -1; + } + } + else + { + free(lpszEnvironmentBlockNew); + return -1; + } + } free(lpszEnvironmentBlockNew); #endif diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c index cad16230f..7d8fb3ab0 100644 --- a/winpr/libwinpr/file/file.c +++ b/winpr/libwinpr/file/file.c @@ -168,6 +168,12 @@ #include #endif +#ifndef _WIN32 +#include +#include +#include +#endif + #ifdef ANDROID #include #else @@ -178,6 +184,37 @@ #include "../pipe/pipe.h" +#ifdef HAVE_AIO_H + +static BOOL g_AioSignalHandlerInstalled = FALSE; + +void AioSignalHandler(int signum, siginfo_t* siginfo, void* arg) +{ + printf("AioSignalHandler\n"); +} + +int InstallAioSignalHandler() +{ + if (!g_AioSignalHandlerInstalled) + { + struct sigaction action; + + sigemptyset(&action.sa_mask); + sigaddset(&action.sa_mask, SIGIO); + + action.sa_flags = SA_SIGINFO; + action.sa_sigaction = (void*) &AioSignalHandler; + + sigaction(SIGIO, &action, NULL); + + g_AioSignalHandlerInstalled = TRUE; + } + + return 0; +} + +#endif + HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { @@ -227,13 +264,23 @@ HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, if (status != 0) { close(pNamedPipe->clientfd); - free((char *)pNamedPipe->name); - free((char *)pNamedPipe->lpFileName); - free((char *)pNamedPipe->lpFilePath); + free((char*) pNamedPipe->name); + free((char*) pNamedPipe->lpFileName); + free((char*) pNamedPipe->lpFilePath); free(pNamedPipe); return INVALID_HANDLE_VALUE; } + if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED) + { +#if 0 + int flags = fcntl(pNamedPipe->clientfd, F_GETFL); + + if (flags != -1) + fcntl(pNamedPipe->clientfd, F_SETFL, flags | O_NONBLOCK); +#endif + } + return hNamedPipe; } @@ -262,57 +309,84 @@ BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, { ULONG Type; PVOID Object; + BOOL status = TRUE; + + /* + * from http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467%28v=vs.85%29.aspx + * lpNumberOfBytesRead can be NULL only when the lpOverlapped parameter is not NULL. + */ + + if (!lpNumberOfBytesRead && !lpOverlapped) + return FALSE; if (!winpr_Handle_GetInfo(hFile, &Type, &Object)) return FALSE; if (Type == HANDLE_TYPE_ANONYMOUS_PIPE) { - int status; + int io_status; WINPR_PIPE* pipe; pipe = (WINPR_PIPE*) Object; - status = read(pipe->fd, lpBuffer, nNumberOfBytesToRead); + io_status = read(pipe->fd, lpBuffer, nNumberOfBytesToRead); - *lpNumberOfBytesRead = status; + if (io_status < 0) + { + status = FALSE; - return TRUE; + switch (errno) + { + case EWOULDBLOCK: + SetLastError(ERROR_NO_DATA); + break; + } + } + + if (lpNumberOfBytesRead) + *lpNumberOfBytesRead = io_status; + + return status; } else if (Type == HANDLE_TYPE_NAMED_PIPE) { - int status; + int io_status; WINPR_NAMED_PIPE* pipe; pipe = (WINPR_NAMED_PIPE*) Object; if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)) { - status = nNumberOfBytesToRead; + io_status = nNumberOfBytesToRead; if (pipe->clientfd == -1) return FALSE; - status = read(pipe->clientfd, lpBuffer, nNumberOfBytesToRead); + io_status = read(pipe->clientfd, lpBuffer, nNumberOfBytesToRead); - if (status == 0) + if (io_status == 0) { switch (errno) { case ECONNRESET: SetLastError(ERROR_BROKEN_PIPE); - status = -1; + io_status = 0; + break; + } + } + else if (io_status < 0) + { + status = FALSE; + + switch (errno) + { + case EWOULDBLOCK: + SetLastError(ERROR_NO_DATA); break; } } - if (status < 0) - { - *lpNumberOfBytesRead = 0; - return FALSE; - } - - *lpNumberOfBytesRead = status; + *lpNumberOfBytesRead = io_status; } else { @@ -328,22 +402,29 @@ BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, #ifdef HAVE_AIO_H { + int aio_status; 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; + cb.aio_nbytes = nNumberOfBytesToRead; + cb.aio_offset = lpOverlapped->Offset; - status = aio_read(&cb); + cb.aio_sigevent.sigev_notify = SIGEV_SIGNAL; + cb.aio_sigevent.sigev_signo = SIGIO; + cb.aio_sigevent.sigev_value.sival_ptr = (void*) lpOverlapped; - printf("aio_read status: %d\n", status); + InstallAioSignalHandler(); - if (status < 0) - { - return FALSE; - } + aio_status = aio_read(&cb); + + printf("aio_read status: %d\n", aio_status); + + if (aio_status < 0) + status = FALSE; + + return status; } #else @@ -358,7 +439,7 @@ BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, #endif } - return TRUE; + return status; } return FALSE; @@ -381,46 +462,60 @@ BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, { ULONG Type; PVOID Object; + BOOL status = TRUE; if (!winpr_Handle_GetInfo(hFile, &Type, &Object)) return FALSE; if (Type == HANDLE_TYPE_ANONYMOUS_PIPE) { - int status; + int io_status; WINPR_PIPE* pipe; pipe = (WINPR_PIPE*) Object; - status = write(pipe->fd, lpBuffer, nNumberOfBytesToWrite); + io_status = write(pipe->fd, lpBuffer, nNumberOfBytesToWrite); - *lpNumberOfBytesWritten = status; + if ((io_status < 0) && (errno == EWOULDBLOCK)) + io_status = 0; + + *lpNumberOfBytesWritten = io_status; return TRUE; } else if (Type == HANDLE_TYPE_NAMED_PIPE) { - int status; + int io_status; WINPR_NAMED_PIPE* pipe; pipe = (WINPR_NAMED_PIPE*) Object; if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)) { - status = nNumberOfBytesToWrite; + io_status = nNumberOfBytesToWrite; if (pipe->clientfd == -1) return FALSE; - status = write(pipe->clientfd, lpBuffer, nNumberOfBytesToWrite); + io_status = write(pipe->clientfd, lpBuffer, nNumberOfBytesToWrite); - if (status < 0) + if (io_status < 0) { *lpNumberOfBytesWritten = 0; - return FALSE; + + switch(errno) + { + case EWOULDBLOCK: + io_status = 0; + status = TRUE; + break; + default: + status = FALSE; + } } - *lpNumberOfBytesWritten = status; + *lpNumberOfBytesWritten = io_status; + return status; } else { @@ -439,19 +534,25 @@ BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, struct aiocb cb; ZeroMemory(&cb, sizeof(struct aiocb)); - cb.aio_nbytes = nNumberOfBytesToWrite; cb.aio_fildes = pipe->clientfd; + cb.aio_buf = (void*) lpBuffer; + cb.aio_nbytes = nNumberOfBytesToWrite; cb.aio_offset = lpOverlapped->Offset; - cb.aio_buf = lpBuffer; - status = aio_write(&cb); + cb.aio_sigevent.sigev_notify = SIGEV_SIGNAL; + cb.aio_sigevent.sigev_signo = SIGIO; + cb.aio_sigevent.sigev_value.sival_ptr = (void*) lpOverlapped; - printf("aio_write status: %d\n", status); + InstallAioSignalHandler(); - if (status < 0) - { - return FALSE; - } + io_status = aio_write(&cb); + + printf("aio_write status: %d\n", io_status); + + if (io_status < 0) + status = FALSE; + + return status; } #else diff --git a/winpr/libwinpr/io/io.c b/winpr/libwinpr/io/io.c index ad2c3930c..3fa4fc207 100644 --- a/winpr/libwinpr/io/io.c +++ b/winpr/libwinpr/io/io.c @@ -57,7 +57,7 @@ BOOL GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumb else if (Type == HANDLE_TYPE_NAMED_PIPE) { - int status; + int status = -1; DWORD request; PVOID lpBuffer; DWORD nNumberOfBytes; diff --git a/winpr/libwinpr/library/library.c b/winpr/libwinpr/library/library.c index 6a5285005..84e20bf0e 100644 --- a/winpr/libwinpr/library/library.c +++ b/winpr/libwinpr/library/library.c @@ -95,7 +95,7 @@ HMODULE LoadLibraryA(LPCSTR lpLibFileName) library = dlopen(lpLibFileName, RTLD_LOCAL | RTLD_LAZY); - if (library == NULL) + if (!library) { fprintf(stderr, "LoadLibraryA: %s\n", dlerror()); return NULL; @@ -115,9 +115,9 @@ HMODULE LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) library = dlopen(lpLibFileName, RTLD_LOCAL | RTLD_LAZY); - if (library == NULL) + if (!library) { - fprintf(stderr, "LoadLibraryA: failed to open %s: %s\n", lpLibFileName, dlerror()); + fprintf(stderr, "LoadLibraryExA: failed to open %s: %s\n", lpLibFileName, dlerror()); return NULL; } diff --git a/winpr/libwinpr/locale/CMakeLists.txt b/winpr/libwinpr/locale/CMakeLists.txt new file mode 100644 index 000000000..913ace67d --- /dev/null +++ b/winpr/libwinpr/locale/CMakeLists.txt @@ -0,0 +1,49 @@ +# WinPR: Windows Portable Runtime +# libwinpr-dsparse 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-locale") +set(MODULE_PREFIX "WINPR_LOCALE") + +set(${MODULE_PREFIX}_SRCS + locale.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} ntdsapi) +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} EXPORT WinPRTargets) +endif() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR") + +if(BUILD_TESTING) + add_subdirectory(test) +endif() diff --git a/winpr/libwinpr/locale/ModuleOptions.cmake b/winpr/libwinpr/locale/ModuleOptions.cmake new file mode 100644 index 000000000..2ed13a07c --- /dev/null +++ b/winpr/libwinpr/locale/ModuleOptions.cmake @@ -0,0 +1,8 @@ + +set(MINWIN_LAYER "1") +set(MINWIN_GROUP "core") +set(MINWIN_MAJOR_VERSION "2") +set(MINWIN_MINOR_VERSION "1") +set(MINWIN_SHORT_NAME "localization") +set(MINWIN_LONG_NAME "Localization Functions") +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/locale/locale.c b/winpr/libwinpr/locale/locale.c new file mode 100644 index 000000000..439401128 --- /dev/null +++ b/winpr/libwinpr/locale/locale.c @@ -0,0 +1,96 @@ +/** + * WinPR: Windows Portable Runtime + * Localization Functions + * + * Copyright 2014 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-localization-l1-2-1.dll: + * + * ConvertDefaultLocale + * EnumSystemGeoID + * EnumSystemLocalesA + * EnumSystemLocalesEx + * EnumSystemLocalesW + * FindNLSString + * FindNLSStringEx + * FormatMessageA + * FormatMessageW + * GetACP + * GetCalendarInfoEx + * GetCalendarInfoW + * GetCPInfo + * GetCPInfoExW + * GetFileMUIInfo + * GetFileMUIPath + * GetGeoInfoW + * GetLocaleInfoA + * GetLocaleInfoEx + * GetLocaleInfoW + * GetNLSVersion + * GetNLSVersionEx + * GetOEMCP + * GetProcessPreferredUILanguages + * GetSystemDefaultLangID + * GetSystemDefaultLCID + * GetSystemPreferredUILanguages + * GetThreadLocale + * GetThreadPreferredUILanguages + * GetThreadUILanguage + * GetUILanguageInfo + * GetUserDefaultLangID + * GetUserDefaultLCID + * GetUserDefaultLocaleName + * GetUserGeoID + * GetUserPreferredUILanguages + * IdnToAscii + * IdnToUnicode + * IsDBCSLeadByte + * IsDBCSLeadByteEx + * IsNLSDefinedString + * IsValidCodePage + * IsValidLanguageGroup + * IsValidLocale + * IsValidLocaleName + * IsValidNLSVersion + * LCMapStringA + * LCMapStringEx + * LCMapStringW + * LocaleNameToLCID + * ResolveLocaleName + * SetCalendarInfoW + * SetLocaleInfoW + * SetProcessPreferredUILanguages + * SetThreadLocale + * SetThreadPreferredUILanguages + * SetThreadUILanguage + * SetUserGeoID + * VerLanguageNameA + * VerLanguageNameW + */ + +#ifndef _WIN32 + + + +#endif + diff --git a/winpr/libwinpr/locale/module.def b/winpr/libwinpr/locale/module.def new file mode 100644 index 000000000..593aba52f --- /dev/null +++ b/winpr/libwinpr/locale/module.def @@ -0,0 +1,2 @@ +LIBRARY "libwinpr-locale" +EXPORTS diff --git a/winpr/libwinpr/locale/test/.gitignore b/winpr/libwinpr/locale/test/.gitignore new file mode 100644 index 000000000..ac4611812 --- /dev/null +++ b/winpr/libwinpr/locale/test/.gitignore @@ -0,0 +1,2 @@ +TestLocale +TestLocale.c diff --git a/winpr/libwinpr/locale/test/CMakeLists.txt b/winpr/libwinpr/locale/test/CMakeLists.txt new file mode 100644 index 000000000..33025b56b --- /dev/null +++ b/winpr/libwinpr/locale/test/CMakeLists.txt @@ -0,0 +1,30 @@ + +set(MODULE_NAME "TestLocale") +set(MODULE_PREFIX "TEST_LOCALE") + +set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) + +set(${MODULE_PREFIX}_TESTS + TestLocaleFormatMessage.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-locale) + +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/locale/test/TestLocaleFormatMessage.c b/winpr/libwinpr/locale/test/TestLocaleFormatMessage.c new file mode 100644 index 000000000..b733872f9 --- /dev/null +++ b/winpr/libwinpr/locale/test/TestLocaleFormatMessage.c @@ -0,0 +1,8 @@ + +#include + +int TestLocaleFormatMessage(int argc, char* argv[]) +{ + return 0; +} + diff --git a/winpr/libwinpr/memory/CMakeLists.txt b/winpr/libwinpr/memory/CMakeLists.txt new file mode 100644 index 000000000..4c7e8e8ac --- /dev/null +++ b/winpr/libwinpr/memory/CMakeLists.txt @@ -0,0 +1,51 @@ +# WinPR: Windows Portable Runtime +# libwinpr-memory 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-memory") +set(MODULE_PREFIX "WINPR_MEMORY") + +set(${MODULE_PREFIX}_SRCS + memory.c + memory.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-crt) + +if(MONOLITHIC_BUILD) + +else() + target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT WinPRTargets) +endif() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR") + +if(BUILD_TESTING) + add_subdirectory(test) +endif() diff --git a/winpr/libwinpr/memory/ModuleOptions.cmake b/winpr/libwinpr/memory/ModuleOptions.cmake new file mode 100644 index 000000000..704ddca19 --- /dev/null +++ b/winpr/libwinpr/memory/ModuleOptions.cmake @@ -0,0 +1,9 @@ + +set(MINWIN_LAYER "1") +set(MINWIN_GROUP "core") +set(MINWIN_MAJOR_VERSION "1") +set(MINWIN_MINOR_VERSION "2") +set(MINWIN_SHORT_NAME "memory") +set(MINWIN_LONG_NAME "Memory Functions") +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/memory/memory.c b/winpr/libwinpr/memory/memory.c new file mode 100644 index 000000000..ec5cb854b --- /dev/null +++ b/winpr/libwinpr/memory/memory.c @@ -0,0 +1,131 @@ +/** + * WinPR: Windows Portable Runtime + * Memory Functions + * + * Copyright 2014 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 + +#ifdef HAVE_UNISTD_H +#include +#endif + +/** + * api-ms-win-core-memory-l1-1-2.dll: + * + * AllocateUserPhysicalPages + * AllocateUserPhysicalPagesNuma + * CreateFileMappingFromApp + * CreateFileMappingNumaW + * CreateFileMappingW + * CreateMemoryResourceNotification + * FlushViewOfFile + * FreeUserPhysicalPages + * GetLargePageMinimum + * GetMemoryErrorHandlingCapabilities + * GetProcessWorkingSetSizeEx + * GetSystemFileCacheSize + * GetWriteWatch + * MapUserPhysicalPages + * MapViewOfFile + * MapViewOfFileEx + * MapViewOfFileFromApp + * OpenFileMappingW + * PrefetchVirtualMemory + * QueryMemoryResourceNotification + * ReadProcessMemory + * RegisterBadMemoryNotification + * ResetWriteWatch + * SetProcessWorkingSetSizeEx + * SetSystemFileCacheSize + * UnmapViewOfFile + * UnmapViewOfFileEx + * UnregisterBadMemoryNotification + * VirtualAlloc + * VirtualAllocEx + * VirtualAllocExNuma + * VirtualFree + * VirtualFreeEx + * VirtualLock + * VirtualProtect + * VirtualProtectEx + * VirtualQuery + * VirtualQueryEx + * VirtualUnlock + * WriteProcessMemory + */ + +#ifndef _WIN32 + +#include "memory.h" + +HANDLE CreateFileMappingA(HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes, DWORD flProtect, + DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCSTR lpName) +{ + if (hFile != INVALID_HANDLE_VALUE) + { + return NULL; /* not yet implemented */ + } + + return NULL; +} + +HANDLE CreateFileMappingW(HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes, DWORD flProtect, + DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCWSTR lpName) +{ + return NULL; +} + +HANDLE OpenFileMappingA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName) +{ + return NULL; +} + +HANDLE OpenFileMappingW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName) +{ + return NULL; +} + +LPVOID MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, + DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap) +{ + return NULL; +} + +LPVOID MapViewOfFileEx(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, + DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, LPVOID lpBaseAddress) +{ + return NULL; +} + +BOOL FlushViewOfFile(LPCVOID lpBaseAddress, SIZE_T dwNumberOfBytesToFlush) +{ + return TRUE; +} + +BOOL UnmapViewOfFile(LPCVOID lpBaseAddress) +{ + return TRUE; +} + +#endif + diff --git a/winpr/libwinpr/memory/memory.h b/winpr/libwinpr/memory/memory.h new file mode 100644 index 000000000..8071088f4 --- /dev/null +++ b/winpr/libwinpr/memory/memory.h @@ -0,0 +1,34 @@ +/** + * WinPR: Windows Portable Runtime + * Memory Functions + * + * Copyright 2014 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_MEMORY_PRIVATE_H +#define WINPR_MEMORY_PRIVATE_H + +#ifndef _WIN32 + +#include +#include + + + +#endif + +#endif /* WINPR_MEMORY_PRIVATE_H */ + + diff --git a/winpr/libwinpr/memory/module.def b/winpr/libwinpr/memory/module.def new file mode 100644 index 000000000..14a9402ee --- /dev/null +++ b/winpr/libwinpr/memory/module.def @@ -0,0 +1,3 @@ +LIBRARY "libwinpr-memory" +EXPORTS + diff --git a/winpr/libwinpr/memory/test/.gitignore b/winpr/libwinpr/memory/test/.gitignore new file mode 100644 index 000000000..34af35fe4 --- /dev/null +++ b/winpr/libwinpr/memory/test/.gitignore @@ -0,0 +1,2 @@ +TestMemory +TestMemory.c diff --git a/winpr/libwinpr/memory/test/CMakeLists.txt b/winpr/libwinpr/memory/test/CMakeLists.txt new file mode 100644 index 000000000..b143d3f82 --- /dev/null +++ b/winpr/libwinpr/memory/test/CMakeLists.txt @@ -0,0 +1,30 @@ + +set(MODULE_NAME "TestMemory") +set(MODULE_PREFIX "TEST_MEMORY") + +set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) + +set(${MODULE_PREFIX}_TESTS + TestMemoryCreateFileMapping.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) + +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/memory/test/TestMemoryCreateFileMapping.c b/winpr/libwinpr/memory/test/TestMemoryCreateFileMapping.c new file mode 100644 index 000000000..918b4c468 --- /dev/null +++ b/winpr/libwinpr/memory/test/TestMemoryCreateFileMapping.c @@ -0,0 +1,9 @@ + +#include +#include + +int TestMemoryCreateFileMapping(int argc, char* argv[]) +{ + return 0; +} + diff --git a/winpr/libwinpr/pipe/pipe.c b/winpr/libwinpr/pipe/pipe.c index 5e3018fea..36ab3be6c 100644 --- a/winpr/libwinpr/pipe/pipe.c +++ b/winpr/libwinpr/pipe/pipe.c @@ -37,6 +37,7 @@ #include "../handle/handle.h" #include +#include #include #include #include @@ -143,8 +144,8 @@ HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD if (pNamedPipe->serverfd == -1) { - fprintf(stderr, "CreateNamedPipeA: socket error\n"); - return NULL; + fprintf(stderr, "CreateNamedPipeA: socket error, %s\n", strerror(errno)); + return INVALID_HANDLE_VALUE; } ZeroMemory(&s, sizeof(struct sockaddr_un)); @@ -155,20 +156,30 @@ HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD if (status != 0) { - fprintf(stderr, "CreateNamedPipeA: bind error\n"); - return NULL; + fprintf(stderr, "CreateNamedPipeA: bind error, %s\n", strerror(errno)); + return INVALID_HANDLE_VALUE; } status = listen(pNamedPipe->serverfd, 2); if (status != 0) { - fprintf(stderr, "CreateNamedPipeA: listen error\n"); - return NULL; + fprintf(stderr, "CreateNamedPipeA: listen error, %s\n", strerror(errno)); + return INVALID_HANDLE_VALUE; } UnixChangeFileMode(pNamedPipe->lpFilePath, 0xFFFF); + if (dwOpenMode & FILE_FLAG_OVERLAPPED) + { +#if 0 + int flags = fcntl(pNamedPipe->serverfd, F_GETFL); + + if (flags != -1) + fcntl(pNamedPipe->serverfd, F_SETFL, flags | O_NONBLOCK); +#endif + } + return hNamedPipe; } diff --git a/winpr/libwinpr/rpc/midl.c b/winpr/libwinpr/rpc/midl.c index aab05d549..51116a68b 100644 --- a/winpr/libwinpr/rpc/midl.c +++ b/winpr/libwinpr/rpc/midl.c @@ -26,6 +26,8 @@ #include +#ifndef _WIN32 + void* MIDL_user_allocate(size_t cBytes) { return (malloc(cBytes)); @@ -35,3 +37,5 @@ void MIDL_user_free(void* p) { free(p); } + +#endif diff --git a/winpr/libwinpr/security/security.c b/winpr/libwinpr/security/security.c index 51250e78b..b7f39d281 100644 --- a/winpr/libwinpr/security/security.c +++ b/winpr/libwinpr/security/security.c @@ -85,13 +85,6 @@ * GetKernelObjectSecurity * GetLengthSid * GetPrivateObjectSecurity - * GetSecurityDescriptorControl - * GetSecurityDescriptorDacl - * GetSecurityDescriptorGroup - * GetSecurityDescriptorLength - * GetSecurityDescriptorOwner - * GetSecurityDescriptorRMControl - * GetSecurityDescriptorSacl * GetSidIdentifierAuthority * GetSidLengthRequired * GetSidSubAuthority @@ -102,11 +95,9 @@ * ImpersonateLoggedOnUser * ImpersonateSelf * InitializeAcl - * InitializeSecurityDescriptor * InitializeSid * IsTokenRestricted * IsValidAcl - * IsValidSecurityDescriptor * IsValidSid * IsWellKnownSid * MakeAbsoluteSD @@ -127,12 +118,6 @@ * SetPrivateObjectSecurity * SetPrivateObjectSecurityEx * SetSecurityAccessMask - * SetSecurityDescriptorControl - * SetSecurityDescriptorDacl - * SetSecurityDescriptorGroup - * SetSecurityDescriptorOwner - * SetSecurityDescriptorRMControl - * SetSecurityDescriptorSacl * SetTokenInformation */ @@ -140,5 +125,82 @@ #include "security.h" +BOOL InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision) +{ + return TRUE; +} + +DWORD GetSecurityDescriptorLength(PSECURITY_DESCRIPTOR pSecurityDescriptor) +{ + return 0; +} + +BOOL IsValidSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor) +{ + return TRUE; +} + +BOOL GetSecurityDescriptorControl(PSECURITY_DESCRIPTOR pSecurityDescriptor, + PSECURITY_DESCRIPTOR_CONTROL pControl, LPDWORD lpdwRevision) +{ + return TRUE; +} + +BOOL SetSecurityDescriptorControl(PSECURITY_DESCRIPTOR pSecurityDescriptor, + SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet) +{ + return TRUE; +} + +BOOL GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbDaclPresent, PACL* pDacl, LPBOOL lpbDaclDefaulted) +{ + return TRUE; +} + +BOOL SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl, BOOL bDaclDefaulted) +{ + return TRUE; +} + +BOOL GetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID* pGroup, LPBOOL lpbGroupDefaulted) +{ + return TRUE; +} + +BOOL SetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pGroup, BOOL bGroupDefaulted) +{ + return TRUE; +} + +BOOL GetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID* pOwner, LPBOOL lpbOwnerDefaulted) +{ + return TRUE; +} + +BOOL SetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pOwner, BOOL bOwnerDefaulted) +{ + return TRUE; +} + +DWORD GetSecurityDescriptorRMControl(PSECURITY_DESCRIPTOR SecurityDescriptor, PUCHAR RMControl) +{ + return 0; +} + +DWORD SetSecurityDescriptorRMControl(PSECURITY_DESCRIPTOR SecurityDescriptor, PUCHAR RMControl) +{ + return 0; +} + +BOOL GetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbSaclPresent, PACL* pSacl, LPBOOL lpbSaclDefaulted) +{ + return TRUE; +} + +BOOL SetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bSaclPresent, PACL pSacl, BOOL bSaclDefaulted) +{ + return TRUE; +} + #endif diff --git a/winpr/libwinpr/sspi/CMakeLists.txt b/winpr/libwinpr/sspi/CMakeLists.txt index 7bfe934f3..c9eac6a6d 100644 --- a/winpr/libwinpr/sspi/CMakeLists.txt +++ b/winpr/libwinpr/sspi/CMakeLists.txt @@ -74,8 +74,6 @@ set(${MODULE_PREFIX}_LIBS if(WIN32) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ws2_32) -else() - set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${ZLIB_LIBRARIES}) endif() set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS diff --git a/winpr/libwinpr/sspi/sspi.c b/winpr/libwinpr/sspi/sspi.c index 4922756ee..f9ec6a74a 100644 --- a/winpr/libwinpr/sspi/sspi.c +++ b/winpr/libwinpr/sspi/sspi.c @@ -209,11 +209,13 @@ void sspi_CredentialsFree(CREDENTIALS* credentials) free(credentials); } -void sspi_SecBufferAlloc(PSecBuffer SecBuffer, size_t size) +void sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size) { SecBuffer->cbBuffer = size; SecBuffer->pvBuffer = malloc(size); - ZeroMemory(SecBuffer->pvBuffer, SecBuffer->cbBuffer); + + if (SecBuffer->pvBuffer) + ZeroMemory(SecBuffer->pvBuffer, SecBuffer->cbBuffer); } void sspi_SecBufferFree(PSecBuffer SecBuffer) @@ -380,7 +382,7 @@ void sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDE PSecBuffer sspi_FindSecBuffer(PSecBufferDesc pMessage, ULONG BufferType) { - int index; + ULONG index; PSecBuffer pSecBuffer = NULL; for (index = 0; index < pMessage->cBuffers; index++) diff --git a/winpr/libwinpr/sspi/test/CMakeLists.txt b/winpr/libwinpr/sspi/test/CMakeLists.txt index 4ea3599d6..593b22c3d 100644 --- a/winpr/libwinpr/sspi/test/CMakeLists.txt +++ b/winpr/libwinpr/sspi/test/CMakeLists.txt @@ -16,8 +16,15 @@ create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS}) +include_directories(${ZLIB_INCLUDE_DIRS}) +include_directories(${OPENSSL_INCLUDE_DIR}) + add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) +set(${MODULE_PREFIX}_LIBS + ${ZLIB_LIBRARIES} + ${OPENSSL_LIBRARIES}) + if(WIN32) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} secur32 crypt32) endif() diff --git a/winpr/libwinpr/synch/CMakeLists.txt b/winpr/libwinpr/synch/CMakeLists.txt index 7104df843..af1279489 100644 --- a/winpr/libwinpr/synch/CMakeLists.txt +++ b/winpr/libwinpr/synch/CMakeLists.txt @@ -57,7 +57,7 @@ endif() set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL MODULE winpr - MODULES winpr-handle winpr-interlocked winpr-thread winpr-sysinfo) + MODULES winpr-handle winpr-error winpr-interlocked winpr-thread winpr-sysinfo) if(MONOLITHIC_BUILD) set(WINPR_LIBS ${WINPR_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE) diff --git a/winpr/libwinpr/synch/critical.c b/winpr/libwinpr/synch/critical.c index 90909e67f..6f7ecdf9e 100644 --- a/winpr/libwinpr/synch/critical.c +++ b/winpr/libwinpr/synch/critical.c @@ -235,7 +235,7 @@ VOID DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection) #endif -#if ((_WIN32) && (_WIN32_WINNT < 0x0600)) +#if ((_WIN32) && (_WIN32_WINNT < 0x0403)) typedef BOOL (WINAPI * PINITIALIZE_CRITICAL_SECTION_EX_FN)(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD Flags); diff --git a/winpr/libwinpr/synch/event.c b/winpr/libwinpr/synch/event.c index 3b96127b7..3a911b2e8 100644 --- a/winpr/libwinpr/synch/event.c +++ b/winpr/libwinpr/synch/event.c @@ -41,6 +41,7 @@ #endif #include "../handle/handle.h" +#include "../pipe/pipe.h" CRITICAL_SECTION cs = { NULL, 0, 0, NULL, NULL, 0 }; @@ -267,6 +268,12 @@ int GetEventFileDescriptor(HANDLE hEvent) return -1; event = (WINPR_EVENT*) Object; + if (Type == HANDLE_TYPE_NAMED_PIPE) + { + WINPR_NAMED_PIPE *named = (WINPR_NAMED_PIPE *)hEvent; + if (named->ServerMode) + return named->serverfd; + } return event->pipe_fd[0]; #else diff --git a/winpr/libwinpr/synch/synch.h b/winpr/libwinpr/synch/synch.h index d0f283f44..fbde1d4a8 100644 --- a/winpr/libwinpr/synch/synch.h +++ b/winpr/libwinpr/synch/synch.h @@ -99,9 +99,6 @@ struct winpr_timer #ifdef WITH_POSIX_TIMER timer_t tid; -#endif - -#ifdef HAVE_TIMERFD_H struct itimerspec timeout; #endif }; @@ -121,7 +118,8 @@ struct winpr_timer_queue struct sched_param param; BOOL bCancelled; - WINPR_TIMER_QUEUE_TIMER* head; + WINPR_TIMER_QUEUE_TIMER* activeHead; + WINPR_TIMER_QUEUE_TIMER* inactiveHead; }; typedef struct winpr_timer_queue WINPR_TIMER_QUEUE; diff --git a/winpr/libwinpr/synch/test/CMakeLists.txt b/winpr/libwinpr/synch/test/CMakeLists.txt index 1d21af0e4..7805d1798 100644 --- a/winpr/libwinpr/synch/test/CMakeLists.txt +++ b/winpr/libwinpr/synch/test/CMakeLists.txt @@ -23,7 +23,7 @@ add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE winpr - MODULES winpr-synch winpr-sysinfo) + MODULES winpr-synch winpr-sysinfo winpr-error) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) diff --git a/winpr/libwinpr/synch/test/TestSynchTimerQueue.c b/winpr/libwinpr/synch/test/TestSynchTimerQueue.c index 67a20db2a..db1261aa9 100644 --- a/winpr/libwinpr/synch/test/TestSynchTimerQueue.c +++ b/winpr/libwinpr/synch/test/TestSynchTimerQueue.c @@ -45,6 +45,8 @@ VOID CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired) { SetEvent(g_Event); } + + Sleep(50); } int TestSynchTimerQueue(int argc, char* argv[]) @@ -60,7 +62,7 @@ int TestSynchTimerQueue(int argc, char* argv[]) if (!hTimerQueue) { - printf("CreateTimerQueue failed (%d)\n", GetLastError()); + printf("CreateTimerQueue failed (%d)\n", (int) GetLastError()); return -1; } @@ -75,14 +77,14 @@ int TestSynchTimerQueue(int argc, char* argv[]) if (!CreateTimerQueueTimer(&hTimers[index], hTimerQueue, (WAITORTIMERCALLBACK) TimerRoutine, &apcData[index], apcData[index].DueTime, apcData[index].Period, 0)) { - printf("CreateTimerQueueTimer failed (%d)\n", GetLastError()); + printf("CreateTimerQueueTimer failed (%d)\n", (int) GetLastError()); return -1; } } if (WaitForSingleObject(g_Event, INFINITE) != WAIT_OBJECT_0) { - printf("WaitForSingleObject failed (%d)\n", GetLastError()); + printf("WaitForSingleObject failed (%d)\n", (int) GetLastError()); return -1; } @@ -90,14 +92,14 @@ int TestSynchTimerQueue(int argc, char* argv[]) { if (!DeleteTimerQueueTimer(hTimerQueue, hTimers[index], NULL)) { - printf("DeleteTimerQueueTimer failed (%d)\n", GetLastError()); + printf("DeleteTimerQueueTimer failed (%d)\n", (int) GetLastError()); return -1; } } if (!DeleteTimerQueue(hTimerQueue)) { - printf("DeleteTimerQueue failed (%d)\n", GetLastError()); + printf("DeleteTimerQueue failed (%d)\n", (int) GetLastError()); return -1; } diff --git a/winpr/libwinpr/synch/timer.c b/winpr/libwinpr/synch/timer.c index 511c1795b..8a4d20631 100644 --- a/winpr/libwinpr/synch/timer.c +++ b/winpr/libwinpr/synch/timer.c @@ -335,6 +335,14 @@ static void timespec_add_ms(struct timespec* tspec, UINT32 ms) tspec->tv_nsec = (ns % 1000000000); } +static UINT64 timespec_to_ms(struct timespec* tspec) +{ + UINT64 ms; + ms = tspec->tv_sec * 1000; + ms += tspec->tv_nsec / 1000000; + return ms; +} + static void timespec_gettimeofday(struct timespec* tspec) { struct timeval tval; @@ -345,13 +353,10 @@ static void timespec_gettimeofday(struct timespec* tspec) static int timespec_compare(const struct timespec* tspec1, const struct timespec* tspec2) { - if (tspec1->tv_sec < tspec2->tv_sec) - return -1; - - if (tspec1->tv_sec > tspec2->tv_sec) - return 1; - - return tspec1->tv_nsec - tspec2->tv_nsec; + if (tspec1->tv_sec == tspec2->tv_sec) + return (tspec1->tv_nsec - tspec2->tv_nsec); + else + return (tspec1->tv_sec - tspec2->tv_sec); } static void timespec_copy(struct timespec* dst, struct timespec* src) @@ -363,37 +368,49 @@ static void timespec_copy(struct timespec* dst, struct timespec* src) void InsertTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TIMER* timer) { WINPR_TIMER_QUEUE_TIMER* node; - + if (!(*pHead)) { *pHead = timer; + timer->next = NULL; return; } node = *pHead; - + while (node->next) { - if (timespec_compare(&(timer->ExpirationTime), &(node->ExpirationTime)) < 0) - break; + if (timespec_compare(&(timer->ExpirationTime), &(node->ExpirationTime)) > 0) + { + if (timespec_compare(&(timer->ExpirationTime), &(node->next->ExpirationTime)) < 0) + break; + } node = node->next; } if (node->next) + { timer->next = node->next->next; - - node->next = timer; + node->next = timer; + } + else + { + node->next = timer; + timer->next = NULL; + } } void RemoveTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TIMER* timer) { + BOOL found = FALSE; WINPR_TIMER_QUEUE_TIMER* node; WINPR_TIMER_QUEUE_TIMER* prevNode; if (timer == *pHead) { *pHead = timer->next; + timer->next = NULL; return; } @@ -403,14 +420,24 @@ void RemoveTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TI while (node) { if (node == timer) + { + found = TRUE; break; + } prevNode = node; node = node->next; } - - prevNode->next = timer->next; - timer->next = NULL; + + if (found) + { + if (prevNode) + { + prevNode->next = timer->next; + } + + timer->next = NULL; + } } int FireExpiredTimerQueueTimers(WINPR_TIMER_QUEUE* timerQueue) @@ -418,12 +445,12 @@ int FireExpiredTimerQueueTimers(WINPR_TIMER_QUEUE* timerQueue) struct timespec CurrentTime; WINPR_TIMER_QUEUE_TIMER* node; - if (!timerQueue->head) + if (!timerQueue->activeHead) return 0; timespec_gettimeofday(&CurrentTime); - node = timerQueue->head; + node = timerQueue->activeHead; while (node) { @@ -432,16 +459,20 @@ int FireExpiredTimerQueueTimers(WINPR_TIMER_QUEUE* timerQueue) node->Callback(node->Parameter, TRUE); node->FireCount++; - timerQueue->head = node->next; + timerQueue->activeHead = node->next; node->next = NULL; if (node->Period) { timespec_add_ms(&(node->ExpirationTime), node->Period); - - InsertTimerQueueTimer(&(timerQueue->head), node); - node = timerQueue->head; + InsertTimerQueueTimer(&(timerQueue->activeHead), node); } + else + { + InsertTimerQueueTimer(&(timerQueue->inactiveHead), node); + } + + node = timerQueue->activeHead; } else { @@ -462,14 +493,18 @@ static void* TimerQueueThread(void* arg) { pthread_mutex_lock(&(timerQueue->cond_mutex)); - if (!timerQueue->head) + timespec_gettimeofday(&timeout); + + if (!timerQueue->activeHead) { - timespec_gettimeofday(&timeout); - timespec_add_ms(&timeout, 100); + timespec_add_ms(&timeout, 50); } else { - timespec_copy(&timeout, &(timerQueue->head->ExpirationTime)); + if (timespec_compare(&timeout, &(timerQueue->activeHead->ExpirationTime)) < 0) + { + timespec_copy(&timeout, &(timerQueue->activeHead->ExpirationTime)); + } } status = pthread_cond_timedwait(&(timerQueue->cond), &(timerQueue->cond_mutex), &timeout); @@ -510,12 +545,15 @@ HANDLE CreateTimerQueue(void) if (timerQueue) { + ZeroMemory(timerQueue, sizeof(WINPR_TIMER_QUEUE)); + WINPR_HANDLE_SET_TYPE(timerQueue, HANDLE_TYPE_TIMER_QUEUE); handle = (HANDLE) timerQueue; - timerQueue->head = NULL; + timerQueue->activeHead = NULL; + timerQueue->inactiveHead = NULL; timerQueue->bCancelled = FALSE; - + StartTimerQueueThread(timerQueue); } @@ -553,7 +591,21 @@ BOOL DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent) { /* Cancel all timers and return immediately */ - node = timerQueue->head; + /* Move all active timers to the inactive timer list */ + + node = timerQueue->activeHead; + + while (node) + { + InsertTimerQueueTimer(&(timerQueue->inactiveHead), node); + node = node->next; + } + + timerQueue->activeHead = NULL; + + /* Once all timers are inactive, free them */ + + node = timerQueue->inactiveHead; while (node) { @@ -564,7 +616,7 @@ BOOL DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent) node = nextNode; } - timerQueue->head = NULL; + timerQueue->inactiveHead = NULL; } /* Delete timer queue */ @@ -592,9 +644,12 @@ BOOL DeleteTimerQueue(HANDLE TimerQueue) BOOL CreateTimerQueueTimer(PHANDLE phNewTimer, HANDLE TimerQueue, WAITORTIMERCALLBACK Callback, PVOID Parameter, DWORD DueTime, DWORD Period, ULONG Flags) { + struct timespec CurrentTime; WINPR_TIMER_QUEUE* timerQueue; WINPR_TIMER_QUEUE_TIMER* timer; + timespec_gettimeofday(&CurrentTime); + timerQueue = (WINPR_TIMER_QUEUE*) TimerQueue; timer = (WINPR_TIMER_QUEUE_TIMER*) malloc(sizeof(WINPR_TIMER_QUEUE_TIMER)); @@ -604,7 +659,7 @@ BOOL CreateTimerQueueTimer(PHANDLE phNewTimer, HANDLE TimerQueue, WINPR_HANDLE_SET_TYPE(timer, HANDLE_TYPE_TIMER_QUEUE_TIMER); *((UINT_PTR*) phNewTimer) = (UINT_PTR) (HANDLE) timer; - timespec_gettimeofday(&(timer->StartTime)); + timespec_copy(&(timer->StartTime), &CurrentTime); timespec_add_ms(&(timer->StartTime), DueTime); timespec_copy(&(timer->ExpirationTime), &(timer->StartTime)); @@ -617,10 +672,11 @@ BOOL CreateTimerQueueTimer(PHANDLE phNewTimer, HANDLE TimerQueue, timer->timerQueue = (WINPR_TIMER_QUEUE*) TimerQueue; timer->FireCount = 0; + timer->next = NULL; pthread_mutex_lock(&(timerQueue->cond_mutex)); - InsertTimerQueueTimer(&(timerQueue->head), timer); + InsertTimerQueueTimer(&(timerQueue->activeHead), timer); pthread_cond_signal(&(timerQueue->cond)); pthread_mutex_unlock(&(timerQueue->cond_mutex)); @@ -630,27 +686,32 @@ BOOL CreateTimerQueueTimer(PHANDLE phNewTimer, HANDLE TimerQueue, BOOL ChangeTimerQueueTimer(HANDLE TimerQueue, HANDLE Timer, ULONG DueTime, ULONG Period) { + struct timespec CurrentTime; WINPR_TIMER_QUEUE* timerQueue; WINPR_TIMER_QUEUE_TIMER* timer; if (!TimerQueue || !Timer) return FALSE; + timespec_gettimeofday(&CurrentTime); + timerQueue = (WINPR_TIMER_QUEUE*) TimerQueue; timer = (WINPR_TIMER_QUEUE_TIMER*) Timer; pthread_mutex_lock(&(timerQueue->cond_mutex)); - RemoveTimerQueueTimer(&(timerQueue->head), timer); + RemoveTimerQueueTimer(&(timerQueue->activeHead), timer); + RemoveTimerQueueTimer(&(timerQueue->inactiveHead), timer); timer->DueTime = DueTime; timer->Period = Period; + timer->next = NULL; - timespec_gettimeofday(&(timer->StartTime)); + timespec_copy(&(timer->StartTime), &CurrentTime); timespec_add_ms(&(timer->StartTime), DueTime); timespec_copy(&(timer->ExpirationTime), &(timer->StartTime)); - InsertTimerQueueTimer(&(timerQueue->head), timer); + InsertTimerQueueTimer(&(timerQueue->activeHead), timer); pthread_cond_signal(&(timerQueue->cond)); pthread_mutex_unlock(&(timerQueue->cond_mutex)); @@ -679,7 +740,7 @@ BOOL DeleteTimerQueueTimer(HANDLE TimerQueue, HANDLE Timer, HANDLE CompletionEve { /* Cancel timer and return immediately */ - RemoveTimerQueueTimer(&(timerQueue->head), timer); + RemoveTimerQueueTimer(&(timerQueue->activeHead), timer); } pthread_cond_signal(&(timerQueue->cond)); diff --git a/winpr/libwinpr/synch/wait.c b/winpr/libwinpr/synch/wait.c index eb2268c11..304b6e9fd 100644 --- a/winpr/libwinpr/synch/wait.c +++ b/winpr/libwinpr/synch/wait.c @@ -505,6 +505,7 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl if (!winpr_Handle_GetInfo(lpHandles[index], &Type, &Object)) { fprintf(stderr, "WaitForMultipleObjects: invalid handle\n"); + return WAIT_FAILED; } diff --git a/winpr/libwinpr/thread/process.c b/winpr/libwinpr/thread/process.c index d3945f28e..f6cdb24f6 100644 --- a/winpr/libwinpr/thread/process.c +++ b/winpr/libwinpr/thread/process.c @@ -251,6 +251,10 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags, if (token->UserId) setuid((uid_t) token->UserId); + + /* TODO: add better cwd handling and error checking */ + if (lpCurrentDirectory && strlen(lpCurrentDirectory) > 0) + chdir(lpCurrentDirectory); } if (execve(filename, pArgs, envp) < 0) diff --git a/winpr/libwinpr/utils/CMakeLists.txt b/winpr/libwinpr/utils/CMakeLists.txt index b156a2bf2..adb2bbcca 100644 --- a/winpr/libwinpr/utils/CMakeLists.txt +++ b/winpr/libwinpr/utils/CMakeLists.txt @@ -28,6 +28,7 @@ set(${MODULE_PREFIX}_COLLECTIONS_SRCS collections/ArrayList.c collections/Dictionary.c collections/LinkedList.c + collections/HashTable.c collections/ListDictionary.c collections/KeyValuePair.c collections/CountdownEvent.c diff --git a/winpr/libwinpr/utils/collections/HashTable.c b/winpr/libwinpr/utils/collections/HashTable.c new file mode 100644 index 000000000..15ae5175e --- /dev/null +++ b/winpr/libwinpr/utils/collections/HashTable.c @@ -0,0 +1,543 @@ +/** + * WinPR: Windows Portable Runtime + * System.Collections.Hashtable + * + * Copyright 2014 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 + +/** + * This implementation is based on the public domain + * hash table implementation made by Keith Pomakis: + * + * http://www.pomakis.com/hashtable/hashtable.c + * http://www.pomakis.com/hashtable/hashtable.h + */ + +static int isProbablePrime(long oddNumber) +{ + long i; + + for (i = 3; i < 51; i += 2) + { + if (oddNumber == i) + return 1; + else if (oddNumber % i == 0) + return 0; + } + + return 1; /* maybe */ +} + +static long calculateIdealNumOfBuckets(wHashTable* table) +{ + long idealNumOfBuckets = table->numOfElements / ((long) table->idealRatio); + + if (idealNumOfBuckets < 5) + idealNumOfBuckets = 5; + else + idealNumOfBuckets |= 0x01; + + while (!isProbablePrime(idealNumOfBuckets)) + idealNumOfBuckets += 2; + + return idealNumOfBuckets; +} + +void HashTable_Rehash(wHashTable* table, long numOfBuckets) +{ + int index; + long hashValue; + wKeyValuePair* pair; + wKeyValuePair* nextPair; + wKeyValuePair** newBucketArray; + + if (numOfBuckets == 0) + numOfBuckets = calculateIdealNumOfBuckets(table); + + if (numOfBuckets == table->numOfBuckets) + return; /* already the right size! */ + + newBucketArray = (wKeyValuePair**) malloc(numOfBuckets * sizeof(wKeyValuePair*)); + + if (newBucketArray == NULL) + { + /* Couldn't allocate memory for the new array. This isn't a fatal + * error; we just can't perform the rehash. */ + return; + } + + for (index = 0; index < numOfBuckets; index++) + newBucketArray[index] = NULL; + + for (index = 0; index < table->numOfBuckets; index++) + { + pair = table->bucketArray[index]; + + while (pair != NULL) + { + nextPair = pair->next; + hashValue = table->hashFunction(pair->key) % numOfBuckets; + pair->next = newBucketArray[hashValue]; + newBucketArray[hashValue] = pair; + pair = nextPair; + } + } + + free(table->bucketArray); + table->bucketArray = newBucketArray; + table->numOfBuckets = numOfBuckets; +} + +void HashTable_SetIdealRatio(wHashTable* table, float idealRatio, + float lowerRehashThreshold, float upperRehashThreshold) +{ + table->idealRatio = idealRatio; + table->lowerRehashThreshold = lowerRehashThreshold; + table->upperRehashThreshold = upperRehashThreshold; +} + +unsigned long HashTable_StringHashFunction(void* key) +{ + int c; + unsigned long hash = 5381; + unsigned char* str = (unsigned char*) key; + + /* djb2 algorithm */ + while ((c = *str++) != '\0') + hash = (hash * 33) + c; + + return hash; +} + +wKeyValuePair* HashTable_Get(wHashTable* table, void* key) +{ + long hashValue = table->hashFunction(key) % table->numOfBuckets; + wKeyValuePair* pair = table->bucketArray[hashValue]; + + while (pair != NULL && table->keycmp(key, pair->key) != 0) + pair = pair->next; + + return pair; +} + +static int pointercmp(void* pointer1, void* pointer2) +{ + return (pointer1 != pointer2); +} + +static unsigned long pointerHashFunction(void* pointer) +{ + return ((unsigned long) pointer) >> 4; +} + +/** + * C equivalent of the C# Hashtable Class: + * http://msdn.microsoft.com/en-us/library/system.collections.hashtable.aspx + */ + +/** + * Properties + */ + +/** + * Gets the number of key/value pairs contained in the HashTable. + */ + +int HashTable_Count(wHashTable* table) +{ + return table->numOfElements; +} + +/** + * Methods + */ + +/** + * Adds an element with the specified key and value into the HashTable. + */ + +int HashTable_Add(wHashTable* table, void* key, void* value) +{ + int status = 0; + long hashValue; + wKeyValuePair* pair; + wKeyValuePair* newPair; + + if (!key || !value) + return -1; + + if (table->synchronized) + EnterCriticalSection(&table->lock); + + hashValue = table->hashFunction(key) % table->numOfBuckets; + pair = table->bucketArray[hashValue]; + + while (pair != NULL && table->keycmp(key, pair->key) != 0) + pair = pair->next; + + if (pair) + { + if (pair->key != key) + { + if (table->keyDeallocator) + table->keyDeallocator((void*) pair->key); + pair->key = key; + } + + if (pair->value != value) + { + if (table->valueDeallocator) + table->valueDeallocator(pair->value); + pair->value = value; + } + } + else + { + newPair = (wKeyValuePair*) malloc(sizeof(wKeyValuePair)); + + if (!newPair) + { + status = -1; + } + else + { + newPair->key = key; + newPair->value = value; + newPair->next = table->bucketArray[hashValue]; + table->bucketArray[hashValue] = newPair; + table->numOfElements++; + + if (table->upperRehashThreshold > table->idealRatio) + { + float elementToBucketRatio = (float) table->numOfElements / (float) table->numOfBuckets; + + if (elementToBucketRatio > table->upperRehashThreshold) + HashTable_Rehash(table, 0); + } + } + } + + if (table->synchronized) + LeaveCriticalSection(&table->lock); + + return status; +} + +/** + * Removes the element with the specified key from the HashTable. + */ + +BOOL HashTable_Remove(wHashTable* table, void* key) +{ + BOOL status = TRUE; + long hashValue = table->hashFunction(key) % table->numOfBuckets; + wKeyValuePair* pair = table->bucketArray[hashValue]; + wKeyValuePair* previousPair = NULL; + + if (table->synchronized) + EnterCriticalSection(&table->lock); + + while (pair && table->keycmp(key, pair->key) != 0) + { + previousPair = pair; + pair = pair->next; + } + + if (!pair) + { + status = FALSE; + } + else + { + if (table->keyDeallocator) + table->keyDeallocator((void*) pair->key); + + if (table->valueDeallocator) + table->valueDeallocator(pair->value); + + if (previousPair) + previousPair->next = pair->next; + else + table->bucketArray[hashValue] = pair->next; + + free(pair); + + table->numOfElements--; + + if (table->lowerRehashThreshold > 0.0) + { + float elementToBucketRatio = (float) table->numOfElements / (float) table->numOfBuckets; + + if (elementToBucketRatio < table->lowerRehashThreshold) + HashTable_Rehash(table, 0); + } + } + + if (table->synchronized) + LeaveCriticalSection(&table->lock); + + return status; +} + +/** + * Get an item value using key + */ + +void* HashTable_GetItemValue(wHashTable* table, void* key) +{ + void* value = NULL; + wKeyValuePair* pair; + + if (table->synchronized) + EnterCriticalSection(&table->lock); + + pair = HashTable_Get(table, key); + + if (pair) + value = pair->value; + + if (table->synchronized) + LeaveCriticalSection(&table->lock); + + return value; +} + +/** + * Set an item value using key + */ + +BOOL HashTable_SetItemValue(wHashTable* table, void* key, void* value) +{ + BOOL status = TRUE; + wKeyValuePair* pair; + + if (table->synchronized) + EnterCriticalSection(&table->lock); + + pair = HashTable_Get(table, key); + + if (!pair) + status = FALSE; + else + pair->value = value; + + if (table->synchronized) + LeaveCriticalSection(&table->lock); + + return status; +} + +/** + * Removes all elements from the HashTable. + */ + +void HashTable_Clear(wHashTable* table) +{ + int index; + wKeyValuePair* pair; + wKeyValuePair* nextPair; + + if (table->synchronized) + EnterCriticalSection(&table->lock); + + for (index = 0; index < table->numOfBuckets; index++) + { + pair = table->bucketArray[index]; + + while (pair) + { + nextPair = pair->next; + + if (table->keyDeallocator) + table->keyDeallocator((void*) pair->key); + + if (table->valueDeallocator) + table->valueDeallocator(pair->value); + + free(pair); + + pair = nextPair; + } + + table->bucketArray[index] = NULL; + } + + table->numOfElements = 0; + HashTable_Rehash(table, 5); + + if (table->synchronized) + LeaveCriticalSection(&table->lock); +} + +/** + * Determines whether the HashTable contains a specific key. + */ + +BOOL HashTable_Contains(wHashTable* table, void* key) +{ + BOOL status; + + if (table->synchronized) + EnterCriticalSection(&table->lock); + + status = (HashTable_Get(table, key) != NULL) ? TRUE : FALSE; + + if (table->synchronized) + LeaveCriticalSection(&table->lock); + + return status; +} + +/** + * Determines whether the HashTable contains a specific key. + */ + +BOOL HashTable_ContainsKey(wHashTable* table, void* key) +{ + BOOL status; + + if (table->synchronized) + EnterCriticalSection(&table->lock); + + status = (HashTable_Get(table, key) != NULL) ? TRUE : FALSE; + + if (table->synchronized) + LeaveCriticalSection(&table->lock); + + return status; +} + +/** + * Determines whether the HashTable contains a specific value. + */ + +BOOL HashTable_ContainsValue(wHashTable* table, void* value) +{ + int index; + BOOL status = FALSE; + wKeyValuePair* pair; + + if (table->synchronized) + EnterCriticalSection(&table->lock); + + for (index = 0; index < table->numOfBuckets; index++) + { + pair = table->bucketArray[index]; + + while (pair) + { + if (table->valuecmp(value, pair->value) == 0) + { + status = TRUE; + break; + } + + pair = pair->next; + } + + if (status) + break; + } + + if (table->synchronized) + LeaveCriticalSection(&table->lock); + + return status; +} + +/** + * Construction, Destruction + */ + +wHashTable* HashTable_New(BOOL synchronized) +{ + int index; + wHashTable* table; + + table = (wHashTable*) calloc(1, sizeof(wHashTable)); + + if (table) + { + table->synchronized = synchronized; + InitializeCriticalSectionAndSpinCount(&table->lock, 4000); + + table->numOfBuckets = 64; + table->numOfElements = 0; + + table->bucketArray = (wKeyValuePair**) malloc(table->numOfBuckets * sizeof(wKeyValuePair*)); + + if (!table->bucketArray) + { + free(table); + return NULL; + } + + for (index = 0; index < table->numOfBuckets; index++) + table->bucketArray[index] = NULL; + + table->idealRatio = 3.0; + table->lowerRehashThreshold = 0.0; + table->upperRehashThreshold = 15.0; + + table->keycmp = pointercmp; + table->valuecmp = pointercmp; + table->hashFunction = pointerHashFunction; + table->keyDeallocator = NULL; + table->valueDeallocator = NULL; + } + + return table; +} + +void HashTable_Free(wHashTable* table) +{ + int index; + wKeyValuePair* pair; + wKeyValuePair* nextPair; + + if (table) + { + for (index = 0; index < table->numOfBuckets; index++) + { + pair = table->bucketArray[index]; + + while (pair) + { + nextPair = pair->next; + + if (table->keyDeallocator) + table->keyDeallocator((void*) pair->key); + + if (table->valueDeallocator) + table->valueDeallocator(pair->value); + + free(pair); + + pair = nextPair; + } + } + + free(table->bucketArray); + free(table); + } +} diff --git a/winpr/libwinpr/utils/collections/LinkedList.c b/winpr/libwinpr/utils/collections/LinkedList.c index f96f9d7c0..5cac91bed 100644 --- a/winpr/libwinpr/utils/collections/LinkedList.c +++ b/winpr/libwinpr/utils/collections/LinkedList.c @@ -192,8 +192,11 @@ void LinkedList_Remove(wLinkedList* list, void* value) if (node->next) node->next->prev = node->prev; - if ((!node->prev) && (!node->next)) - list->head = list->tail = NULL; + if (node == list->head) + list->head = node->next; + + if (node == list->tail) + list->tail = node->prev; free(node); diff --git a/winpr/libwinpr/utils/collections/ListDictionary.c b/winpr/libwinpr/utils/collections/ListDictionary.c index bef4f0757..586e20a7a 100644 --- a/winpr/libwinpr/utils/collections/ListDictionary.c +++ b/winpr/libwinpr/utils/collections/ListDictionary.c @@ -21,8 +21,9 @@ #include "config.h" #endif +#include + #include -#include /** * C equivalent of the C# ListDictionary Class: diff --git a/winpr/libwinpr/utils/collections/Reference.c b/winpr/libwinpr/utils/collections/Reference.c index c2df4773f..b12c121c2 100644 --- a/winpr/libwinpr/utils/collections/Reference.c +++ b/winpr/libwinpr/utils/collections/Reference.c @@ -36,7 +36,7 @@ wReference* ReferenceTable_FindEntry(wReferenceTable* referenceTable, void* ptr) { - int index = 0; + UINT32 index = 0; BOOL found = FALSE; wReference* reference = NULL; @@ -53,7 +53,7 @@ wReference* ReferenceTable_FindEntry(wReferenceTable* referenceTable, void* ptr) wReference* ReferenceTable_GetFreeEntry(wReferenceTable* referenceTable) { - int index = 0; + UINT32 index = 0; BOOL found = FALSE; wReference* reference = NULL; diff --git a/winpr/libwinpr/utils/sam.c b/winpr/libwinpr/utils/sam.c index bd0db1c4e..8c3b91764 100644 --- a/winpr/libwinpr/utils/sam.c +++ b/winpr/libwinpr/utils/sam.c @@ -151,11 +151,11 @@ WINPR_SAM_ENTRY* SamReadEntry(WINPR_SAM* sam, WINPR_SAM_ENTRY* entry) p[5] = strchr(p[4], ':') + 1; p[6] = p[0] + strlen(p[0]); - entry->UserLength = p[1] - p[0] - 1; - entry->DomainLength = p[2] - p[1] - 1; + entry->UserLength = (UINT32) (p[1] - p[0] - 1); + entry->DomainLength = (UINT32) (p[2] - p[1] - 1); - LmHashLength = p[3] - p[2] - 1; - NtHashLength = p[4] - p[3] - 1; + LmHashLength = (int) (p[3] - p[2] - 1); + NtHashLength = (int) (p[4] - p[3] - 1); entry->User = (LPSTR) malloc(entry->UserLength + 1); memcpy(entry->User, p[0], entry->UserLength); @@ -211,7 +211,7 @@ WINPR_SAM_ENTRY* SamLookupUserA(WINPR_SAM* sam, LPSTR User, UINT32 UserLength, L while (sam->line != NULL) { - length = strlen(sam->line); + length = (int) strlen(sam->line); if (length > 1) { @@ -259,7 +259,7 @@ WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength, while (sam->line != NULL) { - length = strlen(sam->line); + length = (int) strlen(sam->line); if (length > 1) { @@ -274,7 +274,7 @@ WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength, { if (entry->DomainLength > 0) { - EntryDomainLength = strlen(entry->Domain) * 2; + EntryDomainLength = (UINT32) strlen(entry->Domain) * 2; EntryDomain = (LPWSTR) malloc(EntryDomainLength + 2); MultiByteToWideChar(CP_ACP, 0, entry->Domain, EntryDomainLength / 2, (LPWSTR) EntryDomain, EntryDomainLength / 2); @@ -300,7 +300,7 @@ WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength, if (DomainMatch) { - EntryUserLength = strlen(entry->User) * 2; + EntryUserLength = (UINT32) strlen(entry->User) * 2; EntryUser = (LPWSTR) malloc(EntryUserLength + 2); MultiByteToWideChar(CP_ACP, 0, entry->User, EntryUserLength / 2, (LPWSTR) EntryUser, EntryUserLength / 2); diff --git a/winpr/libwinpr/utils/test/CMakeLists.txt b/winpr/libwinpr/utils/test/CMakeLists.txt index 1bb18bfca..c1e454065 100644 --- a/winpr/libwinpr/utils/test/CMakeLists.txt +++ b/winpr/libwinpr/utils/test/CMakeLists.txt @@ -13,6 +13,7 @@ set(${MODULE_PREFIX}_TESTS TestListDictionary.c TestCmdLine.c TestWLog.c + TestHashTable.c TestBufferPool.c TestStreamPool.c TestMessageQueue.c diff --git a/winpr/libwinpr/utils/test/TestHashTable.c b/winpr/libwinpr/utils/test/TestHashTable.c new file mode 100644 index 000000000..e71a0ebba --- /dev/null +++ b/winpr/libwinpr/utils/test/TestHashTable.c @@ -0,0 +1,141 @@ + +#include +#include +#include + +static char* key1 = "key1"; +static char* key2 = "key2"; +static char* key3 = "key3"; + +static char* val1 = "val1"; +static char* val2 = "val2"; +static char* val3 = "val3"; + +int TestHashTable(int argc, char* argv[]) +{ + int count; + char* value; + wHashTable* table; + + table = HashTable_New(TRUE); + + HashTable_Add(table, key1, val1); + HashTable_Add(table, key2, val2); + HashTable_Add(table, key3, val3); + + count = HashTable_Count(table); + + if (count != 3) + { + printf("HashTable_Count: Expected : %d, Actual: %d\n", 3, count); + return -1; + } + + HashTable_Remove(table, key2); + + count = HashTable_Count(table); + + if (count != 2) + { + printf("HashTable_Count: Expected : %d, Actual: %d\n", 2, count); + return -1; + } + + HashTable_Remove(table, key3); + + count = HashTable_Count(table); + + if (count != 1) + { + printf("HashTable_Count: Expected : %d, Actual: %d\n", 1, count); + return -1; + } + + HashTable_Remove(table, key1); + + count = HashTable_Count(table); + + if (count != 0) + { + printf("HashTable_Count: Expected : %d, Actual: %d\n", 0, count); + return -1; + } + + HashTable_Add(table, key1, val1); + HashTable_Add(table, key2, val2); + HashTable_Add(table, key3, val3); + + count = HashTable_Count(table); + + if (count != 3) + { + printf("HashTable_Count: Expected : %d, Actual: %d\n", 3, count); + return -1; + } + + value = (char*) HashTable_GetItemValue(table, key1); + + if (strcmp(value, val1) != 0) + { + printf("HashTable_GetItemValue: Expected : %d, Actual: %d\n", val1, value); + return -1; + } + + value = (char*) HashTable_GetItemValue(table, key2); + + if (strcmp(value, val2) != 0) + { + printf("HashTable_GetItemValue: Expected : %d, Actual: %d\n", val2, value); + return -1; + } + + value = (char*) HashTable_GetItemValue(table, key3); + + if (strcmp(value, val3) != 0) + { + printf("HashTable_GetItemValue: Expected : %d, Actual: %d\n", val3, value); + return -1; + } + + HashTable_SetItemValue(table, key2, "apple"); + + value = (char*) HashTable_GetItemValue(table, key2); + + if (strcmp(value, "apple") != 0) + { + printf("HashTable_GetItemValue: Expected : %d, Actual: %d\n", "apple", value); + return -1; + } + + if (!HashTable_Contains(table, key2)) + { + printf("HashTable_Contains: Expected : %d, Actual: %d\n", TRUE, FALSE); + return -1; + } + + if (!HashTable_Remove(table, key2)) + { + printf("HashTable_Remove: Expected : %d, Actual: %d\n", TRUE, FALSE); + return -1; + } + + if (HashTable_Remove(table, key2)) + { + printf("HashTable_Remove: Expected : %d, Actual: %d\n", FALSE, TRUE); + return -1; + } + + HashTable_Clear(table); + + count = HashTable_Count(table); + + if (count != 0) + { + printf("HashTable_Count: Expected : %d, Actual: %d\n", 0, count); + return -1; + } + + HashTable_Free(table); + + return 0; +} diff --git a/winpr/libwinpr/utils/trio/triostr.c b/winpr/libwinpr/utils/trio/triostr.c index 5721b7cb0..c471b4a1d 100644 --- a/winpr/libwinpr/utils/trio/triostr.c +++ b/winpr/libwinpr/utils/trio/triostr.c @@ -103,7 +103,7 @@ # if defined(TRIO_PLATFORM_WINCE) # define strcasecmp(x,y) _stricmp(x,y) # else -# define strcasecmp(x,y) strcmpi(x,y) +# define strcasecmp(x,y) _stricmp(x,y) # endif #endif diff --git a/winpr/libwinpr/utils/wlog/BinaryAppender.c b/winpr/libwinpr/utils/wlog/BinaryAppender.c index f77b99dbb..f0bd1ba5f 100644 --- a/winpr/libwinpr/utils/wlog/BinaryAppender.c +++ b/winpr/libwinpr/utils/wlog/BinaryAppender.c @@ -122,9 +122,6 @@ int WLog_BinaryAppender_WriteMessage(wLog* log, wLogBinaryAppender* appender, wL int FunctionNameLength; int TextStringLength; - if (message->Level > log->Level) - return 0; - fp = appender->FileDescriptor; if (!fp) diff --git a/winpr/libwinpr/utils/wlog/ConsoleAppender.c b/winpr/libwinpr/utils/wlog/ConsoleAppender.c index 0b4375a3e..c9ed6bc66 100644 --- a/winpr/libwinpr/utils/wlog/ConsoleAppender.c +++ b/winpr/libwinpr/utils/wlog/ConsoleAppender.c @@ -68,9 +68,6 @@ int WLog_ConsoleAppender_WriteMessage(wLog* log, wLogConsoleAppender* appender, 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; diff --git a/winpr/libwinpr/utils/wlog/FileAppender.c b/winpr/libwinpr/utils/wlog/FileAppender.c index 5acb75256..c14552857 100644 --- a/winpr/libwinpr/utils/wlog/FileAppender.c +++ b/winpr/libwinpr/utils/wlog/FileAppender.c @@ -117,9 +117,6 @@ int WLog_FileAppender_WriteMessage(wLog* log, wLogFileAppender* appender, wLogMe FILE* fp; char prefix[WLOG_MAX_PREFIX_SIZE]; - if (message->Level > log->Level) - return 0; - fp = appender->FileDescriptor; if (!fp) @@ -130,8 +127,10 @@ int WLog_FileAppender_WriteMessage(wLog* log, wLogFileAppender* appender, wLogMe fprintf(fp, "%s%s\n", message->PrefixString, message->TextString); - //fflush(fp); /* slow! */ - +#ifdef _WIN32 + fflush(fp); /* slow! */ +#endif + return 1; } diff --git a/winpr/libwinpr/utils/wlog/PacketMessage.c b/winpr/libwinpr/utils/wlog/PacketMessage.c index f8919f888..ad6472841 100644 --- a/winpr/libwinpr/utils/wlog/PacketMessage.c +++ b/winpr/libwinpr/utils/wlog/PacketMessage.c @@ -370,7 +370,7 @@ int WLog_PacketMessage_Write(wPcap* pcap, void* data, DWORD length, DWORD flags) ipv4.Version = 4; ipv4.InternetHeaderLength = 5; ipv4.TypeOfService = 0; - ipv4.TotalLength = length + 20 + 20; + ipv4.TotalLength = (UINT16) (length + 20 + 20); ipv4.Identification = 0; ipv4.InternetProtocolFlags = 0x02; ipv4.FragmentOffset = 0; diff --git a/winpr/libwinpr/utils/wlog/wlog.c b/winpr/libwinpr/utils/wlog/wlog.c index 6df27a5ea..286b7bdcb 100644 --- a/winpr/libwinpr/utils/wlog/wlog.c +++ b/winpr/libwinpr/utils/wlog/wlog.c @@ -216,14 +216,20 @@ void WLog_PrintMessage(wLog* log, wLogMessage* message, ...) DWORD WLog_GetLogLevel(wLog* log) { - return log->Level; + if (log->Level == WLOG_LEVEL_INHERIT) { + return WLog_GetLogLevel(log->Parent); + } else { + return log->Level; + } } void WLog_SetLogLevel(wLog* log, DWORD logLevel) { - if (logLevel > WLOG_OFF) - logLevel = WLOG_OFF; + if ((logLevel > WLOG_OFF) && (logLevel != WLOG_LEVEL_INHERIT)) + { + logLevel = WLOG_OFF; + } log->Level = logLevel; } @@ -276,7 +282,7 @@ wLog* WLog_New(LPCSTR name , wLog* rootLogger) log->Name = _strdup(name); WLog_ParseName(log, name); - log->Parent = NULL; + log->Parent = rootLogger; log->ChildrenCount = 0; log->ChildrenSize = 16; @@ -285,41 +291,40 @@ wLog* WLog_New(LPCSTR name , wLog* rootLogger) log->Appender = NULL; if (rootLogger) { - log->Level = rootLogger->Level; + log->Level = WLOG_LEVEL_INHERIT; } else { log->Level = WLOG_WARN; - } + nSize = GetEnvironmentVariableA("WLOG_LEVEL", NULL, 0); - nSize = GetEnvironmentVariableA("WLOG_LEVEL", NULL, 0); - - if (nSize) - { - env = (LPSTR) malloc(nSize); - nSize = GetEnvironmentVariableA("WLOG_LEVEL", env, nSize); - - if (env) + if (nSize) { - if (_stricmp(env, "TRACE") == 0) - log->Level = WLOG_TRACE; - else if (_stricmp(env, "DEBUG") == 0) - log->Level = WLOG_DEBUG; - else if (_stricmp(env, "INFO") == 0) - log->Level = WLOG_INFO; - else if (_stricmp(env, "WARN") == 0) - log->Level = WLOG_WARN; - else if (_stricmp(env, "ERROR") == 0) - log->Level = WLOG_ERROR; - else if (_stricmp(env, "FATAL") == 0) - log->Level = WLOG_FATAL; - else if (_stricmp(env, "OFF") == 0) - log->Level = WLOG_OFF; - else if (_strnicmp(env, "0x", 2) == 0) - { - /* TODO: read custom hex value */ - } + env = (LPSTR) malloc(nSize); + nSize = GetEnvironmentVariableA("WLOG_LEVEL", env, nSize); - free(env); + if (env) + { + if (_stricmp(env, "TRACE") == 0) + log->Level = WLOG_TRACE; + else if (_stricmp(env, "DEBUG") == 0) + log->Level = WLOG_DEBUG; + else if (_stricmp(env, "INFO") == 0) + log->Level = WLOG_INFO; + else if (_stricmp(env, "WARN") == 0) + log->Level = WLOG_WARN; + else if (_stricmp(env, "ERROR") == 0) + log->Level = WLOG_ERROR; + else if (_stricmp(env, "FATAL") == 0) + log->Level = WLOG_FATAL; + else if (_stricmp(env, "OFF") == 0) + log->Level = WLOG_OFF; + else if (_strnicmp(env, "0x", 2) == 0) + { + /* TODO: read custom hex value */ + } + + free(env); + } } } } @@ -403,7 +408,7 @@ int WLog_AddChild(wLog* parent, wLog* child) wLog* WLog_FindChild(LPCSTR name) { - int index; + DWORD index; wLog* root; wLog* child = NULL; BOOL found = FALSE; diff --git a/winpr/libwinpr/winsock/winsock.c b/winpr/libwinpr/winsock/winsock.c index a8cc39eb9..cd1dfed0b 100644 --- a/winpr/libwinpr/winsock/winsock.c +++ b/winpr/libwinpr/winsock/winsock.c @@ -244,6 +244,174 @@ PCSTR inet_ntop(INT Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize) #else /* _WIN32 */ +int WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData) +{ + return 0; +} +int WSACleanup(void) +{ + return 0; +} + +void WSASetLastError(int iError) +{ + +} + +int WSAGetLastError(void) +{ + return 0; +} + +SOCKET _accept(SOCKET s, struct sockaddr* addr, int* addrlen) +{ + return 0; +} + +int _bind(SOCKET s, const struct sockaddr* addr, int namelen) +{ + return 0; +} + +int closesocket(SOCKET s) +{ + return 0; +} + +int _connect(SOCKET s, const struct sockaddr* name, int namelen) +{ + return 0; +} + +int _ioctlsocket(SOCKET s, long cmd, u_long* argp) +{ + return 0; +} + +int _getpeername(SOCKET s, struct sockaddr* name, int* namelen) +{ + return 0; +} + +int _getsockname(SOCKET s, struct sockaddr* name, int* namelen) +{ + return 0; +} + +int _getsockopt(SOCKET s, int level, int optname, char* optval, int* optlen) +{ + return 0; +} + +u_long _htonl(u_long hostlong) +{ + return 0; +} + +u_short _htons(u_short hostshort) +{ + return 0; +} + +unsigned long _inet_addr(const char* cp) +{ + return 0; +} + +char* _inet_ntoa(struct in_addr in) +{ + return 0; +} + +int _listen(SOCKET s, int backlog) +{ + return 0; +} + +u_long _ntohl(u_long netlong) +{ + return 0; +} + +u_short _ntohs(u_short netshort) +{ + return 0; +} + +int _recv(SOCKET s, char* buf, int len, int flags) +{ + return 0; +} + +int _recvfrom(SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int* fromlen) +{ + return 0; +} + +int _select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, const struct timeval* timeout) +{ + return 0; +} + +int _send(SOCKET s, const char* buf, int len, int flags) +{ + return 0; +} + +int _sendto(SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen) +{ + return 0; +} + +int _setsockopt(SOCKET s, int level, int optname, const char* optval, int optlen) +{ + return 0; +} + +int _shutdown(SOCKET s, int how) +{ + return 0; +} + +SOCKET _socket(int af, int type, int protocol) +{ + return 0; +} + +struct hostent* _gethostbyaddr(const char* addr, int len, int type) +{ + return 0; +} + +struct hostent* _gethostbyname(const char* name) +{ + return 0; +} + +int _gethostname(char* name, int namelen) +{ + return 0; +} + +struct servent* _getservbyport(int port, const char* proto) +{ + return 0; +} + +struct servent* _getservbyname(const char* name, const char* proto) +{ + return 0; +} + +struct protoent* _getprotobynumber(int number) +{ + return 0; +} + +struct protoent* _getprotobyname(const char* name) +{ + return 0; +} #endif /* _WIN32 */ diff --git a/winpr/libwinpr/wtsapi/CMakeLists.txt b/winpr/libwinpr/wtsapi/CMakeLists.txt index f00c62109..6590b467f 100644 --- a/winpr/libwinpr/wtsapi/CMakeLists.txt +++ b/winpr/libwinpr/wtsapi/CMakeLists.txt @@ -20,12 +20,7 @@ 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() + wtsapi.h) add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT" MONOLITHIC ${MONOLITHIC_BUILD} diff --git a/winpr/libwinpr/wtsapi/module.def b/winpr/libwinpr/wtsapi/module.def deleted file mode 100644 index b5adf3c6e..000000000 --- a/winpr/libwinpr/wtsapi/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-wtsapi" -EXPORTS diff --git a/winpr/libwinpr/wtsapi/test/CMakeLists.txt b/winpr/libwinpr/wtsapi/test/CMakeLists.txt index fa473d9c2..75fcb8a80 100644 --- a/winpr/libwinpr/wtsapi/test/CMakeLists.txt +++ b/winpr/libwinpr/wtsapi/test/CMakeLists.txt @@ -5,7 +5,14 @@ set(MODULE_PREFIX "TEST_WTSAPI") set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) set(${MODULE_PREFIX}_TESTS - TestWtsApiEnumerate.c) + TestWtsApiEnumerateProcesses.c + TestWtsApiEnumerateSessions.c + TestWtsApiQuerySessionInformation.c + TestWtsApiLogoffSession.c + TestWtsApiShutdownSystem.c + TestWtsApiSessionNotification.c + TestWtsApiWaitSystemEvent.c + TestWtsApiVirtualChannel.c) create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} diff --git a/winpr/libwinpr/wtsapi/test/TestWtsApiEnumerate.c b/winpr/libwinpr/wtsapi/test/TestWtsApiEnumerate.c deleted file mode 100644 index 2f46520b5..000000000 --- a/winpr/libwinpr/wtsapi/test/TestWtsApiEnumerate.c +++ /dev/null @@ -1,8 +0,0 @@ - -#include - -int TestWtsApiEnumerate(int argc, char* argv[]) -{ - return 0; -} - diff --git a/winpr/libwinpr/wtsapi/test/TestWtsApiEnumerateProcesses.c b/winpr/libwinpr/wtsapi/test/TestWtsApiEnumerateProcesses.c new file mode 100644 index 000000000..ea60ac702 --- /dev/null +++ b/winpr/libwinpr/wtsapi/test/TestWtsApiEnumerateProcesses.c @@ -0,0 +1,29 @@ + +#include +#include +#include + +int TestWtsApiEnumerateProcesses(int argc, char* argv[]) +{ + DWORD count; + BOOL bSuccess; + HANDLE hServer; + PWTS_PROCESS_INFO pProcessInfo; + + hServer = WTS_CURRENT_SERVER_HANDLE; + + count = 0; + pProcessInfo = NULL; + + bSuccess = WTSEnumerateProcesses(hServer, 0, 1, &pProcessInfo, &count); + + if (!bSuccess) + { + printf("WTSEnumerateProcesses failed: %d\n", (int) GetLastError()); + //return -1; + } + + WTSFreeMemory(pProcessInfo); + + return 0; +} diff --git a/winpr/libwinpr/wtsapi/test/TestWtsApiEnumerateSessions.c b/winpr/libwinpr/wtsapi/test/TestWtsApiEnumerateSessions.c new file mode 100644 index 000000000..89a29eb91 --- /dev/null +++ b/winpr/libwinpr/wtsapi/test/TestWtsApiEnumerateSessions.c @@ -0,0 +1,39 @@ + +#include +#include +#include + +int TestWtsApiEnumerateSessions(int argc, char* argv[]) +{ + DWORD index; + DWORD count; + BOOL bSuccess; + HANDLE hServer; + PWTS_SESSION_INFO pSessionInfo; + + hServer = WTS_CURRENT_SERVER_HANDLE; + + count = 0; + pSessionInfo = NULL; + + bSuccess = WTSEnumerateSessions(hServer, 0, 1, &pSessionInfo, &count); + + if (!bSuccess) + { + printf("WTSEnumerateSessions failed: %d\n", (int) GetLastError()); + return -1; + } + + printf("WTSEnumerateSessions count: %d\n", count); + + for (index = 0; index < count; index++) + { + printf("[%d] SessionId: %d State: %d\n", (int) index, + (int) pSessionInfo[index].SessionId, + (int) pSessionInfo[index].State); + } + + WTSFreeMemory(pSessionInfo); + + return 0; +} diff --git a/winpr/libwinpr/wtsapi/test/TestWtsApiLogoffSession.c b/winpr/libwinpr/wtsapi/test/TestWtsApiLogoffSession.c new file mode 100644 index 000000000..bd7545161 --- /dev/null +++ b/winpr/libwinpr/wtsapi/test/TestWtsApiLogoffSession.c @@ -0,0 +1,24 @@ + +#include +#include +#include + +int TestWtsApiLogoffSession(int argc, char* argv[]) +{ + BOOL bSuccess; + HANDLE hServer; + DWORD sessionId; + + sessionId = 123; + hServer = WTS_CURRENT_SERVER_HANDLE; + + bSuccess = WTSLogoffSession(hServer, sessionId, FALSE); + + if (!bSuccess) + { + printf("WTSLogoffSession failed: %d\n", (int) GetLastError()); + //return -1; + } + + return 0; +} diff --git a/winpr/libwinpr/wtsapi/test/TestWtsApiQuerySessionInformation.c b/winpr/libwinpr/wtsapi/test/TestWtsApiQuerySessionInformation.c new file mode 100644 index 000000000..33e69f391 --- /dev/null +++ b/winpr/libwinpr/wtsapi/test/TestWtsApiQuerySessionInformation.c @@ -0,0 +1,29 @@ + +#include +#include +#include + +int TestWtsApiQuerySessionInformation(int argc, char* argv[]) +{ + BOOL bSuccess; + HANDLE hServer; + LPSTR pBuffer; + DWORD sessionId; + DWORD bytesReturned; + + sessionId = 123; + hServer = WTS_CURRENT_SERVER_HANDLE; + + pBuffer = NULL; + bytesReturned = 0; + + bSuccess = WTSQuerySessionInformation(hServer, sessionId, WTSConnectState, &pBuffer, &bytesReturned); + + if (!bSuccess) + { + printf("WTSQuerySessionInformation failed: %d\n", (int) GetLastError()); + //return -1; + } + + return 0; +} diff --git a/winpr/libwinpr/wtsapi/test/TestWtsApiSessionNotification.c b/winpr/libwinpr/wtsapi/test/TestWtsApiSessionNotification.c new file mode 100644 index 000000000..03cf8a528 --- /dev/null +++ b/winpr/libwinpr/wtsapi/test/TestWtsApiSessionNotification.c @@ -0,0 +1,32 @@ + +#include +#include +#include + +int TestWtsApiSessionNotification(int argc, char* argv[]) +{ + HWND hWnd; + BOOL bSuccess; + DWORD dwFlags; + + hWnd = NULL; + dwFlags = NOTIFY_FOR_ALL_SESSIONS; + + bSuccess = WTSRegisterSessionNotification(hWnd, dwFlags); + + if (!bSuccess) + { + printf("WTSRegisterSessionNotification failed: %d\n", (int) GetLastError()); + //return -1; + } + + bSuccess = WTSUnRegisterSessionNotification(hWnd); + + if (!bSuccess) + { + printf("WTSUnRegisterSessionNotification failed: %d\n", (int) GetLastError()); + //return -1; + } + + return 0; +} diff --git a/winpr/libwinpr/wtsapi/test/TestWtsApiShutdownSystem.c b/winpr/libwinpr/wtsapi/test/TestWtsApiShutdownSystem.c new file mode 100644 index 000000000..9157d5aee --- /dev/null +++ b/winpr/libwinpr/wtsapi/test/TestWtsApiShutdownSystem.c @@ -0,0 +1,24 @@ + +#include +#include +#include + +int TestWtsApiShutdownSystem(int argc, char* argv[]) +{ + BOOL bSuccess; + HANDLE hServer; + DWORD ShutdownFlag; + + hServer = WTS_CURRENT_SERVER_HANDLE; + ShutdownFlag = WTS_WSD_SHUTDOWN; + + bSuccess = WTSShutdownSystem(hServer, ShutdownFlag); + + if (!bSuccess) + { + printf("WTSShutdownSystem failed: %d\n", (int) GetLastError()); + //return -1; + } + + return 0; +} diff --git a/winpr/libwinpr/wtsapi/test/TestWtsApiVirtualChannel.c b/winpr/libwinpr/wtsapi/test/TestWtsApiVirtualChannel.c new file mode 100644 index 000000000..4a502278a --- /dev/null +++ b/winpr/libwinpr/wtsapi/test/TestWtsApiVirtualChannel.c @@ -0,0 +1,51 @@ + +#include +#include +#include + +int TestWtsApiVirtualChannel(int argc, char* argv[]) +{ + BOOL bSuccess; + ULONG length; + ULONG bytesRead; + ULONG bytesWritten; + BYTE buffer[1024]; + HANDLE hVirtualChannel; + + length = sizeof(buffer); + + hVirtualChannel = WTSVirtualChannelOpen(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, "RDPDBG"); + + if (!hVirtualChannel) + { + printf("WTSVirtualChannelOpen failed: %d\n", (int) GetLastError()); + //return -1; + } + + bytesWritten = 0; + bSuccess = WTSVirtualChannelWrite(hVirtualChannel, (PCHAR) buffer, length, &bytesWritten); + + if (!bSuccess) + { + printf("WTSVirtualChannelWrite failed: %d\n", (int) GetLastError()); + //return -1; + } + + bytesRead = 0; + bSuccess = WTSVirtualChannelRead(hVirtualChannel, 5000, (PCHAR) buffer, length, &bytesRead); + + if (!bSuccess) + { + printf("WTSVirtualChannelRead failed: %d\n", (int) GetLastError()); + //return -1; + } + + if (!WTSVirtualChannelClose(hVirtualChannel)) + { + printf("WTSVirtualChannelClose failed\n"); + //return -1; + } + + return 0; +} + diff --git a/winpr/libwinpr/wtsapi/test/TestWtsApiWaitSystemEvent.c b/winpr/libwinpr/wtsapi/test/TestWtsApiWaitSystemEvent.c new file mode 100644 index 000000000..44b9cb31e --- /dev/null +++ b/winpr/libwinpr/wtsapi/test/TestWtsApiWaitSystemEvent.c @@ -0,0 +1,27 @@ + +#include +#include +#include + +int TestWtsApiWaitSystemEvent(int argc, char* argv[]) +{ + BOOL bSuccess; + HANDLE hServer; + DWORD eventMask; + DWORD eventFlags; + + hServer = WTS_CURRENT_SERVER_HANDLE; + + eventMask = WTS_EVENT_ALL; + eventFlags = 0; + + bSuccess = WTSWaitSystemEvent(hServer, eventMask, &eventFlags); + + if (!bSuccess) + { + printf("WTSWaitSystemEvent failed: %d\n", (int) GetLastError()); + //return -1; + } + + return 0; +} diff --git a/winpr/libwinpr/wtsapi/wtsapi.c b/winpr/libwinpr/wtsapi/wtsapi.c index 03fd6da56..e428b1aa3 100644 --- a/winpr/libwinpr/wtsapi/wtsapi.c +++ b/winpr/libwinpr/wtsapi/wtsapi.c @@ -23,502 +23,395 @@ #include #include +#include #include +#include "wtsapi.h" + /** * Remote Desktop Services API Functions: * http://msdn.microsoft.com/en-us/library/windows/desktop/aa383464/ */ -#ifndef _WIN32 +void InitializeWtsApiStubs(void); -#include "wtsrpc_c.h" +static BOOL g_Initialized = FALSE; +static HMODULE g_WtsApiModule = NULL; -BOOL WTSStartRemoteControlSessionW(LPWSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers) +static PWtsApiFunctionTable g_WtsApi = NULL; + +BOOL WINAPI WTSStartRemoteControlSessionW(LPWSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers) { - return RpcStartRemoteControlSession(NULL, pTargetServerName, TargetLogonId, HotkeyVk, HotkeyModifiers); + WTSAPI_STUB_CALL_BOOL(StartRemoteControlSessionW, pTargetServerName, TargetLogonId, HotkeyVk, HotkeyModifiers); } -BOOL WTSStartRemoteControlSessionA(LPSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers) +BOOL WINAPI WTSStartRemoteControlSessionA(LPSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(StartRemoteControlSessionA, pTargetServerName, TargetLogonId, HotkeyVk, HotkeyModifiers); } -BOOL WTSStopRemoteControlSession(ULONG LogonId) +BOOL WINAPI WTSStopRemoteControlSession(ULONG LogonId) { - return RpcStopRemoteControlSession(NULL, LogonId); + WTSAPI_STUB_CALL_BOOL(StopRemoteControlSession, LogonId); } -BOOL WTSConnectSessionW(ULONG LogonId, ULONG TargetLogonId, PWSTR pPassword, BOOL bWait) +BOOL WINAPI WTSConnectSessionW(ULONG LogonId, ULONG TargetLogonId, PWSTR pPassword, BOOL bWait) { - return RpcConnectSession(NULL, LogonId, TargetLogonId, pPassword, bWait); + WTSAPI_STUB_CALL_BOOL(ConnectSessionW, LogonId, TargetLogonId, pPassword, bWait); } -BOOL WTSConnectSessionA(ULONG LogonId, ULONG TargetLogonId, PSTR pPassword, BOOL bWait) +BOOL WINAPI WTSConnectSessionA(ULONG LogonId, ULONG TargetLogonId, PSTR pPassword, BOOL bWait) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(ConnectSessionA, LogonId, TargetLogonId, pPassword, bWait); } -BOOL WTSEnumerateServersW(LPWSTR pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOW* ppServerInfo, DWORD* pCount) +BOOL WINAPI WTSEnumerateServersW(LPWSTR pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOW* ppServerInfo, DWORD* pCount) { - return RpcEnumerateServers(NULL, pDomainName, Reserved, Version, ppServerInfo, pCount); + WTSAPI_STUB_CALL_BOOL(EnumerateServersW, pDomainName, Reserved, Version, ppServerInfo, pCount); } -BOOL WTSEnumerateServersA(LPSTR pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOA* ppServerInfo, DWORD* pCount) +BOOL WINAPI WTSEnumerateServersA(LPSTR pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOA* ppServerInfo, DWORD* pCount) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(EnumerateServersA, pDomainName, Reserved, Version, ppServerInfo, pCount); } -HANDLE WTSOpenServerW(LPWSTR pServerName) +HANDLE WINAPI WTSOpenServerW(LPWSTR pServerName) { - return RpcOpenServer(NULL, pServerName); + WTSAPI_STUB_CALL_HANDLE(OpenServerW, pServerName); } -HANDLE WTSOpenServerA(LPSTR pServerName) +HANDLE WINAPI WTSOpenServerA(LPSTR pServerName) { - return NULL; + WTSAPI_STUB_CALL_HANDLE(OpenServerA, pServerName); } -HANDLE WTSOpenServerExW(LPWSTR pServerName) +HANDLE WINAPI WTSOpenServerExW(LPWSTR pServerName) { - return RpcOpenServerEx(NULL, pServerName); + WTSAPI_STUB_CALL_HANDLE(OpenServerExW, pServerName); } -HANDLE WTSOpenServerExA(LPSTR pServerName) +HANDLE WINAPI WTSOpenServerExA(LPSTR pServerName) { - return NULL; + WTSAPI_STUB_CALL_HANDLE(OpenServerExA, pServerName); } -VOID WTSCloseServer(HANDLE hServer) +VOID WINAPI WTSCloseServer(HANDLE hServer) { - RpcCloseServer(NULL, hServer); + WTSAPI_STUB_CALL_VOID(CloseServer, hServer); } -BOOL WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOW* ppSessionInfo, DWORD* pCount) +BOOL WINAPI WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOW* ppSessionInfo, DWORD* pCount) { - return RpcEnumerateSessions(NULL, hServer, Reserved, Version, ppSessionInfo, pCount); + WTSAPI_STUB_CALL_BOOL(EnumerateSessionsW, hServer, Reserved, Version, ppSessionInfo, pCount); } -BOOL WTSEnumerateSessionsA(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOA* ppSessionInfo, DWORD* pCount) +BOOL WINAPI WTSEnumerateSessionsA(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOA* ppSessionInfo, DWORD* pCount) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(EnumerateSessionsA, hServer, Reserved, Version, ppSessionInfo, pCount); } -BOOL WTSEnumerateSessionsExW(HANDLE hServer, DWORD* pLevel, DWORD Filter, PWTS_SESSION_INFO_1W* ppSessionInfo, DWORD* pCount) +BOOL WINAPI WTSEnumerateSessionsExW(HANDLE hServer, DWORD* pLevel, DWORD Filter, PWTS_SESSION_INFO_1W* ppSessionInfo, DWORD* pCount) { - return RpcEnumerateSessionsEx(NULL, hServer, pLevel, Filter, ppSessionInfo, pCount); + WTSAPI_STUB_CALL_BOOL(EnumerateSessionsExW, hServer, pLevel, Filter, ppSessionInfo, pCount); } -BOOL WTSEnumerateSessionsExA(HANDLE hServer, DWORD* pLevel, DWORD Filter, PWTS_SESSION_INFO_1A* ppSessionInfo, DWORD* pCount) +BOOL WINAPI WTSEnumerateSessionsExA(HANDLE hServer, DWORD* pLevel, DWORD Filter, PWTS_SESSION_INFO_1A* ppSessionInfo, DWORD* pCount) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(EnumerateSessionsExA, hServer, pLevel, Filter, ppSessionInfo, pCount); } -BOOL WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount) +BOOL WINAPI WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount) { - return RpcEnumerateProcesses(NULL, hServer, Reserved, Version, ppProcessInfo, pCount); + WTSAPI_STUB_CALL_BOOL(EnumerateProcessesW, hServer, Reserved, Version, ppProcessInfo, pCount); } -BOOL WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOA* ppProcessInfo, DWORD* pCount) +BOOL WINAPI WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOA* ppProcessInfo, DWORD* pCount) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(EnumerateProcessesA, hServer, Reserved, Version, ppProcessInfo, pCount); } -BOOL WTSTerminateProcess(HANDLE hServer, DWORD ProcessId, DWORD ExitCode) +BOOL WINAPI WTSTerminateProcess(HANDLE hServer, DWORD ProcessId, DWORD ExitCode) { - return RpcTerminateProcess(NULL, hServer, ProcessId, ExitCode); + WTSAPI_STUB_CALL_BOOL(TerminateProcess, hServer, ProcessId, ExitCode); } -BOOL WTSQuerySessionInformationW(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPWSTR* ppBuffer, DWORD* pBytesReturned) +BOOL WINAPI WTSQuerySessionInformationW(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPWSTR* ppBuffer, DWORD* pBytesReturned) { - return RpcQuerySessionInformation(NULL, hServer, SessionId, WTSInfoClass, ppBuffer, pBytesReturned); + WTSAPI_STUB_CALL_BOOL(QuerySessionInformationW, hServer, SessionId, WTSInfoClass, ppBuffer, pBytesReturned); } -BOOL WTSQuerySessionInformationA(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPSTR* ppBuffer, DWORD* pBytesReturned) +BOOL WINAPI WTSQuerySessionInformationA(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPSTR* ppBuffer, DWORD* pBytesReturned) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(QuerySessionInformationA, hServer, SessionId, WTSInfoClass, ppBuffer, pBytesReturned); } -BOOL WTSQueryUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR* ppBuffer, DWORD* pBytesReturned) +BOOL WINAPI WTSQueryUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR* ppBuffer, DWORD* pBytesReturned) { - return RpcQueryUserConfig(NULL, pServerName, pUserName, WTSConfigClass, ppBuffer, pBytesReturned); + WTSAPI_STUB_CALL_BOOL(QueryUserConfigW, pServerName, pUserName, WTSConfigClass, ppBuffer, pBytesReturned); } -BOOL WTSQueryUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR* ppBuffer, DWORD* pBytesReturned) +BOOL WINAPI WTSQueryUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR* ppBuffer, DWORD* pBytesReturned) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(QueryUserConfigA, pServerName, pUserName, WTSConfigClass, ppBuffer, pBytesReturned); } -BOOL WTSSetUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR pBuffer, DWORD DataLength) +BOOL WINAPI WTSSetUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR pBuffer, DWORD DataLength) { - return RpcSetUserConfig(NULL, pServerName, pUserName, WTSConfigClass, pBuffer, DataLength); + WTSAPI_STUB_CALL_BOOL(SetUserConfigW, pServerName, pUserName, WTSConfigClass, pBuffer, DataLength); } -BOOL WTSSetUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR pBuffer, DWORD DataLength) +BOOL WINAPI WTSSetUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR pBuffer, DWORD DataLength) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(SetUserConfigA, pServerName, pUserName, WTSConfigClass, pBuffer, DataLength); } -BOOL WTSSendMessageW(HANDLE hServer, DWORD SessionId, LPWSTR pTitle, DWORD TitleLength, +BOOL WINAPI 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, + WTSAPI_STUB_CALL_BOOL(SendMessageW, hServer, SessionId, pTitle, TitleLength, pMessage, MessageLength, Style, Timeout, pResponse, bWait); } -BOOL WTSSendMessageA(HANDLE hServer, DWORD SessionId, LPSTR pTitle, DWORD TitleLength, +BOOL WINAPI WTSSendMessageA(HANDLE hServer, DWORD SessionId, LPSTR pTitle, DWORD TitleLength, LPSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(SendMessageA, hServer, SessionId, pTitle, TitleLength, + pMessage, MessageLength, Style, Timeout, pResponse, bWait); } -BOOL WTSDisconnectSession(HANDLE hServer, DWORD SessionId, BOOL bWait) +BOOL WINAPI WTSDisconnectSession(HANDLE hServer, DWORD SessionId, BOOL bWait) { - return RpcDisconnectSession(NULL, hServer, SessionId, bWait); + WTSAPI_STUB_CALL_BOOL(DisconnectSession, hServer, SessionId, bWait); } -BOOL WTSLogoffSession(HANDLE hServer, DWORD SessionId, BOOL bWait) +BOOL WINAPI WTSLogoffSession(HANDLE hServer, DWORD SessionId, BOOL bWait) { - return RpcLogoffSession(NULL, hServer, SessionId, bWait); + WTSAPI_STUB_CALL_BOOL(LogoffSession, hServer, SessionId, bWait); } -BOOL WTSShutdownSystem(HANDLE hServer, DWORD ShutdownFlag) +BOOL WINAPI WTSShutdownSystem(HANDLE hServer, DWORD ShutdownFlag) { - return RpcShutdownSystem(NULL, hServer, ShutdownFlag); + WTSAPI_STUB_CALL_BOOL(ShutdownSystem, hServer, ShutdownFlag); } -BOOL WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags) +BOOL WINAPI WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(WaitSystemEvent, hServer, EventMask, pEventFlags); } -HANDLE WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName) +HANDLE WINAPI WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName) { - HANDLE handle = NULL; - - if (hServer != WTS_CURRENT_SERVER_HANDLE) - { - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - return handle; + WTSAPI_STUB_CALL_HANDLE(VirtualChannelOpen, hServer, SessionId, pVirtualName); } -HANDLE WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags) +HANDLE WINAPI WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags) { - HANDLE handle = NULL; - - if (!flags) - handle = WTSVirtualChannelOpen(WTS_CURRENT_SERVER_HANDLE, SessionId, pVirtualName); - - return handle; + WTSAPI_STUB_CALL_HANDLE(VirtualChannelOpenEx, SessionId, pVirtualName, flags); } -BOOL WTSVirtualChannelClose(HANDLE hChannelHandle) +BOOL WINAPI WTSVirtualChannelClose(HANDLE hChannelHandle) { - if (!hChannelHandle || (hChannelHandle == INVALID_HANDLE_VALUE)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - /* TODO: properly close handle */ - - return TRUE; + WTSAPI_STUB_CALL_BOOL(VirtualChannelClose, hChannelHandle); } -BOOL WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead) +BOOL WINAPI 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); + WTSAPI_STUB_CALL_BOOL(VirtualChannelRead, hChannelHandle, TimeOut, Buffer, BufferSize, pBytesRead); } -BOOL WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten) +BOOL WINAPI 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; + WTSAPI_STUB_CALL_BOOL(VirtualChannelWrite, hChannelHandle, Buffer, Length, pBytesWritten); } -BOOL VirtualChannelIoctl(HANDLE hChannelHandle, ULONG IoControlCode) +BOOL WINAPI WTSVirtualChannelPurgeInput(HANDLE hChannelHandle) { - 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; + WTSAPI_STUB_CALL_BOOL(VirtualChannelPurgeInput, hChannelHandle); } -#define FILE_DEVICE_TERMSRV 0x00000038 - -BOOL WTSVirtualChannelPurgeInput(HANDLE hChannelHandle) +BOOL WINAPI WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle) { - return VirtualChannelIoctl(hChannelHandle, (FILE_DEVICE_TERMSRV << 16) | 0x0107); + WTSAPI_STUB_CALL_BOOL(VirtualChannelPurgeOutput, hChannelHandle); } -BOOL WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle) +BOOL WINAPI WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned) { - return VirtualChannelIoctl(hChannelHandle, (FILE_DEVICE_TERMSRV << 16) | 0x010B); + WTSAPI_STUB_CALL_BOOL(VirtualChannelQuery, hChannelHandle, WtsVirtualClass, ppBuffer, pBytesReturned); } -BOOL WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned) +VOID WINAPI WTSFreeMemory(PVOID pMemory) { - 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; + WTSAPI_STUB_CALL_VOID(FreeMemory, pMemory); } -VOID WTSFreeMemory(PVOID pMemory) +BOOL WINAPI WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries) { - free(pMemory); + WTSAPI_STUB_CALL_BOOL(FreeMemoryExW, WTSTypeClass, pMemory, NumberOfEntries); } -BOOL WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries) +BOOL WINAPI 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; + WTSAPI_STUB_CALL_BOOL(FreeMemoryExA, WTSTypeClass, pMemory, NumberOfEntries); } -BOOL WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries) +BOOL WINAPI WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags) { - BOOL status = TRUE; - - switch (WTSTypeClass) - { - case WTSTypeProcessInfoLevel0: - break; - - case WTSTypeProcessInfoLevel1: - break; - - case WTSTypeSessionInfoLevel1: - break; - - default: - status = FALSE; - break; - } - - return status; + WTSAPI_STUB_CALL_BOOL(RegisterSessionNotification, hWnd, dwFlags); } -BOOL WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags) +BOOL WINAPI WTSUnRegisterSessionNotification(HWND hWnd) { - return RpcRegisterSessionNotification(NULL, hWnd, dwFlags); + WTSAPI_STUB_CALL_BOOL(UnRegisterSessionNotification, hWnd); } -BOOL WTSUnRegisterSessionNotification(HWND hWnd) +BOOL WINAPI WTSRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd, DWORD dwFlags) { - return RpcUnRegisterSessionNotification(NULL, hWnd); + WTSAPI_STUB_CALL_BOOL(RegisterSessionNotificationEx, hServer, hWnd, dwFlags); } -BOOL WTSRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd, DWORD dwFlags) +BOOL WINAPI WTSUnRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd) { - return RpcRegisterSessionNotificationEx(NULL, hServer, hWnd, dwFlags); + WTSAPI_STUB_CALL_BOOL(UnRegisterSessionNotificationEx, hServer, hWnd); } -BOOL WTSUnRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd) +BOOL WINAPI WTSQueryUserToken(ULONG SessionId, PHANDLE phToken) { - return RpcUnRegisterSessionNotificationEx(NULL, hServer, hWnd); + WTSAPI_STUB_CALL_BOOL(QueryUserToken, SessionId, phToken); } -BOOL WTSQueryUserToken(ULONG SessionId, PHANDLE phToken) +BOOL WINAPI WTSEnumerateProcessesExW(HANDLE hServer, DWORD* pLevel, DWORD SessionId, LPWSTR* ppProcessInfo, DWORD* pCount) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(EnumerateProcessesExW, hServer, pLevel, SessionId, ppProcessInfo, pCount); } -BOOL WTSEnumerateProcessesExW(HANDLE hServer, DWORD* pLevel, DWORD SessionId, LPWSTR* ppProcessInfo, DWORD* pCount) +BOOL WINAPI WTSEnumerateProcessesExA(HANDLE hServer, DWORD* pLevel, DWORD SessionId, LPSTR* ppProcessInfo, DWORD* pCount) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(EnumerateProcessesExA, hServer, pLevel, SessionId, ppProcessInfo, pCount); } -BOOL WTSEnumerateProcessesExA(HANDLE hServer, DWORD* pLevel, DWORD SessionId, LPSTR* ppProcessInfo, DWORD* pCount) +BOOL WINAPI WTSEnumerateListenersW(HANDLE hServer, PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEW pListeners, DWORD* pCount) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(EnumerateListenersW, hServer, pReserved, Reserved, pListeners, pCount); } -BOOL WTSEnumerateListenersW(HANDLE hServer, PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEW pListeners, DWORD* pCount) +BOOL WINAPI WTSEnumerateListenersA(HANDLE hServer, PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEA pListeners, DWORD* pCount) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(EnumerateListenersA, hServer, pReserved, Reserved, pListeners, pCount); } -BOOL WTSEnumerateListenersA(HANDLE hServer, PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEA pListeners, DWORD* pCount) +BOOL WINAPI WTSQueryListenerConfigW(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(QueryListenerConfigW, hServer, pReserved, Reserved, pListenerName, pBuffer); } -BOOL WTSQueryListenerConfigW(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer) +BOOL WINAPI WTSQueryListenerConfigA(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(QueryListenerConfigA, hServer, pReserved, Reserved, pListenerName, pBuffer); } -BOOL WTSQueryListenerConfigA(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer) -{ - return TRUE; -} - -BOOL WTSCreateListenerW(HANDLE hServer, PVOID pReserved, DWORD Reserved, +BOOL WINAPI WTSCreateListenerW(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer, DWORD flag) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(CreateListenerW, hServer, pReserved, Reserved, pListenerName, pBuffer, flag); } -BOOL WTSCreateListenerA(HANDLE hServer, PVOID pReserved, DWORD Reserved, +BOOL WINAPI WTSCreateListenerA(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer, DWORD flag) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(CreateListenerA, hServer, pReserved, Reserved, pListenerName, pBuffer, flag); } -BOOL WTSSetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved, +BOOL WINAPI WTSSetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPWSTR pListenerName, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(SetListenerSecurityW, hServer, pReserved, Reserved, + pListenerName, SecurityInformation, pSecurityDescriptor); } -BOOL WTSSetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved, +BOOL WINAPI WTSSetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(SetListenerSecurityA, hServer, pReserved, Reserved, + pListenerName, SecurityInformation, pSecurityDescriptor); } -BOOL WTSGetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved, +BOOL WINAPI WTSGetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPWSTR pListenerName, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(GetListenerSecurityW, hServer, pReserved, Reserved, pListenerName, + SecurityInformation, pSecurityDescriptor, nLength, lpnLengthNeeded); } -BOOL WTSGetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved, +BOOL WINAPI WTSGetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded) { - return TRUE; + WTSAPI_STUB_CALL_BOOL(GetListenerSecurityA, hServer, pReserved, Reserved, pListenerName, + SecurityInformation, pSecurityDescriptor, nLength, lpnLengthNeeded); } -BOOL WTSEnableChildSessions(BOOL bEnable) +BOOL CDECL WTSEnableChildSessions(BOOL bEnable) { - return RpcEnableChildSessions(NULL, bEnable); + WTSAPI_STUB_CALL_BOOL(EnableChildSessions, bEnable); } -BOOL WTSIsChildSessionsEnabled(PBOOL pbEnabled) +BOOL CDECL WTSIsChildSessionsEnabled(PBOOL pbEnabled) { - return RpcIsChildSessionsEnabled(NULL, pbEnabled); + WTSAPI_STUB_CALL_BOOL(IsChildSessionsEnabled, pbEnabled); } -BOOL WTSGetChildSessionId(PULONG pSessionId) +BOOL CDECL WTSGetChildSessionId(PULONG pSessionId) { - return RpcGetChildSessionId(NULL, pSessionId); + WTSAPI_STUB_CALL_BOOL(GetChildSessionId, pSessionId); +} + +#ifndef _WIN32 + +/** + * WTSGetActiveConsoleSessionId is declared in WinBase.h and exported by kernel32.dll + */ + +DWORD WINAPI WTSGetActiveConsoleSessionId(void) +{ + if (!g_Initialized) + InitializeWtsApiStubs(); + + if (!g_WtsApi || !g_WtsApi->pGetActiveConsoleSessionId) + return 0xFFFFFFFF; + + return g_WtsApi->pGetActiveConsoleSessionId(); } #endif + +BOOL WTSRegisterWtsApiFunctionTable(PWtsApiFunctionTable table) +{ + g_WtsApi = table; + return TRUE; +} + +void InitializeWtsApiStubs(void) +{ + INIT_WTSAPI_FN pInitWtsApi; + + g_Initialized = TRUE; + + if (g_WtsApi) + return; + + g_WtsApiModule = LoadLibraryA("/opt/freerds/lib64/libfreerds-fdsapi.so"); + + if (!g_WtsApiModule) + return; + + pInitWtsApi = GetProcAddress(g_WtsApiModule, "InitWtsApi"); + + if (pInitWtsApi) + { + g_WtsApi = pInitWtsApi(); + } +} diff --git a/winpr/libwinpr/wtsapi/wtsapi.h b/winpr/libwinpr/wtsapi/wtsapi.h new file mode 100644 index 000000000..d83ce204e --- /dev/null +++ b/winpr/libwinpr/wtsapi/wtsapi.h @@ -0,0 +1,44 @@ +/** + * 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_PRIVATE_H +#define WINPR_WTSAPI_PRIVATE_H + +#define WTSAPI_STUB_CALL_VOID(_name, ...) \ + if (!g_Initialized) \ + InitializeWtsApiStubs(); \ + if (!g_WtsApi || !g_WtsApi->p ## _name) \ + return; \ + g_WtsApi->p ## _name ( __VA_ARGS__ ) + +#define WTSAPI_STUB_CALL_BOOL(_name, ...) \ + if (!g_Initialized) \ + InitializeWtsApiStubs(); \ + if (!g_WtsApi || !g_WtsApi->p ## _name) \ + return FALSE; \ + return g_WtsApi->p ## _name ( __VA_ARGS__ ) + +#define WTSAPI_STUB_CALL_HANDLE(_name, ...) \ + if (!g_Initialized) \ + InitializeWtsApiStubs(); \ + if (!g_WtsApi || !g_WtsApi->p ## _name) \ + return NULL; \ + return g_WtsApi->p ## _name ( __VA_ARGS__ ) + +#endif /* WINPR_WTSAPI_PRIVATE_H */ diff --git a/winpr/libwinpr/wtsapi/wtsrpc_c.c b/winpr/libwinpr/wtsapi/wtsrpc_c.c deleted file mode 100644 index 18b4a05a9..000000000 --- a/winpr/libwinpr/wtsapi/wtsrpc_c.c +++ /dev/null @@ -1,170 +0,0 @@ -/** - * 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 deleted file mode 100644 index 8377f786f..000000000 --- a/winpr/libwinpr/wtsapi/wtsrpc_c.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * 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/hash/CMakeLists.txt b/winpr/tools/hash/CMakeLists.txt index 3ede0e0b9..e9b307173 100644 --- a/winpr/tools/hash/CMakeLists.txt +++ b/winpr/tools/hash/CMakeLists.txt @@ -18,11 +18,18 @@ set(MODULE_NAME "winpr-hash") set(MODULE_PREFIX "WINPR_TOOLS_HASH") +include_directories(${ZLIB_INCLUDE_DIRS}) +include_directories(${OPENSSL_INCLUDE_DIR}) + set(${MODULE_PREFIX}_SRCS hash.c) add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) +set(${MODULE_PREFIX}_LIBS + ${ZLIB_LIBRARIES} + ${OPENSSL_LIBRARIES}) + set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE winpr diff --git a/winpr/tools/makecert/makecert.c b/winpr/tools/makecert/makecert.c index 5017b1d50..8430d851c 100644 --- a/winpr/tools/makecert/makecert.c +++ b/winpr/tools/makecert/makecert.c @@ -31,10 +31,6 @@ #include #include -#ifdef _WIN32 -#include -#endif - #include "makecert.h" struct _MAKECERT_CONTEXT