1 /* 2 * ReactOS ATL 3 * 4 * Copyright 2005 Jacek Caban 5 * Copyright 2009 Andrew Hill <ash77@reactos.org> 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22 #pragma once 23 24 class IRegistrarBase : public IUnknown 25 { 26 public: 27 virtual HRESULT STDMETHODCALLTYPE AddReplacement(LPCOLESTR key, LPCOLESTR item) = 0; 28 virtual HRESULT STDMETHODCALLTYPE ClearReplacements() = 0; 29 }; 30 31 namespace ATL 32 { 33 34 class CRegObject : public IRegistrarBase 35 { 36 public: 37 typedef struct rep_list_str 38 { 39 LPOLESTR key; 40 LPOLESTR item; 41 int key_len; 42 struct rep_list_str *next; 43 } rep_list; 44 45 typedef struct 46 { 47 LPOLESTR str; 48 DWORD alloc; 49 DWORD len; 50 } strbuf; 51 52 rep_list *m_rep; 53 54 public: 55 CRegObject() 56 { 57 m_rep = NULL; 58 } 59 60 ~CRegObject() 61 { 62 HRESULT hResult; 63 64 hResult = ClearReplacements(); 65 ATLASSERT(SUCCEEDED(hResult)); 66 (void)hResult; 67 } 68 69 HRESULT STDMETHODCALLTYPE QueryInterface(const IID & /* riid */, void ** /* ppvObject */ ) 70 { 71 ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function")); 72 return E_NOTIMPL; 73 } 74 75 ULONG STDMETHODCALLTYPE AddRef() 76 { 77 ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function")); 78 return 1; 79 } 80 81 ULONG STDMETHODCALLTYPE Release() 82 { 83 ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function")); 84 return 0; 85 } 86 87 HRESULT STDMETHODCALLTYPE AddReplacement(LPCOLESTR key, LPCOLESTR item) 88 { 89 int len; 90 rep_list *new_rep; 91 92 new_rep = reinterpret_cast<rep_list *>(HeapAlloc(GetProcessHeap(), 0, sizeof(rep_list))); 93 if (new_rep == NULL) 94 return E_OUTOFMEMORY; 95 96 new_rep->key_len = lstrlenW(key); 97 new_rep->key = reinterpret_cast<OLECHAR *>(HeapAlloc(GetProcessHeap(), 0, (new_rep->key_len + 1) * sizeof(OLECHAR))); 98 if (new_rep->key == NULL) 99 { 100 HeapFree(GetProcessHeap(), 0, new_rep); 101 return E_OUTOFMEMORY; 102 } 103 memcpy(new_rep->key, key, (new_rep->key_len + 1) * sizeof(OLECHAR)); 104 105 len = lstrlenW(item) + 1; 106 new_rep->item = reinterpret_cast<OLECHAR *>(HeapAlloc(GetProcessHeap(), 0, len * sizeof(OLECHAR))); 107 if (new_rep->item == NULL) 108 { 109 HeapFree(GetProcessHeap(), 0, new_rep->key); 110 HeapFree(GetProcessHeap(), 0, new_rep); 111 return E_OUTOFMEMORY; 112 } 113 memcpy(new_rep->item, item, len * sizeof(OLECHAR)); 114 115 new_rep->next = m_rep; 116 m_rep = new_rep; 117 118 return S_OK; 119 } 120 121 HRESULT STDMETHODCALLTYPE ClearReplacements() 122 { 123 rep_list *iter; 124 rep_list *iter2; 125 126 iter = m_rep; 127 while (iter) 128 { 129 iter2 = iter->next; 130 HeapFree(GetProcessHeap(), 0, iter->key); 131 HeapFree(GetProcessHeap(), 0, iter->item); 132 HeapFree(GetProcessHeap(), 0, iter); 133 iter = iter2; 134 } 135 136 m_rep = NULL; 137 return S_OK; 138 } 139 140 HRESULT STDMETHODCALLTYPE ResourceRegisterSz(LPCOLESTR resFileName, LPCOLESTR szID, LPCOLESTR szType) 141 { 142 return RegisterWithResource(resFileName, szID, szType, TRUE); 143 } 144 145 HRESULT STDMETHODCALLTYPE ResourceUnregisterSz(LPCOLESTR resFileName, LPCOLESTR szID, LPCOLESTR szType) 146 { 147 return RegisterWithResource(resFileName, szID, szType, FALSE); 148 } 149 150 HRESULT STDMETHODCALLTYPE FileRegister(LPCOLESTR fileName) 151 { 152 return RegisterWithFile(fileName, TRUE); 153 } 154 155 HRESULT STDMETHODCALLTYPE FileUnregister(LPCOLESTR fileName) 156 { 157 return RegisterWithFile(fileName, FALSE); 158 } 159 160 HRESULT STDMETHODCALLTYPE StringRegister(LPCOLESTR data) 161 { 162 return RegisterWithString(data, TRUE); 163 } 164 165 HRESULT STDMETHODCALLTYPE StringUnregister(LPCOLESTR data) 166 { 167 return RegisterWithString(data, FALSE); 168 } 169 170 HRESULT STDMETHODCALLTYPE ResourceRegister(LPCOLESTR resFileName, UINT nID, LPCOLESTR szType) 171 { 172 return ResourceRegisterSz(resFileName, MAKEINTRESOURCEW(nID), szType); 173 } 174 175 HRESULT STDMETHODCALLTYPE ResourceUnregister(LPCOLESTR resFileName, UINT nID, LPCOLESTR szType) 176 { 177 return ResourceUnregisterSz(resFileName, MAKEINTRESOURCEW(nID), szType); 178 } 179 180 protected: 181 HRESULT STDMETHODCALLTYPE RegisterWithResource(LPCOLESTR resFileName, LPCOLESTR szID, LPCOLESTR szType, BOOL doRegister) 182 { 183 return resource_register(resFileName, szID, szType, doRegister); 184 } 185 186 HRESULT STDMETHODCALLTYPE RegisterWithFile(LPCOLESTR fileName, BOOL doRegister) 187 { 188 return file_register(fileName, doRegister); 189 } 190 191 HRESULT STDMETHODCALLTYPE RegisterWithString(LPCOLESTR data, BOOL doRegister) 192 { 193 return string_register(data, doRegister); 194 } 195 196 private: 197 inline LONG RegDeleteTreeX(HKEY parentKey, LPCWSTR subKeyName) 198 { 199 wchar_t szBuffer[256]; 200 DWORD dwSize; 201 FILETIME time; 202 HKEY childKey; 203 LONG lRes; 204 205 ATLASSERT(parentKey != NULL); 206 lRes = RegOpenKeyExW(parentKey, subKeyName, 0, KEY_READ | KEY_WRITE, &childKey); 207 if (lRes != ERROR_SUCCESS) 208 return lRes; 209 210 dwSize = sizeof(szBuffer) / sizeof(szBuffer[0]); 211 while (RegEnumKeyExW(parentKey, 0, szBuffer, &dwSize, NULL, NULL, NULL, &time) == ERROR_SUCCESS) 212 { 213 lRes = RegDeleteTreeX(childKey, szBuffer); 214 if (lRes != ERROR_SUCCESS) 215 return lRes; 216 dwSize = sizeof(szBuffer) / sizeof(szBuffer[0]); 217 } 218 RegCloseKey(childKey); 219 return RegDeleteKeyW(parentKey, subKeyName); 220 } 221 222 HRESULT strbuf_init(strbuf *buf) 223 { 224 buf->str = reinterpret_cast<LPOLESTR>(HeapAlloc(GetProcessHeap(), 0, 128 * sizeof(WCHAR))); 225 if (buf->str == NULL) 226 return E_OUTOFMEMORY; 227 buf->alloc = 128; 228 buf->len = 0; 229 return S_OK; 230 } 231 232 HRESULT strbuf_write(LPCOLESTR str, strbuf *buf, int len) 233 { 234 LPOLESTR newBuffer; 235 236 if (len == -1) 237 len = lstrlenW(str); 238 if (buf->len + len + 1 >= buf->alloc) 239 { 240 buf->alloc = (buf->len + len) * 2; 241 newBuffer = reinterpret_cast<LPOLESTR>(HeapReAlloc(GetProcessHeap(), 0, buf->str, buf->alloc * sizeof(WCHAR))); 242 if (newBuffer == NULL) 243 return E_OUTOFMEMORY; 244 buf->str = newBuffer; 245 } 246 memcpy(buf->str + buf->len, str, len * sizeof(OLECHAR)); 247 buf->len += len; 248 buf->str[buf->len] = '\0'; 249 return S_OK; 250 } 251 252 253 HRESULT file_register(LPCOLESTR fileName, BOOL do_register) 254 { 255 HANDLE file; 256 DWORD filelen; 257 DWORD len; 258 LPWSTR regstrw; 259 LPSTR regstra; 260 LRESULT lres; 261 HRESULT hResult; 262 263 file = CreateFileW(fileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); 264 if (file != INVALID_HANDLE_VALUE) 265 { 266 filelen = GetFileSize(file, NULL); 267 regstra = reinterpret_cast<LPSTR>(HeapAlloc(GetProcessHeap(), 0, filelen)); 268 if (regstra == NULL) 269 return E_OUTOFMEMORY; 270 lres = ReadFile(file, regstra, filelen, NULL, NULL); 271 if (lres == ERROR_SUCCESS) 272 { 273 len = MultiByteToWideChar(CP_ACP, 0, regstra, filelen, NULL, 0) + 1; 274 regstrw = reinterpret_cast<LPWSTR>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR))); 275 if (regstrw == NULL) 276 { 277 HeapFree(GetProcessHeap(), 0, regstra); 278 return E_OUTOFMEMORY; 279 } 280 MultiByteToWideChar(CP_ACP, 0, regstra, filelen, regstrw, len); 281 regstrw[len - 1] = '\0'; 282 283 hResult = string_register(regstrw, do_register); 284 285 HeapFree(GetProcessHeap(), 0, regstrw); 286 } 287 else 288 { 289 hResult = HRESULT_FROM_WIN32(lres); 290 } 291 HeapFree(GetProcessHeap(), 0, regstra); 292 CloseHandle(file); 293 } 294 else 295 { 296 hResult = HRESULT_FROM_WIN32(GetLastError()); 297 } 298 299 return hResult; 300 } 301 302 HRESULT resource_register(LPCOLESTR resFileName, LPCOLESTR szID, LPCOLESTR szType, BOOL do_register) 303 { 304 HINSTANCE hins; 305 HRSRC src; 306 HGLOBAL regstra; 307 LPWSTR regstrw; 308 DWORD len; 309 DWORD reslen; 310 HRESULT hResult; 311 312 hins = LoadLibraryExW(resFileName, NULL, LOAD_LIBRARY_AS_DATAFILE); 313 if (hins) 314 { 315 src = FindResourceW(hins, szID, szType); 316 if (src) 317 { 318 regstra = LoadResource(hins, src); 319 reslen = SizeofResource(hins, src); 320 if (regstra) 321 { 322 len = MultiByteToWideChar(CP_ACP, 0, reinterpret_cast<LPCSTR>(regstra), reslen, NULL, 0) + 1; 323 regstrw = reinterpret_cast<LPWSTR>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR))); 324 if (regstrw == NULL) 325 return E_OUTOFMEMORY; 326 MultiByteToWideChar(CP_ACP, 0, reinterpret_cast<LPCSTR>(regstra), reslen, regstrw, len); 327 regstrw[len - 1] = '\0'; 328 329 hResult = string_register(regstrw, do_register); 330 331 HeapFree(GetProcessHeap(), 0, regstrw); 332 } 333 else 334 hResult = HRESULT_FROM_WIN32(GetLastError()); 335 } 336 else 337 hResult = HRESULT_FROM_WIN32(GetLastError()); 338 FreeLibrary(hins); 339 } 340 else 341 hResult = HRESULT_FROM_WIN32(GetLastError()); 342 343 return hResult; 344 } 345 346 HRESULT string_register(LPCOLESTR data, BOOL do_register) 347 { 348 strbuf buf; 349 HRESULT hResult; 350 351 hResult = strbuf_init(&buf); 352 if (FAILED(hResult)) 353 return hResult; 354 hResult = do_preprocess(data, &buf); 355 if (SUCCEEDED(hResult)) 356 { 357 hResult = do_process_root_key(buf.str, do_register); 358 if (FAILED(hResult) && do_register) 359 do_process_root_key(buf.str, FALSE); 360 } 361 362 HeapFree(GetProcessHeap(), 0, buf.str); 363 return hResult; 364 } 365 366 HRESULT do_preprocess(LPCOLESTR data, strbuf *buf) 367 { 368 LPCOLESTR iter; 369 LPCOLESTR iter2; 370 rep_list *rep_iter; 371 HRESULT hResult; 372 373 iter2 = data; 374 iter = wcschr(data, '%'); 375 while (iter) 376 { 377 hResult = strbuf_write(iter2, buf, static_cast<int>(iter - iter2)); 378 if (FAILED(hResult)) 379 return hResult; 380 381 iter2 = ++iter; 382 if (!*iter2) 383 return DISP_E_EXCEPTION; 384 iter = wcschr(iter2, '%'); 385 if (!iter) 386 return DISP_E_EXCEPTION; 387 388 if (iter == iter2) 389 { 390 hResult = strbuf_write(L"%", buf, 1); 391 if (FAILED(hResult)) 392 return hResult; 393 } 394 else 395 { 396 for (rep_iter = m_rep; rep_iter; rep_iter = rep_iter->next) 397 { 398 if (rep_iter->key_len == iter - iter2 && !_memicmp(iter2, rep_iter->key, rep_iter->key_len * sizeof(wchar_t))) 399 break; 400 } 401 if (!rep_iter) 402 return DISP_E_EXCEPTION; 403 404 hResult = strbuf_write(rep_iter->item, buf, -1); 405 if (FAILED(hResult)) 406 return hResult; 407 } 408 409 iter2 = ++iter; 410 iter = wcschr(iter, '%'); 411 } 412 413 hResult = strbuf_write(iter2, buf, -1); 414 if (FAILED(hResult)) 415 return hResult; 416 417 return S_OK; 418 } 419 420 HRESULT get_word(LPCOLESTR *str, strbuf *buf) 421 { 422 LPCOLESTR iter; 423 LPCOLESTR iter2; 424 HRESULT hResult; 425 426 iter2 = *str; 427 buf->len = 0; 428 buf->str[0] = '\0'; 429 430 while (iswspace (*iter2)) 431 iter2++; 432 iter = iter2; 433 if (!*iter) 434 { 435 *str = iter; 436 return S_OK; 437 } 438 439 if (*iter == '}' || *iter == '=') 440 { 441 hResult = strbuf_write(iter++, buf, 1); 442 if (FAILED(hResult)) 443 return hResult; 444 } 445 else if (*iter == '\'') 446 { 447 iter2 = ++iter; 448 iter = wcschr(iter, '\''); 449 if (!iter) 450 { 451 *str = iter; 452 return DISP_E_EXCEPTION; 453 } 454 hResult = strbuf_write(iter2, buf, static_cast<int>(iter - iter2)); 455 if (FAILED(hResult)) 456 return hResult; 457 iter++; 458 } 459 else 460 { 461 while (*iter && !iswspace(*iter)) 462 iter++; 463 hResult = strbuf_write(iter2, buf, static_cast<int>(iter - iter2)); 464 if (FAILED(hResult)) 465 return hResult; 466 } 467 468 while (iswspace(*iter)) 469 iter++; 470 *str = iter; 471 return S_OK; 472 } 473 474 inline unsigned int HexToBin(OLECHAR a) 475 { 476 if (a >= '0' && a <= '9') 477 return a - '0'; 478 if (a >= 'A' && a <= 'F') 479 return a - 'A' + 10; 480 if (a >= 'a' && a <= 'f') 481 return a - 'a' + 10; 482 ATLASSERT(false); 483 return 0; 484 } 485 486 HRESULT do_process_key(LPCOLESTR *pstr, HKEY parent_key, strbuf *buf, BOOL do_register) 487 { 488 LPCOLESTR iter; 489 HRESULT hres; 490 LONG lres; 491 HKEY hkey; 492 strbuf name; 493 494 enum { 495 NORMAL, 496 NO_REMOVE, 497 IS_VAL, 498 FORCE_REMOVE, 499 DO_DELETE 500 } key_type = NORMAL; 501 502 static const wchar_t *wstrNoRemove = L"NoRemove"; 503 static const wchar_t *wstrForceRemove = L"ForceRemove"; 504 static const wchar_t *wstrDelete = L"Delete"; 505 static const wchar_t *wstrval = L"val"; 506 507 iter = *pstr; 508 hkey = NULL; 509 hres = get_word(&iter, buf); 510 if (FAILED(hres)) 511 return hres; 512 hres = strbuf_init(&name); 513 if (FAILED(hres)) 514 return hres; 515 516 while(buf->str[1] || buf->str[0] != '}') 517 { 518 key_type = NORMAL; 519 if (!lstrcmpiW(buf->str, wstrNoRemove)) 520 key_type = NO_REMOVE; 521 else if (!lstrcmpiW(buf->str, wstrForceRemove)) 522 key_type = FORCE_REMOVE; 523 else if (!lstrcmpiW(buf->str, wstrval)) 524 key_type = IS_VAL; 525 else if (!lstrcmpiW(buf->str, wstrDelete)) 526 key_type = DO_DELETE; 527 528 if (key_type != NORMAL) 529 { 530 hres = get_word(&iter, buf); 531 if (FAILED(hres)) 532 break; 533 } 534 535 if (do_register) 536 { 537 if (key_type == IS_VAL) 538 { 539 hkey = parent_key; 540 hres = strbuf_write(buf->str, &name, -1); 541 if (FAILED(hres)) 542 return hres; 543 } 544 else if (key_type == DO_DELETE) 545 { 546 RegDeleteTreeX(parent_key, buf->str); 547 } 548 else 549 { 550 if (key_type == FORCE_REMOVE) 551 RegDeleteTreeX(parent_key, buf->str); 552 lres = RegCreateKeyW(parent_key, buf->str, &hkey); 553 if (lres != ERROR_SUCCESS) 554 { 555 hres = HRESULT_FROM_WIN32(lres); 556 break; 557 } 558 } 559 } 560 else if (key_type != IS_VAL && key_type != DO_DELETE) 561 { 562 hres = strbuf_write(buf->str, &name, -1); 563 if (FAILED(hres)) 564 return hres; 565 lres = RegOpenKeyW(parent_key, buf->str, &hkey); 566 if (lres != ERROR_SUCCESS) 567 { 568 } 569 } 570 571 if (key_type != DO_DELETE && *iter == '=') 572 { 573 iter++; 574 hres = get_word(&iter, buf); 575 if (FAILED(hres)) 576 break; 577 if (buf->len != 1) 578 { 579 hres = DISP_E_EXCEPTION; 580 break; 581 } 582 if (do_register) 583 { 584 switch(buf->str[0]) 585 { 586 case 's': 587 hres = get_word(&iter, buf); 588 if (FAILED(hres)) 589 break; 590 lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_SZ, (PBYTE)buf->str, 591 (lstrlenW(buf->str) + 1) * sizeof(WCHAR)); 592 if (lres != ERROR_SUCCESS) 593 hres = HRESULT_FROM_WIN32(lres); 594 break; 595 case 'e': 596 hres = get_word(&iter, buf); 597 if (FAILED(hres)) 598 break; 599 lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_EXPAND_SZ, (PBYTE)buf->str, 600 (lstrlenW(buf->str) + 1) * sizeof(WCHAR)); 601 if (lres != ERROR_SUCCESS) 602 hres = HRESULT_FROM_WIN32(lres); 603 break; 604 case 'd': 605 { 606 hres = get_word(&iter, buf); 607 if (FAILED(hres)) 608 break; 609 WCHAR *end; 610 DWORD dw; 611 if ((buf->str[0] == '0' && buf->str[1] == 'x') || (buf->str[0] == '&' && buf->str[1] == 'H')) 612 dw = wcstoul(&buf->str[2], &end, 16); 613 else 614 dw = wcstol(&buf->str[0], &end, 10); 615 lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_DWORD, (PBYTE)&dw, sizeof(dw)); 616 if (lres != ERROR_SUCCESS) 617 hres = HRESULT_FROM_WIN32(lres); 618 break; 619 } 620 case 'b': 621 { 622 DWORD count; 623 DWORD curIndex; 624 625 hres = get_word(&iter, buf); 626 if (FAILED(hres)) 627 break; 628 count = buf->len; 629 if ((count & 1) != 0) 630 return DISP_E_EXCEPTION; 631 count = count / 2; 632 for (curIndex = 0; curIndex < count; curIndex++) 633 ((BYTE*)buf->str)[curIndex] = (HexToBin(buf->str[curIndex * 2]) << 4) | HexToBin(buf->str[curIndex * 2 + 1]); 634 lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_BINARY, (PBYTE)buf->str, count); 635 if (lres != ERROR_SUCCESS) 636 hres = HRESULT_FROM_WIN32(lres); 637 break; 638 } 639 default: 640 hres = DISP_E_EXCEPTION; 641 } 642 if (FAILED(hres)) 643 break; 644 } 645 else 646 { 647 if (*iter == '-') 648 iter++; 649 hres = get_word(&iter, buf); 650 if (FAILED(hres)) 651 break; 652 } 653 } 654 else if(key_type == IS_VAL) 655 { 656 hres = DISP_E_EXCEPTION; 657 break; 658 } 659 660 if (key_type != IS_VAL && key_type != DO_DELETE && *iter == '{' && iswspace(iter[1])) 661 { 662 hres = get_word(&iter, buf); 663 if (FAILED(hres)) 664 break; 665 hres = do_process_key(&iter, hkey, buf, do_register); 666 if (FAILED(hres)) 667 break; 668 } 669 670 if (!do_register && (key_type == NORMAL || key_type == FORCE_REMOVE)) 671 { 672 RegDeleteKeyW(parent_key, name.str); 673 } 674 675 if (hkey && key_type != IS_VAL) 676 RegCloseKey(hkey); 677 hkey = 0; 678 name.len = 0; 679 680 hres = get_word(&iter, buf); 681 if (FAILED(hres)) 682 break; 683 } 684 685 HeapFree(GetProcessHeap(), 0, name.str); 686 if (hkey && key_type != IS_VAL) 687 RegCloseKey(hkey); 688 *pstr = iter; 689 return hres; 690 } 691 692 HRESULT do_process_root_key(LPCOLESTR data, BOOL do_register) 693 { 694 LPCOLESTR iter; 695 strbuf buf; 696 unsigned int i; 697 HRESULT hResult; 698 static const struct { 699 const wchar_t *name; 700 HKEY key; 701 } root_keys[] = { 702 {L"HKEY_CLASSES_ROOT", HKEY_CLASSES_ROOT}, 703 {L"HKEY_CURRENT_USER", HKEY_CURRENT_USER}, 704 {L"HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE}, 705 {L"HKEY_USERS", HKEY_USERS}, 706 {L"HKEY_PERFORMANCE_DATA", HKEY_PERFORMANCE_DATA}, 707 {L"HKEY_DYN_DATA", HKEY_DYN_DATA}, 708 {L"HKEY_CURRENT_CONFIG", HKEY_CURRENT_CONFIG}, 709 {L"HKCR", HKEY_CLASSES_ROOT}, 710 {L"HKCU", HKEY_CURRENT_USER}, 711 {L"HKLM", HKEY_LOCAL_MACHINE}, 712 {L"HKU", HKEY_USERS}, 713 {L"HKPD", HKEY_PERFORMANCE_DATA}, 714 {L"HKDD", HKEY_DYN_DATA}, 715 {L"HKCC", HKEY_CURRENT_CONFIG}, 716 }; 717 718 iter = data; 719 720 hResult = strbuf_init(&buf); 721 if (FAILED(hResult)) 722 return hResult; 723 hResult = get_word(&iter, &buf); 724 if (FAILED(hResult)) 725 return hResult; 726 727 while (*iter) 728 { 729 if (!buf.len) 730 { 731 hResult = DISP_E_EXCEPTION; 732 break; 733 } 734 for (i = 0; i < sizeof(root_keys) / sizeof(root_keys[0]); i++) 735 { 736 if (!lstrcmpiW(buf.str, root_keys[i].name)) 737 break; 738 } 739 if (i == sizeof(root_keys) / sizeof(root_keys[0])) 740 { 741 hResult = DISP_E_EXCEPTION; 742 break; 743 } 744 hResult = get_word(&iter, &buf); 745 if (FAILED(hResult)) 746 break; 747 if (buf.str[1] || buf.str[0] != '{') 748 { 749 hResult = DISP_E_EXCEPTION; 750 break; 751 } 752 hResult = do_process_key(&iter, root_keys[i].key, &buf, do_register); 753 if (FAILED(hResult)) 754 break; 755 hResult = get_word(&iter, &buf); 756 if (FAILED(hResult)) 757 break; 758 } 759 HeapFree(GetProcessHeap(), 0, buf.str); 760 return hResult; 761 } 762 763 }; 764 765 }; //namespace ATL 766