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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 class IRegistrarBase
: public IUnknown
28 virtual HRESULT STDMETHODCALLTYPE
AddReplacement(LPCOLESTR key
, LPCOLESTR item
) = 0;
29 virtual HRESULT STDMETHODCALLTYPE
ClearReplacements() = 0;
35 class CRegObject
: public IRegistrarBase
38 typedef struct rep_list_str
43 struct rep_list_str
*next
;
65 hResult
= ClearReplacements();
66 ATLASSERT(SUCCEEDED(hResult
));
69 HRESULT STDMETHODCALLTYPE
QueryInterface(const IID
& /* riid */, void ** /* ppvObject */ )
71 ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function"));
75 ULONG STDMETHODCALLTYPE
AddRef()
77 ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function"));
81 ULONG STDMETHODCALLTYPE
Release()
83 ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function"));
87 HRESULT STDMETHODCALLTYPE
AddReplacement(LPCOLESTR key
, LPCOLESTR item
)
92 new_rep
= reinterpret_cast<rep_list
*>(HeapAlloc(GetProcessHeap(), 0, sizeof(rep_list
)));
94 new_rep
->key_len
= lstrlenW(key
);
95 new_rep
->key
= reinterpret_cast<OLECHAR
*>(HeapAlloc(GetProcessHeap(), 0, (new_rep
->key_len
+ 1) * sizeof(OLECHAR
)));
96 memcpy(new_rep
->key
, key
, (new_rep
->key_len
+ 1) * sizeof(OLECHAR
));
98 len
= lstrlenW(item
) + 1;
99 new_rep
->item
= reinterpret_cast<OLECHAR
*>(HeapAlloc(GetProcessHeap(), 0, len
* sizeof(OLECHAR
)));
100 memcpy(new_rep
->item
, item
, len
* sizeof(OLECHAR
));
102 new_rep
->next
= m_rep
;
108 HRESULT STDMETHODCALLTYPE
ClearReplacements()
117 HeapFree(GetProcessHeap(), 0, iter
->key
);
118 HeapFree(GetProcessHeap(), 0, iter
->item
);
119 HeapFree(GetProcessHeap(), 0, iter
);
127 HRESULT STDMETHODCALLTYPE
ResourceRegisterSz(LPCOLESTR resFileName
, LPCOLESTR szID
, LPCOLESTR szType
)
129 return RegisterWithResource(resFileName
, szID
, szType
, TRUE
);
132 HRESULT STDMETHODCALLTYPE
ResourceUnregisterSz(LPCOLESTR resFileName
, LPCOLESTR szID
, LPCOLESTR szType
)
134 return RegisterWithResource(resFileName
, szID
, szType
, FALSE
);
137 HRESULT STDMETHODCALLTYPE
FileRegister(LPCOLESTR fileName
)
139 return RegisterWithFile(fileName
, TRUE
);
142 HRESULT STDMETHODCALLTYPE
FileUnregister(LPCOLESTR fileName
)
144 return RegisterWithFile(fileName
, FALSE
);
147 HRESULT STDMETHODCALLTYPE
StringRegister(LPCOLESTR data
)
149 return RegisterWithString(data
, TRUE
);
152 HRESULT STDMETHODCALLTYPE
StringUnregister(LPCOLESTR data
)
154 return RegisterWithString(data
, FALSE
);
157 HRESULT STDMETHODCALLTYPE
ResourceRegister(LPCOLESTR resFileName
, UINT nID
, LPCOLESTR szType
)
159 return ResourceRegisterSz(resFileName
, MAKEINTRESOURCEW(nID
), szType
);
162 HRESULT STDMETHODCALLTYPE
ResourceUnregister(LPCOLESTR resFileName
, UINT nID
, LPCOLESTR szType
)
164 return ResourceRegisterSz(resFileName
, MAKEINTRESOURCEW(nID
), szType
);
168 HRESULT STDMETHODCALLTYPE
RegisterWithResource(LPCOLESTR resFileName
, LPCOLESTR szID
, LPCOLESTR szType
, BOOL doRegister
)
170 return resource_register(resFileName
, szID
, szType
, doRegister
);
173 HRESULT STDMETHODCALLTYPE
RegisterWithFile(LPCOLESTR fileName
, BOOL doRegister
)
175 return file_register(fileName
, doRegister
);
178 HRESULT STDMETHODCALLTYPE
RegisterWithString(LPCOLESTR data
, BOOL doRegister
)
180 return string_register(data
, doRegister
);
184 inline LONG
RegDeleteTreeX(HKEY parentKey
, LPCTSTR subKeyName
)
186 wchar_t szBuffer
[256];
192 ATLASSERT(parentKey
!= NULL
);
193 lRes
= RegOpenKeyEx(parentKey
, subKeyName
, 0, KEY_READ
| KEY_WRITE
, &childKey
);
194 if (lRes
!= ERROR_SUCCESS
)
197 dwSize
= sizeof(szBuffer
) / sizeof(szBuffer
[0]);
198 while (RegEnumKeyExW(parentKey
, 0, szBuffer
, &dwSize
, NULL
, NULL
, NULL
, &time
) == ERROR_SUCCESS
)
200 lRes
= RegDeleteTreeX(childKey
, szBuffer
);
201 if (lRes
!= ERROR_SUCCESS
)
203 dwSize
= sizeof(szBuffer
) / sizeof(szBuffer
[0]);
205 RegCloseKey(childKey
);
206 return RegDeleteKey(parentKey
, subKeyName
);
209 void strbuf_init(strbuf
*buf
)
211 buf
->str
= reinterpret_cast<LPOLESTR
>(HeapAlloc(GetProcessHeap(), 0, 128 * sizeof(WCHAR
)));
216 void strbuf_write(LPCOLESTR str
, strbuf
*buf
, int len
)
220 if (buf
->len
+len
+1 >= buf
->alloc
)
222 buf
->alloc
= (buf
->len
+ len
) * 2;
223 buf
->str
= reinterpret_cast<LPOLESTR
>(HeapReAlloc(GetProcessHeap(), 0, buf
->str
, buf
->alloc
* sizeof(WCHAR
)));
225 memcpy(buf
->str
+ buf
->len
, str
, len
* sizeof(OLECHAR
));
227 buf
->str
[buf
->len
] = '\0';
231 HRESULT
file_register(LPCOLESTR fileName
, BOOL do_register
)
241 file
= CreateFileW(fileName
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_READONLY
, NULL
);
242 if (file
!= INVALID_HANDLE_VALUE
)
244 filelen
= GetFileSize(file
, NULL
);
245 regstra
= reinterpret_cast<LPSTR
>(HeapAlloc(GetProcessHeap(), 0, filelen
));
246 lres
= ReadFile(file
, regstra
, filelen
, NULL
, NULL
);
247 if (lres
== ERROR_SUCCESS
)
249 len
= MultiByteToWideChar(CP_ACP
, 0, regstra
, filelen
, NULL
, 0) + 1;
250 regstrw
= reinterpret_cast<LPWSTR
>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
)));
251 MultiByteToWideChar(CP_ACP
, 0, regstra
, filelen
, regstrw
, len
);
252 regstrw
[len
- 1] = '\0';
254 hResult
= string_register(regstrw
, do_register
);
256 HeapFree(GetProcessHeap(), 0, regstrw
);
260 hResult
= HRESULT_FROM_WIN32(lres
);
262 HeapFree(GetProcessHeap(), 0, regstra
);
267 hResult
= HRESULT_FROM_WIN32(GetLastError());
273 HRESULT
resource_register(LPCOLESTR resFileName
, LPCOLESTR szID
, LPCOLESTR szType
, BOOL do_register
)
283 hins
= LoadLibraryExW(resFileName
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
286 src
= FindResourceW(hins
, szID
, szType
);
289 regstra
= LoadResource(hins
, src
);
290 reslen
= SizeofResource(hins
, src
);
293 len
= MultiByteToWideChar(CP_ACP
, 0, reinterpret_cast<LPCSTR
>(regstra
), reslen
, NULL
, 0) + 1;
294 regstrw
= reinterpret_cast<LPWSTR
>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
)));
295 MultiByteToWideChar(CP_ACP
, 0, reinterpret_cast<LPCSTR
>(regstra
), reslen
, regstrw
, len
);
296 regstrw
[len
- 1] = '\0';
298 hResult
= string_register(regstrw
, do_register
);
300 HeapFree(GetProcessHeap(), 0, regstrw
);
303 hResult
= HRESULT_FROM_WIN32(GetLastError());
306 hResult
= HRESULT_FROM_WIN32(GetLastError());
310 hResult
= HRESULT_FROM_WIN32(GetLastError());
315 HRESULT
string_register(LPCOLESTR data
, BOOL do_register
)
321 hResult
= do_preprocess(data
, &buf
);
322 if (SUCCEEDED(hResult
))
324 hResult
= do_process_root_key(buf
.str
, do_register
);
325 if (FAILED(hResult
) && do_register
)
326 do_process_root_key(buf
.str
, FALSE
);
329 HeapFree(GetProcessHeap(), 0, buf
.str
);
333 HRESULT
do_preprocess(LPCOLESTR data
, strbuf
*buf
)
340 iter
= wcschr(data
, '%');
343 strbuf_write(iter2
, buf
, static_cast<int>(iter
- iter2
));
347 return DISP_E_EXCEPTION
;
348 iter
= wcschr(iter2
, '%');
350 return DISP_E_EXCEPTION
;
353 strbuf_write(_T("%"), buf
, 1);
356 for (rep_iter
= m_rep
; rep_iter
; rep_iter
= rep_iter
->next
)
358 if (rep_iter
->key_len
== iter
- iter2
&& !_memicmp(iter2
, rep_iter
->key
, rep_iter
->key_len
* sizeof(wchar_t)))
362 return DISP_E_EXCEPTION
;
364 strbuf_write(rep_iter
->item
, buf
, -1);
368 iter
= wcschr(iter
, '%');
371 strbuf_write(iter2
, buf
, -1);
376 HRESULT
get_word(LPCOLESTR
*str
, strbuf
*buf
)
385 while (iswspace (*iter2
))
394 if (*iter
== '}' || *iter
== '=')
396 strbuf_write(iter
++, buf
, 1);
398 else if (*iter
== '\'')
401 iter
= wcschr(iter
, '\'');
405 return DISP_E_EXCEPTION
;
407 strbuf_write(iter2
, buf
, static_cast<int>(iter
- iter2
));
412 while (*iter
&& !iswspace(*iter
))
414 strbuf_write(iter2
, buf
, static_cast<int>(iter
- iter2
));
417 while (iswspace(*iter
))
423 HRESULT
do_process_key(LPCOLESTR
*pstr
, HKEY parent_key
, strbuf
*buf
, BOOL do_register
)
439 static const wchar_t *wstrNoRemove
= _T("NoRemove");
440 static const wchar_t *wstrForceRemove
= _T("ForceRemove");
441 static const wchar_t *wstrDelete
= _T("Delete");
442 static const wchar_t *wstrval
= _T("val");
447 hres
= get_word(&iter
, buf
);
452 while(buf
->str
[1] || buf
->str
[0] != '}')
455 if (!lstrcmpiW(buf
->str
, wstrNoRemove
))
456 key_type
= NO_REMOVE
;
457 else if (!lstrcmpiW(buf
->str
, wstrForceRemove
))
458 key_type
= FORCE_REMOVE
;
459 else if (!lstrcmpiW(buf
->str
, wstrval
))
461 else if (!lstrcmpiW(buf
->str
, wstrDelete
))
462 key_type
= DO_DELETE
;
464 if (key_type
!= NORMAL
)
466 hres
= get_word(&iter
, buf
);
473 if (key_type
== IS_VAL
)
476 strbuf_write(buf
->str
, &name
, -1);
478 else if (key_type
== DO_DELETE
)
480 RegDeleteTreeX(parent_key
, buf
->str
);
484 if (key_type
== FORCE_REMOVE
)
485 RegDeleteTreeX(parent_key
, buf
->str
);
486 lres
= RegCreateKey(parent_key
, buf
->str
, &hkey
);
487 if (lres
!= ERROR_SUCCESS
)
489 hres
= HRESULT_FROM_WIN32(lres
);
494 else if (key_type
!= IS_VAL
&& key_type
!= DO_DELETE
)
496 strbuf_write(buf
->str
, &name
, -1);
497 lres
= RegOpenKey(parent_key
, buf
->str
, &hkey
);
498 if (lres
!= ERROR_SUCCESS
)
503 if (key_type
!= DO_DELETE
&& *iter
== '=')
506 hres
= get_word(&iter
, buf
);
511 hres
= DISP_E_EXCEPTION
;
519 hres
= get_word(&iter
, buf
);
522 lres
= RegSetValueEx(hkey
, name
.len
? name
.str
: NULL
, 0, REG_SZ
, (PBYTE
)buf
->str
,
523 (lstrlenW(buf
->str
) + 1) * sizeof(WCHAR
));
524 if (lres
!= ERROR_SUCCESS
)
526 hres
= HRESULT_FROM_WIN32(lres
);
534 if(*iter
== '0' && iter
[1] == 'x')
537 dw
= wcstol(iter
, &end
, 16);
541 dw
= wcstol(iter
, &end
, 10);
544 lres
= RegSetValueEx(hkey
, name
.len
? name
.str
: NULL
, 0, REG_DWORD
, (PBYTE
)&dw
, sizeof(dw
));
545 if (lres
!= ERROR_SUCCESS
)
547 hres
= HRESULT_FROM_WIN32(lres
);
553 hres
= DISP_E_EXCEPTION
;
562 hres
= get_word(&iter
, buf
);
567 else if(key_type
== IS_VAL
)
569 hres
= DISP_E_EXCEPTION
;
573 if (key_type
!= IS_VAL
&& key_type
!= DO_DELETE
&& *iter
== '{' && iswspace(iter
[1]))
575 hres
= get_word(&iter
, buf
);
578 hres
= do_process_key(&iter
, hkey
, buf
, do_register
);
583 if (!do_register
&& (key_type
== NORMAL
|| key_type
== FORCE_REMOVE
))
585 RegDeleteKey(parent_key
, name
.str
);
588 if (hkey
&& key_type
!= IS_VAL
)
593 hres
= get_word(&iter
, buf
);
598 HeapFree(GetProcessHeap(), 0, name
.str
);
599 if (hkey
&& key_type
!= IS_VAL
)
605 HRESULT
do_process_root_key(LPCOLESTR data
, BOOL do_register
)
611 static const struct {
615 {_T("HKEY_CLASSES_ROOT"), HKEY_CLASSES_ROOT
},
616 {_T("HKEY_CURRENT_USER"), HKEY_CURRENT_USER
},
617 {_T("HKEY_LOCAL_MACHINE"), HKEY_LOCAL_MACHINE
},
618 {_T("HKEY_USERS"), HKEY_USERS
},
619 {_T("HKEY_PERFORMANCE_DATA"), HKEY_PERFORMANCE_DATA
},
620 {_T("HKEY_DYN_DATA"), HKEY_DYN_DATA
},
621 {_T("HKEY_CURRENT_CONFIG"), HKEY_CURRENT_CONFIG
},
622 {_T("HKCR"), HKEY_CLASSES_ROOT
},
623 {_T("HKCU"), HKEY_CURRENT_USER
},
624 {_T("HKLM"), HKEY_LOCAL_MACHINE
},
625 {_T("HKU"), HKEY_USERS
},
626 {_T("HKPD"), HKEY_PERFORMANCE_DATA
},
627 {_T("HKDD"), HKEY_DYN_DATA
},
628 {_T("HKCC"), HKEY_CURRENT_CONFIG
},
635 hResult
= get_word(&iter
, &buf
);
643 hResult
= DISP_E_EXCEPTION
;
646 for (i
= 0; i
< sizeof(root_keys
) / sizeof(root_keys
[0]); i
++)
648 if (!lstrcmpiW(buf
.str
, root_keys
[i
].name
))
651 if (i
== sizeof(root_keys
) / sizeof(root_keys
[0]))
653 hResult
= DISP_E_EXCEPTION
;
656 hResult
= get_word(&iter
, &buf
);
659 if (buf
.str
[1] || buf
.str
[0] != '{')
661 hResult
= DISP_E_EXCEPTION
;
664 hResult
= do_process_key(&iter
, root_keys
[i
].key
, &buf
, do_register
);
667 hResult
= get_word(&iter
, &buf
);
671 HeapFree(GetProcessHeap(), 0, buf
.str
);