0c196574b02997e28cf8499df10d775eba705af0
[reactos.git] / reactos / dll / win32 / msi / handle.c
1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
3 *
4 * Copyright 2002-2004 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 #define WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 #define COBJMACROS
26
27 //#include <stdarg.h>
28
29 //#include "windef.h"
30 //#include "winbase.h"
31 //#include "winreg.h"
32 //#include "shlwapi.h"
33 #include <wine/debug.h>
34 //#include "msi.h"
35 //#include "msiquery.h"
36 #include "msipriv.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(msi);
39
40 static CRITICAL_SECTION MSI_handle_cs;
41 static CRITICAL_SECTION_DEBUG MSI_handle_cs_debug =
42 {
43 0, 0, &MSI_handle_cs,
44 { &MSI_handle_cs_debug.ProcessLocksList,
45 &MSI_handle_cs_debug.ProcessLocksList },
46 0, 0, { (DWORD_PTR)(__FILE__ ": MSI_handle_cs") }
47 };
48 static CRITICAL_SECTION MSI_handle_cs = { &MSI_handle_cs_debug, -1, 0, 0, 0, 0 };
49
50 static CRITICAL_SECTION MSI_object_cs;
51 static CRITICAL_SECTION_DEBUG MSI_object_cs_debug =
52 {
53 0, 0, &MSI_object_cs,
54 { &MSI_object_cs_debug.ProcessLocksList,
55 &MSI_object_cs_debug.ProcessLocksList },
56 0, 0, { (DWORD_PTR)(__FILE__ ": MSI_object_cs") }
57 };
58 static CRITICAL_SECTION MSI_object_cs = { &MSI_object_cs_debug, -1, 0, 0, 0, 0 };
59
60 typedef struct msi_handle_info_t
61 {
62 BOOL remote;
63 union {
64 MSIOBJECTHDR *obj;
65 IUnknown *unk;
66 } u;
67 DWORD dwThreadId;
68 } msi_handle_info;
69
70 static msi_handle_info *msihandletable = NULL;
71 static unsigned int msihandletable_size = 0;
72
73 void msi_free_handle_table(void)
74 {
75 msi_free( msihandletable );
76 msihandletable = NULL;
77 msihandletable_size = 0;
78 DeleteCriticalSection(&MSI_handle_cs);
79 DeleteCriticalSection(&MSI_object_cs);
80 }
81
82 static MSIHANDLE alloc_handle_table_entry(void)
83 {
84 UINT i;
85
86 /* find a slot */
87 for(i=0; i<msihandletable_size; i++)
88 if( !msihandletable[i].u.obj && !msihandletable[i].u.unk )
89 break;
90 if( i==msihandletable_size )
91 {
92 msi_handle_info *p;
93 int newsize;
94 if (msihandletable_size == 0)
95 {
96 newsize = 256;
97 p = msi_alloc_zero(newsize*sizeof(msi_handle_info));
98 }
99 else
100 {
101 newsize = msihandletable_size * 2;
102 p = msi_realloc_zero(msihandletable,
103 newsize*sizeof(msi_handle_info));
104 }
105 if (!p)
106 return 0;
107 msihandletable = p;
108 msihandletable_size = newsize;
109 }
110 return i + 1;
111 }
112
113 MSIHANDLE alloc_msihandle( MSIOBJECTHDR *obj )
114 {
115 msi_handle_info *entry;
116 MSIHANDLE ret;
117
118 EnterCriticalSection( &MSI_handle_cs );
119
120 ret = alloc_handle_table_entry();
121 if (ret)
122 {
123 entry = &msihandletable[ ret - 1 ];
124 msiobj_addref( obj );
125 entry->u.obj = obj;
126 entry->dwThreadId = GetCurrentThreadId();
127 entry->remote = FALSE;
128 }
129
130 LeaveCriticalSection( &MSI_handle_cs );
131
132 TRACE("%p -> %d\n", obj, ret );
133
134 return ret;
135 }
136
137 MSIHANDLE alloc_msi_remote_handle( IUnknown *unk )
138 {
139 msi_handle_info *entry;
140 MSIHANDLE ret;
141
142 EnterCriticalSection( &MSI_handle_cs );
143
144 ret = alloc_handle_table_entry();
145 if (ret)
146 {
147 entry = &msihandletable[ ret - 1 ];
148 IUnknown_AddRef( unk );
149 entry->u.unk = unk;
150 entry->dwThreadId = GetCurrentThreadId();
151 entry->remote = TRUE;
152 }
153
154 LeaveCriticalSection( &MSI_handle_cs );
155
156 TRACE("%p -> %d\n", unk, ret);
157
158 return ret;
159 }
160
161 void *msihandle2msiinfo(MSIHANDLE handle, UINT type)
162 {
163 MSIOBJECTHDR *ret = NULL;
164
165 EnterCriticalSection( &MSI_handle_cs );
166 handle--;
167 if( handle >= msihandletable_size )
168 goto out;
169 if( msihandletable[handle].remote)
170 goto out;
171 if( !msihandletable[handle].u.obj )
172 goto out;
173 if( msihandletable[handle].u.obj->magic != MSIHANDLE_MAGIC )
174 goto out;
175 if( type && (msihandletable[handle].u.obj->type != type) )
176 goto out;
177 ret = msihandletable[handle].u.obj;
178 msiobj_addref( ret );
179
180 out:
181 LeaveCriticalSection( &MSI_handle_cs );
182
183 return ret;
184 }
185
186 IUnknown *msi_get_remote( MSIHANDLE handle )
187 {
188 IUnknown *unk = NULL;
189
190 EnterCriticalSection( &MSI_handle_cs );
191 handle--;
192 if( handle>=msihandletable_size )
193 goto out;
194 if( !msihandletable[handle].remote)
195 goto out;
196 unk = msihandletable[handle].u.unk;
197 if( unk )
198 IUnknown_AddRef( unk );
199
200 out:
201 LeaveCriticalSection( &MSI_handle_cs );
202
203 return unk;
204 }
205
206 void *alloc_msiobject(UINT type, UINT size, msihandledestructor destroy )
207 {
208 MSIOBJECTHDR *info;
209
210 info = msi_alloc_zero( size );
211 if( info )
212 {
213 info->magic = MSIHANDLE_MAGIC;
214 info->type = type;
215 info->refcount = 1;
216 info->destructor = destroy;
217 }
218
219 return info;
220 }
221
222 void msiobj_addref( MSIOBJECTHDR *info )
223 {
224 if( !info )
225 return;
226
227 if( info->magic != MSIHANDLE_MAGIC )
228 {
229 ERR("Invalid handle!\n");
230 return;
231 }
232
233 InterlockedIncrement(&info->refcount);
234 }
235
236 void msiobj_lock( MSIOBJECTHDR *info )
237 {
238 EnterCriticalSection( &MSI_object_cs );
239 }
240
241 void msiobj_unlock( MSIOBJECTHDR *info )
242 {
243 LeaveCriticalSection( &MSI_object_cs );
244 }
245
246 int msiobj_release( MSIOBJECTHDR *info )
247 {
248 int ret;
249
250 if( !info )
251 return -1;
252
253 if( info->magic != MSIHANDLE_MAGIC )
254 {
255 ERR("Invalid handle!\n");
256 return -1;
257 }
258
259 ret = InterlockedDecrement( &info->refcount );
260 if( ret==0 )
261 {
262 if( info->destructor )
263 info->destructor( info );
264 msi_free( info );
265 TRACE("object %p destroyed\n", info);
266 }
267
268 return ret;
269 }
270
271 /***********************************************************
272 * MsiCloseHandle [MSI.@]
273 */
274 UINT WINAPI MsiCloseHandle(MSIHANDLE handle)
275 {
276 MSIOBJECTHDR *info = NULL;
277 UINT ret = ERROR_INVALID_HANDLE;
278
279 TRACE("%x\n",handle);
280
281 if (!handle)
282 return ERROR_SUCCESS;
283
284 EnterCriticalSection( &MSI_handle_cs );
285
286 handle--;
287 if (handle >= msihandletable_size)
288 goto out;
289
290 if (msihandletable[handle].remote)
291 {
292 IUnknown_Release( msihandletable[handle].u.unk );
293 }
294 else
295 {
296 info = msihandletable[handle].u.obj;
297 if( !info )
298 goto out;
299
300 if( info->magic != MSIHANDLE_MAGIC )
301 {
302 ERR("Invalid handle!\n");
303 goto out;
304 }
305 }
306
307 msihandletable[handle].u.obj = NULL;
308 msihandletable[handle].remote = 0;
309 msihandletable[handle].dwThreadId = 0;
310
311 ret = ERROR_SUCCESS;
312
313 TRACE("handle %x destroyed\n", handle+1);
314 out:
315 LeaveCriticalSection( &MSI_handle_cs );
316 if( info )
317 msiobj_release( info );
318
319 return ret;
320 }
321
322 /***********************************************************
323 * MsiCloseAllHandles [MSI.@]
324 *
325 * Closes all handles owned by the current thread
326 *
327 * RETURNS:
328 * The number of handles closed
329 */
330 UINT WINAPI MsiCloseAllHandles(void)
331 {
332 UINT i, n=0;
333
334 TRACE("\n");
335
336 EnterCriticalSection( &MSI_handle_cs );
337 for(i=0; i<msihandletable_size; i++)
338 {
339 if(msihandletable[i].dwThreadId == GetCurrentThreadId())
340 {
341 LeaveCriticalSection( &MSI_handle_cs );
342 MsiCloseHandle( i+1 );
343 EnterCriticalSection( &MSI_handle_cs );
344 n++;
345 }
346 }
347 LeaveCriticalSection( &MSI_handle_cs );
348
349 return n;
350 }