[MSI]
[reactos.git] / reactos / dll / win32 / msi / msi_main.c
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 #define NONAMELESSUNION
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "shlwapi.h"
30 #include "oleauto.h"
31 #include "rpcproxy.h"
32 #include "msipriv.h"
33 #include "msiserver.h"
34
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(msi);
38
39 static LONG dll_count;
40
41 /* the UI level */
42 INSTALLUILEVEL gUILevel = INSTALLUILEVEL_BASIC;
43 HWND gUIhwnd = 0;
44 INSTALLUI_HANDLERA gUIHandlerA = NULL;
45 INSTALLUI_HANDLERW gUIHandlerW = NULL;
46 INSTALLUI_HANDLER_RECORD gUIHandlerRecord = NULL;
47 DWORD gUIFilter = 0;
48 LPVOID gUIContext = NULL;
49 WCHAR *gszLogFile = NULL;
50 HINSTANCE msi_hInstance;
51
52 static WCHAR msi_path[MAX_PATH];
53 static ITypeLib *msi_typelib;
54
55 /*
56 * Dll lifetime tracking declaration
57 */
58 static void LockModule(void)
59 {
60 InterlockedIncrement(&dll_count);
61 }
62
63 static void UnlockModule(void)
64 {
65 InterlockedDecrement(&dll_count);
66 }
67
68 /******************************************************************
69 * DllMain
70 */
71 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
72 {
73 switch (fdwReason)
74 {
75 case DLL_PROCESS_ATTACH:
76 msi_hInstance = hinstDLL;
77 DisableThreadLibraryCalls(hinstDLL);
78 break;
79 case DLL_PROCESS_DETACH:
80 if (msi_typelib) ITypeLib_Release( msi_typelib );
81 msi_dialog_unregister_class();
82 msi_free_handle_table();
83 msi_free( gszLogFile );
84 break;
85 }
86 return TRUE;
87 }
88
89 static CRITICAL_SECTION MSI_typelib_cs;
90 static CRITICAL_SECTION_DEBUG MSI_typelib_cs_debug =
91 {
92 0, 0, &MSI_typelib_cs,
93 { &MSI_typelib_cs_debug.ProcessLocksList,
94 &MSI_typelib_cs_debug.ProcessLocksList },
95 0, 0, { (DWORD_PTR)(__FILE__ ": MSI_typelib_cs") }
96 };
97 static CRITICAL_SECTION MSI_typelib_cs = { &MSI_typelib_cs_debug, -1, 0, 0, 0, 0 };
98
99 ITypeLib *get_msi_typelib( LPWSTR *path )
100 {
101 EnterCriticalSection( &MSI_typelib_cs );
102
103 if (!msi_typelib)
104 {
105 TRACE("loading typelib\n");
106
107 if (GetModuleFileNameW( msi_hInstance, msi_path, MAX_PATH ))
108 LoadTypeLib( msi_path, &msi_typelib );
109 }
110
111 LeaveCriticalSection( &MSI_typelib_cs );
112
113 if (path)
114 *path = msi_path;
115
116 if (msi_typelib)
117 ITypeLib_AddRef( msi_typelib );
118
119 return msi_typelib;
120 }
121
122 typedef struct tagIClassFactoryImpl {
123 IClassFactory IClassFactory_iface;
124 HRESULT (*create_object)( IUnknown*, LPVOID* );
125 } IClassFactoryImpl;
126
127 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
128 {
129 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
130 }
131
132 static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface,
133 REFIID riid,LPVOID *ppobj)
134 {
135 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
136
137 TRACE("%p %s %p\n",This,debugstr_guid(riid),ppobj);
138
139 if( IsEqualCLSID( riid, &IID_IUnknown ) ||
140 IsEqualCLSID( riid, &IID_IClassFactory ) )
141 {
142 IClassFactory_AddRef( iface );
143 *ppobj = iface;
144 return S_OK;
145 }
146 return E_NOINTERFACE;
147 }
148
149 static ULONG WINAPI MsiCF_AddRef(LPCLASSFACTORY iface)
150 {
151 LockModule();
152 return 2;
153 }
154
155 static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface)
156 {
157 UnlockModule();
158 return 1;
159 }
160
161 static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface,
162 LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj)
163 {
164 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
165 IUnknown *unk = NULL;
166 HRESULT r;
167
168 TRACE("%p %p %s %p\n", This, pOuter, debugstr_guid(riid), ppobj);
169
170 r = This->create_object( pOuter, (LPVOID*) &unk );
171 if (SUCCEEDED(r))
172 {
173 r = IUnknown_QueryInterface( unk, riid, ppobj );
174 IUnknown_Release( unk );
175 }
176 return r;
177 }
178
179 static HRESULT WINAPI MsiCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
180 {
181 TRACE("%p %d\n", iface, dolock);
182
183 if (dolock)
184 LockModule();
185 else
186 UnlockModule();
187
188 return S_OK;
189 }
190
191 static const IClassFactoryVtbl MsiCF_Vtbl =
192 {
193 MsiCF_QueryInterface,
194 MsiCF_AddRef,
195 MsiCF_Release,
196 MsiCF_CreateInstance,
197 MsiCF_LockServer
198 };
199
200 static IClassFactoryImpl MsiServer_CF = { { &MsiCF_Vtbl }, create_msiserver };
201 static IClassFactoryImpl WineMsiCustomRemote_CF = { { &MsiCF_Vtbl }, create_msi_custom_remote };
202 static IClassFactoryImpl WineMsiRemotePackage_CF = { { &MsiCF_Vtbl }, create_msi_remote_package };
203
204 /******************************************************************
205 * DllGetClassObject [MSI.@]
206 */
207 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
208 {
209 TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
210
211 if ( IsEqualCLSID (rclsid, &CLSID_MsiInstaller) )
212 {
213 *ppv = &MsiServer_CF;
214 return S_OK;
215 }
216
217 if ( IsEqualCLSID (rclsid, &CLSID_WineMsiRemoteCustomAction) )
218 {
219 *ppv = &WineMsiCustomRemote_CF;
220 return S_OK;
221 }
222
223 if ( IsEqualCLSID (rclsid, &CLSID_WineMsiRemotePackage) )
224 {
225 *ppv = &WineMsiRemotePackage_CF;
226 return S_OK;
227 }
228
229 if( IsEqualCLSID (rclsid, &CLSID_MsiServerMessage) ||
230 IsEqualCLSID (rclsid, &CLSID_MsiServer) ||
231 IsEqualCLSID (rclsid, &CLSID_PSFactoryBuffer) ||
232 IsEqualCLSID (rclsid, &CLSID_MsiServerX3) )
233 {
234 FIXME("create %s object\n", debugstr_guid( rclsid ));
235 }
236
237 return CLASS_E_CLASSNOTAVAILABLE;
238 }
239
240 /******************************************************************
241 * DllGetVersion [MSI.@]
242 */
243 HRESULT WINAPI DllGetVersion(DLLVERSIONINFO *pdvi)
244 {
245 TRACE("%p\n",pdvi);
246
247 if (pdvi->cbSize < sizeof(DLLVERSIONINFO))
248 return E_INVALIDARG;
249
250 pdvi->dwMajorVersion = MSI_MAJORVERSION;
251 pdvi->dwMinorVersion = MSI_MINORVERSION;
252 pdvi->dwBuildNumber = MSI_BUILDNUMBER;
253 pdvi->dwPlatformID = DLLVER_PLATFORM_WINDOWS;
254
255 return S_OK;
256 }
257
258 /******************************************************************
259 * DllCanUnloadNow [MSI.@]
260 */
261 HRESULT WINAPI DllCanUnloadNow(void)
262 {
263 return dll_count == 0 ? S_OK : S_FALSE;
264 }