| /* |
| * 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; |
| 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; |
| 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<sizeof(root_keys)/sizeof(root_keys[0]); i++) { |
| if(!lstrcmpiW(buf.str, root_keys[i].name)) |
| break; |
| } |
| if(i == sizeof(root_keys)/sizeof(root_keys[0])) { |
| WARN("Wrong root key name: %s\n", debugstr_w(buf.str)); |
| hres = DISP_E_EXCEPTION; |
| break; |
| } |
| hres = get_word(&iter, &buf); |
| if(FAILED(hres)) |
| break; |
| if(buf.str[1] || buf.str[0] != '{') { |
| WARN("Failed, expected '{', got %s\n", debugstr_w(buf.str)); |
| hres = DISP_E_EXCEPTION; |
| break; |
| } |
| hres = do_process_key(&iter, root_keys[i].key, &buf, do_register); |
| if(FAILED(hres)) { |
| WARN("Processing key failed: %08x\n", hres); |
| break; |
| } |
| hres = get_word(&iter, &buf); |
| if(FAILED(hres)) |
| break; |
| } |
| HeapFree(GetProcessHeap(), 0, buf.str); |
| return hres; |
| } |
| |
| static HRESULT string_register(Registrar *This, LPCOLESTR data, BOOL do_register) |
| { |
| strbuf buf; |
| HRESULT hres; |
| |
| TRACE("(%p %s %x)\n", This, debugstr_w(data), do_register); |
| |
| strbuf_init(&buf); |
| hres = do_preprocess(This, data, &buf); |
| if(FAILED(hres)) { |
| WARN("preprocessing failed!\n"); |
| HeapFree(GetProcessHeap(), 0, buf.str); |
| return hres; |
| } |
| |
| hres = do_process_root_key(buf.str, do_register); |
| if(FAILED(hres) && do_register) |
| do_process_root_key(buf.str, FALSE); |
| |
| HeapFree(GetProcessHeap(), 0, buf.str); |
| return hres; |
| } |
| |
| static HRESULT resource_register(Registrar *This, LPCOLESTR resFileName, |
| LPCOLESTR szID, LPCOLESTR szType, BOOL do_register) |
| { |
| HINSTANCE hins; |
| HRSRC src; |
| LPSTR regstra; |
| LPWSTR regstrw; |
| DWORD len, reslen; |
| HRESULT hres; |
| |
| hins = LoadLibraryExW(resFileName, NULL, LOAD_LIBRARY_AS_DATAFILE); |
| if(hins) { |
| src = FindResourceW(hins, szID, szType); |
| if(src) { |
| regstra = LoadResource(hins, src); |
| reslen = SizeofResource(hins, src); |
| if(regstra) { |
| len = MultiByteToWideChar(CP_ACP, 0, regstra, reslen, NULL, 0)+1; |
| regstrw = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len*sizeof(WCHAR)); |
| MultiByteToWideChar(CP_ACP, 0, regstra, reslen, regstrw, len); |
| regstrw[len-1] = '\0'; |
| |
| hres = string_register(This, regstrw, do_register); |
| |
| HeapFree(GetProcessHeap(), 0, regstrw); |
| }else { |
| WARN("could not load resource\n"); |
| hres = HRESULT_FROM_WIN32(GetLastError()); |
| } |
| }else { |
| WARN("Could not find source\n"); |
| hres = HRESULT_FROM_WIN32(GetLastError()); |
| } |
| FreeLibrary(hins); |
| }else { |
| WARN("Could not load resource file\n"); |
| hres = HRESULT_FROM_WIN32(GetLastError()); |
| } |
| |
| return hres; |
| } |
| |
| static HRESULT file_register(Registrar *This, LPCOLESTR fileName, BOOL do_register) |
| { |
| HANDLE file; |
| DWORD filelen, len; |
| LPWSTR regstrw; |
| LPSTR regstra; |
| HRESULT hres; |
| |
| file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); |
| if(file != INVALID_HANDLE_VALUE) { |
| filelen = GetFileSize(file, NULL); |
| regstra = HeapAlloc(GetProcessHeap(), 0, filelen); |
| if(ReadFile(file, regstra, filelen, NULL, NULL)) { |
| len = MultiByteToWideChar(CP_ACP, 0, regstra, filelen, NULL, 0)+1; |
| regstrw = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len*sizeof(WCHAR)); |
| MultiByteToWideChar(CP_ACP, 0, regstra, filelen, regstrw, len); |
| regstrw[len-1] = '\0'; |
| |
| hres = string_register(This, regstrw, do_register); |
| |
| HeapFree(GetProcessHeap(), 0, regstrw); |
| }else { |
| WARN("Failed to read file %s\n", debugstr_w(fileName)); |
| hres = HRESULT_FROM_WIN32(GetLastError()); |
| } |
| HeapFree(GetProcessHeap(), 0, regstra); |
| CloseHandle(file); |
| }else { |
| WARN("Could not open file %s\n", debugstr_w(fileName)); |
| hres = HRESULT_FROM_WIN32(GetLastError()); |
| } |
| |
| return hres; |
| } |
| |
| static HRESULT WINAPI Registrar_QueryInterface(IRegistrar *iface, REFIID riid, void **ppvObject) |
| { |
| TRACE("(%p)->(%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; |
| } |
| |
| /*********************************************************************** |
| * AtlUpdateRegistryFromResourceD [atl100.@] |
| */ |
| HRESULT WINAPI AtlUpdateRegistryFromResourceD(HINSTANCE inst, LPCOLESTR res, |
| BOOL bRegister, struct _ATL_REGMAP_ENTRY *pMapEntries, IRegistrar *pReg) |
| { |
| const struct _ATL_REGMAP_ENTRY *iter; |
| WCHAR module_name[MAX_PATH]; |
| IRegistrar *registrar; |
| HRESULT hres; |
| |
| static const WCHAR moduleW[] = {'M','O','D','U','L','E',0}; |
| static const WCHAR registryW[] = {'R','E','G','I','S','T','R','Y',0}; |
| |
| if(!GetModuleFileNameW(inst, module_name, MAX_PATH)) { |
| FIXME("hinst %p: did not get module name\n", inst); |
| return E_FAIL; |
| } |
| |
| TRACE("%p (%s), %s, %d, %p, %p\n", inst, debugstr_w(module_name), |
| debugstr_w(res), bRegister, pMapEntries, pReg); |
| |
| if(pReg) { |
| registrar = pReg; |
| }else { |
| hres = AtlCreateRegistrar(®istrar); |
| if(FAILED(hres)) |
| return hres; |
| } |
| |
| IRegistrar_AddReplacement(registrar, moduleW, module_name); |
| |
| for (iter = pMapEntries; iter && iter->szKey; iter++) |
| IRegistrar_AddReplacement(registrar, iter->szKey, iter->szData); |
| |
| if(bRegister) |
| hres = IRegistrar_ResourceRegisterSz(registrar, module_name, res, registryW); |
| else |
| hres = IRegistrar_ResourceUnregisterSz(registrar, module_name, res, registryW); |
| |
| if(registrar != pReg) |
| IRegistrar_Release(registrar); |
| return hres; |
| } |