4 * Copyright 2005 Jacek Caban
5 * Copyright 2009 Andrew Hill <ash77@reactos.org>
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.
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.
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
24 class IRegistrarBase
: public IUnknown
27 virtual HRESULT STDMETHODCALLTYPE
AddReplacement(LPCOLESTR key
, LPCOLESTR item
) = 0;
28 virtual HRESULT STDMETHODCALLTYPE
ClearReplacements() = 0;
34 class CRegObject
: public IRegistrarBase
37 typedef struct rep_list_str
42 struct rep_list_str
*next
;
64 hResult
= ClearReplacements();
65 ATLASSERT(SUCCEEDED(hResult
));
68 HRESULT STDMETHODCALLTYPE
QueryInterface(const IID
& /* riid */, void ** /* ppvObject */ )
70 ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function"));
74 ULONG STDMETHODCALLTYPE
AddRef()
76 ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function"));
80 ULONG STDMETHODCALLTYPE
Release()
82 ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function"));
86 HRESULT STDMETHODCALLTYPE
AddReplacement(LPCOLESTR key
, LPCOLESTR item
)
91 new_rep
= reinterpret_cast<rep_list
*>(HeapAlloc(GetProcessHeap(), 0, sizeof(rep_list
)));
93 new_rep
->key_len
= lstrlenW(key
);
94 new_rep
->key
= reinterpret_cast<OLECHAR
*>(HeapAlloc(GetProcessHeap(), 0, (new_rep
->key_len
+ 1) * sizeof(OLECHAR
)));
95 memcpy(new_rep
->key
, key
, (new_rep
->key_len
+ 1) * sizeof(OLECHAR
));
97 len
= lstrlenW(item
) + 1;
98 new_rep
->item
= reinterpret_cast<OLECHAR
*>(HeapAlloc(GetProcessHeap(), 0, len
* sizeof(OLECHAR
)));
99 memcpy(new_rep
->item
, item
, len
* sizeof(OLECHAR
));
101 new_rep
->next
= m_rep
;
107 HRESULT STDMETHODCALLTYPE
ClearReplacements()
116 HeapFree(GetProcessHeap(), 0, iter
->key
);
117 HeapFree(GetProcessHeap(), 0, iter
->item
);
118 HeapFree(GetProcessHeap(), 0, iter
);
126 HRESULT STDMETHODCALLTYPE
ResourceRegisterSz(LPCOLESTR resFileName
, LPCOLESTR szID
, LPCOLESTR szType
)
128 return RegisterWithResource(resFileName
, szID
, szType
, TRUE
);
131 HRESULT STDMETHODCALLTYPE
ResourceUnregisterSz(LPCOLESTR resFileName
, LPCOLESTR szID
, LPCOLESTR szType
)
133 return RegisterWithResource(resFileName
, szID
, szType
, FALSE
);
136 HRESULT STDMETHODCALLTYPE
FileRegister(LPCOLESTR fileName
)
138 return RegisterWithFile(fileName
, TRUE
);
141 HRESULT STDMETHODCALLTYPE
FileUnregister(LPCOLESTR fileName
)
143 return RegisterWithFile(fileName
, FALSE
);
146 HRESULT STDMETHODCALLTYPE
StringRegister(LPCOLESTR data
)
148 return RegisterWithString(data
, TRUE
);
151 HRESULT STDMETHODCALLTYPE
StringUnregister(LPCOLESTR data
)
153 return RegisterWithString(data
, FALSE
);
156 HRESULT STDMETHODCALLTYPE
ResourceRegister(LPCOLESTR resFileName
, UINT nID
, LPCOLESTR szType
)
158 return ResourceRegisterSz(resFileName
, MAKEINTRESOURCEW(nID
), szType
);
161 HRESULT STDMETHODCALLTYPE
ResourceUnregister(LPCOLESTR resFileName
, UINT nID
, LPCOLESTR szType
)
163 return ResourceRegisterSz(resFileName
, MAKEINTRESOURCEW(nID
), szType
);
167 HRESULT STDMETHODCALLTYPE
RegisterWithResource(LPCOLESTR resFileName
, LPCOLESTR szID
, LPCOLESTR szType
, BOOL doRegister
)
169 return resource_register(resFileName
, szID
, szType
, doRegister
);
172 HRESULT STDMETHODCALLTYPE
RegisterWithFile(LPCOLESTR fileName
, BOOL doRegister
)
174 return file_register(fileName
, doRegister
);
177 HRESULT STDMETHODCALLTYPE
RegisterWithString(LPCOLESTR data
, BOOL doRegister
)
179 return string_register(data
, doRegister
);
183 inline LONG
RegDeleteTreeX(HKEY parentKey
, LPCTSTR subKeyName
)
185 wchar_t szBuffer
[256];
191 ATLASSERT(parentKey
!= NULL
);
192 lRes
= RegOpenKeyEx(parentKey
, subKeyName
, 0, KEY_READ
| KEY_WRITE
, &childKey
);
193 if (lRes
!= ERROR_SUCCESS
)
196 dwSize
= sizeof(szBuffer
) / sizeof(szBuffer
[0]);
197 while (RegEnumKeyExW(parentKey
, 0, szBuffer
, &dwSize
, NULL
, NULL
, NULL
, &time
) == ERROR_SUCCESS
)
199 lRes
= RegDeleteTreeX(childKey
, szBuffer
);
200 if (lRes
!= ERROR_SUCCESS
)
202 dwSize
= sizeof(szBuffer
) / sizeof(szBuffer
[0]);
204 RegCloseKey(childKey
);
205 return RegDeleteKey(parentKey
, subKeyName
);
208 void strbuf_init(strbuf
*buf
)
210 buf
->str
= reinterpret_cast<LPOLESTR
>(HeapAlloc(GetProcessHeap(), 0, 128 * sizeof(WCHAR
)));
215 void strbuf_write(LPCOLESTR str
, strbuf
*buf
, int len
)
219 if (buf
->len
+len
+1 >= buf
->alloc
)
221 buf
->alloc
= (buf
->len
+ len
) * 2;
222 buf
->str
= reinterpret_cast<LPOLESTR
>(HeapReAlloc(GetProcessHeap(), 0, buf
->str
, buf
->alloc
* sizeof(WCHAR
)));
224 memcpy(buf
->str
+ buf
->len
, str
, len
* sizeof(OLECHAR
));
226 buf
->str
[buf
->len
] = '\0';
230 HRESULT
file_register(LPCOLESTR fileName
, BOOL do_register
)
240 file
= CreateFileW(fileName
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_READONLY
, NULL
);
241 if (file
!= INVALID_HANDLE_VALUE
)
243 filelen
= GetFileSize(file
, NULL
);
244 regstra
= reinterpret_cast<LPSTR
>(HeapAlloc(GetProcessHeap(), 0, filelen
));
245 lres
= ReadFile(file
, regstra
, filelen
, NULL
, NULL
);
246 if (lres
== ERROR_SUCCESS
)
248 len
= MultiByteToWideChar(CP_ACP
, 0, regstra
, filelen
, NULL
, 0) + 1;
249 regstrw
= reinterpret_cast<LPWSTR
>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
)));
250 MultiByteToWideChar(CP_ACP
, 0, regstra
, filelen
, regstrw
, len
);
251 regstrw
[len
- 1] = '\0';
253 hResult
= string_register(regstrw
, do_register
);
255 HeapFree(GetProcessHeap(), 0, regstrw
);
259 hResult
= HRESULT_FROM_WIN32(lres
);
261 HeapFree(GetProcessHeap(), 0, regstra
);
266 hResult
= HRESULT_FROM_WIN32(GetLastError());
272 HRESULT
resource_register(LPCOLESTR resFileName
, LPCOLESTR szID
, LPCOLESTR szType
, BOOL do_register
)
282 hins
= LoadLibraryExW(resFileName
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
285 src
= FindResourceW(hins
, szID
, szType
);
288 regstra
= LoadResource(hins
, src
);
289 reslen
= SizeofResource(hins
, src
);
292 len
= MultiByteToWideChar(CP_ACP
, 0, reinterpret_cast<LPCSTR
>(regstra
), reslen
, NULL
, 0) + 1;
293 regstrw
= reinterpret_cast<LPWSTR
>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
)));
294 MultiByteToWideChar(CP_ACP
, 0, reinterpret_cast<LPCSTR
>(regstra
), reslen
, regstrw
, len
);
295 regstrw
[len
- 1] = '\0';
297 hResult
= string_register(regstrw
, do_register
);
299 HeapFree(GetProcessHeap(), 0, regstrw
);
302 hResult
= HRESULT_FROM_WIN32(GetLastError());
305 hResult
= HRESULT_FROM_WIN32(GetLastError());
309 hResult
= HRESULT_FROM_WIN32(GetLastError());
314 HRESULT
string_register(LPCOLESTR data
, BOOL do_register
)
320 hResult
= do_preprocess(data
, &buf
);
321 if (SUCCEEDED(hResult
))
323 hResult
= do_process_root_key(buf
.str
, do_register
);
324 if (FAILED(hResult
) && do_register
)
325 do_process_root_key(buf
.str
, FALSE
);
328 HeapFree(GetProcessHeap(), 0, buf
.str
);
332 HRESULT
do_preprocess(LPCOLESTR data
, strbuf
*buf
)
339 iter
= wcschr(data
, '%');
342 strbuf_write(iter2
, buf
, static_cast<int>(iter
- iter2
));
346 return DISP_E_EXCEPTION
;
347 iter
= wcschr(iter2
, '%');
349 return DISP_E_EXCEPTION
;
352 strbuf_write(_T("%"), buf
, 1);
355 for (rep_iter
= m_rep
; rep_iter
; rep_iter
= rep_iter
->next
)
357 if (rep_iter
->key_len
== iter
- iter2
&& !_memicmp(iter2
, rep_iter
->key
, rep_iter
->key_len
* sizeof(wchar_t)))
361 return DISP_E_EXCEPTION
;
363 strbuf_write(rep_iter
->item
, buf
, -1);
367 iter
= wcschr(iter
, '%');
370 strbuf_write(iter2
, buf
, -1);
375 HRESULT
get_word(LPCOLESTR
*str
, strbuf
*buf
)
384 while (iswspace (*iter2
))
393 if (*iter
== '}' || *iter
== '=')
395 strbuf_write(iter
++, buf
, 1);
397 else if (*iter
== '\'')
400 iter
= wcschr(iter
, '\'');
404 return DISP_E_EXCEPTION
;
406 strbuf_write(iter2
, buf
, static_cast<int>(iter
- iter2
));
411 while (*iter
&& !iswspace(*iter
))
413 strbuf_write(iter2
, buf
, static_cast<int>(iter
- iter2
));
416 while (iswspace(*iter
))
422 HRESULT
do_process_key(LPCOLESTR
*pstr
, HKEY parent_key
, strbuf
*buf
, BOOL do_register
)
438 static const wchar_t *wstrNoRemove
= _T("NoRemove");
439 static const wchar_t *wstrForceRemove
= _T("ForceRemove");
440 static const wchar_t *wstrDelete
= _T("Delete");
441 static const wchar_t *wstrval
= _T("val");
446 hres
= get_word(&iter
, buf
);
451 while(buf
->str
[1] || buf
->str
[0] != '}')
454 if (!lstrcmpiW(buf
->str
, wstrNoRemove
))
455 key_type
= NO_REMOVE
;
456 else if (!lstrcmpiW(buf
->str
, wstrForceRemove
))
457 key_type
= FORCE_REMOVE
;
458 else if (!lstrcmpiW(buf
->str
, wstrval
))
460 else if (!lstrcmpiW(buf
->str
, wstrDelete
))
461 key_type
= DO_DELETE
;
463 if (key_type
!= NORMAL
)
465 hres
= get_word(&iter
, buf
);
472 if (key_type
== IS_VAL
)
475 strbuf_write(buf
->str
, &name
, -1);
477 else if (key_type
== DO_DELETE
)
479 RegDeleteTreeX(parent_key
, buf
->str
);
483 if (key_type
== FORCE_REMOVE
)
484 RegDeleteTreeX(parent_key
, buf
->str
);
485 lres
= RegCreateKey(parent_key
, buf
->str
, &hkey
);
486 if (lres
!= ERROR_SUCCESS
)
488 hres
= HRESULT_FROM_WIN32(lres
);
493 else if (key_type
!= IS_VAL
&& key_type
!= DO_DELETE
)
495 strbuf_write(buf
->str
, &name
, -1);
496 lres
= RegOpenKey(parent_key
, buf
->str
, &hkey
);
497 if (lres
!= ERROR_SUCCESS
)
502 if (key_type
!= DO_DELETE
&& *iter
== '=')
505 hres
= get_word(&iter
, buf
);
510 hres
= DISP_E_EXCEPTION
;
518 hres
= get_word(&iter
, buf
);
521 lres
= RegSetValueEx(hkey
, name
.len
? name
.str
: NULL
, 0, REG_SZ
, (PBYTE
)buf
->str
,
522 (lstrlenW(buf
->str
) + 1) * sizeof(WCHAR
));
523 if (lres
!= ERROR_SUCCESS
)
525 hres
= HRESULT_FROM_WIN32(lres
);
533 if(*iter
== '0' && iter
[1] == 'x')
536 dw
= wcstol(iter
, &end
, 16);
540 dw
= wcstol(iter
, &end
, 10);
543 lres
= RegSetValueEx(hkey
, name
.len
? name
.str
: NULL
, 0, REG_DWORD
, (PBYTE
)&dw
, sizeof(dw
));
544 if (lres
!= ERROR_SUCCESS
)
546 hres
= HRESULT_FROM_WIN32(lres
);
552 hres
= DISP_E_EXCEPTION
;
561 hres
= get_word(&iter
, buf
);
566 else if(key_type
== IS_VAL
)
568 hres
= DISP_E_EXCEPTION
;
572 if (key_type
!= IS_VAL
&& key_type
!= DO_DELETE
&& *iter
== '{' && iswspace(iter
[1]))
574 hres
= get_word(&iter
, buf
);
577 hres
= do_process_key(&iter
, hkey
, buf
, do_register
);
582 if (!do_register
&& (key_type
== NORMAL
|| key_type
== FORCE_REMOVE
))
584 RegDeleteKey(parent_key
, name
.str
);
587 if (hkey
&& key_type
!= IS_VAL
)
592 hres
= get_word(&iter
, buf
);
597 HeapFree(GetProcessHeap(), 0, name
.str
);
598 if (hkey
&& key_type
!= IS_VAL
)
604 HRESULT
do_process_root_key(LPCOLESTR data
, BOOL do_register
)
610 static const struct {
614 {_T("HKEY_CLASSES_ROOT"), HKEY_CLASSES_ROOT
},
615 {_T("HKEY_CURRENT_USER"), HKEY_CURRENT_USER
},
616 {_T("HKEY_LOCAL_MACHINE"), HKEY_LOCAL_MACHINE
},
617 {_T("HKEY_USERS"), HKEY_USERS
},
618 {_T("HKEY_PERFORMANCE_DATA"), HKEY_PERFORMANCE_DATA
},
619 {_T("HKEY_DYN_DATA"), HKEY_DYN_DATA
},
620 {_T("HKEY_CURRENT_CONFIG"), HKEY_CURRENT_CONFIG
},
621 {_T("HKCR"), HKEY_CLASSES_ROOT
},
622 {_T("HKCU"), HKEY_CURRENT_USER
},
623 {_T("HKLM"), HKEY_LOCAL_MACHINE
},
624 {_T("HKU"), HKEY_USERS
},
625 {_T("HKPD"), HKEY_PERFORMANCE_DATA
},
626 {_T("HKDD"), HKEY_DYN_DATA
},
627 {_T("HKCC"), HKEY_CURRENT_CONFIG
},
634 hResult
= get_word(&iter
, &buf
);
642 hResult
= DISP_E_EXCEPTION
;
645 for (i
= 0; i
< sizeof(root_keys
) / sizeof(root_keys
[0]); i
++)
647 if (!lstrcmpiW(buf
.str
, root_keys
[i
].name
))
650 if (i
== sizeof(root_keys
) / sizeof(root_keys
[0]))
652 hResult
= DISP_E_EXCEPTION
;
655 hResult
= get_word(&iter
, &buf
);
658 if (buf
.str
[1] || buf
.str
[0] != '{')
660 hResult
= DISP_E_EXCEPTION
;
663 hResult
= do_process_key(&iter
, root_keys
[i
].key
, &buf
, do_register
);
666 hResult
= get_word(&iter
, &buf
);
670 HeapFree(GetProcessHeap(), 0, buf
.str
);