/* * 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 */ #include <stdarg.h> #define COBJMACROS #include "windef.h" #include "winbase.h" #include "winuser.h" #include "winreg.h" #include "objbase.h" #include "oaidl.h" #define ATL_INITGUID #include "atliface.h" #include "atlbase.h" #include "wine/debug.h" #include "wine/unicode.h" WINE_DEFAULT_DEBUG_CHANNEL(atl); static LONG dll_count; /************************************************************** * 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 { const IRegistrarVtbl *lpVtbl; LONG ref; rep_list *rep; } Registrar; typedef struct { LPOLESTR str; DWORD alloc; DWORD len; } strbuf; 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': { WCHAR *end; DWORD dw; if(*iter == '0' && iter[1] == 'x') { iter += 2; dw = strtolW(iter, &end, 16); }else { dw = strtolW(iter, &end, 10); } iter = end; 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; } 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<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; LRESULT lres; HRESULT hres; file = CreateFileW(fileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); if(file != INVALID_HANDLE_VALUE) { filelen = GetFileSize(file, NULL); regstra = HeapAlloc(GetProcessHeap(), 0, filelen); lres = ReadFile(file, regstra, filelen, NULL, NULL); if(lres == ERROR_SUCCESS) { 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 faile\n"); hres = HRESULT_FROM_WIN32(lres); } HeapFree(GetProcessHeap(), 0, regstra); CloseHandle(file); }else { WARN("Could not open file\n"); 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)) { IRegistrar_AddRef(iface); *ppvObject = iface; return S_OK; } return E_NOINTERFACE; } static ULONG WINAPI Registrar_AddRef(IRegistrar *iface) { Registrar *This = (Registrar*)iface; ULONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ->%d\n", This, ref); return ref; } static ULONG WINAPI Registrar_Release(IRegistrar *iface) { Registrar *This = (Registrar*)iface; ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) ->%d\n", This, ref); if(!ref) { IRegistrar_ClearReplacements(iface); HeapFree(GetProcessHeap(), 0, This); InterlockedDecrement(&dll_count); } return ref; } static HRESULT WINAPI Registrar_AddReplacement(IRegistrar *iface, LPCOLESTR Key, LPCOLESTR item) { Registrar *This = (Registrar*)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*sizeof(OLECHAR)+1); 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 = (Registrar*)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 = (Registrar*)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 = (Registrar*)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 = (Registrar*)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 = (Registrar*)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 = (Registrar*)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 = (Registrar*)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 = (Registrar*)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 = (Registrar*)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, }; static HRESULT Registrar_create(const IUnknown *pUnkOuter, REFIID riid, void **ppvObject) { Registrar *ret; if(!IsEqualGUID(&IID_IUnknown, riid) && !IsEqualGUID(&IID_IRegistrar, riid)) return E_NOINTERFACE; ret = HeapAlloc(GetProcessHeap(), 0, sizeof(Registrar)); ret->lpVtbl = &RegistrarVtbl; ret->ref = 1; ret->rep = NULL; *ppvObject = ret; InterlockedIncrement(&dll_count); return S_OK; } /************************************************************** * ClassFactory implementation */ static HRESULT WINAPI RegistrarCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppvObject) { TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject); if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IRegistrar, riid)) { *ppvObject = iface; return S_OK; } return E_NOINTERFACE; } static ULONG WINAPI RegistrarCF_AddRef(IClassFactory *iface) { InterlockedIncrement(&dll_count); return 2; } static ULONG WINAPI RegistrarCF_Release(IClassFactory *iface) { InterlockedDecrement(&dll_count); return 1; } static HRESULT WINAPI RegistrarCF_CreateInstance(IClassFactory *iface, LPUNKNOWN pUnkOuter, REFIID riid, void **ppvObject) { TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject); return Registrar_create(pUnkOuter, riid, ppvObject); } static HRESULT WINAPI RegistrarCF_LockServer(IClassFactory *iface, BOOL lock) { TRACE("(%p)->(%x)\n", iface, lock); if(lock) InterlockedIncrement(&dll_count); else InterlockedDecrement(&dll_count); return S_OK; } static const IClassFactoryVtbl IRegistrarCFVtbl = { RegistrarCF_QueryInterface, RegistrarCF_AddRef, RegistrarCF_Release, RegistrarCF_CreateInstance, RegistrarCF_LockServer }; static IClassFactory RegistrarCF = { &IRegistrarCFVtbl }; /************************************************************** * DllGetClassObject (ATL.2) */ HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, LPVOID *ppvObject) { TRACE("(%s %s %p)\n", debugstr_guid(clsid), debugstr_guid(riid), ppvObject); if(IsEqualGUID(&CLSID_ATLRegistrar, clsid)) { *ppvObject = &RegistrarCF; return S_OK; } FIXME("Not supported class %s\n", debugstr_guid(clsid)); return CLASS_E_CLASSNOTAVAILABLE; } extern HINSTANCE hInst; static HRESULT do_register_dll_server(IRegistrar *pRegistrar, LPCOLESTR wszDll, LPCOLESTR wszId, BOOL do_register, const struct _ATL_REGMAP_ENTRY* pMapEntries) { WCHAR buf[MAX_PATH]; HRESULT hres; const struct _ATL_REGMAP_ENTRY *pMapEntry; static const WCHAR wszModule[] = {'M','O','D','U','L','E',0}; static const WCHAR wszRegistry[] = {'R','E','G','I','S','T','R','Y',0}; static const WCHAR wszCLSID_ATLRegistrar[] = {'C','L','S','I','D','_','A','T','L','R','e','g','i','s','t','r','a','r',0}; if (!pRegistrar) Registrar_create(NULL, &IID_IRegistrar, (void**)&pRegistrar); IRegistrar_AddReplacement(pRegistrar, wszModule, wszDll); for (pMapEntry = pMapEntries; pMapEntry && pMapEntry->szKey; pMapEntry++) IRegistrar_AddReplacement(pRegistrar, pMapEntry->szKey, pMapEntry->szData); StringFromGUID2(&CLSID_ATLRegistrar, buf, sizeof(buf)/sizeof(buf[0])); IRegistrar_AddReplacement(pRegistrar, wszCLSID_ATLRegistrar, buf); if(do_register) hres = IRegistrar_ResourceRegisterSz(pRegistrar, wszDll, wszId, wszRegistry); else hres = IRegistrar_ResourceUnregisterSz(pRegistrar, wszDll, wszId, wszRegistry); IRegistrar_Release(pRegistrar); return hres; } static HRESULT do_register_server(BOOL do_register) { static const WCHAR wszDll[] = {'a','t','l','.','d','l','l',0}; return do_register_dll_server(NULL, wszDll, MAKEINTRESOURCEW(101), do_register, NULL); } /*********************************************************************** * AtlModuleUpdateRegistryFromResourceD [ATL.@] * */ HRESULT WINAPI AtlModuleUpdateRegistryFromResourceD(_ATL_MODULEW* pM, LPCOLESTR lpszRes, BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries, IRegistrar* pReg) { HINSTANCE lhInst = pM->m_hInst; /* everything inside this function below this point * should go into atl71.AtlUpdateRegistryFromResourceD */ WCHAR module_name[MAX_PATH]; if(!GetModuleFileNameW(lhInst, module_name, MAX_PATH)) { FIXME("hinst %p: did not get module name\n", lhInst); return E_FAIL; } TRACE("%p (%s), %s, %d, %p, %p\n", hInst, debugstr_w(module_name), debugstr_w(lpszRes), bRegister, pMapEntries, pReg); return do_register_dll_server(pReg, module_name, lpszRes, bRegister, pMapEntries); } /*********************************************************************** * DllRegisterServer (ATL.@) */ HRESULT WINAPI DllRegisterServer(void) { TRACE("\n"); return do_register_server(TRUE); } /*********************************************************************** * DllRegisterServer (ATL.@) */ HRESULT WINAPI DllUnregisterServer(void) { TRACE("\n"); return do_register_server(FALSE); } /*********************************************************************** * DllCanUnloadNow (ATL.@) */ HRESULT WINAPI DllCanUnloadNow(void) { TRACE("dll_count = %u\n", dll_count); return dll_count ? S_FALSE : S_OK; }