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 //--------------------------------------- 29 // 30 //--------------------------------------- 31 32 #ifdef _MSC_VER 33 #pragma warning(push, 1) /* disable warnings within system headers */ 34 #endif 35 #include <windows.h> 36 #ifdef _MSC_VER 37 #pragma warning(pop) 38 #endif 39 40 #include <malloc.h> 41 #include "registrywnt.hxx" 42 #include "registryvalueimpl.hxx" 43 #include "registryexception.hxx" 44 45 #include <assert.h> 46 47 #ifdef _MSC_VER 48 #pragma warning(disable : 4786 4350) 49 #endif 50 51 //--------------------------------------- 52 // 53 //--------------------------------------- 54 55 const size_t MAX_TMP_BUFF_SIZE = 1024 * sizeof(wchar_t); 56 57 58 //############################################ 59 // Creation 60 // only possible through WindowsRegistry class 61 //############################################ 62 63 64 //----------------------------------------------------- 65 /** Create instance and open the specified Registry key 66 */ 67 RegistryKeyImplWinNT::RegistryKeyImplWinNT(HKEY RootKey, const std::wstring& KeyName) : 68 RegistryKeyImpl(RootKey, KeyName) 69 { 70 } 71 72 //----------------------------------------------------- 73 /** Create instance and open the specified Registry key 74 */ 75 RegistryKeyImplWinNT::RegistryKeyImplWinNT(HKEY RootKey) : 76 RegistryKeyImpl(RootKey) 77 { 78 } 79 80 //----------------------------------------------------- 81 /** Create an instances of the specified Registry key, 82 the key is assumed to be already opened. 83 */ 84 RegistryKeyImplWinNT::RegistryKeyImplWinNT(HKEY RootKey, HKEY SubKey, const std::wstring& KeyName, bool Writeable) : 85 RegistryKeyImpl(RootKey, SubKey, KeyName, Writeable) 86 { 87 } 88 89 90 //############################################ 91 // Queries 92 //############################################ 93 94 95 //----------------------------------------------------- 96 /** The number of sub values of the key at hand 97 98 @precond IsOpen = true 99 100 @throws 101 */ 102 size_t RegistryKeyImplWinNT::GetSubValueCount() const 103 { 104 assert(IsOpen()); 105 106 DWORD nSubValues = 0; 107 108 LONG rc = RegQueryInfoKeyW( 109 m_hSubKey, 110 0, 0, 0, 0, 0, 0, &nSubValues, 0, 0, 0, 0); 111 112 if (ERROR_INVALID_HANDLE == rc) 113 throw RegistryIOException(rc); 114 else if (ERROR_SUCCESS != rc) 115 throw RegistryException(rc); 116 117 return nSubValues; 118 } 119 120 //----------------------------------------------------- 121 /** The number of sub-keys of the key at hand 122 123 @precond IsOpen = true 124 125 @throws 126 */ 127 size_t RegistryKeyImplWinNT::GetSubKeyCount() const 128 { 129 assert(IsOpen()); 130 131 DWORD nSubKeys = 0; 132 133 LONG rc = RegQueryInfoKeyA( 134 m_hSubKey, 135 0, 0, 0, &nSubKeys, 0, 0, 0, 0, 0, 0, 0); 136 137 if (ERROR_INVALID_HANDLE == rc) 138 throw RegistryIOException(rc); 139 else if (ERROR_SUCCESS != rc) 140 throw RegistryException(rc); 141 142 return nSubKeys; 143 } 144 145 //----------------------------------------------------- 146 /** 147 */ 148 StringListPtr RegistryKeyImplWinNT::GetSubKeyNames() const 149 { 150 assert(IsOpen()); 151 152 wchar_t buff[1024]; 153 DWORD buff_size = sizeof(buff); 154 FILETIME ftime; 155 156 StringList* key_names = new StringList(); 157 158 LONG rc = ERROR_SUCCESS; 159 160 for (DWORD i = 0; /* left empty */; i++) 161 { 162 rc = RegEnumKeyExW( 163 m_hSubKey, i, buff, &buff_size, 164 0, 0, 0, &ftime); 165 166 if (ERROR_SUCCESS != rc && 167 ERROR_MORE_DATA != rc) 168 break; 169 170 buff_size = sizeof(buff); 171 172 key_names->push_back(buff); 173 } 174 175 if (ERROR_INVALID_HANDLE == rc) 176 throw RegistryIOException(rc); 177 else if (ERROR_NO_MORE_ITEMS != rc && ERROR_SUCCESS != rc) 178 throw RegistryException(rc); 179 180 #if (_MSC_VER < 1300) && !defined(__MINGW32__) 181 return key_names; 182 #else 183 return (StringListPtr) key_names; 184 #endif 185 } 186 187 //----------------------------------------------------- 188 /** 189 */ 190 StringListPtr RegistryKeyImplWinNT::GetSubValueNames() const 191 { 192 assert(IsOpen()); 193 194 wchar_t buff[1024]; 195 DWORD buff_size = sizeof(buff); 196 197 StringList* value_names = new StringList(); 198 199 LONG rc = ERROR_SUCCESS; 200 201 for (DWORD i = 0; /* left empty */; i++) 202 { 203 rc = RegEnumValueW( 204 m_hSubKey, i, buff, &buff_size, 205 0, 0, 0, 0); 206 207 if (ERROR_SUCCESS != rc && 208 ERROR_MORE_DATA != rc) 209 break; 210 211 buff_size = sizeof(buff); 212 213 value_names->push_back(buff); 214 } 215 216 if (ERROR_INVALID_HANDLE == rc) 217 throw RegistryIOException(rc); 218 else if (ERROR_NO_MORE_ITEMS != rc && ERROR_SUCCESS != rc) 219 throw RegistryException(rc); 220 221 #if (_MSC_VER < 1300) && !defined(__MINGW32__) 222 return value_names; 223 #else 224 return (StringListPtr) value_names; 225 #endif 226 } 227 228 //----------------------------------------------------- 229 /** Get the specified registry value 230 231 @precond IsOpen = true 232 */ 233 RegistryValue RegistryKeyImplWinNT::GetValue(const std::wstring& Name) const 234 { 235 assert(IsOpen()); 236 237 DWORD Type; 238 wchar_t buff[MAX_TMP_BUFF_SIZE]; 239 DWORD size = sizeof(buff); 240 241 LONG rc = RegQueryValueExW( 242 m_hSubKey, 243 Name.c_str(), 244 0, 245 &Type, 246 reinterpret_cast<LPBYTE>(buff), 247 &size); 248 249 if (ERROR_FILE_NOT_FOUND == rc) 250 throw RegistryValueNotFoundException(rc); 251 else if (ERROR_ACCESS_DENIED == rc) 252 throw RegistryAccessDeniedException(rc); 253 else if (ERROR_SUCCESS != rc) 254 throw RegistryException(rc); 255 256 RegistryValue regval; 257 258 if (REG_DWORD == Type) 259 { 260 regval = RegistryValue(new RegistryValueImpl(Name, *(reinterpret_cast<int*>(buff)))); 261 } 262 else if (REG_SZ == Type || REG_EXPAND_SZ == Type || REG_MULTI_SZ == Type) 263 { 264 if (size > 0) 265 regval = RegistryValue(new RegistryValueImpl(Name, std::wstring(reinterpret_cast<wchar_t*>(buff)))); 266 else 267 regval = RegistryValue(new RegistryValueImpl(Name, std::wstring())); 268 } 269 else 270 { 271 assert(false); 272 } 273 274 return regval; 275 } 276 277 //----------------------------------------------------- 278 /** Get the specified registry value, return the given 279 default value if value not found 280 281 @precond IsOpen = true 282 */ 283 RegistryValue RegistryKeyImplWinNT::GetValue(const std::wstring& Name, const RegistryValue& Default) const 284 { 285 assert(IsOpen()); 286 287 DWORD Type; 288 wchar_t buff[MAX_TMP_BUFF_SIZE]; 289 DWORD size = sizeof(buff); 290 291 LONG rc = RegQueryValueExW( 292 m_hSubKey, 293 Name.c_str(), 294 0, 295 &Type, 296 reinterpret_cast<LPBYTE>(buff), 297 &size); 298 299 if (ERROR_FILE_NOT_FOUND == rc) 300 { 301 #if (_MSC_VER < 1300) && !defined(__MINGW32__) 302 return Default; 303 #else 304 RegistryValue regval_ptr; 305 regval_ptr = RegistryValue(new RegistryValueImpl(*Default)); 306 return regval_ptr; 307 #endif 308 } 309 310 if (ERROR_ACCESS_DENIED == rc) 311 throw RegistryAccessDeniedException(rc); 312 else if (ERROR_SUCCESS != rc) 313 throw RegistryException(rc); 314 315 RegistryValue regval; 316 317 if (REG_DWORD == Type) 318 regval = RegistryValue(new RegistryValueImpl(Name, *reinterpret_cast<int*>(buff))); 319 else if (REG_SZ == Type || REG_EXPAND_SZ == Type || REG_MULTI_SZ == Type) 320 regval = RegistryValue(new RegistryValueImpl(Name, std::wstring(reinterpret_cast<wchar_t*>(buff)))); 321 else 322 assert(false); 323 324 return regval; 325 } 326 327 328 //############################################ 329 // Commands 330 //############################################ 331 332 333 //----------------------------------------------------- 334 /** Open the registry key, has no effect if 335 the key is already open 336 337 @precond IsOpen = false 338 339 @throws RegistryKeyNotFoundException 340 RegistryWriteAccessDenyException 341 RegistryAccessDenyException 342 */ 343 void RegistryKeyImplWinNT::Open(bool Writeable) 344 { 345 assert(!IsOpen()); 346 347 REGSAM regsam = KEY_READ; 348 349 if (Writeable) 350 regsam |= KEY_WRITE; 351 352 LONG rc = RegOpenKeyExW( 353 m_hRootKey, 354 m_KeyName.c_str(), 355 0, 356 regsam, 357 &m_hSubKey); 358 359 if (ERROR_FILE_NOT_FOUND == rc) 360 throw RegistryKeyNotFoundException(rc); 361 else if (ERROR_ACCESS_DENIED == rc) 362 throw RegistryAccessDeniedException(rc); 363 else if (ERROR_SUCCESS != rc) 364 throw RegistryException(rc); 365 366 m_IsWriteable = Writeable; 367 368 assert(IsOpen()); 369 } 370 371 //----------------------------------------------------- 372 /** Open the specified sub-key of the registry key 373 at hand 374 375 @precond IsOpen = true 376 HasSubKey(Name) = true 377 378 @throws RegistryIOException 379 RegistryKeyNotFoundException 380 RegistryAccessDeniedException 381 */ 382 RegistryKey RegistryKeyImplWinNT::OpenSubKey(const std::wstring& Name, bool Writeable) 383 { 384 RegistryKey regkey(new RegistryKeyImplWinNT(m_hSubKey, Name)); 385 regkey->Open(Writeable); 386 return regkey; 387 } 388 389 //----------------------------------------------------- 390 /** Creates a new sub-key below the key at hand 391 392 @precond IsOpen = true 393 IsWriteable = true 394 395 @throws RegistryIOException 396 RegistryWriteAccessDenyException 397 */ 398 399 RegistryKey RegistryKeyImplWinNT::CreateSubKey(const std::wstring& Name) 400 { 401 assert(IsOpen()); 402 assert(IsWriteable()); 403 404 HKEY hRoot = IsRootKey() ? m_hRootKey : m_hSubKey; 405 406 HKEY hKey; 407 408 LONG rc = RegCreateKeyExW( 409 hRoot, 410 Name.c_str(), 411 0, 412 0, 413 REG_OPTION_NON_VOLATILE, 414 KEY_READ | KEY_WRITE, 415 0, 416 &hKey, 417 0); 418 419 if (ERROR_INVALID_HANDLE == rc) 420 throw RegistryIOException(rc); 421 else if (ERROR_ACCESS_DENIED == rc) 422 throw RegistryAccessDeniedException(rc); 423 else if (ERROR_SUCCESS != rc) 424 throw RegistryException(rc); 425 426 return RegistryKey(new RegistryKeyImplWinNT(hRoot, hKey, Name)); 427 } 428 429 //----------------------------------------------------- 430 /** Deletes a sub-key below the key at hand, the 431 key must not have sub-keys 432 433 @precond IsOpen = true 434 IsWriteable = true 435 436 @throws RegistryIOException 437 RegistryWriteAccessDenyException 438 */ 439 void RegistryKeyImplWinNT::DeleteSubKey(const std::wstring& Name) 440 { 441 assert(IsOpen()); 442 assert(IsWriteable()); 443 assert(HasSubKey(Name)); 444 445 RegistryKey SubKey = OpenSubKey(Name); 446 447 size_t nSubKeyCount = SubKey->GetSubKeyCount(); 448 449 assert(0 == nSubKeyCount); 450 451 if (nSubKeyCount) 452 throw RegistryInvalidOperationException(ERROR_NOT_SUPPORTED); 453 454 LONG rc = RegDeleteKeyW(m_hSubKey, Name.c_str()); 455 456 if (ERROR_INVALID_HANDLE == rc) 457 throw RegistryIOException(rc); 458 else if (ERROR_ACCESS_DENIED == rc) 459 throw RegistryAccessDeniedException(rc); 460 else if (ERROR_SUCCESS != rc) 461 throw RegistryException(rc); 462 } 463 464 //----------------------------------------------------- 465 /** Deletes a sub-key below the key at hand with all 466 its sub-keys 467 468 @precond IsOpen = true 469 IsWriteable = true; 470 471 @throws RegistryIOException 472 RegistryWriteAccessDenyException 473 */ 474 void RegistryKeyImplWinNT::DeleteSubKeyTree(const std::wstring& Name) 475 { 476 ImplDeleteSubKeyTree(m_hSubKey, Name); 477 } 478 479 //----------------------------------------------------- 480 /** Deletes a sub-key below the key at hand with all 481 its sub-keys 482 483 @precond IsOpen = true 484 IsWriteable = true; 485 486 @throws RegistryIOException 487 RegistryWriteAccessDenyException 488 */ 489 LONG RegistryKeyImplWinNT::ImplDeleteSubKeyTree(HKEY RootKey, const std::wstring& Name) 490 { 491 assert(IsOpen()); 492 493 HKEY hKey; 494 495 LONG rc = RegOpenKeyExW( 496 RootKey, 497 Name.c_str(), 498 0, 499 KEY_READ | DELETE, 500 &hKey); 501 502 if (ERROR_SUCCESS == rc) 503 { 504 wchar_t* lpSubKey; 505 DWORD nMaxSubKeyLen; 506 507 rc = RegQueryInfoKeyW( 508 hKey, 0, 0, 0, 0, 509 &nMaxSubKeyLen, 510 0, 0, 0, 0, 0, 0); 511 512 nMaxSubKeyLen++; // space for trailing '\0' 513 514 lpSubKey = reinterpret_cast<wchar_t*>( 515 _alloca(nMaxSubKeyLen*sizeof(wchar_t))); 516 517 while (ERROR_SUCCESS == rc) 518 { 519 DWORD nLen = nMaxSubKeyLen; 520 521 rc = RegEnumKeyExW( 522 hKey, 523 0, // always index zero 524 lpSubKey, 525 &nLen, 526 0, 0, 0, 0); 527 528 if (ERROR_NO_MORE_ITEMS == rc) 529 { 530 rc = RegDeleteKeyW(RootKey, Name.c_str()); 531 break; 532 } 533 else if (rc == ERROR_SUCCESS) 534 { 535 rc = ImplDeleteSubKeyTree(hKey, lpSubKey); 536 } 537 538 } // while 539 540 RegCloseKey(hKey); 541 542 } // if 543 544 if (ERROR_INVALID_HANDLE == rc) 545 throw RegistryIOException(rc); 546 else if (ERROR_ACCESS_DENIED == rc) 547 throw RegistryAccessDeniedException(rc); 548 else if (ERROR_FILE_NOT_FOUND == rc) 549 throw RegistryKeyNotFoundException(rc); 550 else if (ERROR_SUCCESS != rc) 551 throw RegistryException(rc); 552 553 return rc; 554 } 555 556 //----------------------------------------------------- 557 /** Delete the specified value 558 559 @precond IsOpen = true 560 IsWriteable = true 561 HasValue(Name) = true 562 563 @throws RegistryIOException 564 RegistryWriteAccessDeniedException 565 RegistryValueNotFoundException 566 */ 567 void RegistryKeyImplWinNT::DeleteValue(const std::wstring& Name) 568 { 569 assert(IsOpen()); 570 assert(HasValue(Name)); 571 assert(IsWriteable()); 572 573 LONG rc = RegDeleteValueW( 574 m_hSubKey, 575 Name.c_str()); 576 577 if (ERROR_INVALID_HANDLE == rc) 578 throw RegistryIOException(rc); 579 else if (ERROR_ACCESS_DENIED == rc) 580 throw RegistryNoWriteAccessException(rc); 581 else if (ERROR_FILE_NOT_FOUND == rc) 582 throw RegistryValueNotFoundException(rc); 583 else if (ERROR_SUCCESS != rc) 584 throw RegistryException(rc); 585 } 586 587 //----------------------------------------------------- 588 /** Set the specified registry value 589 590 @precond IsOpen = true 591 IsWriteable = true 592 593 @throws RegistryIOException 594 RegistryWriteAccessDenyException 595 */ 596 void RegistryKeyImplWinNT::SetValue(const RegistryValue& Value) 597 { 598 assert(IsOpen()); 599 assert(IsWriteable()); 600 601 LONG rc = RegSetValueExW( 602 m_hSubKey, 603 Value->GetName().c_str(), 604 0, 605 Value->GetType(), 606 reinterpret_cast<const unsigned char*>(Value->GetDataBuffer()), 607 static_cast<DWORD>(Value->GetDataSize())); 608 609 if (ERROR_INVALID_HANDLE == rc) 610 throw RegistryIOException(rc); 611 else if (ERROR_ACCESS_DENIED == rc) 612 throw RegistryAccessDeniedException(rc); 613 else if (ERROR_SUCCESS != rc) 614 throw RegistryException(rc); 615 } 616 617 618 619 620