20#include <freerdp/config.h> 
   27#include <winpr/path.h> 
   28#include <winpr/string.h> 
   29#include <winpr/library.h> 
   31#include <freerdp/addin.h> 
   32#include <freerdp/build-config.h> 
   34#include <freerdp/log.h> 
   35#define TAG FREERDP_TAG("addin") 
   37static inline BOOL is_path_required(LPCSTR path, 
size_t len)
 
   39  if (!path || (len <= 1))
 
   42  if (strcmp(path, 
".") == 0)
 
   48LPSTR freerdp_get_library_install_path(
void)
 
   52  size_t cchLibraryPath = 0;
 
   53  size_t cchInstallPrefix = 0;
 
   55  BOOL needInstallPath = 0;
 
   56  LPCSTR pszLibraryPath = FREERDP_LIBRARY_PATH;
 
   57  LPCSTR pszInstallPrefix = FREERDP_INSTALL_PREFIX;
 
   58  cchLibraryPath = strlen(pszLibraryPath) + 1;
 
   59  cchInstallPrefix = strlen(pszInstallPrefix) + 1;
 
   60  cchPath = cchInstallPrefix + cchLibraryPath;
 
   61  needInstallPath = is_path_required(pszInstallPrefix, cchInstallPrefix);
 
   62  needLibPath = is_path_required(pszLibraryPath, cchLibraryPath);
 
   64  if (!needInstallPath && !needLibPath)
 
   67  pszPath = (LPSTR)malloc(cchPath + 1);
 
   74    CopyMemory(pszPath, pszInstallPrefix, cchInstallPrefix);
 
   75    pszPath[cchInstallPrefix] = 
'\0';
 
   80    if (FAILED(NativePathCchAppendA(pszPath, cchPath + 1, pszLibraryPath)))
 
   90LPSTR freerdp_get_dynamic_addin_install_path(
void)
 
   92#if defined(WITH_ADD_PLUGIN_TO_RPATH) 
   97  size_t cchAddinPath = 0;
 
   98  size_t cchInstallPrefix = 0;
 
  100  BOOL needInstallPath = 0;
 
  101  LPCSTR pszAddinPath = FREERDP_ADDIN_PATH;
 
  102  LPCSTR pszInstallPrefix = FREERDP_INSTALL_PREFIX;
 
  103  cchAddinPath = strlen(pszAddinPath) + 1;
 
  104  cchInstallPrefix = strlen(pszInstallPrefix) + 1;
 
  105  cchPath = cchInstallPrefix + cchAddinPath;
 
  106  needInstallPath = is_path_required(pszInstallPrefix, cchInstallPrefix);
 
  107  needLibPath = is_path_required(pszAddinPath, cchAddinPath);
 
  110           "freerdp_get_dynamic_addin_install_path <- pszInstallPrefix: %s, pszAddinPath: %s",
 
  111           pszInstallPrefix, pszAddinPath);
 
  113  if (!needInstallPath && !needLibPath)
 
  116  pszPath = (LPSTR)calloc(cchPath + 1, 
sizeof(CHAR));
 
  123    CopyMemory(pszPath, pszInstallPrefix, cchInstallPrefix);
 
  124    pszPath[cchInstallPrefix] = 
'\0';
 
  129    if (FAILED(NativePathCchAppendA(pszPath, cchPath + 1, pszAddinPath)))
 
  136  WLog_DBG(TAG, 
"freerdp_get_dynamic_addin_install_path -> pszPath: %s", pszPath);
 
  142PVIRTUALCHANNELENTRY freerdp_load_dynamic_addin(LPCSTR pszFileName, LPCSTR pszPath,
 
  145  LPSTR pszAddinInstallPath = freerdp_get_dynamic_addin_install_path();
 
  146  PVIRTUALCHANNELENTRY entry = NULL;
 
  150  HINSTANCE library = NULL;
 
  151  size_t cchFileName = 0;
 
  152  size_t cchFilePath = 0;
 
  153  LPSTR pszAddinFile = NULL;
 
  154  LPSTR pszFilePath = NULL;
 
  155  LPSTR pszRelativeFilePath = NULL;
 
  156  size_t cchAddinFile = 0;
 
  157  size_t cchAddinInstallPath = 0;
 
  159  if (!pszFileName || !pszEntryName)
 
  162  WLog_DBG(TAG, 
"freerdp_load_dynamic_addin <- pszFileName: %s, pszPath: %s, pszEntryName: %s",
 
  163           pszFileName, pszPath, pszEntryName);
 
  165  cchFileName = strlen(pszFileName);
 
  168  if (FAILED(PathCchFindExtensionA(pszFileName, cchFileName + 1, &pszExt)))
 
  170    pszExt = PathGetSharedLibraryExtensionA(PATH_SHARED_LIB_EXT_WITH_DOT);
 
  171    cchExt = strlen(pszExt);
 
  177    pszAddinFile = _strdup(pszFileName);
 
  184    cchAddinFile = cchFileName + cchExt + 2 + 
sizeof(FREERDP_SHARED_LIBRARY_PREFIX);
 
  185    pszAddinFile = (LPSTR)malloc(cchAddinFile + 1);
 
  190    (void)sprintf_s(pszAddinFile, cchAddinFile, FREERDP_SHARED_LIBRARY_PREFIX 
"%s%s",
 
  191                    pszFileName, pszExt);
 
  194  cchAddinFile = strlen(pszAddinFile);
 
  199    size_t relPathLen = strlen(pszPath) + cchAddinFile + 1;
 
  200    pszRelativeFilePath = calloc(relPathLen, 
sizeof(CHAR));
 
  202    if (!pszRelativeFilePath)
 
  205    (void)sprintf_s(pszRelativeFilePath, relPathLen, 
"%s", pszPath);
 
  206    const HRESULT hr = NativePathCchAppendA(pszRelativeFilePath, relPathLen, pszAddinFile);
 
  211    pszRelativeFilePath = _strdup(pszAddinFile);
 
  213  if (!pszRelativeFilePath)
 
  217  if (pszAddinInstallPath)
 
  219    cchAddinInstallPath = strlen(pszAddinInstallPath);
 
  220    cchFilePath = cchAddinInstallPath + cchFileName + 32;
 
  221    pszFilePath = (LPSTR)malloc(cchFilePath + 1);
 
  226    CopyMemory(pszFilePath, pszAddinInstallPath, cchAddinInstallPath);
 
  227    pszFilePath[cchAddinInstallPath] = 
'\0';
 
  228    const HRESULT hr = NativePathCchAppendA(pszFilePath, cchFilePath + 1, pszRelativeFilePath);
 
  233    pszFilePath = _strdup(pszRelativeFilePath);
 
  235  library = LoadLibraryX(pszFilePath);
 
  240  entry = GetProcAddressAs(library, pszEntryName, PVIRTUALCHANNELENTRY);
 
  242  free(pszRelativeFilePath);
 
  245  free(pszAddinInstallPath);
 
  247  if (!entry && library)
 
  248    FreeLibrary(library);
 
  253PVIRTUALCHANNELENTRY freerdp_load_dynamic_channel_addin_entry(LPCSTR pszName, LPCSTR pszSubsystem,
 
  254                                                              LPCSTR pszType, DWORD dwFlags)
 
  256  PVIRTUALCHANNELENTRY entry = NULL;
 
  257  LPSTR pszFileName = NULL;
 
  258  const size_t cchBaseFileName = 
sizeof(FREERDP_SHARED_LIBRARY_PREFIX) + 32;
 
  260  size_t subsystemLen = 0;
 
  262  size_t cchFileName = 0;
 
  265    nameLen = strnlen(pszName, MAX_PATH);
 
  267    subsystemLen = strnlen(pszSubsystem, MAX_PATH);
 
  269    typeLen = strnlen(pszType, MAX_PATH);
 
  271  if (pszName && pszSubsystem && pszType)
 
  273    cchFileName = cchBaseFileName + nameLen + subsystemLen + typeLen;
 
  274    pszFileName = (LPSTR)malloc(cchFileName);
 
  279    (void)sprintf_s(pszFileName, cchFileName, 
"%s-client-%s-%s", pszName, pszSubsystem,
 
  282  else if (pszName && pszSubsystem)
 
  284    cchFileName = cchBaseFileName + nameLen + subsystemLen;
 
  285    pszFileName = (LPSTR)malloc(cchFileName);
 
  290    (void)sprintf_s(pszFileName, cchFileName, 
"%s-client-%s", pszName, pszSubsystem);
 
  294    cchFileName = cchBaseFileName + nameLen;
 
  295    pszFileName = (LPSTR)malloc(cchFileName);
 
  300    (void)sprintf_s(pszFileName, cchFileName, 
"%s-client", pszName);
 
  308    LPCSTR pszExtension = PathGetSharedLibraryExtensionA(0);
 
  309    const char pszPrefix[] = FREERDP_SHARED_LIBRARY_PREFIX;
 
  312    cchFileName += strnlen(pszPrefix, ARRAYSIZE(pszPrefix));
 
  314      cchFileName += strnlen(pszExtension, MAX_PATH) + 1;
 
  315    LPSTR tmp = calloc(cchFileName, 
sizeof(CHAR));
 
  317      rc = sprintf_s(tmp, cchFileName, 
"%s%s.%s", pszPrefix, pszFileName, pszExtension);
 
  321    if (!pszFileName || (rc < 0))
 
  330    LPSTR pszEntryName = NULL;
 
  331    size_t cchEntryName = 0;
 
  333    cchEntryName = 64 + nameLen;
 
  334    pszEntryName = (LPSTR)malloc(cchEntryName + 1);
 
  342    (void)sprintf_s(pszEntryName, cchEntryName + 1, 
"freerdp_%s_client_subsystem_entry",
 
  344    entry = freerdp_load_dynamic_addin(pszFileName, NULL, pszEntryName);
 
  352  if (dwFlags & FREERDP_ADDIN_CHANNEL_STATIC)
 
  354    if (dwFlags & FREERDP_ADDIN_CHANNEL_ENTRYEX)
 
  355      entry = freerdp_load_dynamic_addin(pszFileName, NULL, 
"VirtualChannelEntryEx");
 
  357      entry = freerdp_load_dynamic_addin(pszFileName, NULL, 
"VirtualChannelEntry");
 
  359  else if (dwFlags & FREERDP_ADDIN_CHANNEL_DYNAMIC)
 
  360    entry = freerdp_load_dynamic_addin(pszFileName, NULL, 
"DVCPluginEntry");
 
  361  else if (dwFlags & FREERDP_ADDIN_CHANNEL_DEVICE)
 
  362    entry = freerdp_load_dynamic_addin(pszFileName, NULL, 
"DeviceServiceEntry");
 
  364    entry = freerdp_load_dynamic_addin(pszFileName, NULL, pszType);
 
  370static FREERDP_LOAD_CHANNEL_ADDIN_ENTRY_FN freerdp_load_static_channel_addin_entry = NULL;
 
  372int freerdp_register_addin_provider(FREERDP_LOAD_CHANNEL_ADDIN_ENTRY_FN provider,
 
  373                                    WINPR_ATTR_UNUSED DWORD dwFlags)
 
  375  freerdp_load_static_channel_addin_entry = provider;
 
  379FREERDP_LOAD_CHANNEL_ADDIN_ENTRY_FN freerdp_get_current_addin_provider(
void)
 
  381  return freerdp_load_static_channel_addin_entry;
 
  384PVIRTUALCHANNELENTRY freerdp_load_channel_addin_entry(LPCSTR pszName, LPCSTR pszSubsystem,
 
  385                                                      LPCSTR pszType, DWORD dwFlags)
 
  387  PVIRTUALCHANNELENTRY entry = NULL;
 
  389  if (freerdp_load_static_channel_addin_entry)
 
  390    entry = freerdp_load_static_channel_addin_entry(pszName, pszSubsystem, pszType, dwFlags);
 
  393    entry = freerdp_load_dynamic_channel_addin_entry(pszName, pszSubsystem, pszType, dwFlags);
 
  396    WLog_WARN(TAG, 
"Failed to load channel %s [%s]", pszName, pszSubsystem);