Wine-20050111 vendor drop
Added: vendor/wine/dlls/msi/Wine-20050111/
Modified: vendor/wine/dlls/msi/Wine-20050111/Makefile.in
Modified: vendor/wine/dlls/msi/Wine-20050111/action.c
Modified: vendor/wine/dlls/msi/Wine-20050111/handle.c
Modified: vendor/wine/dlls/msi/Wine-20050111/msi.c
Modified: vendor/wine/dlls/msi/Wine-20050111/msi.spec
Modified: vendor/wine/dlls/msi/Wine-20050111/msipriv.h
Modified: vendor/wine/dlls/msi/Wine-20050111/msiquery.c
Modified: vendor/wine/dlls/msi/Wine-20050111/package.c
Modified: vendor/wine/dlls/msi/Wine-20050111/query.h
Modified: vendor/wine/dlls/msi/Wine-20050111/record.c
Modified: vendor/wine/dlls/msi/Wine-20050111/sql.y
Modified: vendor/wine/dlls/msi/Wine-20050111/table.c
Modified: vendor/wine/dlls/msi/Wine-20050111/where.c
Modified: vendor/wine/dlls/msi/current/Makefile.in
Modified: vendor/wine/dlls/msi/current/action.c
Modified: vendor/wine/dlls/msi/current/handle.c
Modified: vendor/wine/dlls/msi/current/msi.c
Modified: vendor/wine/dlls/msi/current/msi.spec
Modified: vendor/wine/dlls/msi/current/msipriv.h
Modified: vendor/wine/dlls/msi/current/msiquery.c
Modified: vendor/wine/dlls/msi/current/package.c
Modified: vendor/wine/dlls/msi/current/query.h
Modified: vendor/wine/dlls/msi/current/record.c
Modified: vendor/wine/dlls/msi/current/sql.y
Modified: vendor/wine/dlls/msi/current/table.c
Modified: vendor/wine/dlls/msi/current/where.c

Copied: vendor/wine/dlls/msi/Wine-20050111 (from rev 12927, vendor/wine/dlls/msi/current)

Modified: vendor/wine/dlls/msi/Wine-20050111/Makefile.in
--- vendor/wine/dlls/msi/current/Makefile.in	2005-01-11 20:23:48 UTC (rev 12927)
+++ vendor/wine/dlls/msi/Wine-20050111/Makefile.in	2005-01-12 08:56:56 UTC (rev 12946)
@@ -3,7 +3,7 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = msi.dll
-IMPORTS   = shell32 cabinet oleaut32 ole32 version user32 advapi32 kernel32
+IMPORTS   = shell32 cabinet oleaut32 ole32 version user32 gdi32 advapi32 kernel32
 EXTRALIBS = -luuid $(LIBUNICODE)
 
 C_SRCS = \
@@ -31,6 +31,8 @@
 EXTRA_SRCS = sql.y cond.y
 EXTRA_OBJS = sql.tab.o cond.tab.o
 
+SUBDIRS = tests
+
 @MAKE_DLL_RULES@
 
 sql.tab.c sql.tab.h: sql.y

Modified: vendor/wine/dlls/msi/Wine-20050111/action.c
--- vendor/wine/dlls/msi/current/action.c	2005-01-11 20:23:48 UTC (rev 12927)
+++ vendor/wine/dlls/msi/Wine-20050111/action.c	2005-01-12 08:56:56 UTC (rev 12946)
@@ -50,6 +50,8 @@
 #include "ver.h"
 
 #define CUSTOM_ACTION_TYPE_MASK 0x3F
+#define REG_PROGRESS_VALUE 13200
+#define COMPONENT_PROGRESS_VALUE 24000
 
 WINE_DEFAULT_DEBUG_CHANNEL(msi);
 
@@ -64,8 +66,10 @@
     WCHAR Directory[96];
     INT Attributes;
     
-    INSTALLSTATE State;
-    BOOL Enabled;
+    INSTALLSTATE Installed;
+    INSTALLSTATE ActionRequest;
+    INSTALLSTATE Action;
+
     INT ComponentCount;
     INT Components[1024]; /* yes hardcoded limit.... I am bad */
     INT Cost;
@@ -80,21 +84,23 @@
     WCHAR Condition[0x100];
     WCHAR KeyPath[96];
 
-    INSTALLSTATE State;
-    BOOL FeatureState;
+    INSTALLSTATE Installed;
+    INSTALLSTATE ActionRequest;
+    INSTALLSTATE Action;
+
     BOOL Enabled;
     INT  Cost;
 } MSICOMPONENT;
 
 typedef struct tagMSIFOLDER
 {
-    WCHAR Directory[96];
-    WCHAR TargetDefault[96];
-    WCHAR SourceDefault[96];
+    LPWSTR Directory;
+    LPWSTR TargetDefault;
+    LPWSTR SourceDefault;
 
-    WCHAR ResolvedTarget[MAX_PATH];
-    WCHAR ResolvedSource[MAX_PATH];
-    WCHAR Property[MAX_PATH];   /* initially set property */
+    LPWSTR ResolvedTarget;
+    LPWSTR ResolvedSource;
+    LPWSTR Property;   /* initially set property */
     INT   ParentIndex;
     INT   State;
         /* 0 = uninitialized */
@@ -107,12 +113,12 @@
 
 typedef struct tagMSIFILE
 {
-    WCHAR File[72];
+    LPWSTR File;
     INT ComponentIndex;
-    WCHAR FileName[MAX_PATH];
+    LPWSTR FileName;
     INT FileSize;
-    WCHAR Version[72];
-    WCHAR Language[20];
+    LPWSTR Version;
+    LPWSTR Language;
     INT Attributes;
     INT Sequence;   
 
@@ -122,8 +128,8 @@
        /* 2 = present but replace */
        /* 3 = present do not replace */
        /* 4 = Installed */
-    WCHAR   SourcePath[MAX_PATH];
-    WCHAR   TargetPath[MAX_PATH];
+    LPWSTR  SourcePath;
+    LPWSTR  TargetPath;
     BOOL    Temporary; 
 }MSIFILE;
 
@@ -133,6 +139,7 @@
 static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran);
 static UINT ACTION_ProcessUISequence(MSIPACKAGE *package);
 
+static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq);
 UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action);
 
 static UINT ACTION_LaunchConditions(MSIPACKAGE *package);
@@ -157,15 +164,15 @@
                                 const LPWSTR target, const INT type);
 static UINT HANDLE_CustomType2(MSIPACKAGE *package, const LPWSTR source, 
                                 const LPWSTR target, const INT type);
-static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source, 
+static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source,
                                 const LPWSTR target, const INT type);
-static UINT HANDLE_CustomType50(MSIPACKAGE *package, const LPWSTR source, 
+static UINT HANDLE_CustomType50(MSIPACKAGE *package, const LPWSTR source,
                                 const LPWSTR target, const INT type);
-static UINT HANDLE_CustomType34(MSIPACKAGE *package, const LPWSTR source, 
+static UINT HANDLE_CustomType34(MSIPACKAGE *package, const LPWSTR source,
                                 const LPWSTR target, const INT type);
 
 static DWORD deformat_string(MSIPACKAGE *package, WCHAR* ptr,WCHAR** data);
-static UINT resolve_folder(MSIPACKAGE *package, LPCWSTR name, LPWSTR path, 
+static LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name,
                            BOOL source, BOOL set_prop, MSIFOLDER **folder);
 
 static int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path);
@@ -222,12 +229,9 @@
  ********************************************************/
 inline static void reduce_to_longfilename(WCHAR* filename)
 {
-    if (strchrW(filename,'|'))
-    {
-        WCHAR newname[MAX_PATH];
-        strcpyW(newname,strchrW(filename,'|')+1);
-        strcpyW(filename,newname);
-    }
+    LPWSTR p = strchrW(filename,'|');
+    if (p)
+        memmove(filename, p+1, (strlenW(p+1)+1)*sizeof(WCHAR));
 }
 
 inline static char *strdupWtoA( const WCHAR *str )
@@ -255,6 +259,15 @@
     return ret;
 }
 
+static LPWSTR dupstrW(LPCWSTR src)
+{
+    LPWSTR dest;
+    if (!src) return NULL;
+    dest = HeapAlloc(GetProcessHeap(), 0, (strlenW(src)+1)*sizeof(WCHAR));
+    strcpyW(dest, src);
+    return dest;
+}
+
 inline static WCHAR *load_dynamic_stringW(MSIRECORD *row, INT index)
 {
     UINT rc;
@@ -262,16 +275,58 @@
     LPWSTR ret;
    
     sz = 0; 
-    rc = MSI_RecordGetStringW(row,index,NULL,&sz);
-    if (sz <= 0)
+    if (MSI_RecordIsNull(row,index))
         return NULL;
 
+    rc = MSI_RecordGetStringW(row,index,NULL,&sz);
+
+    /* having an empty string is different than NULL */
+    if (sz == 0)
+    {
+        ret = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR));
+        ret[0] = 0;
+        return ret;
+    }
+
     sz ++;
     ret = HeapAlloc(GetProcessHeap(),0,sz * sizeof (WCHAR));
     rc = MSI_RecordGetStringW(row,index,ret,&sz);
+    if (rc!=ERROR_SUCCESS)
+    {
+        ERR("Unable to load dynamic string\n");
+        HeapFree(GetProcessHeap(), 0, ret);
+        ret = NULL;
+    }
     return ret;
 }
 
+inline static LPWSTR load_dynamic_property(MSIPACKAGE *package, LPCWSTR prop,
+                                           UINT* rc)
+{
+    DWORD sz = 0;
+    LPWSTR str;
+    UINT r;
+
+    r = MSI_GetPropertyW(package, prop, NULL, &sz);
+    if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
+    {
+        if (rc)
+            *rc = r;
+        return NULL;
+    }
+    sz++;
+    str = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));
+    r = MSI_GetPropertyW(package, prop, str, &sz);
+    if (r != ERROR_SUCCESS)
+    {
+        HeapFree(GetProcessHeap(),0,str);
+        str = NULL;
+    }
+    if (rc)
+        *rc = r;
+    return str;
+}
+
 inline static int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component )
 {
     int rc = -1;
@@ -320,6 +375,7 @@
     return rc;
 }
 
+
 static int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path)
 {
     DWORD i;
@@ -342,8 +398,8 @@
 
     memset(&package->files[index],0,sizeof(MSIFILE));
 
-    strcpyW(package->files[index].File,name);
-    strcpyW(package->files[index].TargetPath,path);
+    package->files[index].File = dupstrW(name);
+    package->files[index].TargetPath = dupstrW(path);
     package->files[index].Temporary = TRUE;
 
     TRACE("Tracking tempfile (%s)\n",debugstr_w(package->files[index].File));  
@@ -361,11 +417,103 @@
     for (i = 0; i < package->loaded_files; i++)
     {
         if (package->files[i].Temporary)
+        {
+            TRACE("Cleaning up %s\n",debugstr_w(package->files[i].TargetPath));
             DeleteFileW(package->files[i].TargetPath);
+        }
 
     }
 }
 
+/* Called when the package is being closed */
+extern void ACTION_free_package_structures( MSIPACKAGE* package)
+{
+    INT i;
+    
+    TRACE("Freeing package action data\n");
+
+    /* No dynamic buffers in features */
+    if (package->features && package->loaded_features > 0)
+        HeapFree(GetProcessHeap(),0,package->features);
+
+    for (i = 0; i < package->loaded_folders; i++)
+    {
+        HeapFree(GetProcessHeap(),0,package->folders[i].Directory);
+        HeapFree(GetProcessHeap(),0,package->folders[i].TargetDefault);
+        HeapFree(GetProcessHeap(),0,package->folders[i].SourceDefault);
+        HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedTarget);
+        HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedSource);
+        HeapFree(GetProcessHeap(),0,package->folders[i].Property);
+    }
+    if (package->folders && package->loaded_folders > 0)
+        HeapFree(GetProcessHeap(),0,package->folders);
+
+    /* no dynamic buffers in components */ 
+    if (package->components && package->loaded_components > 0)
+        HeapFree(GetProcessHeap(),0,package->components);
+
+    for (i = 0; i < package->loaded_files; i++)
+    {
+        HeapFree(GetProcessHeap(),0,package->files[i].File);
+        HeapFree(GetProcessHeap(),0,package->files[i].FileName);
+        HeapFree(GetProcessHeap(),0,package->files[i].Version);
+        HeapFree(GetProcessHeap(),0,package->files[i].Language);
+        HeapFree(GetProcessHeap(),0,package->files[i].SourcePath);
+        HeapFree(GetProcessHeap(),0,package->files[i].TargetPath);
+    }
+
+    if (package->files && package->loaded_files > 0)
+        HeapFree(GetProcessHeap(),0,package->files);
+}
+
+static UINT ACTION_OpenQuery( MSIDATABASE *db, MSIQUERY **view, LPCWSTR fmt, ... )
+{
+    LPWSTR szQuery;
+    LPCWSTR p;
+    UINT sz, rc;
+    va_list va;
+
+    /* figure out how much space we need to allocate */
+    va_start(va, fmt);
+    sz = strlenW(fmt) + 1;
+    p = fmt;
+    while (*p)
+    {
+        p = strchrW(p, '%');
+        if (!p)
+            break;
+        p++;
+        switch (*p)
+        {
+        case 's':  /* a string */
+            sz += strlenW(va_arg(va,LPCWSTR));
+            break;
+        case 'd':
+        case 'i':  /* an integer -2147483648 seems to be longest */
+            sz += 3*sizeof(int);
+            (void)va_arg(va,int);
+            break;
+        case '%':  /* a single % - leave it alone */
+            break;
+        default:
+            FIXME("Unhandled character type %c\n",*p);
+        }
+        p++;
+    }
+    va_end(va);
+
+    /* construct the string */
+    szQuery = HeapAlloc(GetProcessHeap(), 0, sz*sizeof(WCHAR));
+    va_start(va, fmt);
+    vsnprintfW(szQuery, sz, fmt, va);
+    va_end(va);
+
+    /* perform the query */
+    rc = MSI_DatabaseOpenViewW(db, szQuery, view);
+    HeapFree(GetProcessHeap(), 0, szQuery);
+    return rc;
+}
+
 static void ui_progress(MSIPACKAGE *package, int a, int b, int c, int d )
 {
     MSIRECORD * row;
@@ -389,17 +537,14 @@
     UINT rc;
     MSIQUERY * view;
     MSIRECORD * row = 0;
-    static WCHAR *ActionFormat=NULL;
-    static WCHAR LastAction[0x100] = {0};
-    WCHAR Query[1024];
     LPWSTR ptr;
 
-    if (strcmpW(LastAction,action)!=0)
+    if (!package->LastAction || strcmpW(package->LastAction,action))
     {
-        sprintfW(Query,Query_t,action);
-        rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
+        rc = ACTION_OpenQuery(package->db, &view, Query_t, action);
         if (rc != ERROR_SUCCESS)
             return;
+
         rc = MSI_ViewExecute(view, 0);
         if (rc != ERROR_SUCCESS)
         {
@@ -421,18 +566,22 @@
             return;
         }
 
-        if (ActionFormat)
-            HeapFree(GetProcessHeap(),0,ActionFormat);
+        /* update the cached actionformat */
+        if (package->ActionFormat)
+            HeapFree(GetProcessHeap(),0,package->ActionFormat);
+        package->ActionFormat = load_dynamic_stringW(row,3);
 
-        ActionFormat = load_dynamic_stringW(row,3);
-        strcpyW(LastAction,action);
+        if (package->LastAction)
+            HeapFree(GetProcessHeap(),0,package->LastAction);
+        package->LastAction = dupstrW(action);
+
         msiobj_release(&row->hdr);
         MSI_ViewClose(view);
         msiobj_release(&view->hdr);
     }
 
     message[0]=0;
-    ptr = ActionFormat;
+    ptr = package->ActionFormat;
     while (*ptr)
     {
         LPWSTR ptr2;
@@ -488,12 +637,10 @@
     MSIQUERY * view;
     MSIRECORD * row = 0;
     WCHAR *ActionText=NULL;
-    WCHAR Query[1024];
 
     GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);
 
-    sprintfW(Query,Query_t,action);
-    rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
+    rc = ACTION_OpenQuery(package->db, &view, Query_t, action);
     if (rc != ERROR_SUCCESS)
         return;
     rc = MSI_ViewExecute(view, 0);
@@ -554,6 +701,58 @@
     msiobj_release(&row->hdr);
 }
 
+/*
+ *  build_directory_name()
+ *
+ *  This function is to save messing round with directory names
+ *  It handles adding backslashes between path segments, 
+ *   and can add \ at the end of the directory name if told to.
+ *
+ *  It takes a variable number of arguments.
+ *  It always allocates a new string for the result, so make sure
+ *   to free the return value when finished with it.
+ *
+ *  The first arg is the number of path segments that follow.
+ *  The arguments following count are a list of path segments.
+ *  A path segment may be NULL.
+ *
+ *  Path segments will be added with a \ separating them.
+ *  A \ will not be added after the last segment, however if the
+ *    last segment is NULL, then the last character will be a \
+ * 
+ */
+static LPWSTR build_directory_name(DWORD count, ...)
+{
+    DWORD sz = 1, i;
+    LPWSTR dir;
+    va_list va;
+
+    va_start(va,count);
+    for(i=0; i<count; i++)
+    {
+        LPCWSTR str = va_arg(va,LPCWSTR);
+        if (str)
+            sz += strlenW(str) + 1;
+    }
+    va_end(va);
+
+    dir = HeapAlloc(GetProcessHeap(), 0, sz*sizeof(WCHAR));
+    dir[0]=0;
+
+    va_start(va,count);
+    for(i=0; i<count; i++)
+    {
+        LPCWSTR str = va_arg(va,LPCWSTR);
+        if (!str)
+            continue;
+        strcatW(dir, str);
+        if( ((i+1)!=count) && dir[strlenW(dir)-1]!='\\')
+            strcatW(dir, cszbs);
+    }
+    return dir;
+}
+
+
 /****************************************************
  * TOP level entry points 
  *****************************************************/
@@ -568,23 +767,23 @@
 
     if (szPackagePath)   
     {
-        LPWSTR p;
-        WCHAR check[MAX_PATH];
-        WCHAR pth[MAX_PATH];
-        DWORD size;
+        LPWSTR p, check, path;
  
-        strcpyW(pth,szPackagePath);
-        p = strrchrW(pth,'\\');    
+        path = dupstrW(szPackagePath);
+        p = strrchrW(path,'\\');    
         if (p)
         {
             p++;
             *p=0;
         }
 
-        size = MAX_PATH;
-        if (MSI_GetPropertyW(package,cszSourceDir,check,&size) 
-            != ERROR_SUCCESS )
-            MSI_SetPropertyW(package, cszSourceDir, pth);
+        check = load_dynamic_property(package, cszSourceDir,NULL);
+        if (!check)
+            MSI_SetPropertyW(package, cszSourceDir, path);
+        else
+            HeapFree(GetProcessHeap(), 0, check);
+
+        HeapFree(GetProcessHeap(), 0, path);
     }
 
     if (szCommandLine)
@@ -594,8 +793,8 @@
        
         while (*ptr)
         {
-            WCHAR prop[0x100];
-            WCHAR val[0x100];
+            WCHAR *prop = NULL;
+            WCHAR *val = NULL;
 
             TRACE("Looking at %s\n",debugstr_w(ptr));
 
@@ -606,10 +805,13 @@
                 DWORD len = 0;
 
                 while (*ptr == ' ') ptr++;
-                strncpyW(prop,ptr,ptr2-ptr);
-                prop[ptr2-ptr]=0;
+                len = ptr2-ptr;
+                prop = HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
+                strncpyW(prop,ptr,len);
+                prop[len]=0;
                 ptr2++;
-            
+           
+                len = 0; 
                 ptr = ptr2; 
                 while (*ptr && (quote || (!quote && *ptr!=' ')))
                 {
@@ -624,14 +826,18 @@
                     ptr2++;
                     len -= 2;
                 }
+                val = HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
                 strncpyW(val,ptr2,len);
-                val[len]=0;
+                val[len] = 0;
 
                 if (strlenW(prop) > 0)
                 {
-                    TRACE("Found commandline property (%s) = (%s)\n", debugstr_w(prop), debugstr_w(val));
+                    TRACE("Found commandline property (%s) = (%s)\n", 
+                                       debugstr_w(prop), debugstr_w(val));
                     MSI_SetPropertyW(package,prop,val);
                 }
+                HeapFree(GetProcessHeap(),0,val);
+                HeapFree(GetProcessHeap(),0,prop);
             }
             ptr++;
         }
@@ -652,10 +858,93 @@
     else
         rc = ACTION_ProcessExecSequence(package,FALSE);
 
+    /* process the ending type action */
+    if (rc == ERROR_SUCCESS)
+        rc = ACTION_PerformActionSequence(package,-1);
+    else if (rc == ERROR_FUNCTION_FAILED) 
+        rc = ACTION_PerformActionSequence(package,-3);
+    
     return rc;
 }
 
+static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq)
+{
+    MSIQUERY * view;
+    UINT rc;
+    WCHAR buffer[0x100];
+    DWORD sz = 0x100;
+    MSIRECORD * row = 0;
+    static const WCHAR ExecSeqQuery[] =  {
+   's','e','l','e','c','t',' ','*',' ',
+   'f','r','o','m',' ',
+       'I','n','s','t','a','l','l','E','x','e','c','u','t','e',
+       'S','e','q','u','e','n','c','e',' ',
+   'w','h','e','r','e',' ','S','e','q','u','e','n','c','e',' ',
+       '=',' ','%','i',0};
 
+    rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, seq);
+
+    if (rc == ERROR_SUCCESS)
+    {
+        rc = MSI_ViewExecute(view, 0);
+
+        if (rc != ERROR_SUCCESS)
+        {
+            MSI_ViewClose(view);
+            msiobj_release(&view->hdr);
+            goto end;
+        }
+       
+        TRACE("Running the actions\n"); 
+
+        rc = MSI_ViewFetch(view,&row);
+        if (rc != ERROR_SUCCESS)
+        {
+            rc = ERROR_SUCCESS;
+            goto end;
+        }
+
+        /* check conditions */
+        if (!MSI_RecordIsNull(row,2))
+        {
+            LPWSTR cond = NULL;
+            cond = load_dynamic_stringW(row,2);
+
+            if (cond)
+            {
+                /* this is a hack to skip errors in the condition code */
+                if (MSI_EvaluateConditionW(package, cond) == MSICONDITION_FALSE)
+                {
+                    HeapFree(GetProcessHeap(),0,cond);
+                    msiobj_release(&row->hdr);
+                    goto end;
+                }
+                else
+                    HeapFree(GetProcessHeap(),0,cond);
+            }
+        }
+
+        sz=0x100;
+        rc =  MSI_RecordGetStringW(row,1,buffer,&sz);
+        if (rc != ERROR_SUCCESS)
+        {
+            ERR("Error is %x\n",rc);
+            msiobj_release(&row->hdr);
+            goto end;
+        }
+
+        rc = ACTION_PerformAction(package,buffer);
+        msiobj_release(&row->hdr);
+end:
+        MSI_ViewClose(view);
+        msiobj_release(&view->hdr);
+    }
+    else
+        rc = ERROR_SUCCESS;
+
+    return rc;
+}
+
 static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran)
 {
     MSIQUERY * view;
@@ -668,7 +957,6 @@
        'w','h','e','r','e',' ','S','e','q','u','e','n','c','e',' ',
            '>',' ','%','i',' ','o','r','d','e','r',' ',
        'b','y',' ','S','e','q','u','e','n','c','e',0 };
-    WCHAR Query[1024];
     MSIRECORD * row = 0;
     static const WCHAR IVQuery[] = {
        's','e','l','e','c','t',' ','S','e','q','u','e','n','c','e',' ',
@@ -677,11 +965,11 @@
        'w','h','e','r','e',' ','A','c','t','i','o','n',' ','=',' ',
            '`','I','n','s','t','a','l','l','V','a','l','i','d','a','t','e','`',
        0};
+    INT seq = 0;
 
+    /* get the sequence number */
     if (UIran)
     {
-        INT seq = 0;
-        
         rc = MSI_DatabaseOpenViewW(package->db, IVQuery, &view);
         if (rc != ERROR_SUCCESS)
             return rc;
@@ -703,12 +991,9 @@
         msiobj_release(&row->hdr);
         MSI_ViewClose(view);
         msiobj_release(&view->hdr);
-        sprintfW(Query,ExecSeqQuery,seq);
     }
-    else
-        sprintfW(Query,ExecSeqQuery,0);
-    
-    rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
+
+    rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, seq);
     if (rc == ERROR_SUCCESS)
     {
         rc = MSI_ViewExecute(view, 0);
@@ -720,7 +1005,7 @@
             goto end;
         }
        
-        TRACE("Running the actions \n"); 
+        TRACE("Running the actions\n"); 
 
         while (1)
         {
@@ -899,7 +1184,6 @@
     TRACE("Performing action (%s)\n",debugstr_w(action));
     ui_actioninfo(package, action, TRUE, 0);
     ui_actionstart(package, action);
-    ui_progress(package,2,1,0,0);
 
     /* pre install, setup and configuration block */
     if (strcmpW(action,szLaunchConditions)==0)
@@ -960,21 +1244,16 @@
     UINT rc = ERROR_SUCCESS;
     MSIQUERY * view;
     MSIRECORD * row = 0;
-    WCHAR ExecSeqQuery[1024] = 
+    static const WCHAR ExecSeqQuery[] =
     {'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','C','u','s','t','o'
-,'m','A','c','t','i','o','n',' ','w','h','e','r','e',' ','`','A','c','t','i'
-,'o','n','`',' ','=',' ','`',0};
-    static const WCHAR end[]={'`',0};
+        ,'m','A','c','t','i','o','n',' ','w','h','e','r','e',' ','`','A','c','t','i'
+        ,'o','n','`',' ','=',' ','`','%','s','`',0};
     UINT type;
     LPWSTR source;
     LPWSTR target;
     WCHAR *deformated=NULL;
 
-    strcatW(ExecSeqQuery,action);
-    strcatW(ExecSeqQuery,end);
-
-    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
-
+    rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, action);
     if (rc != ERROR_SUCCESS)
         return rc;
 
@@ -1021,6 +1300,10 @@
             rc = HANDLE_CustomType34(package,source,target,type);
             break;
         case 35: /* Directory set with formatted text. */
+            deformat_string(package,target,&deformated);
+            MSI_SetTargetPathW(package, source, deformated);
+            HeapFree(GetProcessHeap(),0,deformated);
+            break;
         case 51: /* Property set with formatted text. */
             deformat_string(package,target,&deformated);
             rc = MSI_SetPropertyW(package,source,deformated);
@@ -1062,10 +1345,9 @@
         UINT rc;
         MSIQUERY * view;
         MSIRECORD * row = 0;
-        WCHAR Query[1024] =
+        static const WCHAR fmt[] =
         {'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','B','i'
-,'n','a','r','y',' ','w','h','e','r','e',' ','N','a','m','e','=','`',0};
-        static const WCHAR end[]={'`',0};
+,'n','a','r','y',' ','w','h','e','r','e',' ','N','a','m','e','=','`','%','s','`',0};
         HANDLE the_file;
         CHAR buffer[1024];
 
@@ -1078,10 +1360,7 @@
         if (the_file == INVALID_HANDLE_VALUE)
             return ERROR_FUNCTION_FAILED;
 
-        strcatW(Query,source);
-        strcatW(Query,end);
-
-        rc = MSI_DatabaseOpenViewW( package->db, Query, &view);
+        rc = ACTION_OpenQuery(package->db, &view, fmt, source);
         if (rc != ERROR_SUCCESS)
             return rc;
 
@@ -1126,66 +1405,82 @@
     return ERROR_SUCCESS;
 }
 
-
 typedef UINT __stdcall CustomEntry(MSIHANDLE);
 typedef struct 
 {
         MSIPACKAGE *package;
-        WCHAR target[MAX_PATH];
-        WCHAR source[MAX_PATH];
+        WCHAR *target;
+        WCHAR *source;
 } thread_struct;
 
-#if 0
-static DWORD WINAPI DllThread(LPVOID info)
+static DWORD WINAPI ACTION_CallDllFunction(thread_struct *stuff)
 {
-    HANDLE DLL;
+    HANDLE hModule;
     LPSTR proc;
-    thread_struct *stuff;
     CustomEntry *fn;
-     
-    stuff = (thread_struct*)info;
 
-    TRACE("Asynchronous start (%s, %s) \n", debugstr_w(stuff->source),
+    TRACE("calling function (%s, %s) \n", debugstr_w(stuff->source),
           debugstr_w(stuff->target));
 
-    DLL = LoadLibraryW(stuff->source);
-    if (DLL)
+    hModule = LoadLibraryW(stuff->source);
+    if (hModule)
     {
         proc = strdupWtoA( stuff->target );
-        fn = (CustomEntry*)GetProcAddress(DLL,proc);
+        fn = (CustomEntry*)GetProcAddress(hModule,proc);
         if (fn)
         {
             MSIHANDLE hPackage;
             MSIPACKAGE *package = stuff->package;
 
-            TRACE("Calling function\n");
+            TRACE("Calling function %s\n", proc);
             hPackage = msiobj_findhandle( &package->hdr );
-            if( !hPackage )
+            if (hPackage )
+            {
+                fn(hPackage);
+                msiobj_release( &package->hdr );
+            }
+            else
                 ERR("Handle for object %p not found\n", package );
-            fn(hPackage);
-            msiobj_release( &package->hdr );
         }
         else
             ERR("Cannot load functon\n");
 
         HeapFree(GetProcessHeap(),0,proc);
-        FreeLibrary(DLL);
+        FreeLibrary(hModule);
     }
     else
         ERR("Unable to load library\n");
     msiobj_release( &stuff->package->hdr );
-    HeapFree( GetProcessHeap(), 0, info );
+    HeapFree(GetProcessHeap(),0,stuff->source);
+    HeapFree(GetProcessHeap(),0,stuff->target);
+    HeapFree(GetProcessHeap(), 0, stuff);
     return 0;
 }
-#endif
 
+static DWORD WINAPI DllThread(LPVOID info)
+{
+    thread_struct *stuff;
+    DWORD rc = 0;
+  
+    TRACE("MSI Thread (0x%lx) started for custom action\n",
+                        GetCurrentThreadId());
+    
+    stuff = (thread_struct*)info;
+    rc = ACTION_CallDllFunction(stuff);
+
+    TRACE("MSI Thread (0x%lx) finished\n",GetCurrentThreadId());
+    /* clse all handles for this thread */
+    MsiCloseAllHandles();
+    return rc;
+}
+
 static UINT HANDLE_CustomType1(MSIPACKAGE *package, const LPWSTR source, 
                                 const LPWSTR target, const INT type)
 {
     WCHAR tmp_file[MAX_PATH];
-    CustomEntry *fn;
-    HANDLE DLL;
-    LPSTR proc;
+    thread_struct *info;
+    DWORD ThreadId;
+    HANDLE ThreadHandle;
 
     store_binary_to_temp(package, source, tmp_file);
 
@@ -1198,76 +1493,57 @@
         strcatW(tmp_file,dot);
     } 
 
-    if (type & 0xc0)
-    {
-        /* DWORD ThreadId; */
-        thread_struct *info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) );
+    info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) );
+    msiobj_addref( &package->hdr );
+    info->package = package;
+    info->target = dupstrW(target);
+    info->source = dupstrW(tmp_file);
 
-        /* msiobj_addref( &package->hdr ); */
-        info->package = package;
-        strcpyW(info->target,target);
-        strcpyW(info->source,tmp_file);
-        TRACE("Start Asynchronous execution\n");
-        FIXME("DATABASE NOT THREADSAFE... not starting\n");
-        /* CreateThread(NULL,0,DllThread,(LPVOID)&info,0,&ThreadId); */
-        /* FIXME: release the package if the CreateThread fails */
-        HeapFree( GetProcessHeap(), 0, info );
-        return ERROR_SUCCESS;
-    }
- 
-    DLL = LoadLibraryW(tmp_file);
-    if (DLL)
-    {
-        proc = strdupWtoA( target );
-        fn = (CustomEntry*)GetProcAddress(DLL,proc);
-        if (fn)
-        {
-            MSIHANDLE hPackage;
+    ThreadHandle = CreateThread(NULL,0,DllThread,(LPVOID)info,0,&ThreadId);
 
-            TRACE("Calling function\n");
-            hPackage = msiobj_findhandle( &package->hdr );
-            if( !hPackage )
-                ERR("Handle for object %p not found\n", package );
-            fn(hPackage);
-            msiobj_release( &package->hdr );
-        }
-        else
-            ERR("Cannot load functon\n");
+    if (!(type & 0xc0))
+        WaitForSingleObject(ThreadHandle,INFINITE);
 
-        HeapFree(GetProcessHeap(),0,proc);
-        FreeLibrary(DLL);
-    }
-    else
-        ERR("Unable to load library\n");
-
+    CloseHandle(ThreadHandle);
+ 
     return ERROR_SUCCESS;
 }
 
 static UINT HANDLE_CustomType2(MSIPACKAGE *package, const LPWSTR source, 
                                 const LPWSTR target, const INT type)
 {
-    WCHAR tmp_file[MAX_PATH*2];
+    WCHAR tmp_file[MAX_PATH];
     STARTUPINFOW si;
     PROCESS_INFORMATION info;
     BOOL rc;
+    INT len;
     WCHAR *deformated;
+    WCHAR *cmd;
     static const WCHAR spc[] = {' ',0};
 
     memset(&si,0,sizeof(STARTUPINFOW));
 
     store_binary_to_temp(package, source, tmp_file);
 
-    strcatW(tmp_file,spc);
     deformat_string(package,target,&deformated);
-    strcatW(tmp_file,deformated);
 
+    len = strlenW(tmp_file) + strlenW(deformated) + 2;
+   
+    cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*len);
+
+    strcpyW(cmd,tmp_file);
+    strcatW(cmd,spc);
+    strcatW(cmd,deformated);
+
     HeapFree(GetProcessHeap(),0,deformated);
 
-    TRACE("executing exe %s \n",debugstr_w(tmp_file));
+    TRACE("executing exe %s \n",debugstr_w(cmd));
 
-    rc = CreateProcessW(NULL, tmp_file, NULL, NULL, FALSE, 0, NULL,
+    rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL,
                   c_collen, &si, &info);
 
+    HeapFree(GetProcessHeap(),0,cmd);
+
     if ( !rc )
     {
         ERR("Unable to execute command\n");
@@ -1282,33 +1558,43 @@
     return ERROR_SUCCESS;
 }
 
-static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source, 
+static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source,
                                 const LPWSTR target, const INT type)
 {
-    WCHAR filename[MAX_PATH*2];
     STARTUPINFOW si;
     PROCESS_INFORMATION info;
     BOOL rc;
     WCHAR *deformated;
+    WCHAR *cmd;
+    INT len;
     static const WCHAR spc[] = {' ',0};
     int index;
 
     memset(&si,0,sizeof(STARTUPINFOW));
 
     index = get_loaded_file(package,source);
-    strcpyW(filename,package->files[index].TargetPath);
 
-    strcatW(filename,spc);
[truncated at 1000 lines; 7895 more skipped]