1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #ifndef INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
11 #define INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
13 #include <LibreOfficeKit/LibreOfficeKit.h>
15 #if defined __GNUC__ || defined __clang__
16 # define LOK_TOLERATE_UNUSED __attribute__((used))
18 # define LOK_TOLERATE_UNUSED
21 #if defined(__linux__) || defined (__FreeBSD__) ||\
22 defined(_WIN32) || defined(__APPLE__) || defined (__NetBSD__) ||\
23 defined (__sun) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
35 #define TARGET_LIB "lib" "sofficeapp" ".dylib"
36 #define TARGET_MERGED_LIB "lib" "mergedlo" ".dylib"
38 #define TARGET_LIB "lib" "sofficeapp" ".so"
39 #define TARGET_MERGED_LIB "lib" "mergedlo" ".so"
45 #if !defined WIN32_LEAN_AND_MEAN
46 #define WIN32_LEAN_AND_MEAN
49 #define TARGET_LIB "sofficeapp" ".dll"
50 #define TARGET_MERGED_LIB "mergedlo" ".dll"
51 #define SEPARATOR '\\'
52 #define UNOPATH "\\..\\URE\\bin"
66 static void *lok_loadlib(const char *pFN
)
68 return dlopen(pFN
, RTLD_LAZY
69 #if defined LOK_LOADLIB_GLOBAL
75 static char *lok_dlerror(void)
80 // This function must be called to release memory allocated by lok_dlerror()
81 static void lok_dlerror_free(char *pErrMessage
)
84 // Do nothing for return of dlerror()
87 static void extendUnoPath(const char *pPath
)
92 static void *lok_dlsym(void *Hnd
, const char *pName
)
94 return dlsym(Hnd
, pName
);
97 static int lok_dlclose(void *Hnd
)
105 static void *lok_loadlib(const char *pFN
)
107 return (void *) LoadLibraryA(pFN
);
110 static char *lok_dlerror(void)
113 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
,
114 NULL
, GetLastError(), 0, reinterpret_cast<LPSTR
>(&buf
), 0, NULL
);
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;
143 cChars
= GetEnvironmentVariableA("PATH", sEnvPath
, 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
)
155 //prepare the new PATH. Add the Ure/bin directory at the front.
156 //note also adding ';'
158 size_sEnvPath
= strlen(sEnvPath
);
159 buffer_size
= size_sEnvPath
+ 2*strlen(pPath
) + strlen(UNOPATH
) + 4;
160 sNewPath
= (char *) malloc(buffer_size
);
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
);
179 static void *lok_dlopen( const char *install_path
, char ** _imp_lib
)
184 size_t partial_length
, imp_lib_size
;
192 if (stat(install_path
, &dir_st
) != 0)
194 fprintf(stderr
, "installation path \"%s\" does not exist\n", install_path
);
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
);
204 fprintf( stderr
, "failed to open library : not enough memory\n");
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
);
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.
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
);
233 strncpy(imp_lib
+ partial_length
, TARGET_MERGED_LIB
, imp_lib_size
- partial_length
);
235 dlhandle
= lok_loadlib(imp_lib
);
238 char *pErrMessage
= lok_dlerror();
239 fprintf(stderr
, "failed to open library '%s': %s\n",
240 imp_lib
, pErrMessage
);
241 lok_dlerror_free(pErrMessage
);
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
);
263 static LibreOfficeKit
*lok_init_2( const char *install_path
, const char *user_profile_url
)
265 #if !defined(IOS) && !defined(ANDROID) && !defined(__EMSCRIPTEN__)
268 LokHookFunction
*pSym
;
269 LokHookFunction2
*pSym2
;
271 dlhandle
= lok_dlopen(install_path
, &imp_lib
);
275 pSym2
= (LokHookFunction2
*) lok_dlsym(dlhandle
, "libreofficekit_hook_2");
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",
282 lok_dlclose( dlhandle
);
286 pSym
= (LokHookFunction
*) lok_dlsym( dlhandle
, "libreofficekit_hook" );
289 fprintf( stderr
, "failed to find hook in library '%s'\n", imp_lib
);
290 lok_dlclose( dlhandle
);
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
);
310 // dlhandle is "leaked"
311 // coverity[leaked_storage] - on purpose
312 return pSym2( install_path
, user_profile_url
);
314 return libreofficekit_hook_2( install_path
, user_profile_url
);
318 static LOK_TOLERATE_UNUSED
319 LibreOfficeKit
*lok_init( const char *install_path
)
321 return lok_init_2( install_path
, NULL
);
325 static LOK_TOLERATE_UNUSED
326 int lok_preinit( const char *install_path
, const char *user_profile_url
)
330 LokHookPreInit
*pSym
;
332 dlhandle
= lok_dlopen(install_path
, &imp_lib
);
336 pSym
= (LokHookPreInit
*) lok_dlsym(dlhandle
, "lok_preinit");
339 fprintf( stderr
, "failed to find pre-init hook in library '%s'\n", imp_lib
);
340 lok_dlclose( dlhandle
);
347 // dlhandle is "leaked"
348 // coverity[leaked_storage] - on purpose
349 return pSym( install_path
, user_profile_url
);
353 #undef SEPARATOR // It is used at least in enum class MenuItemType
359 #endif // defined(__linux__) || defined (__FreeBSD__) || defined(_WIN32) || defined(__APPLE__)
361 #endif // INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
363 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */