[ATL][ATL_APITEST] Add CAtlList::InsertBefore/After + test
[reactos.git] / sdk / lib / atl / statreg.h
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