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 */
getPathFromRegistryKey(HKEY hroot,LPCWSTR subKeyName)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 */
getInstallPath()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 */
extendPath(LPCWSTR szUreBinPath)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
loadFromPath(LPCWSTR sLibName)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 */
delayLoadHook(unsigned dliNotify,PDelayLoadInfo pdli)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