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