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 PfnDliHook   __pfnDliFailureHook2 = delayLoadHook;
255 
256 namespace uno
257 {
258 namespace util
259 {
260 
261 /** Bootstrapping native UNO.
262 
263     Bootstrapping requires the existence of many libraries which are contained
264     in an URE installation. To find and load these libraries the Windows
265     registry keys HKEY_CURRENT_USER\Software\OpenOffice\UNO\InstallPath
266     and HKEY_LOCAL_MACHINE\Software\OpenOffice\UNO\InstallPath are examined.
267     The default value contain the path to the office prgoram dir. No seaparate URE
268     anymore.
269 */
270 public __sealed __gc class Bootstrap
271 {
272     inline Bootstrap() {}
273 
274 public:
275 
276     /** Bootstraps the initial component context from a native UNO installation.
277 
278         @see cppuhelper/bootstrap.hxx:defaultBootstrap_InitialComponentContext()
279     */
280     static ::unoidl::com::sun::star::uno::XComponentContext *
281         defaultBootstrap_InitialComponentContext();
282 
283     /** Bootstraps the initial component context from a native UNO installation.
284 
285         @param ini_file
286                a file URL of an ini file, e.g. uno.ini/unorc. (The ini file must
287                reside next to the cppuhelper library)
288         @param bootstrap_parameters
289                bootstrap parameters (maybe null)
290 
291         @see cppuhelper/bootstrap.hxx:defaultBootstrap_InitialComponentContext()
292     */
293     static ::unoidl::com::sun::star::uno::XComponentContext *
294         defaultBootstrap_InitialComponentContext(
295             ::System::String * ini_file,
296             ::System::Collections::IDictionaryEnumerator *
297               bootstrap_parameters );
298 
299     /** Bootstraps the initial component context from a native UNO installation.
300 
301     @see cppuhelper/bootstrap.hxx:bootstrap()
302      */
303     static ::unoidl::com::sun::star::uno::XComponentContext *
304     bootstrap();
305 };
306 
307 //______________________________________________________________________________
308 ::unoidl::com::sun::star::uno::XComponentContext *
309 Bootstrap::defaultBootstrap_InitialComponentContext(
310     ::System::String * ini_file,
311     ::System::Collections::IDictionaryEnumerator * bootstrap_parameters )
312 {
313     if (0 != bootstrap_parameters)
314     {
315         bootstrap_parameters->Reset();
316         while (bootstrap_parameters->MoveNext())
317         {
318             OUString key(
319                 String_to_ustring( __try_cast< ::System::String * >(
320                                        bootstrap_parameters->get_Key() ) ) );
321             OUString value(
322                 String_to_ustring( __try_cast< ::System::String * >(
323                                        bootstrap_parameters->get_Value() ) ) );
324 
325             ::rtl::Bootstrap::set( key, value );
326         }
327     }
328 
329     // bootstrap native uno
330     Reference< XComponentContext > xContext;
331     if (0 == ini_file)
332     {
333         xContext = ::cppu::defaultBootstrap_InitialComponentContext();
334     }
335     else
336     {
337         xContext = ::cppu::defaultBootstrap_InitialComponentContext(
338             String_to_ustring( __try_cast< ::System::String * >( ini_file ) ) );
339     }
340 
341     return __try_cast< ::unoidl::com::sun::star::uno::XComponentContext * >(
342         to_cli( xContext ) );
343 }
344 
345 //______________________________________________________________________________
346 ::unoidl::com::sun::star::uno::XComponentContext *
347 Bootstrap::defaultBootstrap_InitialComponentContext()
348 {
349     return defaultBootstrap_InitialComponentContext( 0, 0 );
350 }
351 
352 ::unoidl::com::sun::star::uno::XComponentContext * Bootstrap::bootstrap()
353 {
354     Reference<XComponentContext> xContext = ::cppu::bootstrap();
355     return __try_cast< ::unoidl::com::sun::star::uno::XComponentContext * >(
356         to_cli( xContext ) );
357 
358 }
359 
360 }
361 }
362