Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FreeRDP/FreeRDP.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernhard Miklautz <bmiklautz@users.noreply.github.com>2022-01-12 12:55:33 +0300
committerGitHub <noreply@github.com>2022-01-12 12:55:33 +0300
commitd50aef95520df4216c638495a6049125c00742cb (patch)
tree1e80ae4a49e3eaecc161ef4a9f58740d6de95344
parent4f15d5c72a82d6a3149a8ef83c152f32fc49e3aa (diff)
parentfd4876a087d63cf2b7adcb8d100bf2ab08fd4cc7 (diff)
Merge pull request #7510 from akallabeth/stable-2.0.fix2.5.0
Stable 2.0.fix
-rw-r--r--CMakeLists.txt2
-rw-r--r--ChangeLog10
-rw-r--r--channels/audin/client/opensles/audin_opensl_es.c2
-rw-r--r--channels/client/addin.c83
-rw-r--r--client/Android/Studio/build.gradle2
-rw-r--r--client/Android/android_freerdp.c2
-rw-r--r--client/Wayland/wlf_cliprdr.c43
-rw-r--r--client/Wayland/wlfreerdp.c9
-rw-r--r--client/Windows/wf_client.c12
-rw-r--r--include/freerdp/locale/locale.h4
-rw-r--r--include/freerdp/settings.h33
-rw-r--r--include/freerdp/update.h2
-rw-r--r--libfreerdp/common/settings_getters.c7
-rw-r--r--libfreerdp/common/settings_str.c1
-rw-r--r--libfreerdp/core/nego.c14
-rw-r--r--libfreerdp/core/settings.c12
-rw-r--r--libfreerdp/core/tcp.c6
-rw-r--r--libfreerdp/core/test/settings_property_lists.h1
-rw-r--r--libfreerdp/locale/CMakeLists.txt10
-rw-r--r--libfreerdp/locale/keyboard.c11
-rw-r--r--libfreerdp/locale/keyboard_apple.c244
-rw-r--r--libfreerdp/locale/keyboard_apple.h28
-rw-r--r--libfreerdp/locale/locale.c191
-rw-r--r--winpr/CMakeLists.txt2
-rw-r--r--winpr/libwinpr/registry/registry.c58
-rw-r--r--winpr/libwinpr/registry/registry_reg.c307
-rw-r--r--winpr/libwinpr/registry/registry_reg.h5
27 files changed, 843 insertions, 258 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a0687025a..22c0347c4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -85,7 +85,7 @@ if ($ENV{BUILD_NUMBER})
endif()
set(WITH_LIBRARY_VERSIONING "ON")
-set(RAW_VERSION_STRING "2.4.1")
+set(RAW_VERSION_STRING "2.5.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 --git a/ChangeLog b/ChangeLog
index 146e00bf7..bf4e50034 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,18 +1,24 @@
-# 20xx-xx-xx Version 2.x.x
+# 2022-01-12 Version 2.5.0
Noteworthy changes:
* Fixed smartcard login in case a redirection occurs the pin was lost
+* Backported windows client drawing fixes
+* Backported improved macOS keyboard layout detection
+* Backported TcpConnectTimeout
* Backported LibreSSL compatibility patches
* Backported signal handler backtrace
* Backported OpenSSL 3.0 support
Fixed issues:
+* Backport #7539: Wayland client clipboard issues
+* Backport #7509: Various fixes regarding registry emulation, addin loader
+ and updated locale detection
* Backport #7466: Android android_register_pointer missing initialization
Important notes:
For a complete and detailed change log since the last release run:
-git log 2.4.1..2.x.x
+git log 2.4.1..2.5.0
# 2021-10-20 Version 2.4.1
diff --git a/channels/audin/client/opensles/audin_opensl_es.c b/channels/audin/client/opensles/audin_opensl_es.c
index 4e3efdeb2..87393ad36 100644
--- a/channels/audin/client/opensles/audin_opensl_es.c
+++ b/channels/audin/client/opensles/audin_opensl_es.c
@@ -248,7 +248,7 @@ static UINT audin_opensles_parse_addin_args(AudinOpenSLESDevice* device, ADDIN_A
{
UINT status;
DWORD flags;
- COMMAND_LINE_ARGUMENT_A* arg;
+ const COMMAND_LINE_ARGUMENT_A* arg;
AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*)device;
COMMAND_LINE_ARGUMENT_A audin_opensles_args[] = {
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL,
diff --git a/channels/client/addin.c b/channels/client/addin.c
index cd6f90e99..db32ff83c 100644
--- a/channels/client/addin.c
+++ b/channels/client/addin.c
@@ -231,10 +231,8 @@ static FREERDP_ADDIN** freerdp_channels_list_dynamic_addins(LPCSTR pszName, LPCS
do
{
- char* p[5];
- FREERDP_ADDIN* pAddin;
- nDashes = 0;
- pAddin = (FREERDP_ADDIN*)calloc(1, sizeof(FREERDP_ADDIN));
+ BOOL used = FALSE;
+ FREERDP_ADDIN* pAddin = (FREERDP_ADDIN*)calloc(1, sizeof(FREERDP_ADDIN));
if (!pAddin)
{
@@ -242,57 +240,116 @@ static FREERDP_ADDIN** freerdp_channels_list_dynamic_addins(LPCSTR pszName, LPCS
goto error_out;
}
+ nDashes = 0;
for (index = 0; FindData.cFileName[index]; index++)
nDashes += (FindData.cFileName[index] == '-') ? 1 : 0;
if (nDashes == 1)
{
+ size_t len;
+ char* p[2] = { 0 };
/* <name>-client.<extension> */
p[0] = FindData.cFileName;
p[1] = strchr(p[0], '-') + 1;
- strncpy(pAddin->cName, p[0], (p[1] - p[0]) - 1);
+
+ len = p[1] - p[0];
+ if (len < 1)
+ {
+ WLog_WARN(TAG, "Skipping file '%s', invalid format", FindData.cFileName);
+ goto skip;
+ }
+ strncpy(pAddin->cName, p[0], MIN(ARRAYSIZE(pAddin->cName), len - 1));
+
pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
pAddin->dwFlags |= FREERDP_ADDIN_DYNAMIC;
pAddin->dwFlags |= FREERDP_ADDIN_NAME;
ppAddins[nAddins++] = pAddin;
+
+ used = TRUE;
}
else if (nDashes == 2)
{
+ size_t len;
+ char* p[4] = { 0 };
/* <name>-client-<subsystem>.<extension> */
p[0] = FindData.cFileName;
p[1] = strchr(p[0], '-') + 1;
p[2] = strchr(p[1], '-') + 1;
p[3] = strchr(p[2], '.') + 1;
- strncpy(pAddin->cName, p[0], (p[1] - p[0]) - 1);
- strncpy(pAddin->cSubsystem, p[2], (p[3] - p[2]) - 1);
+
+ len = p[1] - p[0];
+ if (len < 1)
+ {
+ WLog_WARN(TAG, "Skipping file '%s', invalid format", FindData.cFileName);
+ goto skip;
+ }
+ strncpy(pAddin->cName, p[0], MIN(ARRAYSIZE(pAddin->cName), len - 1));
+
+ len = p[3] - p[2];
+ if (len < 1)
+ {
+ WLog_WARN(TAG, "Skipping file '%s', invalid format", FindData.cFileName);
+ goto skip;
+ }
+ strncpy(pAddin->cSubsystem, p[2], MIN(ARRAYSIZE(pAddin->cSubsystem), len - 1));
+
pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
pAddin->dwFlags |= FREERDP_ADDIN_DYNAMIC;
pAddin->dwFlags |= FREERDP_ADDIN_NAME;
pAddin->dwFlags |= FREERDP_ADDIN_SUBSYSTEM;
ppAddins[nAddins++] = pAddin;
+
+ used = TRUE;
}
else if (nDashes == 3)
{
+ size_t len;
+ char* p[5] = { 0 };
/* <name>-client-<subsystem>-<type>.<extension> */
p[0] = FindData.cFileName;
p[1] = strchr(p[0], '-') + 1;
p[2] = strchr(p[1], '-') + 1;
p[3] = strchr(p[2], '-') + 1;
p[4] = strchr(p[3], '.') + 1;
- strncpy(pAddin->cName, p[0], (p[1] - p[0]) - 1);
- strncpy(pAddin->cSubsystem, p[2], (p[3] - p[2]) - 1);
- strncpy(pAddin->cType, p[3], (p[4] - p[3]) - 1);
+
+ len = p[1] - p[0];
+ if (len < 1)
+ {
+ WLog_WARN(TAG, "Skipping file '%s', invalid format", FindData.cFileName);
+ goto skip;
+ }
+ strncpy(pAddin->cName, p[0], MIN(ARRAYSIZE(pAddin->cName), len - 1));
+
+ len = p[3] - p[2];
+ if (len < 1)
+ {
+ WLog_WARN(TAG, "Skipping file '%s', invalid format", FindData.cFileName);
+ goto skip;
+ }
+ strncpy(pAddin->cSubsystem, p[2], MIN(ARRAYSIZE(pAddin->cSubsystem), len - 1));
+
+ len = p[4] - p[3];
+ if (len < 1)
+ {
+ WLog_WARN(TAG, "Skipping file '%s', invalid format", FindData.cFileName);
+ goto skip;
+ }
+ strncpy(pAddin->cType, p[3], MIN(ARRAYSIZE(pAddin->cType), len - 1));
+
pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
pAddin->dwFlags |= FREERDP_ADDIN_DYNAMIC;
pAddin->dwFlags |= FREERDP_ADDIN_NAME;
pAddin->dwFlags |= FREERDP_ADDIN_SUBSYSTEM;
pAddin->dwFlags |= FREERDP_ADDIN_TYPE;
ppAddins[nAddins++] = pAddin;
+
+ used = TRUE;
}
- else
- {
+
+ skip:
+ if (!used)
free(pAddin);
- }
+
} while (FindNextFileA(hFind, &FindData));
FindClose(hFind);
diff --git a/client/Android/Studio/build.gradle b/client/Android/Studio/build.gradle
index 2d0abd32d..cb52a54d9 100644
--- a/client/Android/Studio/build.gradle
+++ b/client/Android/Studio/build.gradle
@@ -29,7 +29,7 @@ def getVersionName = { ->
ext {
versionName = properties.get('VERSION_NAME', getVersionName())
- versionCode = properties.get('VERSION_CODE', 25)
+ versionCode = properties.get('VERSION_CODE', 26)
compileApi = properties.get('COMPILE_API', 30)
targetApi = properties.get('TARGET_API', 30)
minApi = properties.get('MIN_API', 21)
diff --git a/client/Android/android_freerdp.c b/client/Android/android_freerdp.c
index 78205c751..2cdc020c2 100644
--- a/client/Android/android_freerdp.c
+++ b/client/Android/android_freerdp.c
@@ -56,7 +56,7 @@
#define TAG CLIENT_TAG("android")
/* Defines the JNI version supported by this library. */
-#define FREERDP_JNI_VERSION "2.4.1"
+#define FREERDP_JNI_VERSION "2.5.0"
static void android_OnChannelConnectedEventHandler(void* context, ChannelConnectedEventArgs* e)
{
diff --git a/client/Wayland/wlf_cliprdr.c b/client/Wayland/wlf_cliprdr.c
index 0762cfa3d..0f0195d7c 100644
--- a/client/Wayland/wlf_cliprdr.c
+++ b/client/Wayland/wlf_cliprdr.c
@@ -80,6 +80,7 @@ struct wlf_clipboard
FILE* responseFile;
UINT32 responseFormat;
const char* responseMime;
+ CRITICAL_SECTION lock;
};
static BOOL wlf_mime_is_text(const char* mime)
@@ -275,7 +276,7 @@ BOOL wlf_cliprdr_handle_event(wfClipboard* clipboard, const UwacClipboardEvent*
return TRUE;
case UWAC_EVENT_CLIPBOARD_OFFER:
- WLog_Print(clipboard->log, WLOG_INFO, "client announces mime %s", event->mime);
+ WLog_Print(clipboard->log, WLOG_DEBUG, "client announces mime %s", event->mime);
wlf_cliprdr_add_client_format(clipboard, event->mime);
return TRUE;
@@ -387,6 +388,8 @@ static void wlf_cliprdr_transfer_data(UwacSeat* seat, void* context, const char*
wfClipboard* clipboard = (wfClipboard*)context;
size_t x;
WINPR_UNUSED(seat);
+
+ EnterCriticalSection(&clipboard->lock);
clipboard->responseMime = NULL;
for (x = 0; x < ARRAYSIZE(mime_html); x++)
@@ -427,6 +430,8 @@ static void wlf_cliprdr_transfer_data(UwacSeat* seat, void* context, const char*
if (clipboard->responseMime != NULL)
{
+ if (clipboard->responseFile != NULL)
+ fclose(clipboard->responseFile);
clipboard->responseFile = fdopen(fd, "w");
if (clipboard->responseFile)
@@ -436,6 +441,7 @@ static void wlf_cliprdr_transfer_data(UwacSeat* seat, void* context, const char*
"failed to open clipboard file descriptor for MIME %s",
clipboard->responseMime);
}
+ LeaveCriticalSection(&clipboard->lock);
}
static void wlf_cliprdr_cancel_data(UwacSeat* seat, void* context)
@@ -673,6 +679,8 @@ wlf_cliprdr_server_format_data_response(CliprdrClientContext* context,
const WCHAR* wdata = (const WCHAR*)formatDataResponse->requestedFormatData;
wfClipboard* clipboard = (wfClipboard*)context->custom;
+ EnterCriticalSection(&clipboard->lock);
+
if (size > INT_MAX * sizeof(WCHAR))
return ERROR_INTERNAL_ERROR;
@@ -694,10 +702,16 @@ wlf_cliprdr_server_format_data_response(CliprdrClientContext* context,
break;
}
- fwrite(data, 1, size, clipboard->responseFile);
- fclose(clipboard->responseFile);
+ if (clipboard->responseFile)
+ {
+ fwrite(data, 1, size, clipboard->responseFile);
+ fclose(clipboard->responseFile);
+ clipboard->responseFile = NULL;
+ }
rc = CHANNEL_RC_OK;
free(cdata);
+
+ LeaveCriticalSection(&clipboard->lock);
return rc;
}
@@ -829,17 +843,24 @@ static UINT wlf_cliprdr_clipboard_file_range_failure(wClipboardDelegate* delegat
wfClipboard* wlf_clipboard_new(wlfContext* wfc)
{
rdpChannels* channels;
- wfClipboard* clipboard;
+ wfClipboard* clipboard = (wfClipboard*)calloc(1, sizeof(wfClipboard));
- if (!(clipboard = (wfClipboard*)calloc(1, sizeof(wfClipboard))))
- return NULL;
+ if (!clipboard)
+ goto fail;
+ InitializeCriticalSection(&clipboard->lock);
clipboard->wfc = wfc;
channels = wfc->context.channels;
clipboard->log = WLog_Get(TAG);
clipboard->channels = channels;
clipboard->system = ClipboardCreate();
+ if (!clipboard->system)
+ goto fail;
+
clipboard->delegate = ClipboardGetDelegate(clipboard->system);
+ if (!clipboard->delegate)
+ goto fail;
+
clipboard->delegate->custom = clipboard;
/* TODO: set up a filesystem base path for local URI */
/* clipboard->delegate->basePath = "file:///tmp/foo/bar/gaga"; */
@@ -848,6 +869,10 @@ wfClipboard* wlf_clipboard_new(wlfContext* wfc)
clipboard->delegate->ClipboardFileRangeSuccess = wlf_cliprdr_clipboard_file_range_success;
clipboard->delegate->ClipboardFileRangeFailure = wlf_cliprdr_clipboard_file_range_failure;
return clipboard;
+
+fail:
+ wlf_clipboard_free(clipboard);
+ return NULL;
}
void wlf_clipboard_free(wfClipboard* clipboard)
@@ -858,6 +883,12 @@ void wlf_clipboard_free(wfClipboard* clipboard)
wlf_cliprdr_free_server_formats(clipboard);
wlf_cliprdr_free_client_formats(clipboard);
ClipboardDestroy(clipboard->system);
+
+ EnterCriticalSection(&clipboard->lock);
+ if (clipboard->responseFile)
+ fclose(clipboard->responseFile);
+ LeaveCriticalSection(&clipboard->lock);
+ DeleteCriticalSection(&clipboard->lock);
free(clipboard);
}
diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c
index aca734211..ac8e77230 100644
--- a/client/Wayland/wlfreerdp.c
+++ b/client/Wayland/wlfreerdp.c
@@ -331,12 +331,15 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display)
break;
case UWAC_EVENT_FRAME_DONE:
+ {
+ UwacReturnCode r;
EnterCriticalSection(&context->critical);
- rc = UwacWindowSubmitBuffer(context->window, false);
+ r = UwacWindowSubmitBuffer(context->window, false);
LeaveCriticalSection(&context->critical);
- if (rc != UWAC_SUCCESS)
+ if (r != UWAC_SUCCESS)
return FALSE;
- break;
+ }
+ break;
case UWAC_EVENT_POINTER_ENTER:
if (!wlf_handle_pointer_enter(instance, &event.mouse_enter_leave))
diff --git a/client/Windows/wf_client.c b/client/Windows/wf_client.c
index f61f0c8d2..5ee059402 100644
--- a/client/Windows/wf_client.c
+++ b/client/Windows/wf_client.c
@@ -118,6 +118,18 @@ static BOOL wf_end_paint(rdpContext* context)
updateRect.top = extents->top;
updateRect.right = extents->right;
updateRect.bottom = extents->bottom;
+
+ if (wfc->xScrollVisible)
+ {
+ updateRect.left -= MIN(updateRect.left, wfc->xCurrentScroll);
+ updateRect.right -= MIN(updateRect.right, wfc->xCurrentScroll);
+ }
+ if (wfc->yScrollVisible)
+ {
+ updateRect.top -= MIN(updateRect.top, wfc->yCurrentScroll);
+ updateRect.bottom -= MIN(updateRect.bottom, wfc->yCurrentScroll);
+ }
+
InvalidateRect(wfc->hwnd, &updateRect, FALSE);
if (wfc->rail)
diff --git a/include/freerdp/locale/locale.h b/include/freerdp/locale/locale.h
index 54ab2c660..6647bb22c 100644
--- a/include/freerdp/locale/locale.h
+++ b/include/freerdp/locale/locale.h
@@ -62,6 +62,7 @@
#define BRETON 0x047E
#define BULGARIAN 0x0402
#define CATALAN 0x0403
+#define CHEROKEE 0x045C
#define CHINESE_TAIWAN 0x0404
#define CHINESE_PRC 0x0804
#define CHINESE_HONG_KONG 0x0C04
@@ -113,12 +114,14 @@
#define GREEK 0x0408
#define GREENLANDIC 0x046F
#define GUJARATI 0x0447
+#define HAWAIIAN 0x0475
#define HEBREW 0x040D
#define HINDI 0x0439
#define HUNGARIAN 0x040E
#define ICELANDIC 0x040F
#define IGBO 0x0470
#define INDONESIAN 0x0421
+#define INUKTITUT 0x045D
#define IRISH 0x083C
#define ITALIAN_STANDARD 0x0410
#define ITALIAN_SWISS 0x0810
@@ -146,6 +149,7 @@
#define MARATHI 0x044E
#define MOHAWK 0x047C
#define MONGOLIAN 0x0450
+#define MYANMAR 0x0455
#define NEPALI 0x0461
#define NORWEGIAN_BOKMAL 0x0414
#define NORWEGIAN_NYNORSK 0x0814
diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h
index 26adb624e..3b7a13896 100644
--- a/include/freerdp/settings.h
+++ b/include/freerdp/settings.h
@@ -894,6 +894,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_TcpKeepAliveDelay (5192)
#define FreeRDP_TcpKeepAliveInterval (5193)
#define FreeRDP_TcpAckTimeout (5194)
+#define FreeRDP_TcpConnectTimeout (5197)
/**
* FreeRDP Settings Data Structure
@@ -1342,20 +1343,20 @@ struct rdp_settings
/* Input Capabilities */
ALIGN64 char* KeyboardRemappingList; /* 2622 */
- ALIGN64 UINT32 KeyboardCodePage; /* 2623 */
- ALIGN64 UINT32 KeyboardLayout; /* 2624 */
- ALIGN64 UINT32 KeyboardType; /* 2625 */
- ALIGN64 UINT32 KeyboardSubType; /* 2626 */
- ALIGN64 UINT32 KeyboardFunctionKey; /* 2627 */
- ALIGN64 char* ImeFileName; /* 2628 */
- ALIGN64 BOOL UnicodeInput; /* 2629 */
- ALIGN64 BOOL FastPathInput; /* 2630 */
- ALIGN64 BOOL MultiTouchInput; /* 2631 */
- ALIGN64 BOOL MultiTouchGestures; /* 2632 */
- ALIGN64 UINT32 KeyboardHook; /* 2633 */
- ALIGN64 BOOL HasHorizontalWheel; /* 2634 */
- ALIGN64 BOOL HasExtendedMouseEvent; /* 2635 */
- UINT64 padding2688[2688 - 2636]; /* 2636 */
+ ALIGN64 UINT32 KeyboardCodePage; /* 2623 */
+ ALIGN64 UINT32 KeyboardLayout; /* 2624 */
+ ALIGN64 UINT32 KeyboardType; /* 2625 */
+ ALIGN64 UINT32 KeyboardSubType; /* 2626 */
+ ALIGN64 UINT32 KeyboardFunctionKey; /* 2627 */
+ ALIGN64 char* ImeFileName; /* 2628 */
+ ALIGN64 BOOL UnicodeInput; /* 2629 */
+ ALIGN64 BOOL FastPathInput; /* 2630 */
+ ALIGN64 BOOL MultiTouchInput; /* 2631 */
+ ALIGN64 BOOL MultiTouchGestures; /* 2632 */
+ ALIGN64 UINT32 KeyboardHook; /* 2633 */
+ ALIGN64 BOOL HasHorizontalWheel; /* 2634 */
+ ALIGN64 BOOL HasExtendedMouseEvent; /* 2635 */
+ UINT64 padding2688[2688 - 2636]; /* 2636 */
/* Brush Capabilities */
ALIGN64 UINT32 BrushSupportLevel; /* 2688 */
@@ -1545,7 +1546,9 @@ struct rdp_settings
ALIGN64 UINT32 TcpKeepAliveDelay; /* 5192 */
ALIGN64 UINT32 TcpKeepAliveInterval; /* 5193 */
ALIGN64 UINT32 TcpAckTimeout; /* 5194 */
- UINT64 padding5312[5312 - 5195]; /* 5195 */
+ UINT64 padding5197[5197 - 5195]; /* 5195 */
+ ALIGN64 UINT32 TcpConnectTimeout; /* 5197 */
+ UINT64 padding5312[5312 - 5198]; /* 5198 */
/**
* WARNING: End of ABI stable zone!
diff --git a/include/freerdp/update.h b/include/freerdp/update.h
index ec5336a26..71cb15580 100644
--- a/include/freerdp/update.h
+++ b/include/freerdp/update.h
@@ -254,7 +254,6 @@ struct rdp_update
wStream* us;
UINT16 numberOrders;
- size_t offsetOrders; /* the offset to patch numberOrders in the stream */
BOOL combineUpdates;
rdpBounds currentBounds;
rdpBounds previousBounds;
@@ -264,6 +263,7 @@ struct rdp_update
* fills BITMAP_DATA struct members: flags, cbCompMainBodySize and cbCompFirstRowSize.
*/
BOOL autoCalculateBitmapData;
+ size_t offsetOrders; /* the offset to patch numberOrders in the stream */
};
#endif /* FREERDP_UPDATE_H */
diff --git a/libfreerdp/common/settings_getters.c b/libfreerdp/common/settings_getters.c
index 2a34bb80f..a3ce8e961 100644
--- a/libfreerdp/common/settings_getters.c
+++ b/libfreerdp/common/settings_getters.c
@@ -1570,6 +1570,9 @@ UINT32 freerdp_settings_get_uint32(const rdpSettings* settings, size_t id)
case FreeRDP_TcpAckTimeout:
return settings->TcpAckTimeout;
+ case FreeRDP_TcpConnectTimeout:
+ return settings->TcpConnectTimeout;
+
case FreeRDP_TcpKeepAliveDelay:
return settings->TcpKeepAliveDelay;
@@ -2021,6 +2024,10 @@ BOOL freerdp_settings_set_uint32(rdpSettings* settings, size_t id, UINT32 val)
settings->TcpAckTimeout = val;
break;
+ case FreeRDP_TcpConnectTimeout:
+ settings->TcpConnectTimeout = val;
+ break;
+
case FreeRDP_TcpKeepAliveDelay:
settings->TcpKeepAliveDelay = val;
break;
diff --git a/libfreerdp/common/settings_str.c b/libfreerdp/common/settings_str.c
index b7b8def72..9a545f25d 100644
--- a/libfreerdp/common/settings_str.c
+++ b/libfreerdp/common/settings_str.c
@@ -285,6 +285,7 @@ static const struct settings_str_entry settings_map[] = {
{ FreeRDP_StaticChannelCount, 3, "FreeRDP_StaticChannelCount" },
{ FreeRDP_TargetNetAddressCount, 3, "FreeRDP_TargetNetAddressCount" },
{ FreeRDP_TcpAckTimeout, 3, "FreeRDP_TcpAckTimeout" },
+ { FreeRDP_TcpConnectTimeout, 3, "FreeRDP_TcpConnectTimeout" },
{ FreeRDP_TcpKeepAliveDelay, 3, "FreeRDP_TcpKeepAliveDelay" },
{ FreeRDP_TcpKeepAliveInterval, 3, "FreeRDP_TcpKeepAliveInterval" },
{ FreeRDP_TcpKeepAliveRetries, 3, "FreeRDP_TcpKeepAliveRetries" },
diff --git a/libfreerdp/core/nego.c b/libfreerdp/core/nego.c
index 8357ff9ab..ac4e93f7c 100644
--- a/libfreerdp/core/nego.c
+++ b/libfreerdp/core/nego.c
@@ -277,6 +277,9 @@ static BOOL nego_tcp_connect(rdpNego* nego)
{
if (!nego->TcpConnected)
{
+ const UINT32 TcpConnectTimeout = freerdp_settings_get_uint32(
+ nego->transport->context->settings, FreeRDP_TcpConnectTimeout);
+
if (nego->GatewayEnabled)
{
if (nego->GatewayBypassLocal)
@@ -286,20 +289,21 @@ static BOOL nego_tcp_connect(rdpNego* nego)
"Detecting if host can be reached locally. - This might take some time.");
WLog_INFO(TAG, "To disable auto detection use /gateway-usage-method:direct");
transport_set_gateway_enabled(nego->transport, FALSE);
- nego->TcpConnected =
- transport_connect(nego->transport, nego->hostname, nego->port, 1);
+ nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port,
+ TcpConnectTimeout);
}
if (!nego->TcpConnected)
{
transport_set_gateway_enabled(nego->transport, TRUE);
- nego->TcpConnected =
- transport_connect(nego->transport, nego->hostname, nego->port, 15);
+ nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port,
+ TcpConnectTimeout);
}
}
else
{
- nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port, 15);
+ nego->TcpConnected =
+ transport_connect(nego->transport, nego->hostname, nego->port, TcpConnectTimeout);
}
}
diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c
index eb425dd95..d0c2b56f3 100644
--- a/libfreerdp/core/settings.c
+++ b/libfreerdp/core/settings.c
@@ -547,11 +547,13 @@ rdpSettings* freerdp_settings_new(DWORD flags)
if (!settings->DynamicChannelArray)
goto out_fail;
- settings->TcpKeepAlive = TRUE;
- settings->TcpKeepAliveRetries = 3;
- settings->TcpKeepAliveDelay = 5;
- settings->TcpKeepAliveInterval = 2;
- settings->TcpAckTimeout = 9000;
+ if (!freerdp_settings_set_bool(settings, FreeRDP_TcpKeepAlive, TRUE) ||
+ !freerdp_settings_set_uint32(settings, FreeRDP_TcpKeepAliveRetries, 3) ||
+ !freerdp_settings_set_uint32(settings, FreeRDP_TcpKeepAliveDelay, 5) ||
+ !freerdp_settings_set_uint32(settings, FreeRDP_TcpKeepAliveInterval, 2) ||
+ !freerdp_settings_set_uint32(settings, FreeRDP_TcpAckTimeout, 9000) ||
+ !freerdp_settings_set_uint32(settings, FreeRDP_TcpConnectTimeout, 15000))
+ goto out_fail;
if (!settings->ServerMode)
{
diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c
index ef5f7b193..60b4211b5 100644
--- a/libfreerdp/core/tcp.c
+++ b/libfreerdp/core/tcp.c
@@ -801,14 +801,14 @@ static BOOL freerdp_tcp_is_hostname_resolvable(rdpContext* context, const char*
}
static BOOL freerdp_tcp_connect_timeout(rdpContext* context, int sockfd, struct sockaddr* addr,
- socklen_t addrlen, int timeout)
+ socklen_t addrlen, UINT32 timeout)
{
BOOL rc = FALSE;
HANDLE handles[2];
int status = 0;
int count = 0;
u_long arg = 0;
- DWORD tout = (timeout > 0) ? (DWORD)timeout * 1000U : INFINITE;
+ DWORD tout = (timeout > 0) ? timeout : INFINITE;
handles[count] = CreateEvent(NULL, TRUE, FALSE, NULL);
@@ -894,7 +894,7 @@ static void peer_free(t_peer* peer)
}
static int freerdp_tcp_connect_multi(rdpContext* context, char** hostnames, UINT32* ports,
- UINT32 count, int port, int timeout)
+ UINT32 count, UINT16 port, UINT32 timeout)
{
UINT32 index;
UINT32 sindex = count;
diff --git a/libfreerdp/core/test/settings_property_lists.h b/libfreerdp/core/test/settings_property_lists.h
index ff35a7ec8..db8e5ed8e 100644
--- a/libfreerdp/core/test/settings_property_lists.h
+++ b/libfreerdp/core/test/settings_property_lists.h
@@ -282,6 +282,7 @@ static const size_t uint32_list_indices[] = {
FreeRDP_StaticChannelCount,
FreeRDP_TargetNetAddressCount,
FreeRDP_TcpAckTimeout,
+ FreeRDP_TcpConnectTimeout,
FreeRDP_TcpKeepAliveDelay,
FreeRDP_TcpKeepAliveInterval,
FreeRDP_TcpKeepAliveRetries,
diff --git a/libfreerdp/locale/CMakeLists.txt b/libfreerdp/locale/CMakeLists.txt
index 1a300f22f..9c74e20dc 100644
--- a/libfreerdp/locale/CMakeLists.txt
+++ b/libfreerdp/locale/CMakeLists.txt
@@ -38,10 +38,20 @@ set(${MODULE_PREFIX}_SUN_SRCS
keyboard_sun.c
keyboard_sun.h)
+set(${MODULE_PREFIX}_APPLE_SRCS
+ keyboard_apple.c
+ keyboard_apple.h)
+
if(CMAKE_SYSTEM_NAME MATCHES Solaris)
set(WITH_SUN true)
endif()
+if(APPLE AND (NOT IOS))
+ set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${${MODULE_PREFIX}_APPLE_SRCS})
+ find_library(CARBON Carbon)
+ freerdp_library_add(${CARBON})
+endif()
+
if(WITH_X11)
freerdp_definition_add(-DWITH_X11)
freerdp_include_directory_add(${X11_INCLUDE_DIRS})
diff --git a/libfreerdp/locale/keyboard.c b/libfreerdp/locale/keyboard.c
index eca0d635c..4c5ae03e4 100644
--- a/libfreerdp/locale/keyboard.c
+++ b/libfreerdp/locale/keyboard.c
@@ -32,6 +32,10 @@
#include "liblocale.h"
+#if defined(__MACOSX__)
+#include "keyboard_apple.h"
+#endif
+
#ifdef WITH_X11
#include "keyboard_x11.h"
@@ -64,6 +68,11 @@ int freerdp_detect_keyboard(DWORD* keyboardLayoutId)
*keyboardLayoutId = ((DWORD)GetKeyboardLayout(0) >> 16) & 0x0000FFFF;
#endif
+#if defined(__MACOSX__)
+ if (*keyboardLayoutId == 0)
+ freerdp_detect_keyboard_layout_from_cf(keyboardLayoutId);
+#endif
+
#ifdef WITH_X11
if (*keyboardLayoutId == 0)
freerdp_detect_keyboard_layout_from_xkb(keyboardLayoutId);
@@ -148,7 +157,7 @@ DWORD freerdp_keyboard_init(DWORD keyboardLayoutId)
for (keycode = 0; keycode < ARRAYSIZE(VIRTUAL_SCANCODE_TO_X11_KEYCODE); keycode++)
{
VIRTUAL_SCANCODE_TO_X11_KEYCODE
- [RDP_SCANCODE_CODE(X11_KEYCODE_TO_VIRTUAL_SCANCODE[keycode])]
+ [RDP_SCANCODE_CODE(X11_KEYCODE_TO_VIRTUAL_SCANCODE[keycode])]
[RDP_SCANCODE_EXTENDED(X11_KEYCODE_TO_VIRTUAL_SCANCODE[keycode]) ? 1 : 0] = keycode;
}
diff --git a/libfreerdp/locale/keyboard_apple.c b/libfreerdp/locale/keyboard_apple.c
new file mode 100644
index 000000000..d0d59216e
--- /dev/null
+++ b/libfreerdp/locale/keyboard_apple.c
@@ -0,0 +1,244 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Apple Core Foundation Keyboard Mapping
+ *
+ * Copyright 2021 Thincast Technologies GmbH
+ * Copyright 2021 Martin Fleisz <martin.fleisz@thincast.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <Carbon/Carbon.h>
+#include <string.h>
+
+#include "liblocale.h"
+
+#include <freerdp/locale/locale.h>
+#include <freerdp/locale/keyboard.h>
+
+#include "keyboard_apple.h"
+
+struct KEYBOARD_LAYOUT_MAPPING_
+{
+ const char* inputSourceId; /* Apple input source id (com.apple.keylayout or inputmethod) */
+ DWORD code; /* mapped rdp keyboard layout id */
+};
+typedef struct KEYBOARD_LAYOUT_MAPPING_ KEYBOARD_LAYOUT_MAPPING;
+
+static const KEYBOARD_LAYOUT_MAPPING KEYBOARD_MAPPING_TABLE[] = {
+ { "com.apple.inputmethod.Kotoeri.Japanese", JAPANESE },
+ { "com.apple.inputmethod.Kotoeri.Japanese.FullWidthRoman", JAPANESE },
+ { "com.apple.inputmethod.Kotoeri.Japanese.HalfWidthKana", JAPANESE },
+ { "com.apple.inputmethod.Kotoeri.Japanese.Katakana", JAPANESE },
+ { "com.apple.inputmethod.Kotoeri.Katakana", JAPANESE },
+ { "com.apple.inputmethod.Kotoeri.Roman", JAPANESE },
+ { "com.apple.inputmethod.kotoeri.Ainu", JAPANESE },
+ { "com.apple.keylayout.2SetHangul", KOREAN },
+ { "com.apple.keylayout.390Hangul", KOREAN },
+ { "com.apple.keylayout.3SetHangul", KOREAN },
+ { "com.apple.keylayout.AfghanDari", DARI },
+ { "com.apple.keylayout.AfghanPashto", PASHTO },
+ { "com.apple.keylayout.AfghanUzbek", UZBEK_LATIN },
+ { "com.apple.keylayout.Arabic", ARABIC_EGYPT },
+ { "com.apple.keylayout.Arabic-QWERTY", ARABIC_EGYPT },
+ { "com.apple.keylayout.ArabicPC", ARABIC_EGYPT },
+ { "com.apple.keylayout.Armenian-HMQWERTY", ARMENIAN },
+ { "com.apple.keylayout.Armenian-WesternQWERTY", ARMENIAN },
+ { "com.apple.keylayout.Australian", ENGLISH_AUSTRALIAN },
+ { "com.apple.keylayout.Austrian", GERMAN_AUSTRIAN },
+ { "com.apple.keylayout.Azeri", AZERI_LATIN },
+ { "com.apple.keylayout.Bangla", BENGALI_INDIA },
+ { "com.apple.keylayout.Bangla-QWERTY", BENGALI_INDIA },
+ { "com.apple.keylayout.Belgian", DUTCH_BELGIAN },
+ { "com.apple.keylayout.Brazilian", PORTUGUESE_BRAZILIAN },
+ { "com.apple.keylayout.British", ENGLISH_UNITED_KINGDOM },
+ { "com.apple.keylayout.British-PC", ENGLISH_UNITED_KINGDOM },
+ { "com.apple.keylayout.Bulgarian", BULGARIAN },
+ { "com.apple.keylayout.Bulgarian-Phonetic", BULGARIAN },
+ { "com.apple.keylayout.Byelorussian", BELARUSIAN },
+ { "com.apple.keylayout.Canadian", ENGLISH_CANADIAN },
+ { "com.apple.keylayout.Canadian-CSA", FRENCH_CANADIAN },
+ { "com.apple.keylayout.CangjieKeyboard", CHINESE_TAIWAN },
+ { "com.apple.keylayout.Cherokee-Nation", CHEROKEE },
+ { "com.apple.keylayout.Cherokee-QWERTY", CHEROKEE },
+ { "com.apple.keylayout.Colemak", ENGLISH_UNITED_STATES },
+ { "com.apple.keylayout.Croatian", CROATIAN },
+ { "com.apple.keylayout.Croatian-PC", CROATIAN },
+ { "com.apple.keylayout.Czech", CZECH },
+ { "com.apple.keylayout.Czech-QWERTY", CZECH },
+ { "com.apple.keylayout.DVORAK-QWERTYCMD", ENGLISH_UNITED_STATES },
+ { "com.apple.keylayout.Danish", DANISH },
+ { "com.apple.keylayout.Devanagari", HINDI },
+ { "com.apple.keylayout.Devanagari-QWERTY", HINDI },
+ { "com.apple.keylayout.Dutch", DUTCH_STANDARD },
+ { "com.apple.keylayout.Dvorak", ENGLISH_UNITED_STATES },
+ { "com.apple.keylayout.Dvorak-Left", ENGLISH_UNITED_STATES },
+ { "com.apple.keylayout.Dvorak-Right", ENGLISH_UNITED_STATES },
+ { "com.apple.keylayout.Estonian", ESTONIAN },
+ { "com.apple.keylayout.Faroese", FAEROESE },
+ { "com.apple.keylayout.Finnish", FINNISH },
+ { "com.apple.keylayout.FinnishExtended", FINNISH },
+ { "com.apple.keylayout.FinnishSami-PC", FINNISH },
+ { "com.apple.keylayout.French", FRENCH_STANDARD },
+ { "com.apple.keylayout.French-PC", FRENCH_STANDARD },
+ { "com.apple.keylayout.French-numerical", FRENCH_STANDARD },
+ { "com.apple.keylayout.GJCRomaja", ENGLISH_UNITED_STATES },
+ { "com.apple.keylayout.Georgian-QWERTY", GEORGIAN },
+ { "com.apple.keylayout.German", GERMAN_STANDARD },
+ { "com.apple.keylayout.Greek", GREEK },
+ { "com.apple.keylayout.GreekPolytonic", GREEK },
+ { "com.apple.keylayout.Gujarati", GUJARATI },
+ { "com.apple.keylayout.Gujarati-QWERTY", GUJARATI },
+ { "com.apple.keylayout.Gurmukhi", PUNJABI },
+ { "com.apple.keylayout.Gurmukhi-QWERTY", PUNJABI },
+ { "com.apple.keylayout.HNCRomaja", ENGLISH_UNITED_STATES },
+ { "com.apple.keylayout.Hawaiian", HAWAIIAN },
+ { "com.apple.keylayout.Hebrew", HEBREW },
+ { "com.apple.keylayout.Hebrew-PC", HEBREW },
+ { "com.apple.keylayout.Hebrew-QWERTY", HEBREW },
+ { "com.apple.keylayout.Hungarian", HUNGARIAN },
+ { "com.apple.keylayout.Hungarian-QWERTY", HUNGARIAN },
+ { "com.apple.keylayout.Icelandic", ICELANDIC },
+ { "com.apple.keylayout.Inuktitut-Nunavut", INUKTITUT },
+ { "com.apple.keylayout.Inuktitut-Nutaaq", INUKTITUT },
+ { "com.apple.keylayout.Inuktitut-QWERTY", INUKTITUT },
+ { "com.apple.keylayout.InuttitutNunavik", INUKTITUT },
+ { "com.apple.keylayout.Irish", ENGLISH_IRELAND },
+ { "com.apple.keylayout.IrishExtended", IRISH },
+ { "com.apple.keylayout.Italian", ITALIAN_STANDARD },
+ { "com.apple.keylayout.Italian-Pro", ITALIAN_STANDARD },
+ { "com.apple.keylayout.Jawi-QWERTY", ARABIC_SAUDI_ARABIA },
+ { "com.apple.keylayout.Kannada", KANNADA },
+ { "com.apple.keylayout.Kannada-QWERTY", KANNADA },
+ { "com.apple.keylayout.Kazakh", KAZAKH },
+ { "com.apple.keylayout.Khmer", KHMER },
+ { "com.apple.keylayout.Latvian", LATVIAN },
+ { "com.apple.keylayout.Lithuanian", LITHUANIAN },
+ { "com.apple.keylayout.Macedonian", MACEDONIAN },
+ { "com.apple.keylayout.Malayalam", MALAYALAM },
+ { "com.apple.keylayout.Malayalam-QWERTY", MALAYALAM },
+ { "com.apple.keylayout.Maltese", MALTESE },
+ { "com.apple.keylayout.Maori", MAORI },
+ { "com.apple.keylayout.Myanmar-QWERTY", MYANMAR },
+ { "com.apple.keylayout.Nepali", NEPALI },
+ { "com.apple.keylayout.NorthernSami", SAMI_NORTHERN_NORWAY },
+ { "com.apple.keylayout.Norwegian", NORWEGIAN_BOKMAL },
+ { "com.apple.keylayout.NorwegianExtended", NORWEGIAN_BOKMAL },
+ { "com.apple.keylayout.NorwegianSami-PC", NORWEGIAN_BOKMAL },
+ { "com.apple.keylayout.Oriya", ORIYA },
+ { "com.apple.keylayout.Persian", FARSI },
+ { "com.apple.keylayout.Persian-ISIRI2901", FARSI },
+ { "com.apple.keylayout.Polish", POLISH },
+ { "com.apple.keylayout.PolishPro", POLISH },
+ { "com.apple.keylayout.Portuguese", PORTUGUESE_STANDARD },
+ { "com.apple.keylayout.Romanian", ROMANIAN },
+ { "com.apple.keylayout.Romanian-Standard", ROMANIAN },
+ { "com.apple.keylayout.Russian", RUSSIAN },
+ { "com.apple.keylayout.Russian-Phonetic", RUSSIAN },
+ { "com.apple.keylayout.RussianWin", RUSSIAN },
+ { "com.apple.keylayout.Sami-PC", SAMI_NORTHERN_SWEDEN },
+ { "com.apple.keylayout.Serbian", SERBIAN_CYRILLIC_BOSNIA_HERZEGOVINA },
+ { "com.apple.keylayout.Serbian-Latin", SERBIAN_LATIN_BOSNIA_HERZEGOVINA },
+ { "com.apple.keylayout.Sinhala", SINHALA },
+ { "com.apple.keylayout.Sinhala-QWERTY", SINHALA },
+ { "com.apple.keylayout.Slovak", SLOVAK },
+ { "com.apple.keylayout.Slovak-QWERTY", SLOVAK },
+ { "com.apple.keylayout.Slovenian", SLOVENIAN },
+ { "com.apple.keylayout.Spanish", SPANISH_TRADITIONAL_SORT },
+ { "com.apple.keylayout.Spanish-ISO", SPANISH_MODERN_SORT },
+ { "com.apple.keylayout.Swedish", SWEDISH },
+ { "com.apple.keylayout.Swedish-Pro", SWEDISH },
+ { "com.apple.keylayout.SwedishSami-PC", SWEDISH },
+ { "com.apple.keylayout.SwissFrench", FRENCH_SWISS },
+ { "com.apple.keylayout.SwissGerman", GERMAN_SWISS },
+ { "com.apple.keylayout.Telugu", TELUGU },
+ { "com.apple.keylayout.Telugu-QWERTY", TELUGU },
+ { "com.apple.keylayout.Thai", THAI },
+ { "com.apple.keylayout.Thai-PattaChote", THAI },
+ { "com.apple.keylayout.Tibetan-QWERTY", TIBETAN_PRC },
+ { "com.apple.keylayout.Tibetan-Wylie", TIBETAN_PRC },
+ { "com.apple.keylayout.TibetanOtaniUS", TIBETAN_PRC },
+ { "com.apple.keylayout.Turkish", TURKISH },
+ { "com.apple.keylayout.Turkish-QWERTY", TURKISH },
+ { "com.apple.keylayout.Turkish-QWERTY-PC", TURKISH },
+ { "com.apple.keylayout.US", ENGLISH_UNITED_STATES },
+ { "com.apple.keylayout.USExtended", ENGLISH_UNITED_STATES },
+ { "com.apple.keylayout.USInternational-PC", ENGLISH_UNITED_STATES },
+ { "com.apple.keylayout.Ukrainian", UKRAINIAN },
+ { "com.apple.keylayout.Ukrainian-PC", UKRAINIAN },
+ { "com.apple.keylayout.UnicodeHexInput", ENGLISH_UNITED_STATES },
+ { "com.apple.keylayout.Urdu", URDU },
+ { "com.apple.keylayout.Uyghur", UIGHUR },
+ { "com.apple.keylayout.Vietnamese", VIETNAMESE },
+ { "com.apple.keylayout.Welsh", WELSH }
+};
+
+int freerdp_detect_keyboard_layout_from_cf(DWORD* keyboardLayoutId)
+{
+ int i;
+ CFIndex length;
+ char* inputSourceId = NULL;
+ CFStringRef inputSourceIdRef;
+ TISInputSourceRef inputSrc = TISCopyCurrentKeyboardLayoutInputSource();
+ if (!inputSrc)
+ {
+ DEBUG_KBD("Failed to get current keyboard layout input source!");
+ return 0;
+ }
+
+ /* get current input source id */
+ inputSourceIdRef = (CFStringRef)TISGetInputSourceProperty(inputSrc, kTISPropertyInputSourceID);
+ if (!inputSourceIdRef)
+ {
+ DEBUG_KBD("Failed to get input source id!");
+ goto done;
+ }
+
+ /* convert it to a C-string */
+ length = CFStringGetLength(inputSourceIdRef);
+ length = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
+ inputSourceId = (char*)malloc(length);
+ if (!inputSourceId)
+ {
+ DEBUG_KBD("Failed to allocate string buffer!");
+ goto done;
+ }
+
+ if (!CFStringGetCString(inputSourceIdRef, inputSourceId, length, kCFStringEncodingUTF8))
+ {
+ DEBUG_KBD("Failed to convert CFString to C-string!");
+ goto done;
+ }
+
+ /* Search for the id in the mapping table */
+ for (i = 0; i < ARRAYSIZE(KEYBOARD_MAPPING_TABLE); ++i)
+ {
+ if (strcmp(inputSourceId, KEYBOARD_MAPPING_TABLE[i].inputSourceId) == 0)
+ {
+ *keyboardLayoutId = KEYBOARD_MAPPING_TABLE[i].code;
+ break;
+ }
+ }
+
+done:
+ free(inputSourceId);
+ CFRelease(inputSrc);
+ if (*keyboardLayoutId > 0)
+ return *keyboardLayoutId;
+
+ return 0;
+}
diff --git a/libfreerdp/locale/keyboard_apple.h b/libfreerdp/locale/keyboard_apple.h
new file mode 100644
index 000000000..cd3c3e7be
--- /dev/null
+++ b/libfreerdp/locale/keyboard_apple.h
@@ -0,0 +1,28 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Apple Core Foundation Keyboard Mapping
+ *
+ * Copyright 2021 Thincast Technologies GmbH
+ * Copyright 2021 Martin Fleisz <martin.fleisz@thincast.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FREERDP_LOCALE_KEYBOARD_APPLE_H
+#define FREERDP_LOCALE_KEYBOARD_APPLE_H
+
+#include <freerdp/api.h>
+
+FREERDP_LOCAL int freerdp_detect_keyboard_layout_from_cf(DWORD* keyboardLayoutId);
+
+#endif /* FREERDP_LOCALE_KEYBOARD_APPLE_H */
diff --git a/libfreerdp/locale/locale.c b/libfreerdp/locale/locale.c
index 97ae9e469..e7c6d0078 100644
--- a/libfreerdp/locale/locale.c
+++ b/libfreerdp/locale/locale.c
@@ -3,6 +3,8 @@
* Microsoft Locales
*
* Copyright 2009-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2021 Thincast Technologies GmbH
+ * Copyright 2021 Martin Fleisz <martin.fleisz@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,22 +23,32 @@
#include "config.h"
#endif
+#if defined(__APPLE__)
+#include <CoreFoundation/CFString.h>
+#include <CoreFoundation/CFLocale.h>
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
+#include <assert.h>
#include <winpr/environment.h>
#include "liblocale.h"
#include <freerdp/locale/locale.h>
+#define LOCALE_LANGUAGE_LEN 6
+#define LOCALE_COUNTRY_LEN 10
+
struct _SYSTEM_LOCALE
{
- char language[4]; /* Two or three letter language code */
- char country[10]; /* Two or three letter country code (Sometimes with Cyrl_ prefix) */
- DWORD code; /* 32-bit unsigned integer corresponding to the locale */
+ char language[LOCALE_LANGUAGE_LEN]; /* Two or three letter language code */
+ char country[LOCALE_COUNTRY_LEN]; /* Two or three letter country code (Sometimes with Cyrl_
+ prefix) */
+ DWORD code; /* 32-bit unsigned integer corresponding to the locale */
};
typedef struct _SYSTEM_LOCALE SYSTEM_LOCALE;
@@ -642,77 +654,118 @@ static const LOCALE_KEYBOARD_LAYOUTS LOCALE_KEYBOARD_LAYOUTS_TABLE[] = {
{ XHOSA, { 0x00000409, 0x00000409, 0x0, 0x0, 0x0 } },
};
-static BOOL freerdp_get_system_language_and_country_codes(char* language, char* country)
+static BOOL freerdp_get_system_language_and_country_codes(char* language, size_t languageLen,
+ char* country, size_t countryLen)
{
- int dot;
- DWORD nSize;
- int underscore;
- char* env_lang = NULL;
- LPCSTR lang = "LANG";
- /* LANG = <language>_<country>.<encoding> */
- nSize = GetEnvironmentVariableA(lang, NULL, 0);
-
- if (!nSize)
- return FALSE; /* LANG environment variable was not set */
-
- env_lang = (char*)malloc(nSize);
-
- if (!env_lang)
- return FALSE;
+ assert(language);
+ assert(languageLen > 0);
+ assert(country);
+ assert(countryLen);
- if (GetEnvironmentVariableA(lang, env_lang, nSize) !=
- nSize - 1) /* Get locale from environment variable LANG */
+#if defined(__APPLE__)
{
- free(env_lang);
- return FALSE;
- }
+ CFIndex strSize;
+ CFStringRef langRef, countryRef;
+ CFLocaleRef localeRef = CFLocaleCopyCurrent();
+ if (!localeRef)
+ return FALSE;
+
+ langRef = (CFStringRef)CFLocaleGetValue(localeRef, kCFLocaleLanguageCode);
+ countryRef = (CFStringRef)CFLocaleGetValue(localeRef, kCFLocaleCountryCode);
+ if (!langRef || !countryRef)
+ {
+ CFRelease(localeRef);
+ return FALSE;
+ }
- underscore = strcspn(env_lang, "_");
+ if (!CFStringGetCString(langRef, language, languageLen, kCFStringEncodingUTF8) ||
+ !CFStringGetCString(countryRef, country, countryLen, kCFStringEncodingUTF8))
+ {
+ CFRelease(localeRef);
+ return FALSE;
+ }
- if (underscore > 3)
- {
- free(env_lang);
- return FALSE; /* The language name should not be more than 3 letters long */
+ CFRelease(localeRef);
+ return TRUE;
}
- else
+#else
{
- /* Get language code */
- strncpy(language, env_lang, underscore);
- language[underscore] = '\0';
- }
+ int dot;
+ DWORD nSize;
+ int underscore;
+ char* env_lang = NULL;
+ LPCSTR lang = "LANG";
+ /* LANG = <language>_<country>.<encoding> */
+ nSize = GetEnvironmentVariableA(lang, NULL, 0);
- dot = strcspn(env_lang, ".");
+ if (!nSize)
+ return FALSE; /* LANG environment variable was not set */
+
+ env_lang = (char*)malloc(nSize);
+
+ if (!env_lang)
+ return FALSE;
+
+ if (GetEnvironmentVariableA(lang, env_lang, nSize) !=
+ nSize - 1) /* Get locale from environment variable LANG */
+ {
+ free(env_lang);
+ return FALSE;
+ }
+
+ underscore = strcspn(env_lang, "_");
+
+ if (underscore > 3)
+ {
+ free(env_lang);
+ return FALSE; /* The language name should not be more than 3 letters long */
+ }
+ else
+ {
+ /* Get language code */
+ size_t len = MIN(languageLen - 1, underscore);
+ strncpy(language, env_lang, len);
+ language[len] = '\0';
+ }
+
+ dot = strcspn(env_lang, ".");
+
+ /* Get country code */
+ if (dot > underscore)
+ {
+ size_t len = MIN(countryLen - 1, dot - underscore - 1);
+ strncpy(country, &env_lang[underscore + 1], len);
+ country[len] = '\0';
+ }
+ else
+ {
+ free(env_lang);
+ return FALSE; /* Invalid locale */
+ }
- /* Get country code */
- if (dot > underscore)
- {
- strncpy(country, &env_lang[underscore + 1], dot - underscore - 1);
- country[dot - underscore - 1] = '\0';
- }
- else
- {
free(env_lang);
- return FALSE; /* Invalid locale */
+ return TRUE;
}
-
- free(env_lang);
- return TRUE;
+#endif
}
-static SYSTEM_LOCALE* freerdp_detect_system_locale(void)
+static const SYSTEM_LOCALE* freerdp_detect_system_locale(void)
{
size_t i;
- char language[4];
- char country[10];
- SYSTEM_LOCALE* locale = NULL;
- freerdp_get_system_language_and_country_codes(language, country);
+ char language[LOCALE_LANGUAGE_LEN] = { 0 };
+ char country[LOCALE_COUNTRY_LEN] = { 0 };
+ const SYSTEM_LOCALE* locale = NULL;
+
+ freerdp_get_system_language_and_country_codes(language, ARRAYSIZE(language), country,
+ ARRAYSIZE(country));
for (i = 0; i < ARRAYSIZE(SYSTEM_LOCALE_TABLE); i++)
{
- if ((strcmp(language, SYSTEM_LOCALE_TABLE[i].language) == 0) &&
- (strcmp(country, SYSTEM_LOCALE_TABLE[i].country) == 0))
+ const SYSTEM_LOCALE* current = &SYSTEM_LOCALE_TABLE[i];
+
+ if ((strcmp(language, current->language) == 0) && (strcmp(country, current->country) == 0))
{
- locale = (SYSTEM_LOCALE*)&SYSTEM_LOCALE_TABLE[i];
+ locale = current;
break;
}
}
@@ -722,7 +775,7 @@ static SYSTEM_LOCALE* freerdp_detect_system_locale(void)
DWORD freerdp_get_system_locale_id(void)
{
- SYSTEM_LOCALE* locale;
+ const SYSTEM_LOCALE* locale;
locale = freerdp_detect_system_locale();
if (locale != NULL)
@@ -737,8 +790,10 @@ const char* freerdp_get_system_locale_name_from_id(DWORD localeId)
for (index = 0; index < ARRAYSIZE(LOCALE_NAME_TABLE); index++)
{
- if (localeId == LOCALE_NAME_TABLE[index].localeId)
- return LOCALE_NAME_TABLE[index].name;
+ const LOCALE_NAME* const current = &LOCALE_NAME_TABLE[index];
+
+ if (localeId == current->localeId)
+ return current->name;
}
return NULL;
@@ -747,10 +802,12 @@ const char* freerdp_get_system_locale_name_from_id(DWORD localeId)
int freerdp_detect_keyboard_layout_from_system_locale(DWORD* keyboardLayoutId)
{
size_t i, j;
- char language[4];
- char country[10];
- SYSTEM_LOCALE* locale;
- freerdp_get_system_language_and_country_codes(language, country);
+ char language[LOCALE_LANGUAGE_LEN] = { 0 };
+ char country[LOCALE_COUNTRY_LEN] = { 0 };
+ const SYSTEM_LOCALE* locale;
+
+ freerdp_get_system_language_and_country_codes(language, ARRAYSIZE(language), country,
+ ARRAYSIZE(country));
if ((strcmp(language, "C") == 0) || (strcmp(language, "POSIX") == 0))
{
@@ -767,22 +824,24 @@ int freerdp_detect_keyboard_layout_from_system_locale(DWORD* keyboardLayoutId)
for (i = 0; i < ARRAYSIZE(LOCALE_KEYBOARD_LAYOUTS_TABLE); i++)
{
- if (LOCALE_KEYBOARD_LAYOUTS_TABLE[i].locale == locale->code)
+ const LOCALE_KEYBOARD_LAYOUTS* const current = &LOCALE_KEYBOARD_LAYOUTS_TABLE[i];
+
+ if (current->locale == locale->code)
{
/* Locale found in list of default keyboard layouts */
for (j = 0; j < 5; j++)
{
- if (LOCALE_KEYBOARD_LAYOUTS_TABLE[i].keyboardLayouts[j] == ENGLISH_UNITED_STATES)
+ if (current->keyboardLayouts[j] == ENGLISH_UNITED_STATES)
{
continue; /* Skip, try to get a more localized keyboard layout */
}
- else if (LOCALE_KEYBOARD_LAYOUTS_TABLE[i].keyboardLayouts[j] == 0)
+ else if (current->keyboardLayouts[j] == 0)
{
break; /* No more keyboard layouts */
}
else
{
- *keyboardLayoutId = LOCALE_KEYBOARD_LAYOUTS_TABLE[i].keyboardLayouts[j];
+ *keyboardLayoutId = current->keyboardLayouts[j];
return 0;
}
}
diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt
index 036b50f83..620f9a78b 100644
--- a/winpr/CMakeLists.txt
+++ b/winpr/CMakeLists.txt
@@ -51,7 +51,7 @@ if (NOT WIN32)
endif()
# Soname versioning
-set(RAW_VERSION_STRING "2.4.1")
+set(RAW_VERSION_STRING "2.5.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 --git a/winpr/libwinpr/registry/registry.c b/winpr/libwinpr/registry/registry.c
index 726233e3d..e0c148b5a 100644
--- a/winpr/libwinpr/registry/registry.c
+++ b/winpr/libwinpr/registry/registry.c
@@ -34,18 +34,18 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
#include <winpr/crt.h>
+#include <assert.h>
#include "registry_reg.h"
static Reg* instance = NULL;
-static Reg* RegGetInstance()
+static Reg* RegGetInstance(void)
{
if (!instance)
- {
instance = reg_open(1);
- }
return instance;
}
@@ -213,18 +213,23 @@ LONG RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesir
LONG RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
{
- Reg* reg;
RegKey* pKey;
- reg = RegGetInstance();
+ Reg* reg = RegGetInstance();
if (!reg)
return -1;
+ if (hKey != HKEY_LOCAL_MACHINE)
+ return ERROR_FILE_NOT_FOUND;
+
+ assert(reg->root_key);
pKey = reg->root_key->subkeys;
while (pKey != NULL)
{
- if (_stricmp(pKey->subname, lpSubKey) == 0)
+ assert(lpSubKey);
+
+ if (pKey->subname && (_stricmp(pKey->subname, lpSubKey) == 0))
{
*phkResult = (HKEY)pKey;
return ERROR_SUCCESS;
@@ -271,24 +276,48 @@ LONG RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD
RegKey* key;
RegVal* pValue;
+ WINPR_UNUSED(lpReserved);
+
key = (RegKey*)hKey;
+ assert(key);
+
pValue = key->values;
while (pValue != NULL)
{
if (strcmp(pValue->name, lpValueName) == 0)
{
+ if (lpType)
+ *lpType = pValue->type;
+
if (pValue->type == REG_DWORD)
{
DWORD* pData = (DWORD*)lpData;
- if (pData != NULL)
+ if (lpcbData)
{
- *pData = pValue->data.dword;
+ DWORD size = *lpcbData;
+ *lpcbData = sizeof(DWORD);
+ if (pData)
+ {
+ if (size < *lpcbData)
+ return ERROR_MORE_DATA;
+ }
}
- *lpcbData = sizeof(DWORD);
+ if (pData != NULL)
+ {
+ DWORD size;
+ assert(lpcbData);
+ size = *lpcbData;
+ *lpcbData = sizeof(DWORD);
+ if (size < sizeof(DWORD))
+ return ERROR_MORE_DATA;
+ *pData = pValue->data.dword;
+ }
+ else if (lpcbData != NULL)
+ *lpcbData = sizeof(DWORD);
return ERROR_SUCCESS;
}
else if (pValue->type == REG_SZ)
@@ -300,11 +329,18 @@ LONG RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD
if (pData != NULL)
{
+ DWORD size;
+ assert(lpcbData);
+
+ size = *lpcbData;
+ *lpcbData = length;
+ if (size < length)
+ return ERROR_MORE_DATA;
memcpy(pData, pValue->data.string, length);
pData[length] = '\0';
}
-
- *lpcbData = (UINT32)length;
+ else if (lpcbData)
+ *lpcbData = (UINT32)length;
return ERROR_SUCCESS;
}
diff --git a/winpr/libwinpr/registry/registry_reg.c b/winpr/libwinpr/registry/registry_reg.c
index 353e490c1..511d92790 100644
--- a/winpr/libwinpr/registry/registry_reg.c
+++ b/winpr/libwinpr/registry/registry_reg.c
@@ -27,6 +27,7 @@
#include <string.h>
#include <winpr/wtypes.h>
+#include <assert.h>
#include <winpr/crt.h>
#include <winpr/file.h>
@@ -35,12 +36,14 @@
#include "../log.h"
#define TAG WINPR_TAG("registry")
+#define WINPR_ASSERT assert
+
#define WINPR_HKLM_HIVE "/etc/winpr/HKLM.reg"
struct reg_data_type
{
char* tag;
- int length;
+ size_t length;
DWORD type;
};
@@ -52,50 +55,71 @@ static struct reg_data_type REG_DATA_TYPE_TABLE[] = { { "\"", 1, REG_SZ },
{ "hex:", 4, REG_BINARY },
{ "hex(2):\"", 8, REG_EXPAND_SZ },
{ "hex(7):\"", 8, REG_MULTI_SZ },
- { "hex(b):\"", 8, REG_QWORD },
- { NULL, 0, 0 } };
-
-static char* REG_DATA_TYPE_STRINGS[] = { "REG_NONE",
- "REG_SZ",
- "REG_EXPAND_SZ",
- "REG_BINARY",
- "REG_DWORD",
- "REG_DWORD_BIG_ENDIAN",
- "REG_LINK",
- "REG_MULTI_SZ",
- "REG_RESOURCE_LIST",
- "REG_FULL_RESOURCE_DESCRIPTOR",
- "REG_RESOURCE_REQUIREMENTS_LIST",
- "REG_QWORD" };
-
-static void reg_load_start(Reg* reg)
+ { "hex(b):\"", 8, REG_QWORD } };
+
+static char* reg_data_type_string(DWORD type)
{
+ switch (type)
+ {
+ case REG_NONE:
+ return "REG_NONE";
+ case REG_SZ:
+ return "REG_SZ";
+ case REG_EXPAND_SZ:
+ return "REG_EXPAND_SZ";
+ case REG_BINARY:
+ return "REG_BINARY";
+ case REG_DWORD:
+ return "REG_DWORD";
+ case REG_DWORD_BIG_ENDIAN:
+ return "REG_DWORD_BIG_ENDIAN";
+ case REG_LINK:
+ return "REG_LINK";
+ case REG_MULTI_SZ:
+ return "REG_MULTI_SZ";
+ case REG_RESOURCE_LIST:
+ return "REG_RESOURCE_LIST";
+ case REG_FULL_RESOURCE_DESCRIPTOR:
+ return "REG_FULL_RESOURCE_DESCRIPTOR";
+ case REG_RESOURCE_REQUIREMENTS_LIST:
+ return "REG_RESOURCE_REQUIREMENTS_LIST";
+ case REG_QWORD:
+ return "REG_QWORD";
+ default:
+ return "REG_UNKNOWN";
+ }
+}
+
+static BOOL reg_load_start(Reg* reg)
+{
+ char* buffer;
INT64 file_size;
+
+ WINPR_ASSERT(reg);
+ WINPR_ASSERT(reg->fp);
+
_fseeki64(reg->fp, 0, SEEK_END);
file_size = _ftelli64(reg->fp);
_fseeki64(reg->fp, 0, SEEK_SET);
reg->line = NULL;
reg->next_line = NULL;
- reg->buffer = NULL;
if (file_size < 1)
- return;
+ return FALSE;
- reg->buffer = (char*)malloc(file_size + 2);
+ buffer = (char*)realloc(reg->buffer, (size_t)file_size + 2);
- if (!reg->buffer)
- return;
+ if (!buffer)
+ return FALSE;
+ reg->buffer = buffer;
- if (fread(reg->buffer, file_size, 1, reg->fp) != 1)
- {
- free(reg->buffer);
- reg->buffer = NULL;
- return;
- }
+ if (fread(reg->buffer, (size_t)file_size, 1, reg->fp) != 1)
+ return FALSE;
reg->buffer[file_size] = '\n';
reg->buffer[file_size + 1] = '\0';
reg->next_line = strtok(reg->buffer, "\n");
+ return TRUE;
}
static void reg_load_finish(Reg* reg)
@@ -112,15 +136,23 @@ static void reg_load_finish(Reg* reg)
static RegVal* reg_load_value(Reg* reg, RegKey* key)
{
- int index;
- char* p[5];
- int length;
- char* name;
+ size_t index;
+ char* p[5] = { 0 };
+ size_t length;
+ char* name = NULL;
char* type;
char* data;
- RegVal* value;
+ RegVal* value = NULL;
+
+ WINPR_ASSERT(reg);
+ WINPR_ASSERT(key);
+ WINPR_ASSERT(reg->line);
+
p[0] = reg->line + 1;
p[1] = strstr(p[0], "\"=");
+ if (!p[1])
+ return NULL;
+
p[2] = p[1] + 2;
type = p[2];
@@ -129,67 +161,85 @@ static RegVal* reg_load_value(Reg* reg, RegKey* key)
else
p[3] = strchr(p[2], ':');
+ if (!p[3])
+ return NULL;
+
data = p[3] + 1;
- length = p[1] - p[0];
- name = (char*)malloc(length + 1);
+ length = (size_t)(p[1] - p[0]);
+ if (length < 1)
+ goto fail;
+
+ name = (char*)calloc(length + 1, sizeof(char));
if (!name)
- return NULL;
+ goto fail;
memcpy(name, p[0], length);
- name[length] = '\0';
- value = (RegVal*)malloc(sizeof(RegVal));
+ value = (RegVal*)calloc(1, sizeof(RegVal));
if (!value)
- {
- free(name);
- return NULL;
- }
+ goto fail;
value->name = name;
value->type = REG_NONE;
- value->next = value->prev = NULL;
- for (index = 0; REG_DATA_TYPE_TABLE[index].length > 0; index++)
+ for (index = 0; index < ARRAYSIZE(REG_DATA_TYPE_TABLE); index++)
{
- if (strncmp(type, REG_DATA_TYPE_TABLE[index].tag, REG_DATA_TYPE_TABLE[index].length) == 0)
+ const struct reg_data_type* current = &REG_DATA_TYPE_TABLE[index];
+ WINPR_ASSERT(current->tag);
+ WINPR_ASSERT(current->length > 0);
+ WINPR_ASSERT(current->type != REG_NONE);
+
+ if (strncmp(type, current->tag, current->length) == 0)
{
- value->type = REG_DATA_TYPE_TABLE[index].type;
+ value->type = current->type;
break;
}
}
- if (value->type == REG_DWORD)
+ switch (value->type)
{
- unsigned long val;
- errno = 0;
- val = strtoul(data, NULL, 16);
-
- if ((errno != 0) || (val > UINT32_MAX))
+ case REG_DWORD:
{
- free(value);
- free(name);
- return NULL;
- }
+ unsigned long val;
+ errno = 0;
+ val = strtoul(data, NULL, 16);
- value->data.dword = val;
- }
- else if (value->type == REG_SZ)
- {
- p[4] = strchr(data, '"');
- p[4][0] = '\0';
- value->data.string = _strdup(data);
+ if ((errno != 0) || (val > UINT32_MAX))
+ goto fail;
- if (!value->data.string)
+ value->data.dword = (DWORD)val;
+ }
+ break;
+ case REG_SZ:
{
- free(value);
- free(name);
- return NULL;
+ size_t len, cmp;
+ char* end;
+ char* start = strchr(data, '"');
+ if (!start)
+ goto fail;
+
+ /* Check for terminating quote, check it is the last symbol */
+ len = strlen(start);
+ end = strchr(start + 1, '"');
+ if (!end)
+ goto fail;
+ cmp = end - start + 1;
+ if (len != cmp)
+ goto fail;
+ if (start[0] == '"')
+ start++;
+ if (end[0] == '"')
+ end[0] = '\0';
+ value->data.string = _strdup(start);
+
+ if (!value->data.string)
+ goto fail;
}
- }
- else
- {
- WLog_ERR(TAG, "unimplemented format: %s", REG_DATA_TYPE_STRINGS[value->type]);
+ break;
+ default:
+ WLog_ERR(TAG, "unimplemented format: %s", reg_data_type_string(value->type));
+ break;
}
if (!key->values)
@@ -210,6 +260,11 @@ static RegVal* reg_load_value(Reg* reg, RegKey* key)
}
return value;
+
+fail:
+ free(value);
+ free(name);
+ return NULL;
}
static BOOL reg_load_has_next_line(Reg* reg)
@@ -233,15 +288,21 @@ static char* reg_load_get_next_line(Reg* reg)
static char* reg_load_peek_next_line(Reg* reg)
{
+ WINPR_ASSERT(reg);
return reg->next_line;
}
static void reg_insert_key(Reg* reg, RegKey* key, RegKey* subkey)
{
- char* name;
- char* path;
- char* save;
- int length;
+ char* name = NULL;
+ char* path = NULL;
+ char* save = NULL;
+
+ WINPR_ASSERT(reg);
+ WINPR_ASSERT(key);
+ WINPR_ASSERT(subkey);
+ WINPR_ASSERT(subkey->name);
+
path = _strdup(subkey->name);
if (!path)
@@ -253,9 +314,8 @@ static void reg_insert_key(Reg* reg, RegKey* key, RegKey* subkey)
{
if (strcmp(key->name, name) == 0)
{
- length = strlen(name);
- name += length + 1;
- subkey->subname = _strdup(name);
+ if (save)
+ subkey->subname = _strdup(save);
/* TODO: free allocated memory in error case */
if (!subkey->subname)
@@ -274,19 +334,24 @@ static void reg_insert_key(Reg* reg, RegKey* key, RegKey* subkey)
static RegKey* reg_load_key(Reg* reg, RegKey* key)
{
char* p[2];
- int length;
- char* line;
+ size_t length;
RegKey* subkey;
+
+ WINPR_ASSERT(reg);
+ WINPR_ASSERT(key);
+
+ WINPR_ASSERT(reg->line);
p[0] = reg->line + 1;
p[1] = strrchr(p[0], ']');
- subkey = (RegKey*)malloc(sizeof(RegKey));
+ if (!p[1])
+ return NULL;
+
+ subkey = (RegKey*)calloc(1, sizeof(RegKey));
if (!subkey)
return NULL;
- subkey->values = NULL;
- subkey->prev = subkey->next = NULL;
- length = p[1] - p[0];
+ length = (size_t)(p[1] - p[0]);
subkey->name = (char*)malloc(length + 1);
if (!subkey->name)
@@ -300,7 +365,7 @@ static RegKey* reg_load_key(Reg* reg, RegKey* key)
while (reg_load_has_next_line(reg))
{
- line = reg_load_peek_next_line(reg);
+ char* line = reg_load_peek_next_line(reg);
if (line[0] == '[')
break;
@@ -354,16 +419,16 @@ static void reg_load(Reg* reg)
static void reg_unload_value(Reg* reg, RegVal* value)
{
- if (value->type == REG_DWORD)
- {
- }
- else if (value->type == REG_SZ)
- {
- free(value->data.string);
- }
- else
+ WINPR_ASSERT(reg);
+ WINPR_ASSERT(value);
+
+ switch (value->type)
{
- WLog_ERR(TAG, "unimplemented format: %s", REG_DATA_TYPE_STRINGS[value->type]);
+ case REG_SZ:
+ free(value->data.string);
+ break;
+ default:
+ break;
}
free(value);
@@ -372,12 +437,15 @@ static void reg_unload_value(Reg* reg, RegVal* value)
static void reg_unload_key(Reg* reg, RegKey* key)
{
RegVal* pValue;
- RegVal* pValueNext;
+
+ WINPR_ASSERT(reg);
+ WINPR_ASSERT(key);
+
pValue = key->values;
while (pValue != NULL)
{
- pValueNext = pValue->next;
+ RegVal* pValueNext = pValue->next;
reg_unload_value(reg, pValue);
pValue = pValueNext;
}
@@ -389,23 +457,26 @@ static void reg_unload_key(Reg* reg, RegKey* key)
static void reg_unload(Reg* reg)
{
RegKey* pKey;
- RegKey* pKeyNext;
- pKey = reg->root_key->subkeys;
- while (pKey != NULL)
+ WINPR_ASSERT(reg);
+ if (reg->root_key)
{
- pKeyNext = pKey->next;
- reg_unload_key(reg, pKey);
- pKey = pKeyNext;
- }
+ pKey = reg->root_key->subkeys;
+
+ while (pKey != NULL)
+ {
+ RegKey* pKeyNext = pKey->next;
+ reg_unload_key(reg, pKey);
+ pKey = pKeyNext;
+ }
- free(reg->root_key);
+ free(reg->root_key);
+ }
}
Reg* reg_open(BOOL read_only)
{
- Reg* reg;
- reg = (Reg*)malloc(sizeof(Reg));
+ Reg* reg = (Reg*)calloc(1, sizeof(Reg));
if (!reg)
return NULL;
@@ -414,9 +485,7 @@ Reg* reg_open(BOOL read_only)
reg->filename = WINPR_HKLM_HIVE;
if (reg->read_only)
- {
reg->fp = winpr_fopen(reg->filename, "r");
- }
else
{
reg->fp = winpr_fopen(reg->filename, "r+");
@@ -426,25 +495,22 @@ Reg* reg_open(BOOL read_only)
}
if (!reg->fp)
- {
- free(reg);
- return NULL;
- }
+ goto fail;
- reg->root_key = (RegKey*)malloc(sizeof(RegKey));
+ reg->root_key = (RegKey*)calloc(1, sizeof(RegKey));
if (!reg->root_key)
- {
- fclose(reg->fp);
- free(reg);
- return NULL;
- }
+ goto fail;
reg->root_key->values = NULL;
reg->root_key->subkeys = NULL;
reg->root_key->name = "HKEY_LOCAL_MACHINE";
reg_load(reg);
return reg;
+
+fail:
+ reg_close(reg);
+ return NULL;
}
void reg_close(Reg* reg)
@@ -452,7 +518,8 @@ void reg_close(Reg* reg)
if (reg)
{
reg_unload(reg);
- fclose(reg->fp);
+ if (reg->fp)
+ fclose(reg->fp);
free(reg);
}
}
diff --git a/winpr/libwinpr/registry/registry_reg.h b/winpr/libwinpr/registry/registry_reg.h
index 90db136b4..ab3b34f3b 100644
--- a/winpr/libwinpr/registry/registry_reg.h
+++ b/winpr/libwinpr/registry/registry_reg.h
@@ -30,7 +30,7 @@ struct _reg
FILE* fp;
char* line;
char* next_line;
- int line_length;
+ size_t line_length;
char* buffer;
char* filename;
BOOL read_only;
@@ -44,7 +44,8 @@ struct _reg_val
RegVal* prev;
RegVal* next;
- union reg_data {
+ union reg_data
+ {
DWORD dword;
char* string;
} data;