20 #include <freerdp/config.h>
26 #include <winpr/crt.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")
37 static INLINE BOOL is_path_required(LPCSTR path,
size_t len)
39 if (!path || (len <= 1))
42 if (strcmp(path,
".") == 0)
48 LPSTR 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)))
90 LPSTR 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);
142 PVIRTUALCHANNELENTRY 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);
253 PVIRTUALCHANNELENTRY 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);
370 static FREERDP_LOAD_CHANNEL_ADDIN_ENTRY_FN freerdp_load_static_channel_addin_entry = NULL;
372 int freerdp_register_addin_provider(FREERDP_LOAD_CHANNEL_ADDIN_ENTRY_FN provider, DWORD dwFlags)
374 freerdp_load_static_channel_addin_entry = provider;
378 FREERDP_LOAD_CHANNEL_ADDIN_ENTRY_FN freerdp_get_current_addin_provider(
void)
380 return freerdp_load_static_channel_addin_entry;
383 PVIRTUALCHANNELENTRY freerdp_load_channel_addin_entry(LPCSTR pszName, LPCSTR pszSubsystem,
384 LPCSTR pszType, DWORD dwFlags)
386 PVIRTUALCHANNELENTRY entry = NULL;
388 if (freerdp_load_static_channel_addin_entry)
389 entry = freerdp_load_static_channel_addin_entry(pszName, pszSubsystem, pszType, dwFlags);
392 entry = freerdp_load_dynamic_channel_addin_entry(pszName, pszSubsystem, pszType, dwFlags);
395 WLog_WARN(TAG,
"Failed to load channel %s [%s]", pszName, pszSubsystem);