Version 24.8.3.2, tag libreoffice-24.8.3.2
[LibreOffice.git] / include / LibreOfficeKit / LibreOfficeKitInit.h
blob10085d3c1c355d80bcf361f9e52ae2d6f166cb3f
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #ifndef INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
11 #define INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
13 #include "LibreOfficeKit.h"
15 #if defined __GNUC__ || defined __clang__
16 # define LOK_TOLERATE_UNUSED __attribute__((used))
17 #else
18 # define LOK_TOLERATE_UNUSED
19 #endif
21 #if defined(__linux__) || defined (__FreeBSD__) ||\
22 defined(_WIN32) || defined(__APPLE__) || defined (__NetBSD__) ||\
23 defined (__sun) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/stat.h>
30 #ifndef _WIN32
32 #include <dlfcn.h>
34 #ifdef __APPLE__
35 #define TARGET_LIB "lib" "sofficeapp" ".dylib"
36 #define TARGET_MERGED_LIB "lib" "mergedlo" ".dylib"
37 #else
38 #define TARGET_LIB "lib" "sofficeapp" ".so"
39 #define TARGET_MERGED_LIB "lib" "mergedlo" ".so"
40 #endif
41 #define SEPARATOR '/'
43 #else
45 #if !defined WIN32_LEAN_AND_MEAN
46 #define WIN32_LEAN_AND_MEAN
47 #endif
48 #include <windows.h>
49 #define TARGET_LIB "sofficeapp" ".dll"
50 #define TARGET_MERGED_LIB "mergedlo" ".dll"
51 #define SEPARATOR '\\'
52 #define UNOPATH "\\..\\URE\\bin"
54 #undef DELETE
56 #endif
58 #ifdef __cplusplus
59 extern "C"
61 #endif
63 #ifndef _WIN32
65 #if !defined(IOS)
66 static void *lok_loadlib(const char *pFN)
68 return dlopen(pFN, RTLD_LAZY
69 #if defined LOK_LOADLIB_GLOBAL
70 | RTLD_GLOBAL
71 #endif
75 static char *lok_dlerror(void)
77 return dlerror();
80 // This function must be called to release memory allocated by lok_dlerror()
81 static void lok_dlerror_free(char *pErrMessage)
83 (void)pErrMessage;
84 // Do nothing for return of dlerror()
87 static void extendUnoPath(const char *pPath)
89 (void)pPath;
92 static void *lok_dlsym(void *Hnd, const char *pName)
94 return dlsym(Hnd, pName);
97 static int lok_dlclose(void *Hnd)
99 return dlclose(Hnd);
101 #endif // IOS
104 #else
105 static void *lok_loadlib(const char *pFN)
107 return (void *) LoadLibraryA(pFN);
110 static char *lok_dlerror(void)
112 LPSTR buf = NULL;
113 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
114 NULL, GetLastError(), 0, reinterpret_cast<LPSTR>(&buf), 0, NULL);
115 return buf;
118 // This function must be called to release memory allocated by lok_dlerror()
119 static void lok_dlerror_free(char *pErrMessage)
121 HeapFree(GetProcessHeap(), 0, pErrMessage);
124 static void *lok_dlsym(void *Hnd, const char *pName)
126 return reinterpret_cast<void *>(GetProcAddress((HINSTANCE) Hnd, pName));
129 static int lok_dlclose(void *Hnd)
131 return FreeLibrary((HINSTANCE) Hnd);
134 static void extendUnoPath(const char *pPath)
136 char *sNewPath = NULL, *sEnvPath = NULL;
137 size_t size_sEnvPath = 0, buffer_size = 0;
138 DWORD cChars;
140 if (!pPath)
141 return;
143 cChars = GetEnvironmentVariableA("PATH", sEnvPath, 0);
144 if (cChars > 0)
146 sEnvPath = (char *) malloc(cChars);
147 cChars = GetEnvironmentVariableA("PATH", sEnvPath, cChars);
148 //If PATH is not set then it is no error
149 if (cChars == 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND)
151 free(sEnvPath);
152 return;
155 //prepare the new PATH. Add the Ure/bin directory at the front.
156 //note also adding ';'
157 if(sEnvPath)
158 size_sEnvPath = strlen(sEnvPath);
159 buffer_size = size_sEnvPath + 2*strlen(pPath) + strlen(UNOPATH) + 4;
160 sNewPath = (char *) malloc(buffer_size);
161 sNewPath[0] = L'\0';
162 strcat_s(sNewPath, buffer_size, pPath); // program to PATH
163 strcat_s(sNewPath, buffer_size, ";");
164 strcat_s(sNewPath, buffer_size, UNOPATH); // UNO to PATH
165 if (size_sEnvPath > 0)
167 strcat_s(sNewPath, buffer_size, ";");
168 strcat_s(sNewPath, buffer_size, sEnvPath);
171 SetEnvironmentVariableA("PATH", sNewPath);
173 free(sNewPath);
174 free(sEnvPath);
176 #endif
178 #if !defined(IOS)
179 static void *lok_dlopen( const char *install_path, char ** _imp_lib )
181 char *imp_lib;
182 void *dlhandle;
184 size_t partial_length, imp_lib_size;
185 struct stat dir_st;
187 *_imp_lib = NULL;
189 if (!install_path)
190 return NULL;
192 if (stat(install_path, &dir_st) != 0)
194 fprintf(stderr, "installation path \"%s\" does not exist\n", install_path);
195 return NULL;
198 // allocate large enough buffer
199 partial_length = strlen(install_path);
200 imp_lib_size = partial_length + sizeof(TARGET_LIB) + sizeof(TARGET_MERGED_LIB) + 2;
201 imp_lib = (char *) malloc(imp_lib_size);
202 if (!imp_lib)
204 fprintf( stderr, "failed to open library : not enough memory\n");
205 return NULL;
208 memcpy(imp_lib, install_path, partial_length);
210 extendUnoPath(install_path);
212 imp_lib[partial_length++] = SEPARATOR;
213 strncpy(imp_lib + partial_length, TARGET_LIB, imp_lib_size - partial_length);
215 dlhandle = lok_loadlib(imp_lib);
216 if (!dlhandle)
218 // If TARGET_LIB exists, and likely is a real library (not a
219 // small one-line text stub as in the --enable-mergedlib
220 // case), but dlopen failed for some reason, don't try
221 // TARGET_MERGED_LIB.
222 struct stat st;
223 if (stat(imp_lib, &st) == 0 && st.st_size > 100)
225 char *pErrMessage = lok_dlerror();
226 fprintf(stderr, "failed to open library '%s': %s\n",
227 imp_lib, pErrMessage);
228 lok_dlerror_free(pErrMessage);
229 free(imp_lib);
230 return NULL;
233 strncpy(imp_lib + partial_length, TARGET_MERGED_LIB, imp_lib_size - partial_length);
235 dlhandle = lok_loadlib(imp_lib);
236 if (!dlhandle)
238 char *pErrMessage = lok_dlerror();
239 fprintf(stderr, "failed to open library '%s': %s\n",
240 imp_lib, pErrMessage);
241 lok_dlerror_free(pErrMessage);
242 free(imp_lib);
243 return NULL;
246 *_imp_lib = imp_lib;
247 return dlhandle;
249 #endif
251 typedef LibreOfficeKit *(LokHookFunction)( const char *install_path);
253 typedef LibreOfficeKit *(LokHookFunction2)( const char *install_path, const char *user_profile_url );
255 typedef int (LokHookPreInit) ( const char *install_path, const char *user_profile_url );
257 typedef int (LokHookPreInit2) ( const char *install_path, const char *user_profile_url, LibreOfficeKit** kit);
259 #if defined(IOS) || defined(ANDROID) || defined(__EMSCRIPTEN__)
260 LibreOfficeKit *libreofficekit_hook_2(const char* install_path, const char* user_profile_path);
261 #endif
263 static LibreOfficeKit *lok_init_2( const char *install_path, const char *user_profile_url )
265 #if !defined(IOS) && !defined(ANDROID) && !defined(__EMSCRIPTEN__)
266 void *dlhandle;
267 char *imp_lib;
268 LokHookFunction *pSym;
269 LokHookFunction2 *pSym2;
271 dlhandle = lok_dlopen(install_path, &imp_lib);
272 if (!dlhandle)
273 return NULL;
275 pSym2 = (LokHookFunction2 *) lok_dlsym(dlhandle, "libreofficekit_hook_2");
276 if (!pSym2)
278 if (user_profile_url != NULL)
280 fprintf( stderr, "the LibreOffice version in '%s' does not support passing a user profile to the hook function\n",
281 imp_lib );
282 lok_dlclose( dlhandle );
283 free( imp_lib );
284 return NULL;
286 pSym = (LokHookFunction *) lok_dlsym( dlhandle, "libreofficekit_hook" );
287 if (!pSym)
289 fprintf( stderr, "failed to find hook in library '%s'\n", imp_lib );
290 lok_dlclose( dlhandle );
291 free( imp_lib );
292 return NULL;
294 free( imp_lib );
295 // dlhandle is "leaked"
296 // coverity[leaked_storage] - on purpose
297 return pSym( install_path );
300 if (user_profile_url != NULL && user_profile_url[0] == '/')
302 // It should be either a file: URL or a vnd.sun.star.pathname: URL.
303 fprintf( stderr, "second parameter to lok_init_2 '%s' should be a URL, not a pathname\n", user_profile_url );
304 lok_dlclose( dlhandle );
305 free( imp_lib );
306 return NULL;
309 free( imp_lib );
310 // dlhandle is "leaked"
311 // coverity[leaked_storage] - on purpose
312 return pSym2( install_path, user_profile_url );
313 #else
314 return libreofficekit_hook_2( install_path, user_profile_url );
315 #endif
318 static LOK_TOLERATE_UNUSED
319 LibreOfficeKit *lok_init( const char *install_path )
321 return lok_init_2( install_path, NULL );
324 #if !defined(IOS)
325 static LOK_TOLERATE_UNUSED
326 int lok_preinit( const char *install_path, const char *user_profile_url )
328 void *dlhandle;
329 char *imp_lib;
330 LokHookPreInit *pSym;
332 dlhandle = lok_dlopen(install_path, &imp_lib);
333 if (!dlhandle)
334 return -1;
336 pSym = (LokHookPreInit *) lok_dlsym(dlhandle, "lok_preinit");
337 if (!pSym)
339 fprintf( stderr, "failed to find pre-init hook in library '%s'\n", imp_lib );
340 lok_dlclose( dlhandle );
341 free( imp_lib );
342 return -1;
345 free( imp_lib );
347 // dlhandle is "leaked"
348 // coverity[leaked_storage] - on purpose
349 return pSym( install_path, user_profile_url );
351 #endif
353 #undef SEPARATOR // It is used at least in enum class MenuItemType
355 #ifdef __cplusplus
357 #endif
359 #endif // defined(__linux__) || defined (__FreeBSD__) || defined(_WIN32) || defined(__APPLE__)
361 #endif // INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
363 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */