diff --git a/configure b/configure index 2baf8c874e1..8f4e778c387 100755 --- a/configure +++ b/configure @@ -15247,7 +15247,7 @@ wine_fn_config_test dlls/apphelp/tests apphelp_test wine_fn_config_dll appwiz.cpl enable_appwiz_cpl po wine_fn_config_dll atl enable_atl implib wine_fn_config_test dlls/atl/tests atl_test -wine_fn_config_dll atl100 enable_atl100 +wine_fn_config_dll atl100 enable_atl100 implib wine_fn_config_dll atl80 enable_atl80 wine_fn_config_dll authz enable_authz wine_fn_config_dll avicap32 enable_avicap32 implib diff --git a/configure.ac b/configure.ac index d003e8a9e41..8e6a70f5421 100644 --- a/configure.ac +++ b/configure.ac @@ -2513,7 +2513,7 @@ WINE_CONFIG_TEST(dlls/apphelp/tests) WINE_CONFIG_DLL(appwiz.cpl,,[po]) WINE_CONFIG_DLL(atl,,[implib]) WINE_CONFIG_TEST(dlls/atl/tests) -WINE_CONFIG_DLL(atl100) +WINE_CONFIG_DLL(atl100,,[implib]) WINE_CONFIG_DLL(atl80) WINE_CONFIG_DLL(authz) WINE_CONFIG_DLL(avicap32,,[implib]) diff --git a/dlls/atl/Makefile.in b/dlls/atl/Makefile.in index fd7d629a5c6..4151de56be3 100644 --- a/dlls/atl/Makefile.in +++ b/dlls/atl/Makefile.in @@ -1,6 +1,6 @@ MODULE = atl.dll IMPORTLIB = atl -IMPORTS = uuid ole32 oleaut32 user32 gdi32 advapi32 +IMPORTS = uuid atl100 ole32 oleaut32 user32 gdi32 C_SRCS = \ atl_ax.c \ diff --git a/dlls/atl/registrar.c b/dlls/atl/registrar.c index b03fdf0251c..41a5dc3f468 100644 --- a/dlls/atl/registrar.c +++ b/dlls/atl/registrar.c @@ -27,682 +27,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(atl); -/************************************************************** - * ATLRegistrar implementation - */ - -static const struct { - WCHAR name[22]; - HKEY key; -} root_keys[] = { - {{'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T',0}, - HKEY_CLASSES_ROOT}, - {{'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R',0}, - HKEY_CURRENT_USER}, - {{'H','K','E','Y','_','L','O','C','A','L','_','M','A','C','H','I','N','E',0}, - HKEY_LOCAL_MACHINE}, - {{'H','K','E','Y','_','U','S','E','R','S',0}, - HKEY_USERS}, - {{'H','K','E','Y','_','P','E','R','F','O','R','M','A','N','C','E','_','D','A','T','A',0}, - HKEY_PERFORMANCE_DATA}, - {{'H','K','E','Y','_','D','Y','N','_','D','A','T','A',0}, - HKEY_DYN_DATA}, - {{'H','K','E','Y','_','C','U','R','R','E','N','T','_','C','O','N','F','I','G',0}, - HKEY_CURRENT_CONFIG}, - {{'H','K','C','R',0}, HKEY_CLASSES_ROOT}, - {{'H','K','C','U',0}, HKEY_CURRENT_USER}, - {{'H','K','L','M',0}, HKEY_LOCAL_MACHINE}, - {{'H','K','U',0}, HKEY_USERS}, - {{'H','K','P','D',0}, HKEY_PERFORMANCE_DATA}, - {{'H','K','D','D',0}, HKEY_DYN_DATA}, - {{'H','K','C','C',0}, HKEY_CURRENT_CONFIG} -}; - -typedef struct rep_list_str { - LPOLESTR key; - LPOLESTR item; - int key_len; - struct rep_list_str *next; -} rep_list; - -typedef struct { - IRegistrar IRegistrar_iface; - LONG ref; - rep_list *rep; -} Registrar; - -typedef struct { - LPOLESTR str; - DWORD alloc; - DWORD len; -} strbuf; - -static inline Registrar *impl_from_IRegistrar(IRegistrar *iface) -{ - return CONTAINING_RECORD(iface, Registrar, IRegistrar_iface); -} - -static void strbuf_init(strbuf *buf) -{ - buf->str = HeapAlloc(GetProcessHeap(), 0, 128*sizeof(WCHAR)); - buf->alloc = 128; - buf->len = 0; -} - -static void strbuf_write(LPCOLESTR str, strbuf *buf, int len) -{ - if(len == -1) - len = lstrlenW(str); - if(buf->len+len+1 >= buf->alloc) { - buf->alloc = (buf->len+len)<<1; - buf->str = HeapReAlloc(GetProcessHeap(), 0, buf->str, buf->alloc*sizeof(WCHAR)); - } - memcpy(buf->str+buf->len, str, len*sizeof(OLECHAR)); - buf->len += len; - buf->str[buf->len] = '\0'; -} - -static HRESULT get_word(LPCOLESTR *str, strbuf *buf) -{ - LPCOLESTR iter, iter2 = *str; - - buf->len = 0; - buf->str[0] = '\0'; - - while(isspaceW(*iter2)) - iter2++; - iter = iter2; - if(!*iter) { - *str = iter; - return S_OK; - } - - if(*iter == '}' || *iter == '=') { - strbuf_write(iter++, buf, 1); - }else if(*iter == '\'') { - iter2 = ++iter; - iter = strchrW(iter, '\''); - if(!iter) { - WARN("Unexpected end of script\n"); - *str = iter; - return DISP_E_EXCEPTION; - } - strbuf_write(iter2, buf, iter-iter2); - iter++; - }else { - while(*iter && !isspaceW(*iter)) - iter++; - strbuf_write(iter2, buf, iter-iter2); - } - - while(isspaceW(*iter)) - iter++; - *str = iter; - return S_OK; -} - -static HRESULT do_preprocess(const Registrar *This, LPCOLESTR data, strbuf *buf) -{ - LPCOLESTR iter, iter2 = data; - rep_list *rep_iter; - static const WCHAR wstr[] = {'%',0}; - - iter = strchrW(data, '%'); - while(iter) { - strbuf_write(iter2, buf, iter-iter2); - - iter2 = ++iter; - if(!*iter2) - return DISP_E_EXCEPTION; - iter = strchrW(iter2, '%'); - if(!iter) - return DISP_E_EXCEPTION; - - if(iter == iter2) { - strbuf_write(wstr, buf, 1); - }else { - for(rep_iter = This->rep; rep_iter; rep_iter = rep_iter->next) { - if(rep_iter->key_len == iter-iter2 - && !memicmpW(iter2, rep_iter->key, rep_iter->key_len)) - break; - } - if(!rep_iter) { - WARN("Could not find replacement: %s\n", debugstr_wn(iter2, iter-iter2)); - return DISP_E_EXCEPTION; - } - - strbuf_write(rep_iter->item, buf, -1); - } - - iter2 = ++iter; - iter = strchrW(iter, '%'); - } - - strbuf_write(iter2, buf, -1); - TRACE("%s\n", debugstr_w(buf->str)); - - return S_OK; -} - -static HRESULT do_process_key(LPCOLESTR *pstr, HKEY parent_key, strbuf *buf, BOOL do_register) -{ - LPCOLESTR iter = *pstr; - HRESULT hres; - LONG lres; - HKEY hkey = 0; - strbuf name; - - enum { - NORMAL, - NO_REMOVE, - IS_VAL, - FORCE_REMOVE, - DO_DELETE - } key_type = NORMAL; - - static const WCHAR wstrNoRemove[] = {'N','o','R','e','m','o','v','e',0}; - static const WCHAR wstrForceRemove[] = {'F','o','r','c','e','R','e','m','o','v','e',0}; - static const WCHAR wstrDelete[] = {'D','e','l','e','t','e',0}; - static const WCHAR wstrval[] = {'v','a','l',0}; - - iter = *pstr; - hres = get_word(&iter, buf); - if(FAILED(hres)) - return hres; - strbuf_init(&name); - - while(buf->str[1] || buf->str[0] != '}') { - key_type = NORMAL; - if(!lstrcmpiW(buf->str, wstrNoRemove)) - key_type = NO_REMOVE; - else if(!lstrcmpiW(buf->str, wstrForceRemove)) - key_type = FORCE_REMOVE; - else if(!lstrcmpiW(buf->str, wstrval)) - key_type = IS_VAL; - else if(!lstrcmpiW(buf->str, wstrDelete)) - key_type = DO_DELETE; - - if(key_type != NORMAL) { - hres = get_word(&iter, buf); - if(FAILED(hres)) - break; - } - TRACE("name = %s\n", debugstr_w(buf->str)); - - if(do_register) { - if(key_type == IS_VAL) { - hkey = parent_key; - strbuf_write(buf->str, &name, -1); - }else if(key_type == DO_DELETE) { - TRACE("Deleting %s\n", debugstr_w(buf->str)); - RegDeleteTreeW(parent_key, buf->str); - }else { - if(key_type == FORCE_REMOVE) - RegDeleteTreeW(parent_key, buf->str); - lres = RegCreateKeyW(parent_key, buf->str, &hkey); - if(lres != ERROR_SUCCESS) { - WARN("Could not create(open) key: %08x\n", lres); - hres = HRESULT_FROM_WIN32(lres); - break; - } - } - }else if(key_type != IS_VAL && key_type != DO_DELETE) { - strbuf_write(buf->str, &name, -1); - lres = RegOpenKeyW(parent_key, buf->str, &hkey); - if(lres != ERROR_SUCCESS) - WARN("Could not open key %s: %08x\n", debugstr_w(name.str), lres); - } - - if(key_type != DO_DELETE && *iter == '=') { - iter++; - hres = get_word(&iter, buf); - if(FAILED(hres)) - break; - if(buf->len != 1) { - WARN("Wrong registry type: %s\n", debugstr_w(buf->str)); - hres = DISP_E_EXCEPTION; - break; - } - if(do_register) { - switch(buf->str[0]) { - case 's': - hres = get_word(&iter, buf); - if(FAILED(hres)) - break; - lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_SZ, (PBYTE)buf->str, - (lstrlenW(buf->str)+1)*sizeof(WCHAR)); - if(lres != ERROR_SUCCESS) { - WARN("Could set value of key: %08x\n", lres); - hres = HRESULT_FROM_WIN32(lres); - break; - } - break; - case 'd': { - DWORD dw; - hres = get_word(&iter, buf); - if(FAILED(hres)) - break; - dw = atoiW(buf->str); - lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_DWORD, - (PBYTE)&dw, sizeof(dw)); - if(lres != ERROR_SUCCESS) { - WARN("Could set value of key: %08x\n", lres); - hres = HRESULT_FROM_WIN32(lres); - break; - } - break; - } - case 'b': { - BYTE *bytes; - DWORD count; - DWORD i; - hres = get_word(&iter, buf); - if(FAILED(hres)) - break; - count = (lstrlenW(buf->str) + 1) / 2; - bytes = HeapAlloc(GetProcessHeap(), 0, count); - if(bytes == NULL) { - hres = E_OUTOFMEMORY; - break; - } - for(i = 0; i < count && buf->str[2*i]; i++) { - WCHAR digits[3]; - if(!isxdigitW(buf->str[2*i]) || !isxdigitW(buf->str[2*i + 1])) { - hres = E_FAIL; - break; - } - digits[0] = buf->str[2*i]; - digits[1] = buf->str[2*i + 1]; - digits[2] = 0; - bytes[i] = (BYTE) strtoulW(digits, NULL, 16); - } - if(SUCCEEDED(hres)) { - lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_BINARY, - bytes, count); - if(lres != ERROR_SUCCESS) { - WARN("Could not set value of key: 0x%08x\n", lres); - hres = HRESULT_FROM_WIN32(lres); - } - } - HeapFree(GetProcessHeap(), 0, bytes); - break; - } - default: - WARN("Wrong resource type: %s\n", debugstr_w(buf->str)); - hres = DISP_E_EXCEPTION; - }; - if(FAILED(hres)) - break; - }else { - if(*iter == '-') - iter++; - hres = get_word(&iter, buf); - if(FAILED(hres)) - break; - } - }else if(key_type == IS_VAL) { - WARN("value not set!\n"); - hres = DISP_E_EXCEPTION; - break; - } - - if(key_type != IS_VAL && key_type != DO_DELETE && *iter == '{' && isspaceW(iter[1])) { - hres = get_word(&iter, buf); - if(FAILED(hres)) - break; - hres = do_process_key(&iter, hkey, buf, do_register); - if(FAILED(hres)) - break; - } - - TRACE("%x %x\n", do_register, key_type); - if(!do_register && (key_type == NORMAL || key_type == FORCE_REMOVE)) { - TRACE("Deleting %s\n", debugstr_w(name.str)); - RegDeleteKeyW(parent_key, name.str); - } - - if(hkey && key_type != IS_VAL) - RegCloseKey(hkey); - hkey = 0; - name.len = 0; - - hres = get_word(&iter, buf); - if(FAILED(hres)) - break; - } - - HeapFree(GetProcessHeap(), 0, name.str); - if(hkey && key_type != IS_VAL) - RegCloseKey(hkey); - *pstr = iter; - return hres; -} - -static HRESULT do_process_root_key(LPCOLESTR data, BOOL do_register) -{ - LPCOLESTR iter = data; - strbuf buf; - HRESULT hres = S_OK; - unsigned int i; - - strbuf_init(&buf); - hres = get_word(&iter, &buf); - if(FAILED(hres)) - return hres; - - while(*iter) { - if(!buf.len) { - WARN("ward.len == 0, failed\n"); - hres = DISP_E_EXCEPTION; - break; - } - for(i=0; i(%s %p\n", iface, debugstr_guid(riid), ppvObject); - - if(IsEqualGUID(&IID_IUnknown, riid) - || IsEqualGUID(&IID_IRegistrar, riid) - || IsEqualGUID(&IID_IRegistrarBase, riid)) { - IRegistrar_AddRef(iface); - *ppvObject = iface; - return S_OK; - } - return E_NOINTERFACE; -} - -static ULONG WINAPI Registrar_AddRef(IRegistrar *iface) -{ - Registrar *This = impl_from_IRegistrar(iface); - ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) ->%d\n", This, ref); - return ref; -} - -static ULONG WINAPI Registrar_Release(IRegistrar *iface) -{ - Registrar *This = impl_from_IRegistrar(iface); - ULONG ref = InterlockedDecrement(&This->ref); - - TRACE("(%p) ->%d\n", This, ref); - if(!ref) { - IRegistrar_ClearReplacements(iface); - HeapFree(GetProcessHeap(), 0, This); - } - return ref; -} - -static HRESULT WINAPI Registrar_AddReplacement(IRegistrar *iface, LPCOLESTR Key, LPCOLESTR item) -{ - Registrar *This = impl_from_IRegistrar(iface); - int len; - rep_list *new_rep; - - TRACE("(%p)->(%s %s)\n", This, debugstr_w(Key), debugstr_w(item)); - - new_rep = HeapAlloc(GetProcessHeap(), 0, sizeof(rep_list)); - - new_rep->key_len = lstrlenW(Key); - new_rep->key = HeapAlloc(GetProcessHeap(), 0, (new_rep->key_len + 1) * sizeof(OLECHAR)); - memcpy(new_rep->key, Key, (new_rep->key_len+1)*sizeof(OLECHAR)); - - len = lstrlenW(item)+1; - new_rep->item = HeapAlloc(GetProcessHeap(), 0, len*sizeof(OLECHAR)); - memcpy(new_rep->item, item, len*sizeof(OLECHAR)); - - new_rep->next = This->rep; - This->rep = new_rep; - - return S_OK; -} - -static HRESULT WINAPI Registrar_ClearReplacements(IRegistrar *iface) -{ - Registrar *This = impl_from_IRegistrar(iface); - rep_list *iter, *iter2; - - TRACE("(%p)\n", This); - - if(!This->rep) - return S_OK; - - iter = This->rep; - while(iter) { - iter2 = iter->next; - HeapFree(GetProcessHeap(), 0, iter->key); - HeapFree(GetProcessHeap(), 0, iter->item); - HeapFree(GetProcessHeap(), 0, iter); - iter = iter2; - } - - This->rep = NULL; - return S_OK; -} - -static HRESULT WINAPI Registrar_ResourceRegisterSz(IRegistrar* iface, LPCOLESTR resFileName, - LPCOLESTR szID, LPCOLESTR szType) -{ - Registrar *This = impl_from_IRegistrar(iface); - TRACE("(%p)->(%s %s %s)\n", This, debugstr_w(resFileName), debugstr_w(szID), debugstr_w(szType)); - return resource_register(This, resFileName, szID, szType, TRUE); -} - -static HRESULT WINAPI Registrar_ResourceUnregisterSz(IRegistrar* iface, LPCOLESTR resFileName, - LPCOLESTR szID, LPCOLESTR szType) -{ - Registrar *This = impl_from_IRegistrar(iface); - TRACE("(%p)->(%s %s %s)\n", This, debugstr_w(resFileName), debugstr_w(szID), debugstr_w(szType)); - return resource_register(This, resFileName, szID, szType, FALSE); -} - -static HRESULT WINAPI Registrar_FileRegister(IRegistrar* iface, LPCOLESTR fileName) -{ - Registrar *This = impl_from_IRegistrar(iface); - TRACE("(%p)->(%s)\n", This, debugstr_w(fileName)); - return file_register(This, fileName, TRUE); -} - -static HRESULT WINAPI Registrar_FileUnregister(IRegistrar* iface, LPCOLESTR fileName) -{ - Registrar *This = impl_from_IRegistrar(iface); - FIXME("(%p)->(%s)\n", This, debugstr_w(fileName)); - return file_register(This, fileName, FALSE); -} - -static HRESULT WINAPI Registrar_StringRegister(IRegistrar* iface, LPCOLESTR data) -{ - Registrar *This = impl_from_IRegistrar(iface); - TRACE("(%p)->(%s)\n", This, debugstr_w(data)); - return string_register(This, data, TRUE); -} - -static HRESULT WINAPI Registrar_StringUnregister(IRegistrar* iface, LPCOLESTR data) -{ - Registrar *This = impl_from_IRegistrar(iface); - TRACE("(%p)->(%s)\n", This, debugstr_w(data)); - return string_register(This, data, FALSE); -} - -static HRESULT WINAPI Registrar_ResourceRegister(IRegistrar* iface, LPCOLESTR resFileName, - UINT nID, LPCOLESTR szType) -{ - Registrar *This = impl_from_IRegistrar(iface); - TRACE("(%p)->(%s %d %s)\n", iface, debugstr_w(resFileName), nID, debugstr_w(szType)); - return resource_register(This, resFileName, MAKEINTRESOURCEW(nID), szType, TRUE); -} - -static HRESULT WINAPI Registrar_ResourceUnregister(IRegistrar* iface, LPCOLESTR resFileName, - UINT nID, LPCOLESTR szType) -{ - Registrar *This = impl_from_IRegistrar(iface); - TRACE("(%p)->(%s %d %s)\n", This, debugstr_w(resFileName), nID, debugstr_w(szType)); - return resource_register(This, resFileName, MAKEINTRESOURCEW(nID), szType, FALSE); -} - -static const IRegistrarVtbl RegistrarVtbl = { - Registrar_QueryInterface, - Registrar_AddRef, - Registrar_Release, - Registrar_AddReplacement, - Registrar_ClearReplacements, - Registrar_ResourceRegisterSz, - Registrar_ResourceUnregisterSz, - Registrar_FileRegister, - Registrar_FileUnregister, - Registrar_StringRegister, - Registrar_StringUnregister, - Registrar_ResourceRegister, - Registrar_ResourceUnregister, -}; - -/* Exported only by newer ATL versions */ -static HRESULT AtlCreateRegistrar(IRegistrar **ret) -{ - Registrar *registrar; - - registrar = HeapAlloc(GetProcessHeap(), 0, sizeof(*registrar)); - if(!registrar) - return E_OUTOFMEMORY; - - registrar->IRegistrar_iface.lpVtbl = &RegistrarVtbl; - registrar->ref = 1; - registrar->rep = NULL; - - *ret = ®istrar->IRegistrar_iface; - return S_OK; -} - /************************************************************** * ClassFactory implementation */ diff --git a/dlls/atl100/Makefile.in b/dlls/atl100/Makefile.in index 9121a105377..aaa5a42f02a 100644 --- a/dlls/atl100/Makefile.in +++ b/dlls/atl100/Makefile.in @@ -1,5 +1,9 @@ MODULE = atl100.dll +IMPORTLIB = atl100 +IMPORTS = uuid advapi32 -C_SRCS = atl.c +C_SRCS = \ + atl.c \ + registrar.c @MAKE_DLL_RULES@ diff --git a/dlls/atl100/atl100.spec b/dlls/atl100/atl100.spec index d367615a4c0..bc1ee23f27e 100644 --- a/dlls/atl100/atl100.spec +++ b/dlls/atl100/atl100.spec @@ -42,7 +42,7 @@ 58 stub AtlModuleAddTermFunc 59 stub AtlAxCreateControlLic 60 stub AtlAxCreateControlLicEx -61 stub AtlCreateRegistrar +61 stdcall AtlCreateRegistrar(ptr) 62 stub AtlWinModuleRegisterClassExW 63 stub AtlWinModuleRegisterClassExA 64 stub AtlCallTermFunc diff --git a/dlls/atl100/registrar.c b/dlls/atl100/registrar.c new file mode 100644 index 00000000000..f9f5b3c66b5 --- /dev/null +++ b/dlls/atl100/registrar.c @@ -0,0 +1,704 @@ +/* + * Copyright 2005 Jacek Caban + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include "atlbase.h" + +#include "wine/debug.h" +#include "wine/unicode.h" + +WINE_DEFAULT_DEBUG_CHANNEL(atl); + +/************************************************************** + * ATLRegistrar implementation + */ + +static const struct { + WCHAR name[22]; + HKEY key; +} root_keys[] = { + {{'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T',0}, + HKEY_CLASSES_ROOT}, + {{'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R',0}, + HKEY_CURRENT_USER}, + {{'H','K','E','Y','_','L','O','C','A','L','_','M','A','C','H','I','N','E',0}, + HKEY_LOCAL_MACHINE}, + {{'H','K','E','Y','_','U','S','E','R','S',0}, + HKEY_USERS}, + {{'H','K','E','Y','_','P','E','R','F','O','R','M','A','N','C','E','_','D','A','T','A',0}, + HKEY_PERFORMANCE_DATA}, + {{'H','K','E','Y','_','D','Y','N','_','D','A','T','A',0}, + HKEY_DYN_DATA}, + {{'H','K','E','Y','_','C','U','R','R','E','N','T','_','C','O','N','F','I','G',0}, + HKEY_CURRENT_CONFIG}, + {{'H','K','C','R',0}, HKEY_CLASSES_ROOT}, + {{'H','K','C','U',0}, HKEY_CURRENT_USER}, + {{'H','K','L','M',0}, HKEY_LOCAL_MACHINE}, + {{'H','K','U',0}, HKEY_USERS}, + {{'H','K','P','D',0}, HKEY_PERFORMANCE_DATA}, + {{'H','K','D','D',0}, HKEY_DYN_DATA}, + {{'H','K','C','C',0}, HKEY_CURRENT_CONFIG} +}; + +typedef struct rep_list_str { + LPOLESTR key; + LPOLESTR item; + int key_len; + struct rep_list_str *next; +} rep_list; + +typedef struct { + IRegistrar IRegistrar_iface; + LONG ref; + rep_list *rep; +} Registrar; + +typedef struct { + LPOLESTR str; + DWORD alloc; + DWORD len; +} strbuf; + +static inline Registrar *impl_from_IRegistrar(IRegistrar *iface) +{ + return CONTAINING_RECORD(iface, Registrar, IRegistrar_iface); +} + +static void strbuf_init(strbuf *buf) +{ + buf->str = HeapAlloc(GetProcessHeap(), 0, 128*sizeof(WCHAR)); + buf->alloc = 128; + buf->len = 0; +} + +static void strbuf_write(LPCOLESTR str, strbuf *buf, int len) +{ + if(len == -1) + len = lstrlenW(str); + if(buf->len+len+1 >= buf->alloc) { + buf->alloc = (buf->len+len)<<1; + buf->str = HeapReAlloc(GetProcessHeap(), 0, buf->str, buf->alloc*sizeof(WCHAR)); + } + memcpy(buf->str+buf->len, str, len*sizeof(OLECHAR)); + buf->len += len; + buf->str[buf->len] = '\0'; +} + +static HRESULT get_word(LPCOLESTR *str, strbuf *buf) +{ + LPCOLESTR iter, iter2 = *str; + + buf->len = 0; + buf->str[0] = '\0'; + + while(isspaceW(*iter2)) + iter2++; + iter = iter2; + if(!*iter) { + *str = iter; + return S_OK; + } + + if(*iter == '}' || *iter == '=') { + strbuf_write(iter++, buf, 1); + }else if(*iter == '\'') { + iter2 = ++iter; + iter = strchrW(iter, '\''); + if(!iter) { + WARN("Unexpected end of script\n"); + *str = iter; + return DISP_E_EXCEPTION; + } + strbuf_write(iter2, buf, iter-iter2); + iter++; + }else { + while(*iter && !isspaceW(*iter)) + iter++; + strbuf_write(iter2, buf, iter-iter2); + } + + while(isspaceW(*iter)) + iter++; + *str = iter; + return S_OK; +} + +static HRESULT do_preprocess(const Registrar *This, LPCOLESTR data, strbuf *buf) +{ + LPCOLESTR iter, iter2 = data; + rep_list *rep_iter; + static const WCHAR wstr[] = {'%',0}; + + iter = strchrW(data, '%'); + while(iter) { + strbuf_write(iter2, buf, iter-iter2); + + iter2 = ++iter; + if(!*iter2) + return DISP_E_EXCEPTION; + iter = strchrW(iter2, '%'); + if(!iter) + return DISP_E_EXCEPTION; + + if(iter == iter2) { + strbuf_write(wstr, buf, 1); + }else { + for(rep_iter = This->rep; rep_iter; rep_iter = rep_iter->next) { + if(rep_iter->key_len == iter-iter2 + && !memicmpW(iter2, rep_iter->key, rep_iter->key_len)) + break; + } + if(!rep_iter) { + WARN("Could not find replacement: %s\n", debugstr_wn(iter2, iter-iter2)); + return DISP_E_EXCEPTION; + } + + strbuf_write(rep_iter->item, buf, -1); + } + + iter2 = ++iter; + iter = strchrW(iter, '%'); + } + + strbuf_write(iter2, buf, -1); + TRACE("%s\n", debugstr_w(buf->str)); + + return S_OK; +} + +static HRESULT do_process_key(LPCOLESTR *pstr, HKEY parent_key, strbuf *buf, BOOL do_register) +{ + LPCOLESTR iter = *pstr; + HRESULT hres; + LONG lres; + HKEY hkey = 0; + strbuf name; + + enum { + NORMAL, + NO_REMOVE, + IS_VAL, + FORCE_REMOVE, + DO_DELETE + } key_type = NORMAL; + + static const WCHAR wstrNoRemove[] = {'N','o','R','e','m','o','v','e',0}; + static const WCHAR wstrForceRemove[] = {'F','o','r','c','e','R','e','m','o','v','e',0}; + static const WCHAR wstrDelete[] = {'D','e','l','e','t','e',0}; + static const WCHAR wstrval[] = {'v','a','l',0}; + + iter = *pstr; + hres = get_word(&iter, buf); + if(FAILED(hres)) + return hres; + strbuf_init(&name); + + while(buf->str[1] || buf->str[0] != '}') { + key_type = NORMAL; + if(!lstrcmpiW(buf->str, wstrNoRemove)) + key_type = NO_REMOVE; + else if(!lstrcmpiW(buf->str, wstrForceRemove)) + key_type = FORCE_REMOVE; + else if(!lstrcmpiW(buf->str, wstrval)) + key_type = IS_VAL; + else if(!lstrcmpiW(buf->str, wstrDelete)) + key_type = DO_DELETE; + + if(key_type != NORMAL) { + hres = get_word(&iter, buf); + if(FAILED(hres)) + break; + } + TRACE("name = %s\n", debugstr_w(buf->str)); + + if(do_register) { + if(key_type == IS_VAL) { + hkey = parent_key; + strbuf_write(buf->str, &name, -1); + }else if(key_type == DO_DELETE) { + TRACE("Deleting %s\n", debugstr_w(buf->str)); + RegDeleteTreeW(parent_key, buf->str); + }else { + if(key_type == FORCE_REMOVE) + RegDeleteTreeW(parent_key, buf->str); + lres = RegCreateKeyW(parent_key, buf->str, &hkey); + if(lres != ERROR_SUCCESS) { + WARN("Could not create(open) key: %08x\n", lres); + hres = HRESULT_FROM_WIN32(lres); + break; + } + } + }else if(key_type != IS_VAL && key_type != DO_DELETE) { + strbuf_write(buf->str, &name, -1); + lres = RegOpenKeyW(parent_key, buf->str, &hkey); + if(lres != ERROR_SUCCESS) + WARN("Could not open key %s: %08x\n", debugstr_w(name.str), lres); + } + + if(key_type != DO_DELETE && *iter == '=') { + iter++; + hres = get_word(&iter, buf); + if(FAILED(hres)) + break; + if(buf->len != 1) { + WARN("Wrong registry type: %s\n", debugstr_w(buf->str)); + hres = DISP_E_EXCEPTION; + break; + } + if(do_register) { + switch(buf->str[0]) { + case 's': + hres = get_word(&iter, buf); + if(FAILED(hres)) + break; + lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_SZ, (PBYTE)buf->str, + (lstrlenW(buf->str)+1)*sizeof(WCHAR)); + if(lres != ERROR_SUCCESS) { + WARN("Could set value of key: %08x\n", lres); + hres = HRESULT_FROM_WIN32(lres); + break; + } + break; + case 'd': { + DWORD dw; + hres = get_word(&iter, buf); + if(FAILED(hres)) + break; + dw = atoiW(buf->str); + lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_DWORD, + (PBYTE)&dw, sizeof(dw)); + if(lres != ERROR_SUCCESS) { + WARN("Could set value of key: %08x\n", lres); + hres = HRESULT_FROM_WIN32(lres); + break; + } + break; + } + case 'b': { + BYTE *bytes; + DWORD count; + DWORD i; + hres = get_word(&iter, buf); + if(FAILED(hres)) + break; + count = (lstrlenW(buf->str) + 1) / 2; + bytes = HeapAlloc(GetProcessHeap(), 0, count); + if(bytes == NULL) { + hres = E_OUTOFMEMORY; + break; + } + for(i = 0; i < count && buf->str[2*i]; i++) { + WCHAR digits[3]; + if(!isxdigitW(buf->str[2*i]) || !isxdigitW(buf->str[2*i + 1])) { + hres = E_FAIL; + break; + } + digits[0] = buf->str[2*i]; + digits[1] = buf->str[2*i + 1]; + digits[2] = 0; + bytes[i] = (BYTE) strtoulW(digits, NULL, 16); + } + if(SUCCEEDED(hres)) { + lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_BINARY, + bytes, count); + if(lres != ERROR_SUCCESS) { + WARN("Could not set value of key: 0x%08x\n", lres); + hres = HRESULT_FROM_WIN32(lres); + } + } + HeapFree(GetProcessHeap(), 0, bytes); + break; + } + default: + WARN("Wrong resource type: %s\n", debugstr_w(buf->str)); + hres = DISP_E_EXCEPTION; + }; + if(FAILED(hres)) + break; + }else { + if(*iter == '-') + iter++; + hres = get_word(&iter, buf); + if(FAILED(hres)) + break; + } + }else if(key_type == IS_VAL) { + WARN("value not set!\n"); + hres = DISP_E_EXCEPTION; + break; + } + + if(key_type != IS_VAL && key_type != DO_DELETE && *iter == '{' && isspaceW(iter[1])) { + hres = get_word(&iter, buf); + if(FAILED(hres)) + break; + hres = do_process_key(&iter, hkey, buf, do_register); + if(FAILED(hres)) + break; + } + + TRACE("%x %x\n", do_register, key_type); + if(!do_register && (key_type == NORMAL || key_type == FORCE_REMOVE)) { + TRACE("Deleting %s\n", debugstr_w(name.str)); + RegDeleteKeyW(parent_key, name.str); + } + + if(hkey && key_type != IS_VAL) + RegCloseKey(hkey); + hkey = 0; + name.len = 0; + + hres = get_word(&iter, buf); + if(FAILED(hres)) + break; + } + + HeapFree(GetProcessHeap(), 0, name.str); + if(hkey && key_type != IS_VAL) + RegCloseKey(hkey); + *pstr = iter; + return hres; +} + +static HRESULT do_process_root_key(LPCOLESTR data, BOOL do_register) +{ + LPCOLESTR iter = data; + strbuf buf; + HRESULT hres = S_OK; + unsigned int i; + + strbuf_init(&buf); + hres = get_word(&iter, &buf); + if(FAILED(hres)) + return hres; + + while(*iter) { + if(!buf.len) { + WARN("ward.len == 0, failed\n"); + hres = DISP_E_EXCEPTION; + break; + } + for(i=0; i(%s %p\n", iface, debugstr_guid(riid), ppvObject); + + if(IsEqualGUID(&IID_IUnknown, riid) + || IsEqualGUID(&IID_IRegistrar, riid) + || IsEqualGUID(&IID_IRegistrarBase, riid)) { + IRegistrar_AddRef(iface); + *ppvObject = iface; + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG WINAPI Registrar_AddRef(IRegistrar *iface) +{ + Registrar *This = impl_from_IRegistrar(iface); + ULONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p) ->%d\n", This, ref); + return ref; +} + +static ULONG WINAPI Registrar_Release(IRegistrar *iface) +{ + Registrar *This = impl_from_IRegistrar(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ->%d\n", This, ref); + if(!ref) { + IRegistrar_ClearReplacements(iface); + HeapFree(GetProcessHeap(), 0, This); + } + return ref; +} + +static HRESULT WINAPI Registrar_AddReplacement(IRegistrar *iface, LPCOLESTR Key, LPCOLESTR item) +{ + Registrar *This = impl_from_IRegistrar(iface); + int len; + rep_list *new_rep; + + TRACE("(%p)->(%s %s)\n", This, debugstr_w(Key), debugstr_w(item)); + + new_rep = HeapAlloc(GetProcessHeap(), 0, sizeof(rep_list)); + + new_rep->key_len = lstrlenW(Key); + new_rep->key = HeapAlloc(GetProcessHeap(), 0, (new_rep->key_len + 1) * sizeof(OLECHAR)); + memcpy(new_rep->key, Key, (new_rep->key_len+1)*sizeof(OLECHAR)); + + len = lstrlenW(item)+1; + new_rep->item = HeapAlloc(GetProcessHeap(), 0, len*sizeof(OLECHAR)); + memcpy(new_rep->item, item, len*sizeof(OLECHAR)); + + new_rep->next = This->rep; + This->rep = new_rep; + + return S_OK; +} + +static HRESULT WINAPI Registrar_ClearReplacements(IRegistrar *iface) +{ + Registrar *This = impl_from_IRegistrar(iface); + rep_list *iter, *iter2; + + TRACE("(%p)\n", This); + + if(!This->rep) + return S_OK; + + iter = This->rep; + while(iter) { + iter2 = iter->next; + HeapFree(GetProcessHeap(), 0, iter->key); + HeapFree(GetProcessHeap(), 0, iter->item); + HeapFree(GetProcessHeap(), 0, iter); + iter = iter2; + } + + This->rep = NULL; + return S_OK; +} + +static HRESULT WINAPI Registrar_ResourceRegisterSz(IRegistrar* iface, LPCOLESTR resFileName, + LPCOLESTR szID, LPCOLESTR szType) +{ + Registrar *This = impl_from_IRegistrar(iface); + TRACE("(%p)->(%s %s %s)\n", This, debugstr_w(resFileName), debugstr_w(szID), debugstr_w(szType)); + return resource_register(This, resFileName, szID, szType, TRUE); +} + +static HRESULT WINAPI Registrar_ResourceUnregisterSz(IRegistrar* iface, LPCOLESTR resFileName, + LPCOLESTR szID, LPCOLESTR szType) +{ + Registrar *This = impl_from_IRegistrar(iface); + TRACE("(%p)->(%s %s %s)\n", This, debugstr_w(resFileName), debugstr_w(szID), debugstr_w(szType)); + return resource_register(This, resFileName, szID, szType, FALSE); +} + +static HRESULT WINAPI Registrar_FileRegister(IRegistrar* iface, LPCOLESTR fileName) +{ + Registrar *This = impl_from_IRegistrar(iface); + TRACE("(%p)->(%s)\n", This, debugstr_w(fileName)); + return file_register(This, fileName, TRUE); +} + +static HRESULT WINAPI Registrar_FileUnregister(IRegistrar* iface, LPCOLESTR fileName) +{ + Registrar *This = impl_from_IRegistrar(iface); + FIXME("(%p)->(%s)\n", This, debugstr_w(fileName)); + return file_register(This, fileName, FALSE); +} + +static HRESULT WINAPI Registrar_StringRegister(IRegistrar* iface, LPCOLESTR data) +{ + Registrar *This = impl_from_IRegistrar(iface); + TRACE("(%p)->(%s)\n", This, debugstr_w(data)); + return string_register(This, data, TRUE); +} + +static HRESULT WINAPI Registrar_StringUnregister(IRegistrar* iface, LPCOLESTR data) +{ + Registrar *This = impl_from_IRegistrar(iface); + TRACE("(%p)->(%s)\n", This, debugstr_w(data)); + return string_register(This, data, FALSE); +} + +static HRESULT WINAPI Registrar_ResourceRegister(IRegistrar* iface, LPCOLESTR resFileName, + UINT nID, LPCOLESTR szType) +{ + Registrar *This = impl_from_IRegistrar(iface); + TRACE("(%p)->(%s %d %s)\n", iface, debugstr_w(resFileName), nID, debugstr_w(szType)); + return resource_register(This, resFileName, MAKEINTRESOURCEW(nID), szType, TRUE); +} + +static HRESULT WINAPI Registrar_ResourceUnregister(IRegistrar* iface, LPCOLESTR resFileName, + UINT nID, LPCOLESTR szType) +{ + Registrar *This = impl_from_IRegistrar(iface); + TRACE("(%p)->(%s %d %s)\n", This, debugstr_w(resFileName), nID, debugstr_w(szType)); + return resource_register(This, resFileName, MAKEINTRESOURCEW(nID), szType, FALSE); +} + +static const IRegistrarVtbl RegistrarVtbl = { + Registrar_QueryInterface, + Registrar_AddRef, + Registrar_Release, + Registrar_AddReplacement, + Registrar_ClearReplacements, + Registrar_ResourceRegisterSz, + Registrar_ResourceUnregisterSz, + Registrar_FileRegister, + Registrar_FileUnregister, + Registrar_StringRegister, + Registrar_StringUnregister, + Registrar_ResourceRegister, + Registrar_ResourceUnregister, +}; + +/*********************************************************************** + * AtlCreateRegistrar [atl100.@] + */ +HRESULT WINAPI AtlCreateRegistrar(IRegistrar **ret) +{ + Registrar *registrar; + + registrar = HeapAlloc(GetProcessHeap(), 0, sizeof(*registrar)); + if(!registrar) + return E_OUTOFMEMORY; + + registrar->IRegistrar_iface.lpVtbl = &RegistrarVtbl; + registrar->ref = 1; + registrar->rep = NULL; + + *ret = ®istrar->IRegistrar_iface; + return S_OK; +} diff --git a/include/atlbase.h b/include/atlbase.h index 8fa99871a9e..4033f9a727e 100644 --- a/include/atlbase.h +++ b/include/atlbase.h @@ -182,5 +182,6 @@ HRESULT WINAPI AtlModuleUnregisterServerEx(_ATL_MODULEW* pM, BOOL bUnRegTypeLib, HRESULT WINAPI AtlModuleTerm(_ATL_MODULEW* pM); HRESULT WINAPI AtlUnadvise(IUnknown *pUnkCP, const IID * iid, DWORD dw); HRESULT WINAPI AtlUnmarshalPtr(IStream *pStream, const IID *iid, IUnknown **ppUnk); +HRESULT WINAPI AtlCreateRegistrar(IRegistrar**); #endif /* __WINE_ATLBASE_H__ */