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