diff -upr -upr freerdp2-2.6.1+dfsg1/ChangeLog freerdp2-2.7.0+dfsg1/ChangeLog --- freerdp2-2.6.1+dfsg1/ChangeLog 2022-05-20 09:09:02.000000000 -0400 +++ freerdp2-2.7.0+dfsg1/ChangeLog 2022-04-25 09:04:48.000000000 -0400 @@ -1,18 +1,22 @@ -# 2022-XX-YY Version 2.X.Y +# 2022-04-25 Version 2.7.0 Noteworthy changes: +* Backported OpenSSL3 gateway support (#7822) * Backported various NTLM fixes * Backported WINPR_ASSERT to ease future backports Fixed issues: * Backported #6786: Use /network:auto by default * Backported #7714: Workaround for broken surface frame marker +* Backported #7733: Support 10bit X11 color (BGRX32 only) * Backported #7745: GFX progressive double free +* Backported #7808: Disable websockets with /gt:rpc +* Backported #7815: RAIL expect LOGON_MSG_SESSION_CONTINUE Important notes: For a complete and detailed change log since the last release run: -git log 2.6.1..2.X.Y +git log 2.6.1..2.7.0 # 2022-03-07 Version 2.6.1 diff -upr -upr freerdp2-2.6.1+dfsg1/channels/rdpsnd/server/rdpsnd_main.c freerdp2-2.7.0+dfsg1/channels/rdpsnd/server/rdpsnd_main.c --- freerdp2-2.6.1+dfsg1/channels/rdpsnd/server/rdpsnd_main.c 2022-03-07 09:24:08.000000000 -0500 +++ freerdp2-2.7.0+dfsg1/channels/rdpsnd/server/rdpsnd_main.c 2022-04-25 09:04:48.000000000 -0400 @@ -673,12 +673,40 @@ static UINT rdpsnd_server_start(RdpsndSe DWORD bytesReturned; RdpsndServerPrivate* priv = context->priv; UINT error = ERROR_INTERNAL_ERROR; - priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "rdpsnd"); + PULONG pSessionId = NULL; - if (!priv->ChannelHandle) + priv->SessionId = WTS_CURRENT_SESSION; + + if (context->use_dynamic_virtual_channel) + { + if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId, + (LPSTR*)&pSessionId, &bytesReturned)) + { + priv->SessionId = (DWORD)*pSessionId; + WTSFreeMemory(pSessionId); + priv->ChannelHandle = (HANDLE)WTSVirtualChannelOpenEx( + priv->SessionId, "AUDIO_PLAYBACK_DVC", WTS_CHANNEL_OPTION_DYNAMIC); + if (!priv->ChannelHandle) + { + WLog_ERR(TAG, "Open audio dynamic virtual channel (AUDIO_PLAYBACK_DVC) failed!"); + return ERROR_INTERNAL_ERROR; + } + } + else + { + WLog_ERR(TAG, "WTSQuerySessionInformationA failed!"); + return ERROR_INTERNAL_ERROR; + } + } + else { - WLog_ERR(TAG, "WTSVirtualChannelOpen failed!"); - return ERROR_INTERNAL_ERROR; + priv->ChannelHandle = + WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "rdpsnd"); + if (!priv->ChannelHandle) + { + WLog_ERR(TAG, "Open audio static virtual channel (rdpsnd) failed!"); + return ERROR_INTERNAL_ERROR; + } } if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer, diff -upr -upr freerdp2-2.6.1+dfsg1/channels/rdpsnd/server/rdpsnd_main.h freerdp2-2.7.0+dfsg1/channels/rdpsnd/server/rdpsnd_main.h --- freerdp2-2.6.1+dfsg1/channels/rdpsnd/server/rdpsnd_main.h 2022-03-07 09:24:08.000000000 -0500 +++ freerdp2-2.7.0+dfsg1/channels/rdpsnd/server/rdpsnd_main.h 2022-04-25 09:04:48.000000000 -0400 @@ -39,6 +39,7 @@ struct _rdpsnd_server_private HANDLE StopEvent; HANDLE channelEvent; void* ChannelHandle; + DWORD SessionId; BOOL waitingHeader; DWORD expectedBytes; diff -upr -upr freerdp2-2.6.1+dfsg1/client/common/cmdline.c freerdp2-2.7.0+dfsg1/client/common/cmdline.c --- freerdp2-2.6.1+dfsg1/client/common/cmdline.c 2022-05-20 09:09:02.000000000 -0400 +++ freerdp2-2.7.0+dfsg1/client/common/cmdline.c 2022-04-25 09:04:48.000000000 -0400 @@ -2291,8 +2291,10 @@ int freerdp_client_settings_parse_comman { if (_stricmp(arg->Value, "rpc") == 0) { - settings->GatewayRpcTransport = TRUE; - settings->GatewayHttpTransport = FALSE; + if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayRpcTransport, TRUE) || + !freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpTransport, FALSE) || + !freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpUseWebsockets, FALSE)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } else { @@ -2301,21 +2303,24 @@ int freerdp_client_settings_parse_comman { *c++ = '\0'; if (_stricmp(c, "no-websockets") != 0) - { return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - } - freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpUseWebsockets, FALSE); + + if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpUseWebsockets, + FALSE)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } if (_stricmp(arg->Value, "http") == 0) { - settings->GatewayRpcTransport = FALSE; - settings->GatewayHttpTransport = TRUE; + if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayRpcTransport, FALSE) || + !freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpTransport, TRUE)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } else if (_stricmp(arg->Value, "auto") == 0) { - settings->GatewayRpcTransport = TRUE; - settings->GatewayHttpTransport = TRUE; + if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayRpcTransport, TRUE) || + !freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpTransport, TRUE)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } } } diff -upr -upr freerdp2-2.6.1+dfsg1/client/X11/xf_client.c freerdp2-2.7.0+dfsg1/client/X11/xf_client.c --- freerdp2-2.6.1+dfsg1/client/X11/xf_client.c 2022-03-07 09:24:08.000000000 -0500 +++ freerdp2-2.7.0+dfsg1/client/X11/xf_client.c 2022-04-25 09:04:48.000000000 -0400 @@ -1384,7 +1384,10 @@ static int xf_logon_error_info(freerdp* const char* str_data = freerdp_get_logon_error_info_data(data); const char* str_type = freerdp_get_logon_error_info_type(type); WLog_INFO(TAG, "Logon Error Info %s [%s]", str_data, str_type); - xf_rail_disable_remoteapp_mode(xfc); + if(type != LOGON_MSG_SESSION_CONTINUE) + { + xf_rail_disable_remoteapp_mode(xfc); + } return 1; } diff -upr -upr freerdp2-2.6.1+dfsg1/client/X11/xf_graphics.c freerdp2-2.7.0+dfsg1/client/X11/xf_graphics.c --- freerdp2-2.6.1+dfsg1/client/X11/xf_graphics.c 2022-03-07 09:24:08.000000000 -0500 +++ freerdp2-2.7.0+dfsg1/client/X11/xf_graphics.c 2022-04-25 09:04:48.000000000 -0400 @@ -729,6 +729,8 @@ UINT32 xf_get_local_color_format(xfConte if (xfc->depth == 32) DstFormat = (!invert) ? PIXEL_FORMAT_RGBA32 : PIXEL_FORMAT_BGRA32; + else if (xfc->depth == 30) + DstFormat = (!invert) ? PIXEL_FORMAT_RGBX32_DEPTH30 : PIXEL_FORMAT_BGRX32_DEPTH30; else if (xfc->depth == 24) { if (aligned) diff -upr -upr freerdp2-2.6.1+dfsg1/CMakeLists.txt freerdp2-2.7.0+dfsg1/CMakeLists.txt --- freerdp2-2.6.1+dfsg1/CMakeLists.txt 2022-03-07 09:24:08.000000000 -0500 +++ freerdp2-2.7.0+dfsg1/CMakeLists.txt 2022-04-25 09:04:48.000000000 -0400 @@ -85,7 +85,7 @@ if ($ENV{BUILD_NUMBER}) endif() set(WITH_LIBRARY_VERSIONING "ON") -set(RAW_VERSION_STRING "2.6.1") +set(RAW_VERSION_STRING "2.7.0") if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag") file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING) elseif(USE_VERSION_FROM_GIT_TAG) diff -upr -upr freerdp2-2.6.1+dfsg1/include/freerdp/codec/color.h freerdp2-2.7.0+dfsg1/include/freerdp/codec/color.h --- freerdp2-2.6.1+dfsg1/include/freerdp/codec/color.h 2022-03-07 09:24:08.000000000 -0500 +++ freerdp2-2.7.0+dfsg1/include/freerdp/codec/color.h 2022-04-25 09:04:48.000000000 -0400 @@ -68,6 +68,8 @@ #define PIXEL_FORMAT_BGRX32 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 0, 8, 8, 8) #define PIXEL_FORMAT_RGBA32 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 8, 8, 8, 8) #define PIXEL_FORMAT_RGBX32 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 0, 8, 8, 8) +#define PIXEL_FORMAT_BGRX32_DEPTH30 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 0, 10, 10, 10) +#define PIXEL_FORMAT_RGBX32_DEPTH30 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 0, 10, 10, 10) /* 24bpp formats */ #define PIXEL_FORMAT_RGB24 FREERDP_PIXEL_FORMAT(24, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8) @@ -149,6 +151,12 @@ extern "C" case PIXEL_FORMAT_RGBX32: return "PIXEL_FORMAT_RGBX32"; + case PIXEL_FORMAT_BGRX32_DEPTH30: + return "PIXEL_FORMAT_BGRX32_DEPTH30"; + + case PIXEL_FORMAT_RGBX32_DEPTH30: + return "PIXEL_FORMAT_RGBX32_DEPTH30"; + /* 24bpp formats */ case PIXEL_FORMAT_RGB24: return "PIXEL_FORMAT_RGB24"; @@ -607,6 +615,7 @@ extern "C" UINT32 _g = g; UINT32 _b = b; UINT32 _a = a; + UINT32 t; switch (format) { @@ -635,6 +644,18 @@ extern "C" case PIXEL_FORMAT_BGRX32: return (_b << 24) | (_g << 16) | (_r << 8) | _a; + case PIXEL_FORMAT_RGBX32_DEPTH30: + // TODO: Not tested + t = (_r << 22) | (_g << 12) | (_b << 2); + // NOTE: Swapping byte-order because WriteColor written UINT32 in big-endian + return ((t & 0xff) << 24) | (((t >> 8) & 0xff) << 16) | (((t >> 16) & 0xff) << 8) | (t >> 24); + + case PIXEL_FORMAT_BGRX32_DEPTH30: + // NOTE: Swapping b and r channel (unknown reason) + t = (_r << 22) | (_g << 12) | (_b << 2); + // NOTE: Swapping byte-order because WriteColor written UINT32 in big-endian + return ((t & 0xff) << 24) | (((t >> 8) & 0xff) << 16) | (((t >> 16) & 0xff) << 8) | (t >> 24); + /* 24bpp formats */ case PIXEL_FORMAT_RGB24: return (_r << 16) | (_g << 8) | _b; diff -upr -upr freerdp2-2.6.1+dfsg1/include/freerdp/crypto/crypto.h freerdp2-2.7.0+dfsg1/include/freerdp/crypto/crypto.h --- freerdp2-2.6.1+dfsg1/include/freerdp/crypto/crypto.h 2022-03-07 09:24:08.000000000 -0500 +++ freerdp2-2.7.0+dfsg1/include/freerdp/crypto/crypto.h 2022-04-25 09:04:48.000000000 -0400 @@ -88,9 +88,9 @@ extern "C" DWORD* PublicKeyLength); #define TSSK_KEY_LENGTH 64 - extern const BYTE tssk_modulus[]; - extern const BYTE tssk_privateExponent[]; - extern const BYTE tssk_exponent[]; + WINPR_API extern const BYTE tssk_modulus[]; + WINPR_API extern const BYTE tssk_privateExponent[]; + WINPR_API extern const BYTE tssk_exponent[]; FREERDP_API int crypto_rsa_public_encrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* exponent, diff -upr -upr freerdp2-2.6.1+dfsg1/include/freerdp/rail.h freerdp2-2.7.0+dfsg1/include/freerdp/rail.h --- freerdp2-2.6.1+dfsg1/include/freerdp/rail.h 2022-03-07 09:24:08.000000000 -0500 +++ freerdp2-2.7.0+dfsg1/include/freerdp/rail.h 2022-04-25 09:04:48.000000000 -0400 @@ -142,6 +142,7 @@ enum SPI_MASK #define TS_RAIL_CLIENTSTATUS_HIGH_DPI_ICONS_SUPPORTED 0x00000020 #define TS_RAIL_CLIENTSTATUS_APPBAR_REMOTING_SUPPORTED 0x00000040 #define TS_RAIL_CLIENTSTATUS_POWER_DISPLAY_REQUEST_SUPPORTED 0x00000080 +#define TS_RAIL_CLIENTSTATUS_GET_APPID_RESPONSE_EX_SUPPORTED 0x00000100 #define TS_RAIL_CLIENTSTATUS_BIDIRECTIONAL_CLOAK_SUPPORTED 0x00000200 /* Server Move/Size Start PDU */ diff -upr -upr freerdp2-2.6.1+dfsg1/include/freerdp/server/rdpsnd.h freerdp2-2.7.0+dfsg1/include/freerdp/server/rdpsnd.h --- freerdp2-2.6.1+dfsg1/include/freerdp/server/rdpsnd.h 2022-03-07 09:24:08.000000000 -0500 +++ freerdp2-2.7.0+dfsg1/include/freerdp/server/rdpsnd.h 2022-04-25 09:04:48.000000000 -0400 @@ -119,6 +119,9 @@ struct _rdpsnd_server_context UINT16 clientVersion; rdpContext* rdpcontext; + + /* Server to request to use dynamic virtual channel. */ + BOOL use_dynamic_virtual_channel; }; #ifdef __cplusplus diff -upr -upr freerdp2-2.6.1+dfsg1/winpr/CMakeLists.txt freerdp2-2.7.0+dfsg1/winpr/CMakeLists.txt --- freerdp2-2.6.1+dfsg1/winpr/CMakeLists.txt 2022-05-20 09:09:02.000000000 -0400 +++ freerdp2-2.7.0+dfsg1/winpr/CMakeLists.txt 2022-04-25 09:04:48.000000000 -0400 @@ -57,7 +57,7 @@ if (NOT WIN32) endif() # Soname versioning -set(RAW_VERSION_STRING "2.6.1") +set(RAW_VERSION_STRING "2.7.0") if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag") file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING) elseif(USE_VERSION_FROM_GIT_TAG) diff -upr -upr freerdp2-2.6.1+dfsg1/winpr/include/winpr/crypto.h freerdp2-2.7.0+dfsg1/winpr/include/winpr/crypto.h --- freerdp2-2.6.1+dfsg1/winpr/include/winpr/crypto.h 2022-03-07 09:24:08.000000000 -0500 +++ freerdp2-2.7.0+dfsg1/winpr/include/winpr/crypto.h 2022-04-25 09:04:48.000000000 -0400 @@ -472,8 +472,8 @@ typedef const CERT_CONTEXT* PCCERT_CONTE #define CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE \ (CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT) -HCERTSTORE CertOpenStore(LPCSTR lpszStoreProvider, DWORD dwMsgAndCertEncodingType, - HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags, const void* pvPara); +WINPR_API HCERTSTORE CertOpenStore(LPCSTR lpszStoreProvider, DWORD dwMsgAndCertEncodingType, + HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags, const void* pvPara); WINPR_API HCERTSTORE CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv, LPCWSTR szSubsystemProtocol); WINPR_API HCERTSTORE CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv, LPCSTR szSubsystemProtocol); @@ -597,15 +597,17 @@ extern "C" #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); +WINPR_API BOOL CryptStringToBinaryW(LPCWSTR pszString, DWORD cchString, DWORD dwFlags, + BYTE* pbBinary, DWORD* pcbBinary, DWORD* pdwSkip, + DWORD* pdwFlags); +WINPR_API BOOL CryptStringToBinaryA(LPCSTR pszString, DWORD cchString, DWORD dwFlags, + BYTE* pbBinary, DWORD* pcbBinary, DWORD* pdwSkip, + DWORD* pdwFlags); + +WINPR_API BOOL CryptBinaryToStringW(CONST BYTE* pbBinary, DWORD cbBinary, DWORD dwFlags, + LPWSTR pszString, DWORD* pcchString); +WINPR_API BOOL CryptBinaryToStringA(CONST BYTE* pbBinary, DWORD cbBinary, DWORD dwFlags, + LPSTR pszString, DWORD* pcchString); #ifdef UNICODE #define CryptStringToBinary CryptStringToBinaryW diff -upr -upr freerdp2-2.6.1+dfsg1/winpr/include/winpr/locale.h freerdp2-2.7.0+dfsg1/winpr/include/winpr/locale.h --- freerdp2-2.6.1+dfsg1/winpr/include/winpr/locale.h 2022-03-07 09:24:08.000000000 -0500 +++ freerdp2-2.7.0+dfsg1/winpr/include/winpr/locale.h 2022-04-25 09:04:48.000000000 -0400 @@ -484,13 +484,13 @@ extern "C" { #endif - DWORD WINAPI FormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, - DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize, - va_list* Arguments); + WINPR_API DWORD WINAPI FormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, + DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize, + va_list* Arguments); - DWORD WINAPI FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, - DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, - va_list* Arguments); + WINPR_API DWORD WINAPI FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, + DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, + va_list* Arguments); #ifdef UNICODE #define FormatMessage FormatMessageW diff -upr -upr freerdp2-2.6.1+dfsg1/winpr/include/winpr/smartcard.h freerdp2-2.7.0+dfsg1/winpr/include/winpr/smartcard.h --- freerdp2-2.6.1+dfsg1/winpr/include/winpr/smartcard.h 2022-03-07 09:24:08.000000000 -0500 +++ freerdp2-2.7.0+dfsg1/winpr/include/winpr/smartcard.h 2022-04-25 09:04:48.000000000 -0400 @@ -590,9 +590,9 @@ extern "C" { #endif - extern const SCARD_IO_REQUEST g_rgSCardT0Pci; - extern const SCARD_IO_REQUEST g_rgSCardT1Pci; - extern const SCARD_IO_REQUEST g_rgSCardRawPci; + WINPR_API extern const SCARD_IO_REQUEST g_rgSCardT0Pci; + WINPR_API extern const SCARD_IO_REQUEST g_rgSCardT1Pci; + WINPR_API extern const SCARD_IO_REQUEST g_rgSCardRawPci; #define SCARD_PCI_T0 (&g_rgSCardT0Pci) #define SCARD_PCI_T1 (&g_rgSCardT1Pci) diff -upr -upr freerdp2-2.6.1+dfsg1/winpr/include/winpr/thread.h freerdp2-2.7.0+dfsg1/winpr/include/winpr/thread.h --- freerdp2-2.6.1+dfsg1/winpr/include/winpr/thread.h 2022-05-20 09:09:02.000000000 -0400 +++ freerdp2-2.7.0+dfsg1/winpr/include/winpr/thread.h 2022-05-20 09:09:05.000000000 -0400 @@ -207,7 +207,7 @@ extern "C" LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); - WINPR_API DECLSPEC_NORETURN VOID ExitThread(DWORD dwExitCode); + WINPR_API VOID ExitThread(DWORD dwExitCode); WINPR_API BOOL GetExitCodeThread(HANDLE hThread, LPDWORD lpExitCode); WINPR_API HANDLE _GetCurrentThread(void); diff -upr -upr freerdp2-2.6.1+dfsg1/winpr/libwinpr/pipe/test/TestPipeCreateNamedPipeOverlapped.c freerdp2-2.7.0+dfsg1/winpr/libwinpr/pipe/test/TestPipeCreateNamedPipeOverlapped.c --- freerdp2-2.6.1+dfsg1/winpr/libwinpr/pipe/test/TestPipeCreateNamedPipeOverlapped.c 2022-03-07 09:24:08.000000000 -0500 +++ freerdp2-2.7.0+dfsg1/winpr/libwinpr/pipe/test/TestPipeCreateNamedPipeOverlapped.c 2022-05-20 09:09:05.000000000 -0400 @@ -19,7 +19,7 @@ static BYTE CLIENT_MESSAGE[PIPE_BUFFER_S static BOOL bClientSuccess = FALSE; static BOOL bServerSuccess = FALSE; -static HANDLE serverReadyEvent; +static HANDLE serverReadyEvent = NULL; static LPTSTR lpszPipeName = _T("\\\\.\\pipe\\winpr_test_pipe_overlapped"); @@ -30,11 +30,13 @@ static DWORD WINAPI named_pipe_client_th HANDLE hNamedPipe = NULL; BYTE* lpReadBuffer = NULL; BOOL fSuccess = FALSE; - OVERLAPPED overlapped; + OVERLAPPED overlapped = { 0 }; DWORD nNumberOfBytesToRead; DWORD nNumberOfBytesToWrite; DWORD NumberOfBytesTransferred; + WINPR_UNUSED(arg); + status = WaitForSingleObject(serverReadyEvent, PIPE_TIMEOUT_MS); if (status != WAIT_OBJECT_0) { @@ -43,8 +45,6 @@ static DWORD WINAPI named_pipe_client_th } /* 1: initialize overlapped structure */ - - ZeroMemory(&overlapped, sizeof(OVERLAPPED)); if (!(hEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) { printf("client: CreateEvent failure: %" PRIu32 "\n", GetLastError()); @@ -159,16 +159,16 @@ static DWORD WINAPI named_pipe_server_th HANDLE hEvent = NULL; HANDLE hNamedPipe = NULL; BYTE* lpReadBuffer = NULL; - OVERLAPPED overlapped; + OVERLAPPED overlapped = { 0 }; BOOL fSuccess = FALSE; BOOL fConnected = FALSE; DWORD nNumberOfBytesToRead; DWORD nNumberOfBytesToWrite; DWORD NumberOfBytesTransferred; - /* 1: initialize overlapped structure */ + WINPR_UNUSED(arg); - ZeroMemory(&overlapped, sizeof(OVERLAPPED)); + /* 1: initialize overlapped structure */ if (!(hEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) { printf("server: CreateEvent failure: %" PRIu32 "\n", GetLastError()); @@ -332,8 +332,8 @@ finish: int TestPipeCreateNamedPipeOverlapped(int argc, char* argv[]) { - HANDLE ClientThread; - HANDLE ServerThread; + HANDLE ClientThread = NULL; + HANDLE ServerThread = NULL; int result = -1; FillMemory(SERVER_MESSAGE, PIPE_BUFFER_SIZE, 0xAA); @@ -349,8 +349,7 @@ int TestPipeCreateNamedPipeOverlapped(in printf("CreateThread (client) failed: %" PRIu32 "\n", GetLastError()); goto out; } - if (!(ServerThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)named_pipe_server_thread, - NULL, 0, NULL))) + if (!(ServerThread = CreateThread(NULL, 0, named_pipe_server_thread, NULL, 0, NULL))) { printf("CreateThread (server) failed: %" PRIu32 "\n", GetLastError()); goto out; @@ -372,6 +371,13 @@ int TestPipeCreateNamedPipeOverlapped(in out: + if (ClientThread) + CloseHandle(ClientThread); + if (ServerThread) + CloseHandle(ServerThread); + if (serverReadyEvent) + CloseHandle(serverReadyEvent); + #ifndef _WIN32 if (result == 0) { diff -upr -upr freerdp2-2.6.1+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm_compute.c freerdp2-2.7.0+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm_compute.c --- freerdp2-2.6.1+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm_compute.c 2022-05-20 09:09:02.000000000 -0400 +++ freerdp2-2.7.0+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm_compute.c 2022-04-25 09:04:48.000000000 -0400 @@ -280,10 +280,11 @@ void ntlm_generate_timestamp(NTLM_CONTEX ntlm_current_time(context->Timestamp); } -static int ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash) +static BOOL ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash) { - WINPR_SAM* sam; - WINPR_SAM_ENTRY* entry; + BOOL rc = FALSE; + WINPR_SAM* sam = NULL; + WINPR_SAM_ENTRY* entry = NULL; SSPI_CREDENTIALS* credentials; WINPR_ASSERT(context); @@ -293,48 +294,39 @@ static int ntlm_fetch_ntlm_v2_hash(NTLM_ sam = SamOpen(context->SamFile, TRUE); if (!sam) - return -1; + goto fail; entry = SamLookupUserW( - sam, (LPWSTR)credentials->identity.User, credentials->identity.UserLength * 2, - (LPWSTR)credentials->identity.Domain, credentials->identity.DomainLength * 2); + sam, (LPWSTR)credentials->identity.User, credentials->identity.UserLength * sizeof(WCHAR), + (LPWSTR)credentials->identity.Domain, credentials->identity.DomainLength * sizeof(WCHAR)); - if (entry) + if (!entry) { -#ifdef WITH_DEBUG_NTLM - WLog_VRB(TAG, "NTLM Hash:"); - winpr_HexDump(TAG, WLOG_DEBUG, entry->NtHash, 16); -#endif - NTOWFv2FromHashW(entry->NtHash, (LPWSTR)credentials->identity.User, - credentials->identity.UserLength * 2, (LPWSTR)credentials->identity.Domain, - credentials->identity.DomainLength * 2, (BYTE*)hash); - SamFreeEntry(sam, entry); - SamClose(sam); - return 1; + entry = SamLookupUserW(sam, (LPWSTR)credentials->identity.User, + credentials->identity.UserLength * sizeof(WCHAR), NULL, 0); } - entry = SamLookupUserW(sam, (LPWSTR)credentials->identity.User, - credentials->identity.UserLength * 2, NULL, 0); + if (!entry) + goto fail; - if (entry) - { #ifdef WITH_DEBUG_NTLM WLog_VRB(TAG, "NTLM Hash:"); winpr_HexDump(TAG, WLOG_DEBUG, entry->NtHash, 16); #endif - NTOWFv2FromHashW(entry->NtHash, (LPWSTR)credentials->identity.User, - credentials->identity.UserLength * 2, (LPWSTR)credentials->identity.Domain, - credentials->identity.DomainLength * 2, (BYTE*)hash); - SamFreeEntry(sam, entry); - SamClose(sam); - return 1; - } - else - { - SamClose(sam); + NTOWFv2FromHashW(entry->NtHash, (LPWSTR)credentials->identity.User, + credentials->identity.UserLength * sizeof(WCHAR), + (LPWSTR)credentials->identity.Domain, + credentials->identity.DomainLength * sizeof(WCHAR), (BYTE*)hash); + + rc = TRUE; + +fail: + SamFreeEntry(sam, entry); + SamClose(sam); + if (!rc) WLog_ERR(TAG, "Error: Could not find user in SAM database"); - return 0; - } + + return rc; } static int ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash) diff -upr -upr freerdp2-2.6.1+dfsg1/winpr/libwinpr/thread/thread.c freerdp2-2.7.0+dfsg1/winpr/libwinpr/thread/thread.c --- freerdp2-2.6.1+dfsg1/winpr/libwinpr/thread/thread.c 2022-05-20 09:09:02.000000000 -0400 +++ freerdp2-2.7.0+dfsg1/winpr/libwinpr/thread/thread.c 2022-05-20 09:09:05.000000000 -0400 @@ -24,7 +24,7 @@ #include "config.h" #endif -#include +#include #include @@ -98,7 +98,10 @@ #define TAG WINPR_TAG("thread") static WINPR_THREAD mainThread; + +#if defined(WITH_THREAD_LIST) static wListDictionary* thread_list = NULL; +#endif static BOOL ThreadCloseHandle(HANDLE handle); static void cleanup_handle(void* obj); @@ -126,14 +129,190 @@ static int ThreadGetFd(HANDLE handle) return pThread->event.fds[0]; } +#define run_mutex_init(fkt, mux, arg) run_mutex_init_(fkt, #fkt, mux, arg) +static BOOL run_mutex_init_(int (*fkt)(pthread_mutex_t*, const pthread_mutexattr_t*), + const char* name, pthread_mutex_t* mutex, + const pthread_mutexattr_t* mutexattr) +{ + int rc; + + WINPR_ASSERT(fkt); + WINPR_ASSERT(mutex); + + rc = fkt(mutex, mutexattr); + if (rc != 0) + { + WLog_WARN(TAG, "[%s] failed with [%s]", name, strerror(rc)); + } + return rc == 0; +} + +#define run_mutex_fkt(fkt, mux) run_mutex_fkt_(fkt, #fkt, mux) +static BOOL run_mutex_fkt_(int (*fkt)(pthread_mutex_t* mux), const char* name, + pthread_mutex_t* mutex) +{ + int rc; + + WINPR_ASSERT(fkt); + WINPR_ASSERT(mutex); + + rc = fkt(mutex); + if (rc != 0) + { + WLog_WARN(TAG, "[%s] failed with [%s]", name, strerror(rc)); + } + return rc == 0; +} + +#define run_cond_init(fkt, cond, arg) run_cond_init_(fkt, #fkt, cond, arg) +static BOOL run_cond_init_(int (*fkt)(pthread_cond_t*, const pthread_condattr_t*), const char* name, + pthread_cond_t* condition, const pthread_condattr_t* conditionattr) +{ + int rc; + + WINPR_ASSERT(fkt); + WINPR_ASSERT(condition); + + rc = fkt(condition, conditionattr); + if (rc != 0) + { + WLog_WARN(TAG, "[%s] failed with [%s]", name, strerror(rc)); + } + return rc == 0; +} + +#define run_cond_fkt(fkt, cond) run_cond_fkt_(fkt, #fkt, cond) +static BOOL run_cond_fkt_(int (*fkt)(pthread_cond_t* mux), const char* name, + pthread_cond_t* condition) +{ + int rc; + + WINPR_ASSERT(fkt); + WINPR_ASSERT(condition); + + rc = fkt(condition); + if (rc != 0) + { + WLog_WARN(TAG, "[%s] failed with [%s]", name, strerror(rc)); + } + return rc == 0; +} + +static int pthread_mutex_checked_unlock(pthread_mutex_t* mutex) +{ + WINPR_ASSERT(mutex); + WINPR_ASSERT(pthread_mutex_trylock(mutex) == EBUSY); + return pthread_mutex_unlock(mutex); +} + +static BOOL mux_condition_bundle_init(mux_condition_bundle* bundle) +{ + WINPR_ASSERT(bundle); + + bundle->val = FALSE; + if (!run_mutex_init(pthread_mutex_init, &bundle->mux, NULL)) + return FALSE; + + if (!run_cond_init(pthread_cond_init, &bundle->cond, NULL)) + return FALSE; + return TRUE; +} + +static void mux_condition_bundle_uninit(mux_condition_bundle* bundle) +{ + mux_condition_bundle empty = { 0 }; + + WINPR_ASSERT(bundle); + + run_cond_fkt(pthread_cond_destroy, &bundle->cond); + run_mutex_fkt(pthread_mutex_destroy, &bundle->mux); + *bundle = empty; +} + +static BOOL mux_condition_bundle_signal(mux_condition_bundle* bundle) +{ + BOOL rc = TRUE; + WINPR_ASSERT(bundle); + + if (!run_mutex_fkt(pthread_mutex_lock, &bundle->mux)) + return FALSE; + bundle->val = TRUE; + if (!run_cond_fkt(pthread_cond_signal, &bundle->cond)) + rc = FALSE; + if (!run_mutex_fkt(pthread_mutex_checked_unlock, &bundle->mux)) + rc = FALSE; + return rc; +} + +static BOOL mux_condition_bundle_lock(mux_condition_bundle* bundle) +{ + WINPR_ASSERT(bundle); + return run_mutex_fkt(pthread_mutex_lock, &bundle->mux); +} + +static BOOL mux_condition_bundle_unlock(mux_condition_bundle* bundle) +{ + WINPR_ASSERT(bundle); + return run_mutex_fkt(pthread_mutex_checked_unlock, &bundle->mux); +} + +static BOOL mux_condition_bundle_wait(mux_condition_bundle* bundle, const char* name) +{ + BOOL rc = FALSE; + + WINPR_ASSERT(bundle); + WINPR_ASSERT(name); + WINPR_ASSERT(pthread_mutex_trylock(&bundle->mux) == EBUSY); + + while (!bundle->val) + { + int r = pthread_cond_wait(&bundle->cond, &bundle->mux); + if (r != 0) + { + WLog_ERR(TAG, "failed to wait for %s [%s]", name, strerror(r)); + switch (r) + { + case ENOTRECOVERABLE: + case EPERM: + case ETIMEDOUT: + case EINVAL: + goto fail; + + default: + break; + } + } + } + + rc = bundle->val; + +fail: + return rc; +} + +static BOOL signal_thread_ready(WINPR_THREAD* thread) +{ + WINPR_ASSERT(thread); + + return mux_condition_bundle_signal(&thread->isCreated); +} + +static BOOL signal_thread_is_running(WINPR_THREAD* thread) +{ + WINPR_ASSERT(thread); + + return mux_condition_bundle_signal(&thread->isRunning); +} + static DWORD ThreadCleanupHandle(HANDLE handle) { + DWORD status = WAIT_FAILED; WINPR_THREAD* thread = (WINPR_THREAD*)handle; if (!ThreadIsHandled(handle)) return WAIT_FAILED; - if (pthread_mutex_lock(&thread->mutex)) + if (!run_mutex_fkt(pthread_mutex_lock, &thread->mutex)) return WAIT_FAILED; if (!thread->joined) @@ -144,17 +323,19 @@ static DWORD ThreadCleanupHandle(HANDLE if (status != 0) { WLog_ERR(TAG, "pthread_join failure: [%d] %s", status, strerror(status)); - pthread_mutex_unlock(&thread->mutex); - return WAIT_FAILED; + goto fail; } else thread->joined = TRUE; } - if (pthread_mutex_unlock(&thread->mutex)) + status = WAIT_OBJECT_0; + +fail: + if (!run_mutex_fkt(pthread_mutex_checked_unlock, &thread->mutex)) return WAIT_FAILED; - return WAIT_OBJECT_0; + return status; } static HANDLE_OPS ops = { ThreadIsHandled, @@ -218,7 +399,8 @@ static void dump_thread(WINPR_THREAD* th free(msg); } - +#else + WINPR_UNUSED(thread); #endif } @@ -236,6 +418,7 @@ static BOOL reset_event(WINPR_THREAD* th return winpr_event_reset(&thread->event); } +#if defined(WITH_THREAD_LIST) static BOOL thread_compare(const void* a, const void* b) { const pthread_t* p1 = a; @@ -243,12 +426,13 @@ static BOOL thread_compare(const void* a BOOL rc = pthread_equal(*p1, *p2); return rc; } +#endif static INIT_ONCE threads_InitOnce = INIT_ONCE_STATIC_INIT; static pthread_t mainThreadId; static DWORD currentThreadTlsIndex = TLS_OUT_OF_INDEXES; -BOOL initializeThreads(PINIT_ONCE InitOnce, PVOID Parameter, PVOID* Context) +static BOOL initializeThreads(PINIT_ONCE InitOnce, PVOID Parameter, PVOID* Context) { if (!apc_init(&mainThread.apc)) { @@ -265,10 +449,54 @@ BOOL initializeThreads(PINIT_ONCE InitOn WLog_ERR(TAG, "Major bug, unable to allocate a TLS value for currentThread"); } +#if defined(WITH_THREAD_LIST) + thread_list = ListDictionary_New(TRUE); + + if (!thread_list) + { + WLog_ERR(TAG, "Couldn't create global thread list"); + goto error_thread_list; + } + + thread_list->objectKey.fnObjectEquals = thread_compare; +#endif + out: return TRUE; } +static BOOL signal_and_wait_for_ready(WINPR_THREAD* thread) +{ + BOOL res = FALSE; + + WINPR_ASSERT(thread); + + if (!mux_condition_bundle_lock(&thread->isRunning)) + return FALSE; + + if (!signal_thread_ready(thread)) + goto fail; + + if (!mux_condition_bundle_wait(&thread->isRunning, "threadIsRunning")) + goto fail; + +#if defined(WITH_THREAD_LIST) + if (!ListDictionary_Contains(thread_list, &thread->thread)) + { + WLog_ERR(TAG, "Thread not in thread_list, startup failed!"); + goto fail; + } +#endif + + res = TRUE; + +fail: + if (!mux_condition_bundle_unlock(&thread->isRunning)) + return FALSE; + + return res; +} + /* Thread launcher function responsible for registering * cleanup handlers and calling pthread_exit, if not done * in thread function. */ @@ -296,23 +524,9 @@ static void* thread_launcher(void* arg) goto exit; } - if (pthread_mutex_lock(&thread->threadIsReadyMutex)) - goto exit; - - if (!ListDictionary_Contains(thread_list, &thread->thread)) - { - if (pthread_cond_wait(&thread->threadIsReady, &thread->threadIsReadyMutex) != 0) - { - WLog_ERR(TAG, "The thread could not be made ready"); - pthread_mutex_unlock(&thread->threadIsReadyMutex); - goto exit; - } - } - - if (pthread_mutex_unlock(&thread->threadIsReadyMutex)) + if (!signal_and_wait_for_ready(thread)) goto exit; - assert(ListDictionary_Contains(thread_list, &thread->thread)); rc = fkt(thread->lpParameter); exit: @@ -325,6 +539,8 @@ exit: set_event(thread); + signal_thread_ready(thread); + if (thread->detached || !thread->started) cleanup_handle(thread); } @@ -334,7 +550,14 @@ exit: static BOOL winpr_StartThread(WINPR_THREAD* thread) { - pthread_attr_t attr; + BOOL rc = FALSE; + BOOL locked = FALSE; + pthread_attr_t attr = { 0 }; + + if (!mux_condition_bundle_lock(&thread->isCreated)) + return FALSE; + locked = TRUE; + pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); @@ -344,35 +567,44 @@ static BOOL winpr_StartThread(WINPR_THRE thread->started = TRUE; reset_event(thread); +#if defined(WITH_THREAD_LIST) + if (!ListDictionary_Add(thread_list, &thread->thread, thread)) + { + WLog_ERR(TAG, "failed to add the thread to the thread list"); + goto error; + } +#endif + if (pthread_create(&thread->thread, &attr, thread_launcher, thread)) goto error; - if (pthread_mutex_lock(&thread->threadIsReadyMutex)) + if (!mux_condition_bundle_wait(&thread->isCreated, "threadIsCreated")) goto error; - if (!ListDictionary_Add(thread_list, &thread->thread, thread)) - { - WLog_ERR(TAG, "failed to add the thread to the thread list"); - pthread_mutex_unlock(&thread->threadIsReadyMutex); + locked = FALSE; + if (!mux_condition_bundle_unlock(&thread->isCreated)) goto error; - } - if (pthread_cond_signal(&thread->threadIsReady) != 0) + if (!signal_thread_is_running(thread)) { WLog_ERR(TAG, "failed to signal the thread was ready"); - pthread_mutex_unlock(&thread->threadIsReadyMutex); goto error; } - if (pthread_mutex_unlock(&thread->threadIsReadyMutex)) - goto error; - - pthread_attr_destroy(&attr); - dump_thread(thread); - return TRUE; + rc = TRUE; error: + if (locked) + { + if (!mux_condition_bundle_unlock(&thread->isCreated)) + rc = FALSE; + } + pthread_attr_destroy(&attr); - return FALSE; + + if (rc) + dump_thread(thread); + + return rc; } HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, @@ -380,8 +612,7 @@ HANDLE CreateThread(LPSECURITY_ATTRIBUTE DWORD dwCreationFlags, LPDWORD lpThreadId) { HANDLE handle; - WINPR_THREAD* thread; - thread = (WINPR_THREAD*)calloc(1, sizeof(WINPR_THREAD)); + WINPR_THREAD* thread = (WINPR_THREAD*)calloc(1, sizeof(WINPR_THREAD)); if (!thread) return NULL; @@ -399,104 +630,66 @@ HANDLE CreateThread(LPSECURITY_ATTRIBUTE if (!winpr_event_init(&thread->event)) { WLog_ERR(TAG, "failed to create event"); - goto error_event; + goto fail; } - if (pthread_mutex_init(&thread->mutex, NULL) != 0) + if (!run_mutex_init(pthread_mutex_init, &thread->mutex, NULL)) { WLog_ERR(TAG, "failed to initialize thread mutex"); - goto error_mutex; + goto fail; } if (!apc_init(&thread->apc)) { WLog_ERR(TAG, "failed to initialize APC"); - goto error_APC; + goto fail; } - if (pthread_mutex_init(&thread->threadIsReadyMutex, NULL) != 0) - { - WLog_ERR(TAG, "failed to initialize a mutex for a condition variable"); - goto error_thread_ready_mutex; - } - - if (pthread_cond_init(&thread->threadIsReady, NULL) != 0) - { - WLog_ERR(TAG, "failed to initialize a condition variable"); - goto error_thread_ready; - } + if (!mux_condition_bundle_init(&thread->isCreated)) + goto fail; + if (!mux_condition_bundle_init(&thread->isRunning)) + goto fail; WINPR_HANDLE_SET_TYPE_AND_MODE(thread, HANDLE_TYPE_THREAD, WINPR_FD_READ); handle = (HANDLE)thread; - if (!thread_list) - { - InitOnceExecuteOnce(&threads_InitOnce, initializeThreads, NULL, NULL); - thread_list = ListDictionary_New(TRUE); - - if (!thread_list) - { - WLog_ERR(TAG, "Couldn't create global thread list"); - goto error_thread_list; - } - - thread_list->objectKey.fnObjectEquals = thread_compare; - } + InitOnceExecuteOnce(&threads_InitOnce, initializeThreads, NULL, NULL); if (!(dwCreationFlags & CREATE_SUSPENDED)) { if (!winpr_StartThread(thread)) - goto error_thread_list; + goto fail; } else { if (!set_event(thread)) - goto error_thread_list; + goto fail; } return handle; -error_thread_list: - pthread_cond_destroy(&thread->threadIsReady); -error_thread_ready: - pthread_mutex_destroy(&thread->threadIsReadyMutex); -error_thread_ready_mutex: - apc_uninit(&thread->apc); -error_APC: - pthread_mutex_destroy(&thread->mutex); -error_mutex: - winpr_event_uninit(&thread->event); -error_event: - free(thread); +fail: + cleanup_handle(thread); return NULL; } void cleanup_handle(void* obj) { - int rc; WINPR_THREAD* thread = (WINPR_THREAD*)obj; + if (!thread) + return; if (!apc_uninit(&thread->apc)) WLog_ERR(TAG, "failed to destroy APC"); - rc = pthread_cond_destroy(&thread->threadIsReady); - if (rc) - WLog_ERR(TAG, "failed to destroy thread->threadIsReady [%d] %s (%d)", rc, strerror(errno), - errno); - - rc = pthread_mutex_destroy(&thread->threadIsReadyMutex); - if (rc) - WLog_ERR(TAG, "failed to destroy thread->threadIsReadyMutex [%d] %s (%d)", rc, - strerror(errno), errno); - - rc = pthread_mutex_destroy(&thread->mutex); - if (rc) - WLog_ERR(TAG, "failed to destroy thread->mutex [%d] %s (%d)", rc, strerror(errno), errno); + mux_condition_bundle_uninit(&thread->isCreated); + mux_condition_bundle_uninit(&thread->isRunning); + run_mutex_fkt(pthread_mutex_destroy, &thread->mutex); winpr_event_uninit(&thread->event); - if (thread_list && ListDictionary_Contains(thread_list, &thread->thread)) - ListDictionary_Remove(thread_list, &thread->thread); - +#if defined(WITH_THREAD_LIST) + ListDictionary_Remove(thread_list, &thread->thread); +#endif #if defined(WITH_DEBUG_THREADS) if (thread->create_stack) @@ -513,6 +706,7 @@ BOOL ThreadCloseHandle(HANDLE handle) { WINPR_THREAD* thread = (WINPR_THREAD*)handle; +#if defined(WITH_THREAD_LIST) if (!thread_list) { WLog_ERR(TAG, "Thread list does not exist, check call!"); @@ -526,6 +720,7 @@ BOOL ThreadCloseHandle(HANDLE handle) else { ListDictionary_Lock(thread_list); +#endif dump_thread(thread); if ((thread->started) && (WaitForSingleObject(thread, 0) != WAIT_OBJECT_0)) @@ -539,14 +734,10 @@ BOOL ThreadCloseHandle(HANDLE handle) cleanup_handle(thread); } +#if defined(WITH_THREAD_LIST) ListDictionary_Unlock(thread_list); - - if (ListDictionary_Count(thread_list) < 1) - { - ListDictionary_Free(thread_list); - thread_list = NULL; - } } +#endif return TRUE; } @@ -562,6 +753,7 @@ HANDLE CreateRemoteThread(HANDLE hProces VOID ExitThread(DWORD dwExitCode) { +#if defined(WITH_THREAD_LIST) DWORD rc; pthread_t tid = pthread_self(); @@ -586,7 +778,7 @@ VOID ExitThread(DWORD dwExitCode) WINPR_THREAD* thread; ListDictionary_Lock(thread_list); thread = ListDictionary_GetItemValue(thread_list, &tid); - assert(thread); + WINPR_ASSERT(thread); thread->exited = TRUE; thread->dwExitCode = dwExitCode; #if defined(WITH_DEBUG_THREADS) @@ -601,6 +793,9 @@ VOID ExitThread(DWORD dwExitCode) pthread_exit((void*)(size_t)rc); } +#else + WINPR_UNUSED(dwExitCode); +#endif } BOOL GetExitCodeThread(HANDLE hThread, LPDWORD lpExitCode) @@ -657,7 +852,7 @@ typedef struct ULONG_PTR completionArg; } UserApcItem; -void userAPC(LPVOID arg) +static void userAPC(LPVOID arg) { UserApcItem* userApc = (UserApcItem*)arg; @@ -670,7 +865,6 @@ DWORD QueueUserAPC(PAPCFUNC pfnAPC, HAND { ULONG Type; WINPR_HANDLE* Object; - WINPR_THREAD* thread; WINPR_APC_ITEM* apc; UserApcItem* apcItem; @@ -683,7 +877,6 @@ DWORD QueueUserAPC(PAPCFUNC pfnAPC, HAND SetLastError(ERROR_INVALID_PARAMETER); return (DWORD)0; } - thread = (WINPR_THREAD*)Object; apcItem = calloc(1, sizeof(*apcItem)); if (!apcItem) @@ -715,21 +908,21 @@ DWORD ResumeThread(HANDLE hThread) thread = (WINPR_THREAD*)Object; - if (pthread_mutex_lock(&thread->mutex)) + if (!run_mutex_fkt(pthread_mutex_lock, &thread->mutex)) return (DWORD)-1; if (!thread->started) { if (!winpr_StartThread(thread)) { - pthread_mutex_unlock(&thread->mutex); + run_mutex_fkt(pthread_mutex_checked_unlock, &thread->mutex); return (DWORD)-1; } } else WLog_WARN(TAG, "Thread already started!"); - if (pthread_mutex_unlock(&thread->mutex)) + if (!run_mutex_fkt(pthread_mutex_checked_unlock, &thread->mutex)) return (DWORD)-1; return 0; @@ -767,7 +960,7 @@ BOOL TerminateThread(HANDLE hThread, DWO thread->exited = TRUE; thread->dwExitCode = dwExitCode; - if (pthread_mutex_lock(&thread->mutex)) + if (!run_mutex_fkt(pthread_mutex_lock, &thread->mutex)) return FALSE; #ifndef ANDROID @@ -776,7 +969,7 @@ BOOL TerminateThread(HANDLE hThread, DWO WLog_ERR(TAG, "Function not supported on this platform!"); #endif - if (pthread_mutex_unlock(&thread->mutex)) + if (!run_mutex_fkt(pthread_mutex_checked_unlock, &thread->mutex)) return FALSE; set_event(thread); @@ -801,6 +994,7 @@ VOID DumpThreadHandles(void) winpr_backtrace_free(stack); WLog_DBG(TAG, "---------------- Start Dumping thread handles -----------"); +#if defined(WITH_THREAD_LIST) if (!thread_list) { WLog_DBG(TAG, "All threads properly shut down and disposed of."); @@ -844,6 +1038,7 @@ VOID DumpThreadHandles(void) free(keys); ListDictionary_Unlock(thread_list); } +#endif WLog_DBG(TAG, "---------------- End Dumping thread handles -------------"); #endif diff -upr -upr freerdp2-2.6.1+dfsg1/winpr/libwinpr/thread/thread.h freerdp2-2.7.0+dfsg1/winpr/libwinpr/thread/thread.h --- freerdp2-2.6.1+dfsg1/winpr/libwinpr/thread/thread.h 2022-03-07 09:24:08.000000000 -0500 +++ freerdp2-2.7.0+dfsg1/winpr/libwinpr/thread/thread.h 2022-05-20 09:09:05.000000000 -0400 @@ -32,47 +32,63 @@ #include "../synch/event.h" #include "apc.h" +#ifdef __GNUC__ +#define ALIGN64 __attribute__((aligned(8))) +#else +#ifdef _WIN32 +#define ALIGN64 __declspec(align(8)) +#else +#define ALIGN64 +#endif +#endif + typedef void* (*pthread_start_routine)(void*); typedef struct winpr_APC_item WINPR_APC_ITEM; +typedef struct +{ + ALIGN64 pthread_mutex_t mux; + ALIGN64 pthread_cond_t cond; + ALIGN64 BOOL val; +} mux_condition_bundle; + struct winpr_thread { WINPR_HANDLE_DEF(); - BOOL started; - WINPR_EVENT_IMPL event; - BOOL mainProcess; - BOOL detached; - BOOL joined; - BOOL exited; - DWORD dwExitCode; - pthread_t thread; - SIZE_T dwStackSize; - LPVOID lpParameter; - pthread_mutex_t mutex; - pthread_mutex_t threadIsReadyMutex; - pthread_cond_t threadIsReady; - LPTHREAD_START_ROUTINE lpStartAddress; - LPSECURITY_ATTRIBUTES lpThreadAttributes; - APC_QUEUE apc; + ALIGN64 BOOL started; + ALIGN64 WINPR_EVENT_IMPL event; + ALIGN64 BOOL mainProcess; + ALIGN64 BOOL detached; + ALIGN64 BOOL joined; + ALIGN64 BOOL exited; + ALIGN64 DWORD dwExitCode; + ALIGN64 pthread_t thread; + ALIGN64 SIZE_T dwStackSize; + ALIGN64 LPVOID lpParameter; + ALIGN64 pthread_mutex_t mutex; + mux_condition_bundle isRunning; + mux_condition_bundle isCreated; + ALIGN64 LPTHREAD_START_ROUTINE lpStartAddress; + ALIGN64 LPSECURITY_ATTRIBUTES lpThreadAttributes; + ALIGN64 APC_QUEUE apc; #if defined(WITH_DEBUG_THREADS) - void* create_stack; - void* exit_stack; + ALIGN64 void* create_stack; + ALIGN64 void* exit_stack; #endif }; typedef struct winpr_thread WINPR_THREAD; WINPR_THREAD* winpr_GetCurrentThread(VOID); -struct winpr_process +typedef struct { WINPR_HANDLE_DEF(); pid_t pid; int status; DWORD dwExitCode; -}; -typedef struct winpr_process WINPR_PROCESS; +} WINPR_PROCESS; #endif