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