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