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