1 /* 2 * Implementation of the Microsoft Installer (msi.dll) 3 * 4 * Copyright 2006 Mike McCormack for CodeWeavers 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <stdarg.h> 22 23 #define COBJMACROS 24 25 #include "windef.h" 26 #include "winbase.h" 27 #include "winreg.h" 28 #include "shlwapi.h" 29 #include "oleauto.h" 30 #include "rpcproxy.h" 31 #include "msipriv.h" 32 #include "msiserver.h" 33 34 #include "wine/debug.h" 35 36 WINE_DEFAULT_DEBUG_CHANNEL(msi); 37 38 static LONG dll_count; 39 40 /* the UI level */ 41 INSTALLUILEVEL gUILevel = INSTALLUILEVEL_DEFAULT; 42 HWND gUIhwnd = 0; 43 INSTALLUI_HANDLERA gUIHandlerA = NULL; 44 INSTALLUI_HANDLERW gUIHandlerW = NULL; 45 INSTALLUI_HANDLER_RECORD gUIHandlerRecord = NULL; 46 DWORD gUIFilter = 0; 47 DWORD gUIFilterRecord = 0; 48 LPVOID gUIContext = NULL; 49 LPVOID gUIContextRecord = NULL; 50 WCHAR *gszLogFile = NULL; 51 HINSTANCE msi_hInstance; 52 53 54 /* 55 * Dll lifetime tracking declaration 56 */ 57 static void LockModule(void) 58 { 59 InterlockedIncrement(&dll_count); 60 } 61 62 static void UnlockModule(void) 63 { 64 InterlockedDecrement(&dll_count); 65 } 66 67 /****************************************************************** 68 * DllMain 69 */ 70 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 71 { 72 switch (fdwReason) 73 { 74 case DLL_PROCESS_ATTACH: 75 msi_hInstance = hinstDLL; 76 DisableThreadLibraryCalls(hinstDLL); 77 IsWow64Process( GetCurrentProcess(), &is_wow64 ); 78 break; 79 case DLL_PROCESS_DETACH: 80 if (lpvReserved) break; 81 msi_dialog_unregister_class(); 82 msi_free_handle_table(); 83 msi_free( gszLogFile ); 84 release_typelib(); 85 break; 86 } 87 return TRUE; 88 } 89 90 typedef struct tagIClassFactoryImpl { 91 IClassFactory IClassFactory_iface; 92 HRESULT (*create_object)( IUnknown*, LPVOID* ); 93 } IClassFactoryImpl; 94 95 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface) 96 { 97 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface); 98 } 99 100 static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface, 101 REFIID riid,LPVOID *ppobj) 102 { 103 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 104 105 TRACE("%p %s %p\n",This,debugstr_guid(riid),ppobj); 106 107 if( IsEqualCLSID( riid, &IID_IUnknown ) || 108 IsEqualCLSID( riid, &IID_IClassFactory ) ) 109 { 110 IClassFactory_AddRef( iface ); 111 *ppobj = iface; 112 return S_OK; 113 } 114 return E_NOINTERFACE; 115 } 116 117 static ULONG WINAPI MsiCF_AddRef(LPCLASSFACTORY iface) 118 { 119 LockModule(); 120 return 2; 121 } 122 123 static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface) 124 { 125 UnlockModule(); 126 return 1; 127 } 128 129 static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface, 130 LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) 131 { 132 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 133 IUnknown *unk = NULL; 134 HRESULT r; 135 136 TRACE("%p %p %s %p\n", This, pOuter, debugstr_guid(riid), ppobj); 137 138 r = This->create_object( pOuter, (LPVOID*) &unk ); 139 if (SUCCEEDED(r)) 140 { 141 r = IUnknown_QueryInterface( unk, riid, ppobj ); 142 IUnknown_Release( unk ); 143 } 144 return r; 145 } 146 147 static HRESULT WINAPI MsiCF_LockServer(LPCLASSFACTORY iface, BOOL dolock) 148 { 149 TRACE("%p %d\n", iface, dolock); 150 151 if (dolock) 152 LockModule(); 153 else 154 UnlockModule(); 155 156 return S_OK; 157 } 158 159 static const IClassFactoryVtbl MsiCF_Vtbl = 160 { 161 MsiCF_QueryInterface, 162 MsiCF_AddRef, 163 MsiCF_Release, 164 MsiCF_CreateInstance, 165 MsiCF_LockServer 166 }; 167 168 static IClassFactoryImpl MsiServer_CF = { { &MsiCF_Vtbl }, create_msiserver }; 169 static IClassFactoryImpl WineMsiCustomRemote_CF = { { &MsiCF_Vtbl }, create_msi_custom_remote }; 170 static IClassFactoryImpl WineMsiRemotePackage_CF = { { &MsiCF_Vtbl }, create_msi_remote_package }; 171 172 /****************************************************************** 173 * DllGetClassObject [MSI.@] 174 */ 175 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) 176 { 177 TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); 178 179 if ( IsEqualCLSID (rclsid, &CLSID_MsiInstaller) ) 180 { 181 *ppv = &MsiServer_CF; 182 return S_OK; 183 } 184 185 if ( IsEqualCLSID (rclsid, &CLSID_WineMsiRemoteCustomAction) ) 186 { 187 *ppv = &WineMsiCustomRemote_CF; 188 return S_OK; 189 } 190 191 if ( IsEqualCLSID (rclsid, &CLSID_WineMsiRemotePackage) ) 192 { 193 *ppv = &WineMsiRemotePackage_CF; 194 return S_OK; 195 } 196 197 if( IsEqualCLSID (rclsid, &CLSID_MsiServerMessage) || 198 IsEqualCLSID (rclsid, &CLSID_MsiServer) || 199 IsEqualCLSID (rclsid, &CLSID_PSFactoryBuffer) || 200 IsEqualCLSID (rclsid, &CLSID_MsiServerX3) ) 201 { 202 FIXME("create %s object\n", debugstr_guid( rclsid )); 203 } 204 205 return CLASS_E_CLASSNOTAVAILABLE; 206 } 207 208 /****************************************************************** 209 * DllGetVersion [MSI.@] 210 */ 211 HRESULT WINAPI DllGetVersion(DLLVERSIONINFO *pdvi) 212 { 213 TRACE("%p\n",pdvi); 214 215 if (pdvi->cbSize < sizeof(DLLVERSIONINFO)) 216 return E_INVALIDARG; 217 218 pdvi->dwMajorVersion = MSI_MAJORVERSION; 219 pdvi->dwMinorVersion = MSI_MINORVERSION; 220 pdvi->dwBuildNumber = MSI_BUILDNUMBER; 221 pdvi->dwPlatformID = DLLVER_PLATFORM_WINDOWS; 222 223 return S_OK; 224 } 225 226 /****************************************************************** 227 * DllCanUnloadNow [MSI.@] 228 */ 229 HRESULT WINAPI DllCanUnloadNow(void) 230 { 231 return dll_count == 0 ? S_OK : S_FALSE; 232 } 233 234 /*********************************************************************** 235 * DllRegisterServer (MSI.@) 236 */ 237 HRESULT WINAPI DllRegisterServer(void) 238 { 239 return __wine_register_resources( msi_hInstance ); 240 } 241 242 /*********************************************************************** 243 * DllUnregisterServer (MSI.@) 244 */ 245 HRESULT WINAPI DllUnregisterServer(void) 246 { 247 return __wine_unregister_resources( msi_hInstance ); 248 } 249