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