xref: /trunk/main/cli_ure/source/native/native_bootstrap.cxx (revision 137931e43899a1545869cb6af6ea936d8cee4956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // Use UNICODE Windows and C API.
25 #define _UNICODE
26 #define UNICODE
27 
28 #ifdef _MSC_VER
29 #pragma warning(push, 1)
30 #endif
31 #include <windows.h>
32 #include "uno/environment.hxx"
33 #ifdef _MSC_VER
34 #pragma warning(pop)
35 #endif
36 
37 #include <tchar.h>
38 
39 #include "native_share.h"
40 
41 #include "rtl/bootstrap.hxx"
42 #include "com/sun/star/uno/XComponentContext.hpp"
43 #include "cppuhelper/bootstrap.hxx"
44 #include <delayimp.h>
45 #include <stdio.h>
46 
47 using namespace ::rtl;
48 using namespace ::com::sun::star;
49 using namespace ::com::sun::star::uno;
50 
51 namespace cli_ure {
52     WCHAR * resolveLink(WCHAR * path);
53 }
54 
55 // INSTALL_PATH value needs to correspond to the Windows registry subkey
56 // in main\scp2\source\ooo\registryitem_ooo.scp
57 #define INSTALL_PATH L"Software\\OpenOffice\\UNO\\InstallPath"
58 #define INSTALL_PATH_64 L"Software\\Wow6432Node\\OpenOffice\\UNO\\InstallPath"
59 #define UNO_PATH L"UNO_PATH"
60 
61 namespace
62 {
63 
64  /*
65  * Gets the installation path from the Windows Registry for the specified
66  * registry key.
67  *
68  * @param hroot       open handle to predefined root registry key
69  * @param subKeyName  name of the subkey to open
70  *
71  * @return the installation path or NULL, if no installation was found or
72  *         if an error occurred
73  */
74 WCHAR* getPathFromRegistryKey( HKEY hroot, LPCWSTR subKeyName )
75 {
76     HKEY hkey;
77     DWORD type;
78     TCHAR* data = NULL;
79     DWORD size;
80 
81     /* open the specified registry key */
82     if ( RegOpenKeyEx( hroot, subKeyName, 0, KEY_READ, &hkey ) != ERROR_SUCCESS )
83     {
84         return NULL;
85     }
86 
87     /* find the type and size of the default value */
88     if ( RegQueryValueEx( hkey, NULL, NULL, &type, NULL, &size) != ERROR_SUCCESS )
89     {
90         RegCloseKey( hkey );
91         return NULL;
92     }
93 
94     /* get memory to hold the default value */
95     data = new WCHAR[size];
96 
97     /* read the default value */
98     if ( RegQueryValueEx( hkey, NULL, NULL, &type, (LPBYTE) data, &size ) != ERROR_SUCCESS )
99     {
100         RegCloseKey( hkey );
101         return NULL;
102     }
103 
104     /* release registry key handle */
105     RegCloseKey( hkey );
106 
107     return data;
108 }
109 
110 /* Returns the path to the program folder of the brand layer,
111     for example c:/openoffice.org 3/program
112    This path is either obtained from the environment variable UNO_PATH
113    or the registry item
114    "Software\\OpenOffice\\UNO\\InstallPath"
115    either in HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE
116    The return value must be freed with delete[]
117 */
118 WCHAR * getInstallPath()
119 {
120     WCHAR * szInstallPath = NULL;
121 
122     DWORD  cChars = GetEnvironmentVariable(UNO_PATH, NULL, 0);
123     if (cChars > 0)
124     {
125         szInstallPath = new WCHAR[cChars+1];
126         cChars = GetEnvironmentVariable(UNO_PATH, szInstallPath, cChars+1);
127         //If PATH is not set then it is no error
128         if (cChars == 0)
129         {
130             delete[] szInstallPath;
131             return NULL;
132         }
133     }
134 
135     if (! szInstallPath)
136     {
137         szInstallPath = getPathFromRegistryKey( HKEY_CURRENT_USER, INSTALL_PATH );
138         if ( szInstallPath == NULL )
139         {
140             /* read the key's default value from HKEY_LOCAL_USER */
141             szInstallPath = getPathFromRegistryKey( HKEY_CURRENT_USER, INSTALL_PATH_64 );
142         }
143         if ( szInstallPath == NULL )
144         {
145             /* read the key's default value from HKEY_LOCAL_MACHINE */
146             szInstallPath = getPathFromRegistryKey( HKEY_LOCAL_MACHINE, INSTALL_PATH );
147         }
148         if ( szInstallPath == NULL )
149         {
150             /* read the key's default value from HKEY_LOCAL_MACHINE */
151             szInstallPath = getPathFromRegistryKey( HKEY_LOCAL_MACHINE, INSTALL_PATH_64 );
152         }
153     }
154     return szInstallPath;
155 }
156 
157 
158 /*We extend the path to contain the URE/bin folder,
159   so that components can use osl_loadModule with arguments, such as
160   "reg3.dll". That is, the arguments are only the library names.
161 */
162 void extendPath(LPCWSTR szUreBinPath)
163 {
164     if (!szUreBinPath)
165         return;
166 
167     WCHAR * sEnvPath = NULL;
168     DWORD  cChars = GetEnvironmentVariable(L"PATH", sEnvPath, 0);
169     if (cChars > 0)
170     {
171         sEnvPath = new WCHAR[cChars];
172         cChars = GetEnvironmentVariable(L"PATH", sEnvPath, cChars);
173         //If PATH is not set then it is no error
174         if (cChars == 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND)
175         {
176             delete[] sEnvPath;
177             return;
178         }
179     }
180     //prepare the new PATH. Add the Ure/bin directory at the front.
181     //note also adding ';'
182     WCHAR * sNewPath = new WCHAR[lstrlen(sEnvPath) + lstrlen(szUreBinPath) + 2];
183     sNewPath[0] = L'\0';
184     lstrcat(sNewPath, szUreBinPath);
185     if (lstrlen(sEnvPath))
186     {
187         lstrcat(sNewPath, L";");
188         lstrcat(sNewPath, sEnvPath);
189     }
190     BOOL bSet = SetEnvironmentVariable(L"PATH", sNewPath);
191 
192     delete[] sEnvPath;
193     delete[] sNewPath;
194 }
195 
196 
197 HMODULE loadFromPath(LPCWSTR sLibName)
198 {
199     if (sLibName == NULL)
200         return NULL;
201 
202     WCHAR * szUreBinPath = getInstallPath();
203     if (!szUreBinPath)
204         return NULL;
205 
206     extendPath(szUreBinPath);
207 
208     WCHAR*  szFullPath = new WCHAR[lstrlen(sLibName) + lstrlen(szUreBinPath) + 2];
209     szFullPath[0] = L'\0';
210     lstrcat(szFullPath, szUreBinPath);
211     lstrcat(szFullPath, L"\\");
212     lstrcat(szFullPath, sLibName);
213     HMODULE handle = LoadLibraryEx(szFullPath, NULL,
214         LOAD_WITH_ALTERED_SEARCH_PATH);
215 
216     delete[] szFullPath;
217     delete[] szUreBinPath;
218     return handle;
219 }
220 
221 /*Hook for delayed loading of libraries which this library is linked with.
222     This is a failure hook. That is, it is only called when the loading of
223     a library failed. It will be called when loading of cppuhelper failed.
224     Because we extend the PATH to the URE/bin folder while this function is
225     executed (see extendPath), all other libraries are found.
226 */
227 extern "C" FARPROC WINAPI delayLoadHook(
228     unsigned        dliNotify,
229     PDelayLoadInfo  pdli
230     )
231 {
232     if (dliNotify == dliFailLoadLib)
233     {
234         LPWSTR szLibName = NULL;
235         //Convert the ansi file name to wchar_t*
236         int size = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pdli->szDll, -1, NULL, 0);
237         if (size > 0)
238         {
239             szLibName = new WCHAR[size];
240             if (! MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pdli->szDll, -1, szLibName, size))
241             {
242                 return 0;
243             }
244         }
245         HANDLE h = loadFromPath(szLibName);
246         delete[] szLibName;
247         return (FARPROC) h;
248     }
249     return 0;
250 }
251 }
252 
253 ExternC
254 #if defined(_MSC_VER) && _MSC_VER >= 1900
255 // A modern delayimp.h declares this hook const unless
256 // DELAYIMP_INSECURE_WRITABLE_HOOKS is defined, and the definition has to
257 // agree with the declaration.  VC9's is writable, so it keeps the old form.
258 const
259 #endif
260 PfnDliHook   __pfnDliFailureHook2 = delayLoadHook;
261 
262 namespace uno
263 {
264 namespace util
265 {
266 
267 /** Bootstrapping native UNO.
268 
269     Bootstrapping requires the existence of many libraries which are contained
270     in an URE installation. To find and load these libraries the Windows
271     registry keys HKEY_CURRENT_USER\Software\OpenOffice\UNO\InstallPath
272     and HKEY_LOCAL_MACHINE\Software\OpenOffice\UNO\InstallPath are examined.
273     The default value contain the path to the office program dir. No separate URE
274     anymore.
275 */
276 public ref class Bootstrap sealed
277 {
278     inline Bootstrap() {}
279 
280 public:
281 
282     /** Bootstraps the initial component context from a native UNO installation.
283 
284         @see cppuhelper/bootstrap.hxx:defaultBootstrap_InitialComponentContext()
285     */
286     static ::unoidl::com::sun::star::uno::XComponentContext ^
287         defaultBootstrap_InitialComponentContext();
288 
289     /** Bootstraps the initial component context from a native UNO installation.
290 
291         @param ini_file
292                a file URL of an ini file, e.g. uno.ini/unorc. (The ini file must
293                reside next to the cppuhelper library)
294         @param bootstrap_parameters
295                bootstrap parameters (maybe null)
296 
297         @see cppuhelper/bootstrap.hxx:defaultBootstrap_InitialComponentContext()
298     */
299     static ::unoidl::com::sun::star::uno::XComponentContext ^
300         defaultBootstrap_InitialComponentContext(
301             ::System::String ^ ini_file,
302             ::System::Collections::IDictionaryEnumerator ^
303               bootstrap_parameters );
304 
305     /** Bootstraps the initial component context from a native UNO installation.
306 
307     @see cppuhelper/bootstrap.hxx:bootstrap()
308      */
309     static ::unoidl::com::sun::star::uno::XComponentContext ^
310     bootstrap();
311 };
312 
313 //______________________________________________________________________________
314 ::unoidl::com::sun::star::uno::XComponentContext ^
315 Bootstrap::defaultBootstrap_InitialComponentContext(
316     ::System::String ^ ini_file,
317     ::System::Collections::IDictionaryEnumerator ^ bootstrap_parameters )
318 {
319     if (nullptr != bootstrap_parameters)
320     {
321         bootstrap_parameters->Reset();
322         while (bootstrap_parameters->MoveNext())
323         {
324             OUString key(
325                 String_to_ustring( safe_cast< ::System::String ^ >(
326                                        bootstrap_parameters->Key ) ) );
327             OUString value(
328                 String_to_ustring( safe_cast< ::System::String ^ >(
329                                        bootstrap_parameters->Value ) ) );
330 
331             ::rtl::Bootstrap::set( key, value );
332         }
333     }
334 
335     // bootstrap native UNO
336     Reference< XComponentContext > xContext;
337     if (nullptr == ini_file)
338     {
339         xContext = ::cppu::defaultBootstrap_InitialComponentContext();
340     }
341     else
342     {
343         xContext = ::cppu::defaultBootstrap_InitialComponentContext(
344             String_to_ustring( safe_cast< ::System::String ^ >( ini_file ) ) );
345     }
346 
347     return safe_cast< ::unoidl::com::sun::star::uno::XComponentContext ^ >(
348         to_cli( xContext ) );
349 }
350 
351 //______________________________________________________________________________
352 ::unoidl::com::sun::star::uno::XComponentContext ^
353 Bootstrap::defaultBootstrap_InitialComponentContext()
354 {
355     return defaultBootstrap_InitialComponentContext( nullptr, nullptr );
356 }
357 
358 ::unoidl::com::sun::star::uno::XComponentContext ^ Bootstrap::bootstrap()
359 {
360     Reference<XComponentContext> xContext = ::cppu::bootstrap();
361     return safe_cast< ::unoidl::com::sun::star::uno::XComponentContext ^ >(
362         to_cli( xContext ) );
363 
364 }
365 
366 }
367 }
368