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>
20 #if defined __GNUC__ || defined __clang__
21 # define LOK_TOLERATE_UNUSED __attribute__((used))
23 # define LOK_TOLERATE_UNUSED
26 #if defined(__linux__) || defined (__FreeBSD__) || defined(_AIX) ||\
27 defined(_WIN32) || defined(__APPLE__) || defined (__NetBSD__) ||\
28 defined (__sun) || defined(__OpenBSD__)
43 #define TARGET_LIB "lib" "sofficeapp" ".dylib"
44 #define TARGET_MERGED_LIB "lib" "mergedlo" ".dylib"
46 #define TARGET_LIB "lib" "sofficeapp" ".so"
47 #define TARGET_MERGED_LIB "lib" "mergedlo" ".so"
52 static void *lok_loadlib(const char *pFN
)
54 return dlopen(pFN
, RTLD_LAZY
55 #if defined LOK_LOADLIB_GLOBAL
61 static char *lok_dlerror(void)
66 // This function must be called to release memory allocated by lok_dlerror()
67 static void lok_dlerror_free(char *pErrMessage
)
70 // Do nothing for return of dlerror()
73 static void extendUnoPath(const char *pPath
)
78 static void *lok_dlsym(void *Hnd
, const char *pName
)
80 return dlsym(Hnd
, pName
);
83 static int lok_dlclose(void *Hnd
)
91 #if !defined WIN32_LEAN_AND_MEAN
92 #define WIN32_LEAN_AND_MEAN
95 #define TARGET_LIB "sofficeapp" ".dll"
96 #define TARGET_MERGED_LIB "mergedlo" ".dll"
97 #define SEPARATOR '\\'
98 #define UNOPATH "\\..\\URE\\bin"
100 static void *lok_loadlib(const char *pFN
)
102 return (void *) LoadLibraryA(pFN
);
105 static char *lok_dlerror(void)
108 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
,
109 NULL
, GetLastError(), 0, reinterpret_cast<LPSTR
>(&buf
), 0, NULL
);
113 // This function must be called to release memory allocated by lok_dlerror()
114 static void lok_dlerror_free(char *pErrMessage
)
116 HeapFree(GetProcessHeap(), 0, pErrMessage
);
119 static void *lok_dlsym(void *Hnd
, const char *pName
)
121 return reinterpret_cast<void *>(GetProcAddress((HINSTANCE
) Hnd
, pName
));
124 static int lok_dlclose(void *Hnd
)
126 return FreeLibrary((HINSTANCE
) Hnd
);
129 static void extendUnoPath(const char *pPath
)
131 char *sNewPath
= NULL
, *sEnvPath
= NULL
;
132 size_t size_sEnvPath
= 0, buffer_size
= 0;
138 cChars
= GetEnvironmentVariableA("PATH", sEnvPath
, 0);
141 sEnvPath
= (char *) malloc(cChars
);
142 cChars
= GetEnvironmentVariableA("PATH", sEnvPath
, cChars
);
143 //If PATH is not set then it is no error
144 if (cChars
== 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND
)
150 //prepare the new PATH. Add the Ure/bin directory at the front.
151 //note also adding ';'
153 size_sEnvPath
= strlen(sEnvPath
);
154 buffer_size
= size_sEnvPath
+ 2*strlen(pPath
) + strlen(UNOPATH
) + 4;
155 sNewPath
= (char *) malloc(buffer_size
);
157 strcat_s(sNewPath
, buffer_size
, pPath
); // program to PATH
158 strcat_s(sNewPath
, buffer_size
, ";");
159 strcat_s(sNewPath
, buffer_size
, UNOPATH
); // UNO to PATH
160 if (size_sEnvPath
> 0)
162 strcat_s(sNewPath
, buffer_size
, ";");
163 strcat_s(sNewPath
, buffer_size
, sEnvPath
);
166 SetEnvironmentVariableA("PATH", sNewPath
);
174 static void *lok_dlopen( const char *install_path
, char ** _imp_lib
)
179 size_t partial_length
, imp_lib_size
;
187 if (stat(install_path
, &dir_st
) != 0)
189 fprintf(stderr
, "installation path \"%s\" does not exist\n", install_path
);
193 // allocate large enough buffer
194 partial_length
= strlen(install_path
);
195 imp_lib_size
= partial_length
+ sizeof(TARGET_LIB
) + sizeof(TARGET_MERGED_LIB
) + 2;
196 imp_lib
= (char *) malloc(imp_lib_size
);
199 fprintf( stderr
, "failed to open library : not enough memory\n");
203 memcpy(imp_lib
, install_path
, partial_length
);
205 extendUnoPath(install_path
);
207 imp_lib
[partial_length
++] = SEPARATOR
;
208 strncpy(imp_lib
+ partial_length
, TARGET_LIB
, imp_lib_size
- partial_length
);
210 dlhandle
= lok_loadlib(imp_lib
);
213 // If TARGET_LIB exists, and likely is a real library (not a
214 // small one-line text stub as in the --enable-mergedlib
215 // case), but dlopen failed for some reason, don't try
216 // TARGET_MERGED_LIB.
218 if (stat(imp_lib
, &st
) == 0 && st
.st_size
> 100)
220 char *pErrMessage
= lok_dlerror();
221 fprintf(stderr
, "failed to open library '%s': %s\n",
222 imp_lib
, pErrMessage
);
223 lok_dlerror_free(pErrMessage
);
228 strncpy(imp_lib
+ partial_length
, TARGET_MERGED_LIB
, imp_lib_size
- partial_length
);
230 dlhandle
= lok_loadlib(imp_lib
);
233 char *pErrMessage
= lok_dlerror();
234 fprintf(stderr
, "failed to open library '%s': %s\n",
235 imp_lib
, pErrMessage
);
236 lok_dlerror_free(pErrMessage
);
246 typedef LibreOfficeKit
*(LokHookFunction
)( const char *install_path
);
248 typedef LibreOfficeKit
*(LokHookFunction2
)( const char *install_path
, const char *user_profile_url
);
250 typedef int (LokHookPreInit
) ( const char *install_path
, const char *user_profile_url
);
252 #if defined(IOS) || defined(ANDROID)
253 LibreOfficeKit
*libreofficekit_hook_2(const char* install_path
, const char* user_profile_path
);
256 static LibreOfficeKit
*lok_init_2( const char *install_path
, const char *user_profile_url
)
258 #if !defined(IOS) && !defined(ANDROID)
261 LokHookFunction
*pSym
;
262 LokHookFunction2
*pSym2
;
264 dlhandle
= lok_dlopen(install_path
, &imp_lib
);
268 pSym2
= (LokHookFunction2
*) lok_dlsym(dlhandle
, "libreofficekit_hook_2");
271 if (user_profile_url
!= NULL
)
273 fprintf( stderr
, "the LibreOffice version in '%s' does not support passing a user profile to the hook function\n",
275 lok_dlclose( dlhandle
);
279 pSym
= (LokHookFunction
*) lok_dlsym( dlhandle
, "libreofficekit_hook" );
282 fprintf( stderr
, "failed to find hook in library '%s'\n", imp_lib
);
283 lok_dlclose( dlhandle
);
288 // dlhandle is "leaked"
289 // coverity[leaked_storage] - on purpose
290 return pSym( install_path
);
293 if (user_profile_url
!= NULL
&& user_profile_url
[0] == '/')
295 // It should be either a file: URL or a vnd.sun.star.pathname: URL.
296 fprintf( stderr
, "second parameter to lok_init_2 '%s' should be a URL, not a pathname\n", user_profile_url
);
297 lok_dlclose( dlhandle
);
303 // dlhandle is "leaked"
304 // coverity[leaked_storage] - on purpose
305 return pSym2( install_path
, user_profile_url
);
307 return libreofficekit_hook_2( install_path
, user_profile_url
);
311 static LOK_TOLERATE_UNUSED
312 LibreOfficeKit
*lok_init( const char *install_path
)
314 return lok_init_2( install_path
, NULL
);
318 static LOK_TOLERATE_UNUSED
319 int lok_preinit( const char *install_path
, const char *user_profile_url
)
323 LokHookPreInit
*pSym
;
325 dlhandle
= lok_dlopen(install_path
, &imp_lib
);
329 pSym
= (LokHookPreInit
*) lok_dlsym(dlhandle
, "lok_preinit");
332 fprintf( stderr
, "failed to find pre-init hook in library '%s'\n", imp_lib
);
333 lok_dlclose( dlhandle
);
340 // dlhandle is "leaked"
341 // coverity[leaked_storage] - on purpose
342 return pSym( install_path
, user_profile_url
);
346 #undef SEPARATOR // It is used at least in enum class MenuItemType
348 #endif // defined(__linux__) || defined (__FreeBSD__) || defined(_AIX) || defined(_WIN32) || defined(__APPLE__)
354 #endif // INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
356 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */