-/*\r
- * Implementation of the Microsoft Installer (msi.dll)\r
- *\r
- * Copyright 2002-2004 Mike McCormack for CodeWeavers\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
- */\r
-\r
-#include <stdarg.h>\r
-\r
-#include "windef.h"\r
-#include "winbase.h"\r
-#include "winreg.h"\r
-#include "shlwapi.h"\r
-#include "wine/debug.h"\r
-#include "msi.h"\r
-#include "msiquery.h"\r
-#include "msipriv.h"\r
-\r
-WINE_DEFAULT_DEBUG_CHANNEL(msi);\r
-\r
-static CRITICAL_SECTION MSI_handle_cs;\r
-static CRITICAL_SECTION_DEBUG MSI_handle_cs_debug =\r
-{\r
- 0, 0, &MSI_handle_cs,\r
- { &MSI_handle_cs_debug.ProcessLocksList, \r
- &MSI_handle_cs_debug.ProcessLocksList },\r
- 0, 0, { 0, (DWORD)(__FILE__ ": MSI_handle_cs") }\r
-};\r
-static CRITICAL_SECTION MSI_handle_cs = { &MSI_handle_cs_debug, -1, 0, 0, 0, 0 };\r
-\r
-static CRITICAL_SECTION MSI_object_cs;\r
-static CRITICAL_SECTION_DEBUG MSI_object_cs_debug =\r
-{\r
- 0, 0, &MSI_object_cs,\r
- { &MSI_object_cs_debug.ProcessLocksList, \r
- &MSI_object_cs_debug.ProcessLocksList },\r
- 0, 0, { 0, (DWORD)(__FILE__ ": MSI_object_cs") }\r
-};\r
-static CRITICAL_SECTION MSI_object_cs = { &MSI_object_cs_debug, -1, 0, 0, 0, 0 };\r
-\r
-typedef struct msi_handle_info_t\r
-{\r
- MSIOBJECTHDR *obj;\r
- DWORD dwThreadId;\r
-} msi_handle_info;\r
-\r
-static msi_handle_info msihandletable[MSIMAXHANDLES];\r
-\r
-MSIHANDLE alloc_msihandle( MSIOBJECTHDR *obj )\r
-{\r
- MSIHANDLE ret = 0;\r
- UINT i;\r
-\r
- EnterCriticalSection( &MSI_handle_cs );\r
-\r
- /* find a slot */\r
- for(i=0; i<MSIMAXHANDLES; i++)\r
- if( !msihandletable[i].obj )\r
- break;\r
- if( (i>=MSIMAXHANDLES) || msihandletable[i].obj )\r
- goto out;\r
-\r
- msiobj_addref( obj );\r
- msihandletable[i].obj = obj;\r
- msihandletable[i].dwThreadId = GetCurrentThreadId();\r
- ret = (MSIHANDLE) (i+1);\r
-out:\r
- TRACE("%p -> %ld\n", obj, ret );\r
-\r
- LeaveCriticalSection( &MSI_handle_cs );\r
- return ret;\r
-}\r
-\r
-void *msihandle2msiinfo(MSIHANDLE handle, UINT type)\r
-{\r
- MSIOBJECTHDR *ret = NULL;\r
-\r
- EnterCriticalSection( &MSI_handle_cs );\r
- handle--;\r
- if( handle<0 )\r
- goto out;\r
- if( handle>=MSIMAXHANDLES )\r
- goto out;\r
- if( !msihandletable[handle].obj )\r
- goto out;\r
- if( msihandletable[handle].obj->magic != MSIHANDLE_MAGIC )\r
- goto out;\r
- if( type && (msihandletable[handle].obj->type != type) )\r
- goto out;\r
- ret = msihandletable[handle].obj;\r
- msiobj_addref( ret );\r
- \r
-out:\r
- LeaveCriticalSection( &MSI_handle_cs );\r
-\r
- return (void*) ret;\r
-}\r
-\r
-MSIHANDLE msiobj_findhandle( MSIOBJECTHDR *hdr )\r
-{\r
- MSIHANDLE ret = 0;\r
- UINT i;\r
-\r
- TRACE("%p\n", hdr);\r
-\r
- EnterCriticalSection( &MSI_handle_cs );\r
- for(i=0; (i<MSIMAXHANDLES) && !ret; i++)\r
- if( msihandletable[i].obj == hdr )\r
- ret = i+1;\r
- LeaveCriticalSection( &MSI_handle_cs );\r
-\r
- TRACE("%p -> %ld\n", hdr, ret);\r
-\r
- msiobj_addref( hdr );\r
- return ret;\r
-}\r
-\r
-void *alloc_msiobject(UINT type, UINT size, msihandledestructor destroy )\r
-{\r
- MSIOBJECTHDR *info;\r
-\r
- info = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );\r
- if( info )\r
- {\r
- info->magic = MSIHANDLE_MAGIC;\r
- info->type = type;\r
- info->refcount = 1;\r
- info->destructor = destroy;\r
- }\r
-\r
- return info;\r
-}\r
-\r
-void msiobj_addref( MSIOBJECTHDR *info )\r
-{\r
- TRACE("%p\n", info);\r
-\r
- if( !info )\r
- return;\r
-\r
- if( info->magic != MSIHANDLE_MAGIC )\r
- {\r
- ERR("Invalid handle!\n");\r
- return;\r
- }\r
-\r
- InterlockedIncrement(&info->refcount);\r
-}\r
-\r
-void msiobj_lock( MSIOBJECTHDR *info )\r
-{\r
- EnterCriticalSection( &MSI_object_cs );\r
-}\r
-\r
-void msiobj_unlock( MSIOBJECTHDR *info )\r
-{\r
- LeaveCriticalSection( &MSI_object_cs );\r
-}\r
-\r
-int msiobj_release( MSIOBJECTHDR *info )\r
-{\r
- int ret;\r
-\r
- TRACE("%p\n",info);\r
-\r
- if( !info )\r
- return -1;\r
-\r
- if( info->magic != MSIHANDLE_MAGIC )\r
- {\r
- ERR("Invalid handle!\n");\r
- return -1;\r
- }\r
-\r
- ret = InterlockedDecrement( &info->refcount );\r
- if( ret==0 )\r
- {\r
- if( info->destructor )\r
- info->destructor( info );\r
- HeapFree( GetProcessHeap(), 0, info );\r
- TRACE("object %p destroyed\n", info);\r
- }\r
-\r
- return ret;\r
-}\r
-\r
-/***********************************************************\r
- * MsiCloseHandle [MSI.@]\r
- */\r
-UINT WINAPI MsiCloseHandle(MSIHANDLE handle)\r
-{\r
- MSIOBJECTHDR *info;\r
- UINT ret = ERROR_INVALID_HANDLE;\r
-\r
- TRACE("%lx\n",handle);\r
-\r
- EnterCriticalSection( &MSI_handle_cs );\r
-\r
- info = msihandle2msiinfo(handle, 0);\r
- if( !info )\r
- goto out;\r
-\r
- if( info->magic != MSIHANDLE_MAGIC )\r
- {\r
- ERR("Invalid handle!\n");\r
- goto out;\r
- }\r
-\r
- msiobj_release( info );\r
- msihandletable[handle-1].obj = NULL;\r
- ret = ERROR_SUCCESS;\r
-\r
- TRACE("handle %lx Destroyed\n", handle);\r
-out:\r
- LeaveCriticalSection( &MSI_handle_cs );\r
- if( info )\r
- msiobj_release( info );\r
-\r
- return ret;\r
-}\r
-\r
-/***********************************************************\r
- * MsiCloseAllHandles [MSI.@]\r
- *\r
- * Closes all handles owned by the current thread\r
- *\r
- * RETURNS:\r
- * The number of handles closed\r
- */\r
-UINT WINAPI MsiCloseAllHandles(void)\r
-{\r
- UINT i, n=0;\r
-\r
- TRACE("\n");\r
-\r
- for(i=0; i<MSIMAXHANDLES; i++)\r
- {\r
- if(msihandletable[i].dwThreadId == GetCurrentThreadId())\r
- {\r
- MsiCloseHandle( i+1 );\r
- n++;\r
- }\r
- }\r
-\r
- return n;\r
-}\r
+/*
+ * Implementation of the Microsoft Installer (msi.dll)
+ *
+ * Copyright 2002-2004 Mike McCormack for CodeWeavers
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "shlwapi.h"
+#include "wine/debug.h"
+#include "msi.h"
+#include "msiquery.h"
+#include "msipriv.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msi);
+
+static CRITICAL_SECTION MSI_handle_cs;
+static CRITICAL_SECTION_DEBUG MSI_handle_cs_debug =
+{
+ 0, 0, &MSI_handle_cs,
+ { &MSI_handle_cs_debug.ProcessLocksList,
+ &MSI_handle_cs_debug.ProcessLocksList },
+ 0, 0, { 0, (DWORD)(__FILE__ ": MSI_handle_cs") }
+};
+static CRITICAL_SECTION MSI_handle_cs = { &MSI_handle_cs_debug, -1, 0, 0, 0, 0 };
+
+static CRITICAL_SECTION MSI_object_cs;
+static CRITICAL_SECTION_DEBUG MSI_object_cs_debug =
+{
+ 0, 0, &MSI_object_cs,
+ { &MSI_object_cs_debug.ProcessLocksList,
+ &MSI_object_cs_debug.ProcessLocksList },
+ 0, 0, { 0, (DWORD)(__FILE__ ": MSI_object_cs") }
+};
+static CRITICAL_SECTION MSI_object_cs = { &MSI_object_cs_debug, -1, 0, 0, 0, 0 };
+
+typedef struct msi_handle_info_t
+{
+ MSIOBJECTHDR *obj;
+ DWORD dwThreadId;
+} msi_handle_info;
+
+static msi_handle_info msihandletable[MSIMAXHANDLES];
+
+MSIHANDLE alloc_msihandle( MSIOBJECTHDR *obj )
+{
+ MSIHANDLE ret = 0;
+ UINT i;
+
+ EnterCriticalSection( &MSI_handle_cs );
+
+ /* find a slot */
+ for(i=0; i<MSIMAXHANDLES; i++)
+ if( !msihandletable[i].obj )
+ break;
+ if( (i>=MSIMAXHANDLES) || msihandletable[i].obj )
+ goto out;
+
+ msiobj_addref( obj );
+ msihandletable[i].obj = obj;
+ msihandletable[i].dwThreadId = GetCurrentThreadId();
+ ret = (MSIHANDLE) (i+1);
+out:
+ TRACE("%p -> %ld\n", obj, ret );
+
+ LeaveCriticalSection( &MSI_handle_cs );
+ return ret;
+}
+
+void *msihandle2msiinfo(MSIHANDLE handle, UINT type)
+{
+ MSIOBJECTHDR *ret = NULL;
+
+ EnterCriticalSection( &MSI_handle_cs );
+ handle--;
+ if( handle<0 )
+ goto out;
+ if( handle>=MSIMAXHANDLES )
+ goto out;
+ if( !msihandletable[handle].obj )
+ goto out;
+ if( msihandletable[handle].obj->magic != MSIHANDLE_MAGIC )
+ goto out;
+ if( type && (msihandletable[handle].obj->type != type) )
+ goto out;
+ ret = msihandletable[handle].obj;
+ msiobj_addref( ret );
+
+out:
+ LeaveCriticalSection( &MSI_handle_cs );
+
+ return (void*) ret;
+}
+
+MSIHANDLE msiobj_findhandle( MSIOBJECTHDR *hdr )
+{
+ MSIHANDLE ret = 0;
+ UINT i;
+
+ TRACE("%p\n", hdr);
+
+ EnterCriticalSection( &MSI_handle_cs );
+ for(i=0; (i<MSIMAXHANDLES) && !ret; i++)
+ if( msihandletable[i].obj == hdr )
+ ret = i+1;
+ LeaveCriticalSection( &MSI_handle_cs );
+
+ TRACE("%p -> %ld\n", hdr, ret);
+
+ msiobj_addref( hdr );
+ return ret;
+}
+
+void *alloc_msiobject(UINT type, UINT size, msihandledestructor destroy )
+{
+ MSIOBJECTHDR *info;
+
+ info = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
+ if( info )
+ {
+ info->magic = MSIHANDLE_MAGIC;
+ info->type = type;
+ info->refcount = 1;
+ info->destructor = destroy;
+ }
+
+ return info;
+}
+
+void msiobj_addref( MSIOBJECTHDR *info )
+{
+ TRACE("%p\n", info);
+
+ if( !info )
+ return;
+
+ if( info->magic != MSIHANDLE_MAGIC )
+ {
+ ERR("Invalid handle!\n");
+ return;
+ }
+
+ InterlockedIncrement(&info->refcount);
+}
+
+void msiobj_lock( MSIOBJECTHDR *info )
+{
+ EnterCriticalSection( &MSI_object_cs );
+}
+
+void msiobj_unlock( MSIOBJECTHDR *info )
+{
+ LeaveCriticalSection( &MSI_object_cs );
+}
+
+int msiobj_release( MSIOBJECTHDR *info )
+{
+ int ret;
+
+ TRACE("%p\n",info);
+
+ if( !info )
+ return -1;
+
+ if( info->magic != MSIHANDLE_MAGIC )
+ {
+ ERR("Invalid handle!\n");
+ return -1;
+ }
+
+ ret = InterlockedDecrement( &info->refcount );
+ if( ret==0 )
+ {
+ if( info->destructor )
+ info->destructor( info );
+ HeapFree( GetProcessHeap(), 0, info );
+ TRACE("object %p destroyed\n", info);
+ }
+
+ return ret;
+}
+
+/***********************************************************
+ * MsiCloseHandle [MSI.@]
+ */
+UINT WINAPI MsiCloseHandle(MSIHANDLE handle)
+{
+ MSIOBJECTHDR *info;
+ UINT ret = ERROR_INVALID_HANDLE;
+
+ TRACE("%lx\n",handle);
+
+ EnterCriticalSection( &MSI_handle_cs );
+
+ info = msihandle2msiinfo(handle, 0);
+ if( !info )
+ goto out;
+
+ if( info->magic != MSIHANDLE_MAGIC )
+ {
+ ERR("Invalid handle!\n");
+ goto out;
+ }
+
+ msiobj_release( info );
+ msihandletable[handle-1].obj = NULL;
+ ret = ERROR_SUCCESS;
+
+ TRACE("handle %lx Destroyed\n", handle);
+out:
+ LeaveCriticalSection( &MSI_handle_cs );
+ if( info )
+ msiobj_release( info );
+
+ return ret;
+}
+
+/***********************************************************
+ * MsiCloseAllHandles [MSI.@]
+ *
+ * Closes all handles owned by the current thread
+ *
+ * RETURNS:
+ * The number of handles closed
+ */
+UINT WINAPI MsiCloseAllHandles(void)
+{
+ UINT i, n=0;
+
+ TRACE("\n");
+
+ for(i=0; i<MSIMAXHANDLES; i++)
+ {
+ if(msihandletable[i].dwThreadId == GetCurrentThreadId())
+ {
+ MsiCloseHandle( i+1 );
+ n++;
+ }
+ }
+
+ return n;
+}