From 3f6bd603e9f5629cc341b505fb70dbe31cc5dc8d Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 10 Nov 2016 10:18:55 +0100 Subject: [PATCH] Fixed addin loader, prefer system library paths. --- CMakeLists.txt | 24 ++-- include/freerdp/build-config.h.in | 2 +- libfreerdp/common/addin.c | 179 +++++++++++++++++++----------- 3 files changed, 128 insertions(+), 77 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 66be20c61..68b9436c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -766,15 +766,21 @@ if (TARGET_ARCH MATCHES "sparc") set(HAVE_ALIGNED_REQUIRED 1) endif() -# Path to put FreeRDP data -set(FREERDP_DATA_PATH "${CMAKE_INSTALL_PREFIX}/share/freerdp${FREERDP_VERSION_MAJOR}") - -# Path to put plugins - -set(FREERDP_LIBRARY_PATH "${CMAKE_INSTALL_LIBDIR}") - -set(FREERDP_PLUGIN_PATH "${CMAKE_INSTALL_LIBDIR}/freerdp${FREERDP_VERSION_MAJOR}") -set(FREERDP_ADDIN_PATH "${FREERDP_PLUGIN_PATH}") +# Android expects all libraries to be loadable +# without paths. +if (ANDROID) + set(FREERDP_DATA_PATH "share") + set(FREERDP_INSTALL_PREFIX ".") + set(FREERDP_LIBRARY_PATH ".") + set(FREERDP_PLUGIN_PATH ".") + set(FREERDP_ADDIN_PATH ".") +else (ANDROID) + set(FREERDP_DATA_PATH "${CMAKE_INSTALL_PREFIX}/share/freerdp${FREERDP_VERSION_MAJOR}") + set(FREERDP_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + set(FREERDP_LIBRARY_PATH "${CMAKE_INSTALL_LIBDIR}") + set(FREERDP_PLUGIN_PATH "${CMAKE_INSTALL_LIBDIR}/freerdp${FREERDP_VERSION_MAJOR}") + set(FREERDP_ADDIN_PATH "${FREERDP_PLUGIN_PATH}") +endif(ANDROID) # Path to put extensions set(FREERDP_EXTENSION_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/freerdp${FREERDP_VERSION_MAJOR}/extensions") diff --git a/include/freerdp/build-config.h.in b/include/freerdp/build-config.h.in index 788e27f2f..261b8ded6 100644 --- a/include/freerdp/build-config.h.in +++ b/include/freerdp/build-config.h.in @@ -5,7 +5,7 @@ #define FREERDP_KEYMAP_PATH "${FREERDP_KEYMAP_PATH}" #define FREERDP_PLUGIN_PATH "${FREERDP_PLUGIN_PATH}" -#define FREERDP_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" +#define FREERDP_INSTALL_PREFIX "${FREERDP_INSTALL_PREFIX}" #define FREERDP_LIBRARY_PATH "${FREERDP_LIBRARY_PATH}" diff --git a/libfreerdp/common/addin.c b/libfreerdp/common/addin.c index 555c100ac..006339092 100644 --- a/libfreerdp/common/addin.c +++ b/libfreerdp/common/addin.c @@ -35,29 +35,52 @@ #include #define TAG FREERDP_TAG("addin") +static INLINE BOOL is_path_required(LPCSTR path, size_t len) +{ + if (!path || (len <= 1)) + return FALSE; + if (strcmp(path, ".") == 0) + return FALSE; + return TRUE; +} + LPSTR freerdp_get_library_install_path(void) { LPSTR pszPath; size_t cchPath; size_t cchLibraryPath; size_t cchInstallPrefix; + BOOL needLibPath, needInstallPath; LPCSTR pszLibraryPath = FREERDP_LIBRARY_PATH; LPCSTR pszInstallPrefix = FREERDP_INSTALL_PREFIX; - cchLibraryPath = strlen(pszLibraryPath); - cchInstallPrefix = strlen(pszInstallPrefix); - cchPath = cchInstallPrefix + cchLibraryPath + 2; + cchLibraryPath = strlen(pszLibraryPath) + 1; + cchInstallPrefix = strlen(pszInstallPrefix) + 1; + cchPath = cchInstallPrefix + cchLibraryPath; + + needInstallPath = is_path_required(pszInstallPrefix, cchInstallPrefix); + needLibPath = is_path_required(pszLibraryPath, cchLibraryPath); + + if (!needInstallPath && !needLibPath) + return NULL; + pszPath = (LPSTR) malloc(cchPath + 1); if (!pszPath) return NULL; - CopyMemory(pszPath, pszInstallPrefix, cchInstallPrefix); - pszPath[cchInstallPrefix] = '\0'; - - if (FAILED(NativePathCchAppendA(pszPath, cchPath + 1, pszLibraryPath))) + if (needInstallPath) { - free(pszPath); - return NULL; + CopyMemory(pszPath, pszInstallPrefix, cchInstallPrefix); + pszPath[cchInstallPrefix] = '\0'; + } + + if (needLibPath) + { + if (FAILED(NativePathCchAppendA(pszPath, cchPath + 1, pszLibraryPath))) + { + free(pszPath); + return NULL; + } } return pszPath; @@ -69,23 +92,37 @@ LPSTR freerdp_get_dynamic_addin_install_path(void) size_t cchPath; size_t cchAddinPath; size_t cchInstallPrefix; + BOOL needLibPath, needInstallPath; LPCSTR pszAddinPath = FREERDP_ADDIN_PATH; LPCSTR pszInstallPrefix = FREERDP_INSTALL_PREFIX; - cchAddinPath = strlen(pszAddinPath); - cchInstallPrefix = strlen(pszInstallPrefix); - cchPath = cchInstallPrefix + cchAddinPath + 2; - pszPath = (LPSTR) malloc(cchPath + 1); + cchAddinPath = strlen(pszAddinPath) + 1; + cchInstallPrefix = strlen(pszInstallPrefix) + 1; + cchPath = cchInstallPrefix + cchAddinPath; + + needInstallPath = is_path_required(pszInstallPrefix, cchInstallPrefix); + needLibPath = is_path_required(pszAddinPath, cchAddinPath); + + if (!needInstallPath && !needLibPath) + return NULL; + + pszPath = (LPSTR) calloc(cchPath + 1, sizeof(CHAR)); if (!pszPath) return NULL; - CopyMemory(pszPath, pszInstallPrefix, cchInstallPrefix); - pszPath[cchInstallPrefix] = '\0'; - - if (FAILED(NativePathCchAppendA(pszPath, cchPath + 1, pszAddinPath))) + if (needInstallPath) { - free(pszPath); - return NULL; + CopyMemory(pszPath, pszInstallPrefix, cchInstallPrefix); + pszPath[cchInstallPrefix] = '\0'; + } + + if (needLibPath) + { + if (FAILED(NativePathCchAppendA(pszPath, cchPath + 1, pszAddinPath))) + { + free(pszPath); + return NULL; + } } return pszPath; @@ -94,23 +131,26 @@ LPSTR freerdp_get_dynamic_addin_install_path(void) PVIRTUALCHANNELENTRY freerdp_load_dynamic_addin(LPCSTR pszFileName, LPCSTR pszPath, LPCSTR pszEntryName) { - PVIRTUALCHANNELENTRY entry; - BOOL bHasExt; + LPSTR pszAddinInstallPath = freerdp_get_dynamic_addin_install_path(); + PVIRTUALCHANNELENTRY entry = NULL; + BOOL bHasExt = TRUE; PCSTR pszExt; - size_t cchExt; - HINSTANCE library; + size_t cchExt = 0; + HINSTANCE library = NULL; size_t cchFileName; - LPSTR pszFilePath; size_t cchFilePath; LPSTR pszAddinFile; + LPSTR pszFilePath = NULL; + LPSTR pszRelativeFilePath = NULL; size_t cchAddinFile; - LPSTR pszAddinInstallPath; size_t cchAddinInstallPath; - entry = NULL; - cchExt = 0; - bHasExt = TRUE; + + if (!pszFileName || !pszEntryName) + goto fail; + cchFileName = strlen(pszFileName); + /* Get file name with prefix and extension */ if (FAILED(PathCchFindExtensionA(pszFileName, cchFileName + 1, &pszExt))) { pszExt = PathGetSharedLibraryExtensionA(PATH_SHARED_LIB_EXT_WITH_DOT); @@ -118,33 +158,12 @@ PVIRTUALCHANNELENTRY freerdp_load_dynamic_addin(LPCSTR pszFileName, bHasExt = FALSE; } - pszAddinInstallPath = freerdp_get_dynamic_addin_install_path(); - - if (!pszAddinInstallPath) - return NULL; - - cchAddinInstallPath = strlen(pszAddinInstallPath); - cchFilePath = cchAddinInstallPath + cchFileName + 32; - pszFilePath = (LPSTR) malloc(cchFilePath + 1); - - if (!pszFilePath) - { - free(pszAddinInstallPath); - return NULL; - } - if (bHasExt) { pszAddinFile = _strdup(pszFileName); if (!pszAddinFile) - { - free(pszAddinInstallPath); - free(pszFilePath); - return NULL; - } - - cchAddinFile = strlen(pszAddinFile); + goto fail; } else { @@ -152,34 +171,60 @@ PVIRTUALCHANNELENTRY freerdp_load_dynamic_addin(LPCSTR pszFileName, pszAddinFile = (LPSTR) malloc(cchAddinFile + 1); if (!pszAddinFile) - { - free(pszAddinInstallPath); - free(pszFilePath); - return NULL; - } + goto fail; sprintf_s(pszAddinFile, cchAddinFile, FREERDP_SHARED_LIBRARY_PREFIX"%s%s", pszFileName, pszExt); - cchAddinFile = strlen(pszAddinFile); } + cchAddinFile = strlen(pszAddinFile); + + /* If a path is provided prefix the library name with it. */ + if (pszPath) + { + size_t relPathLen = strlen(pszPath) + cchAddinFile + 1; + pszRelativeFilePath = calloc(relPathLen, sizeof(CHAR)); + if (!pszRelativeFilePath) + goto fail; + sprintf_s(pszRelativeFilePath, relPathLen, "%s", pszRelativeFilePath); + NativePathCchAppendA(pszRelativeFilePath, relPathLen, pszAddinFile); + } + else + pszRelativeFilePath = _strdup(pszAddinFile); + + if (!pszRelativeFilePath) + goto fail; + + /* If a system prefix path is provided try these locations too. */ + if (pszAddinInstallPath) + { + cchAddinInstallPath = strlen(pszAddinInstallPath); + cchFilePath = cchAddinInstallPath + cchFileName + 32; + pszFilePath = (LPSTR) malloc(cchFilePath + 1); + + if (!pszFilePath) + goto fail; + + CopyMemory(pszFilePath, pszAddinInstallPath, cchAddinInstallPath); + pszFilePath[cchAddinInstallPath] = '\0'; + NativePathCchAppendA((LPSTR) pszFilePath, cchFilePath + 1, pszRelativeFilePath); + } + else + pszFilePath = _strdup(pszRelativeFilePath); - CopyMemory(pszFilePath, pszAddinInstallPath, cchAddinInstallPath); - pszFilePath[cchAddinInstallPath] = '\0'; - NativePathCchAppendA((LPSTR) pszFilePath, cchFilePath + 1, pszAddinFile); library = LoadLibraryA(pszFilePath); - free(pszAddinInstallPath); - free(pszAddinFile); - free(pszFilePath); if (!library) - return NULL; + goto fail; entry = (PVIRTUALCHANNELENTRY)GetProcAddress(library, pszEntryName); - if (entry) - return entry; - - FreeLibrary(library); +fail: + free(pszRelativeFilePath); + free(pszAddinFile); + free(pszFilePath); + free(pszAddinInstallPath); + if (!entry && library) + FreeLibrary(library); return entry; }