1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // Use UNICODE Windows and C API. 29 #define _UNICODE 30 #define UNICODE 31 32 #ifdef _MSC_VER 33 #pragma warning(push, 1) 34 #endif 35 #include <windows.h> 36 #include "uno/environment.hxx" 37 #ifdef _MSC_VER 38 #pragma warning(pop) 39 #endif 40 41 #include <tchar.h> 42 43 #include "native_share.h" 44 45 #include "rtl/bootstrap.hxx" 46 #include "com/sun/star/uno/XComponentContext.hpp" 47 #include "cppuhelper/bootstrap.hxx" 48 #include <delayimp.h> 49 #include <stdio.h> 50 51 using namespace ::rtl; 52 using namespace ::com::sun::star; 53 using namespace ::com::sun::star::uno; 54 55 namespace cli_ure { 56 WCHAR * resolveLink(WCHAR * path); 57 } 58 59 #define INSTALL_PATH L"Software\\OpenOffice.org\\UNO\\InstallPath" 60 #define BASIS_LINK L"\\basis-link" 61 #define URE_LINK L"\\ure-link" 62 #define URE_BIN L"\\bin" 63 #define UNO_PATH L"UNO_PATH" 64 65 namespace 66 { 67 68 /* 69 * Gets the installation path from the Windows Registry for the specified 70 * registry key. 71 * 72 * @param hroot open handle to predefined root registry key 73 * @param subKeyName name of the subkey to open 74 * 75 * @return the installation path or NULL, if no installation was found or 76 * if an error occured 77 */ 78 WCHAR* getPathFromRegistryKey( HKEY hroot, LPCWSTR subKeyName ) 79 { 80 HKEY hkey; 81 DWORD type; 82 TCHAR* data = NULL; 83 DWORD size; 84 85 /* open the specified registry key */ 86 if ( RegOpenKeyEx( hroot, subKeyName, 0, KEY_READ, &hkey ) != ERROR_SUCCESS ) 87 { 88 return NULL; 89 } 90 91 /* find the type and size of the default value */ 92 if ( RegQueryValueEx( hkey, NULL, NULL, &type, NULL, &size) != ERROR_SUCCESS ) 93 { 94 RegCloseKey( hkey ); 95 return NULL; 96 } 97 98 /* get memory to hold the default value */ 99 data = new WCHAR[size]; 100 101 /* read the default value */ 102 if ( RegQueryValueEx( hkey, NULL, NULL, &type, (LPBYTE) data, &size ) != ERROR_SUCCESS ) 103 { 104 RegCloseKey( hkey ); 105 return NULL; 106 } 107 108 /* release registry key handle */ 109 RegCloseKey( hkey ); 110 111 return data; 112 } 113 114 /* If the path does not end with '\' the las segment will be removed. 115 path: C:\a\b 116 -> C:\a 117 @param io_path 118 in/out parameter. The string is not reallocated. Simply a '\0' 119 will be inserted to shorten the string. 120 */ 121 void oneDirUp(LPTSTR io_path) 122 { 123 WCHAR * pEnd = io_path + lstrlen(io_path) - 1; 124 while (pEnd > io_path //prevent crashing if provided string does not contain a backslash 125 && *pEnd != L'\\') 126 pEnd --; 127 *pEnd = L'\0'; 128 } 129 130 131 /* Returns the path to the program folder of the brand layer, 132 for example c:/openoffice.org 3/program 133 This path is either obtained from the environment variable UNO_PATH 134 or the registry item 135 "Software\\OpenOffice.org\\UNO\\InstallPath" 136 either in HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE 137 The return value must be freed with delete[] 138 */ 139 WCHAR * getInstallPath() 140 { 141 WCHAR * szInstallPath = NULL; 142 143 DWORD cChars = GetEnvironmentVariable(UNO_PATH, NULL, 0); 144 if (cChars > 0) 145 { 146 szInstallPath = new WCHAR[cChars]; 147 cChars = GetEnvironmentVariable(UNO_PATH, szInstallPath, cChars); 148 //If PATH is not set then it is no error 149 if (cChars == 0) 150 { 151 delete[] szInstallPath; 152 return NULL; 153 } 154 } 155 156 if (! szInstallPath) 157 { 158 szInstallPath = getPathFromRegistryKey( HKEY_CURRENT_USER, INSTALL_PATH ); 159 if ( szInstallPath == NULL ) 160 { 161 /* read the key's default value from HKEY_LOCAL_MACHINE */ 162 szInstallPath = getPathFromRegistryKey( HKEY_LOCAL_MACHINE, INSTALL_PATH ); 163 } 164 } 165 return szInstallPath; 166 } 167 168 /* Returns the path to the URE/bin path, where cppuhelper lib resides. 169 The returned string must be freed with delete[] 170 */ 171 WCHAR* getUnoPath() 172 { 173 WCHAR * szLinkPath = NULL; 174 WCHAR * szUrePath = NULL; 175 WCHAR * szUreBin = NULL; //the return value 176 177 WCHAR * szInstallPath = getInstallPath(); 178 if (szInstallPath) 179 { 180 //build the path tho the basis-link file 181 oneDirUp(szInstallPath); 182 int sizeLinkPath = lstrlen(szInstallPath) + lstrlen(INSTALL_PATH) + 1; 183 if (sizeLinkPath < MAX_PATH) 184 sizeLinkPath = MAX_PATH; 185 szLinkPath = new WCHAR[sizeLinkPath]; 186 szLinkPath[0] = L'\0'; 187 lstrcat(szLinkPath, szInstallPath); 188 lstrcat(szLinkPath, BASIS_LINK); 189 190 //get the path to the actual Basis folder 191 if (cli_ure::resolveLink(szLinkPath)) 192 { 193 //build the path to the ure-link file 194 int sizeUrePath = lstrlen(szLinkPath) + lstrlen(URE_LINK) + 1; 195 if (sizeUrePath < MAX_PATH) 196 sizeUrePath = MAX_PATH; 197 szUrePath = new WCHAR[sizeUrePath]; 198 szUrePath[0] = L'\0'; 199 lstrcat(szUrePath, szLinkPath); 200 lstrcat(szUrePath, URE_LINK); 201 202 //get the path to the actual Ure folder 203 if (cli_ure::resolveLink(szUrePath)) 204 { 205 //build the path to the URE/bin directory 206 szUreBin = new WCHAR[lstrlen(szUrePath) + lstrlen(URE_BIN) + 1]; 207 szUreBin[0] = L'\0'; 208 lstrcat(szUreBin, szUrePath); 209 lstrcat(szUreBin, URE_BIN); 210 } 211 } 212 } 213 #if OSL_DEBUG_LEVEL >=2 214 if (szUreBin) 215 { 216 fwprintf(stdout,L"[cli_cppuhelper]: Path to URE libraries:\n %s \n", szUreBin); 217 } 218 else 219 { 220 fwprintf(stdout,L"[cli_cppuhelper]: Failed to determine location of URE.\n"); 221 } 222 #endif 223 delete[] szInstallPath; 224 delete[] szLinkPath; 225 delete[] szUrePath; 226 return szUreBin; 227 } 228 229 230 /*We extend the path to contain the Ure/bin folder, 231 so that components can use osl_loadModule with arguments, such as 232 "reg3.dll". That is, the arguments are only the library names. 233 */ 234 void extendPath(LPCWSTR szUreBinPath) 235 { 236 if (!szUreBinPath) 237 return; 238 239 WCHAR * sEnvPath = NULL; 240 DWORD cChars = GetEnvironmentVariable(L"PATH", sEnvPath, 0); 241 if (cChars > 0) 242 { 243 sEnvPath = new WCHAR[cChars]; 244 cChars = GetEnvironmentVariable(L"PATH", sEnvPath, cChars); 245 //If PATH is not set then it is no error 246 if (cChars == 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND) 247 { 248 delete[] sEnvPath; 249 return; 250 } 251 } 252 //prepare the new PATH. Add the Ure/bin directory at the front. 253 //note also adding ';' 254 WCHAR * sNewPath = new WCHAR[lstrlen(sEnvPath) + lstrlen(szUreBinPath) + 2]; 255 sNewPath[0] = L'\0'; 256 lstrcat(sNewPath, szUreBinPath); 257 if (lstrlen(sEnvPath)) 258 { 259 lstrcat(sNewPath, L";"); 260 lstrcat(sNewPath, sEnvPath); 261 } 262 BOOL bSet = SetEnvironmentVariable(L"PATH", sNewPath); 263 264 delete[] sEnvPath; 265 delete[] sNewPath; 266 } 267 268 269 HMODULE loadFromPath(LPCWSTR sLibName) 270 { 271 if (sLibName == NULL) 272 return NULL; 273 274 WCHAR * szUreBinPath = getUnoPath(); 275 if (!szUreBinPath) 276 return NULL; 277 278 extendPath(szUreBinPath); 279 280 WCHAR* szFullPath = new WCHAR[lstrlen(sLibName) + lstrlen(szUreBinPath) + 2]; 281 szFullPath[0] = L'\0'; 282 lstrcat(szFullPath, szUreBinPath); 283 lstrcat(szFullPath, L"\\"); 284 lstrcat(szFullPath, sLibName); 285 HMODULE handle = LoadLibraryEx(szFullPath, NULL, 286 LOAD_WITH_ALTERED_SEARCH_PATH); 287 288 delete[] szFullPath; 289 delete[] szUreBinPath; 290 return handle; 291 } 292 293 /*Hook for delayed loading of libraries which this library is linked with. 294 This is a failure hook. That is, it is only called when the loading of 295 a library failed. It will be called when loading of cppuhelper failed. 296 Because we extend the PATH to the URE/bin folder while this function is 297 executed (see extendPath), all other libraries are found. 298 */ 299 extern "C" FARPROC WINAPI delayLoadHook( 300 unsigned dliNotify, 301 PDelayLoadInfo pdli 302 ) 303 { 304 if (dliNotify == dliFailLoadLib) 305 { 306 LPWSTR szLibName = NULL; 307 //Convert the ansi file name to wchar_t* 308 int size = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pdli->szDll, -1, NULL, 0); 309 if (size > 0) 310 { 311 szLibName = new WCHAR[size]; 312 if (! MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pdli->szDll, -1, szLibName, size)) 313 { 314 return 0; 315 } 316 } 317 HANDLE h = loadFromPath(szLibName); 318 delete[] szLibName; 319 return (FARPROC) h; 320 } 321 return 0; 322 } 323 } 324 325 ExternC 326 PfnDliHook __pfnDliFailureHook2 = delayLoadHook; 327 328 namespace uno 329 { 330 namespace util 331 { 332 333 /** Bootstrapping native UNO. 334 335 Bootstrapping requires the existence of many libraries which are contained 336 in an URE installation. To find and load these libraries the Windows 337 registry keys HKEY_CURRENT_USER\Software\OpenOffice.org\Layer\URE\1 338 and HKEY_LOCAL_MACHINE\Software\OpenOffice.org\Layer\URE\1 are examined. 339 These contain a named value UREINSTALLLOCATION which holds a path to the URE 340 installation folder. 341 */ 342 public __sealed __gc class Bootstrap 343 { 344 inline Bootstrap() {} 345 346 public: 347 348 /** Bootstraps the initial component context from a native UNO installation. 349 350 @see cppuhelper/bootstrap.hxx:defaultBootstrap_InitialComponentContext() 351 */ 352 static ::unoidl::com::sun::star::uno::XComponentContext * 353 defaultBootstrap_InitialComponentContext(); 354 355 /** Bootstraps the initial component context from a native UNO installation. 356 357 @param ini_file 358 a file URL of an ini file, e.g. uno.ini/unorc. (The ini file must 359 reside next to the cppuhelper library) 360 @param bootstrap_parameters 361 bootstrap parameters (maybe null) 362 363 @see cppuhelper/bootstrap.hxx:defaultBootstrap_InitialComponentContext() 364 */ 365 static ::unoidl::com::sun::star::uno::XComponentContext * 366 defaultBootstrap_InitialComponentContext( 367 ::System::String * ini_file, 368 ::System::Collections::IDictionaryEnumerator * 369 bootstrap_parameters ); 370 371 /** Bootstraps the initial component context from a native UNO installation. 372 373 @see cppuhelper/bootstrap.hxx:bootstrap() 374 */ 375 static ::unoidl::com::sun::star::uno::XComponentContext * 376 bootstrap(); 377 }; 378 379 //______________________________________________________________________________ 380 ::unoidl::com::sun::star::uno::XComponentContext * 381 Bootstrap::defaultBootstrap_InitialComponentContext( 382 ::System::String * ini_file, 383 ::System::Collections::IDictionaryEnumerator * bootstrap_parameters ) 384 { 385 if (0 != bootstrap_parameters) 386 { 387 bootstrap_parameters->Reset(); 388 while (bootstrap_parameters->MoveNext()) 389 { 390 OUString key( 391 String_to_ustring( __try_cast< ::System::String * >( 392 bootstrap_parameters->get_Key() ) ) ); 393 OUString value( 394 String_to_ustring( __try_cast< ::System::String * >( 395 bootstrap_parameters->get_Value() ) ) ); 396 397 ::rtl::Bootstrap::set( key, value ); 398 } 399 } 400 401 // bootstrap native uno 402 Reference< XComponentContext > xContext; 403 if (0 == ini_file) 404 { 405 xContext = ::cppu::defaultBootstrap_InitialComponentContext(); 406 } 407 else 408 { 409 xContext = ::cppu::defaultBootstrap_InitialComponentContext( 410 String_to_ustring( __try_cast< ::System::String * >( ini_file ) ) ); 411 } 412 413 return __try_cast< ::unoidl::com::sun::star::uno::XComponentContext * >( 414 to_cli( xContext ) ); 415 } 416 417 //______________________________________________________________________________ 418 ::unoidl::com::sun::star::uno::XComponentContext * 419 Bootstrap::defaultBootstrap_InitialComponentContext() 420 { 421 return defaultBootstrap_InitialComponentContext( 0, 0 ); 422 } 423 424 ::unoidl::com::sun::star::uno::XComponentContext * Bootstrap::bootstrap() 425 { 426 Reference<XComponentContext> xContext = ::cppu::bootstrap(); 427 return __try_cast< ::unoidl::com::sun::star::uno::XComponentContext * >( 428 to_cli( xContext ) ); 429 430 } 431 432 } 433 } 434