MSI: start implementing MsiOpenPackage

Mike McCormack mike at codeweavers.com
Tue Jun 29 07:44:50 CDT 2004


ChangeLog:
<aric at codeweavers.com>
* start implementing MsiOpenPackage
-------------- next part --------------
diff -ur dlls/msi.old/Makefile.in dlls/msi/Makefile.in
--- dlls/msi.old/Makefile.in	2004-06-29 07:27:41.000000000 -0500
+++ dlls/msi/Makefile.in	2004-06-29 07:41:17.000000000 -0500
@@ -15,6 +15,7 @@
 	msi.c \
 	msiquery.c \
 	order.c \
+	package.c \
 	record.c \
 	regsvr.c \
 	select.c \
diff -ur dlls/msi.old/action.c dlls/msi/action.c
--- dlls/msi.old/action.c	2004-06-29 07:27:41.000000000 -0500
+++ dlls/msi/action.c	2004-06-29 07:29:03.000000000 -0500
@@ -47,23 +47,6 @@
 
 #define CUSTOM_ACTION_TYPE_MASK 0x3F
 
-/*
- * These are hacks to get around the inability to write
- * to the database and the inability to select on string values
- * once those values are done then it will be possible to do
- * all this inside the database.
- */
-
-#define MAX_PROP 1024
-
-typedef struct {
-    WCHAR *prop_name;
-    WCHAR *prop_value;
-    } internal_property;
-
-static internal_property PropTableHack[MAX_PROP];
-static INT PropCount = -1;
-
 WINE_DEFAULT_DEBUG_CHANNEL(msi);
 
 /*
@@ -83,13 +66,6 @@
 static UINT HANDLE_CustomType2(MSIHANDLE hPackage, const LPWSTR source, 
                                 const LPWSTR target, const INT type);
 
-
-static UINT set_property(MSIHANDLE hPackage, const WCHAR* prop, 
-                          const WCHAR* value);
-UINT get_property(MSIHANDLE hPackage, const WCHAR* prop, WCHAR* value, 
-                  DWORD* size);
-static VOID blitz_propertytable();
-static VOID set_installer_properties(MSIHANDLE hPackage);
 static DWORD deformat_string(MSIHANDLE hPackage, WCHAR* ptr,WCHAR** data);
 
 /*
@@ -98,7 +74,8 @@
 static const WCHAR cszSourceDir[] = {'S','o','u','r','c','e','D','i','r',0};
 static const WCHAR cszRootDrive[] = {'R','O','O','T','D','R','I','V','E',0};
 static const WCHAR cszTargetDir[] = {'T','A','R','G','E','T','D','I','R',0};
-
+static const WCHAR c_collen[] = {'C',':','\\',0};
+ 
 static const WCHAR cszlsb[]={'[',0};
 static const WCHAR cszrsb[]={']',0};
 static const WCHAR cszbs[]={'\\',0};
@@ -120,226 +97,6 @@
     return ret;
 }
 
-static VOID blitz_propertytable()
-{
-    if (PropCount == -1)
-    {
-        PropCount = 0;
-        memset(&PropTableHack,0,sizeof(PropTableHack));
-    }
-    else if (PropCount > 0)
-    {
-        int i;
-        TRACE("Clearing %i properties\n",PropCount);
-        for (i = 0; i < PropCount; i++)
-        {
-            HeapFree(GetProcessHeap(), 0, PropTableHack[i].prop_name);
-            HeapFree(GetProcessHeap(), 0, PropTableHack[i].prop_value);
-        }
-        memset(&PropTableHack,0,sizeof(PropTableHack));
-        PropCount = 0;
-    }
-}
-
-UINT get_property(MSIHANDLE hPackage, const WCHAR* prop, WCHAR* value, 
-                  DWORD* size)
-{
-    UINT rc = 1;
-    int index = 0;
-    WCHAR* pName = PropTableHack[0].prop_name;
-
-    TRACE("Looking for property %s\n",debugstr_w(prop));
-
-    /* prop table hacks take presidence */
-
-    while (pName && strcmpW(pName,prop) && index < PropCount)
-    {
-        index ++;
-        pName = PropTableHack[index].prop_name;
-    }
-
-    if (pName && index < PropCount)
-    {
-        if (*size > strlenW(PropTableHack[index].prop_value))
-        {
-            *size = strlenW(PropTableHack[index].prop_value)+1;
-            TRACE("    index %i\n", index);
-            strcpyW(value , PropTableHack[index].prop_value);
-            TRACE("    found value %s\n",debugstr_w(value));
-            return 0;
-        }
-        else
-        {
-            *size = strlenW(PropTableHack[index].prop_value);
-            return ERROR_MORE_DATA;
-        }
-    }
-
-    rc = MsiGetPropertyW(hPackage,prop,value,size);
-
-    if (rc == ERROR_SUCCESS)
-        TRACE("    found value %s\n",debugstr_w(value));
-    else
-        TRACE("    value not found\n");
-
-    return rc;
-}
-
-static UINT set_property(MSIHANDLE hPackage, const WCHAR* prop, 
-                          const WCHAR* value)
-{
-    /* prop table hacks take precedence */
-    UINT rc;
-    int index = 0;
-    WCHAR* pName;
-
-    if (PropCount == -1)
-        blitz_propertytable();
-
-    pName = PropTableHack[0].prop_name;
-
-    TRACE("Setting property %s to %s\n",debugstr_w(prop),debugstr_w(value));
-
-    while (pName  && strcmpW(pName,prop) &&  index < MAX_PROP)
-    {
-        index ++;
-        pName = PropTableHack[index].prop_name;
-    }
-
-    if (pName && index < MAX_PROP)
-    {
-        TRACE("property index %i\n",index);
-        strcpyW(PropTableHack[index].prop_value,value);
-        return 0;
-    }
-    else
-    {
-        if (index >= MAX_PROP)
-        {
-            ERR("EXCEEDING MAX PROP!!!!\n");
-            return ERROR_FUNCTION_FAILED;
-        }
-        PropTableHack[index].prop_name = HeapAlloc(GetProcessHeap(),0,1024);
-        PropTableHack[index].prop_value= HeapAlloc(GetProcessHeap(),0,1024);
-        strcpyW(PropTableHack[index].prop_name,prop);
-        strcpyW(PropTableHack[index].prop_value,value);
-        PropCount++;
-        TRACE("new property index %i (%i)\n",index,PropCount);
-        return 0;
-    }
-
-    /* currently unreachable */
-    rc = MsiSetPropertyW(hPackage,prop,value);
-    return rc;
-}
-
-/*
- * There are a whole slew of these we need to set
- *
- *
-http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/properties.asp
- */
-
-static VOID set_installer_properties(MSIHANDLE hPackage)
-{
-    WCHAR pth[MAX_PATH];
-
-    static const WCHAR c_col[] = 
-{'C',':','\\',0};
-    static const WCHAR CFF[] = 
-{'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
-    static const WCHAR PFF[] = 
-{'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
-    static const WCHAR CADF[] = 
-{'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
-    static const WCHAR ATF[] = 
-{'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
-    static const WCHAR ADF[] = 
-{'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
-    static const WCHAR SF[] = 
-{'S','y','s','t','e','m','F','o','l','d','e','r',0};
-    static const WCHAR LADF[] = 
-{'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
-    static const WCHAR MPF[] = 
-{'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
-    static const WCHAR PF[] = 
-{'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
-    static const WCHAR WF[] = 
-{'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
-    static const WCHAR TF[]=
-{'T','e','m','p','F','o','l','d','e','r',0};
-
-/* Not yet set ...  but needed by iTunes
- *
-    static const WCHAR DF[] = 
-{'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
-    static const WCHAR FF[] = 
-{'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0};
-    static const WCHAR FoF[] = 
-{'F','o','n','t','s','F','o','l','d','e','r',0};
-PrimaryVolumePath
-ProgramFiles64Folder
-ProgramMenuFolder
-SendToFolder
-StartMenuFolder
-StartupFolder
-System16Folder
-System64Folder
-TemplateFolder
- */
-
-/* asked for by iTunes ... but are they installer set? 
- *
- *  GlobalAssemblyCache
- */
-
-    set_property(hPackage, cszRootDrive, c_col);
-
-    SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
-    strcatW(pth,cszbs);
-    set_property(hPackage, CFF, pth);
-
-    SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
-    strcatW(pth,cszbs);
-    set_property(hPackage, PFF, pth);
-
-    SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
-    strcatW(pth,cszbs);
-    set_property(hPackage, CADF, pth);
-
-    SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
-    strcatW(pth,cszbs);
-    set_property(hPackage, ATF, pth);
-
-    SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
-    strcatW(pth,cszbs);
-    set_property(hPackage, ADF, pth);
-
-    SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
-    strcatW(pth,cszbs);
-    set_property(hPackage, SF, pth);
-
-    SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
-    strcatW(pth,cszbs);
-    set_property(hPackage, LADF, pth);
-
-    SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
-    strcatW(pth,cszbs);
-    set_property(hPackage, MPF, pth);
-
-    SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
-    strcatW(pth,cszbs);
-    set_property(hPackage, PF, pth);
-
-    SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
-    strcatW(pth,cszbs);
-    set_property(hPackage, WF, pth);
-
-    GetTempPathW(MAX_PATH,pth);
-    set_property(hPackage, TF, pth);
-}
-
-
 /****************************************************
  * TOP level entry points 
  *****************************************************/
@@ -351,23 +108,17 @@
     UINT rc;
     static const CHAR *ExecSeqQuery = 
 "select * from InstallExecuteSequence where Sequence > 0 order by Sequence";
+    MSIHANDLE db;
 
     FIXME("****We do not do any of the UI level stuff yet***\n");
 
-    /* reset our properties */
-    blitz_propertytable();
-
     if (szPackagePath)   
     {
-        static const WCHAR OriginalDatabase[] =
-{'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
         LPWSTR p;
         WCHAR check[MAX_PATH];
         WCHAR pth[MAX_PATH];
         DWORD size;
  
-        set_property(hPackage, OriginalDatabase, szPackagePath);
-
         strcpyW(pth,szPackagePath);
         p = strrchrW(pth,'\\');    
         if (p)
@@ -377,11 +128,13 @@
         }
 
         size = MAX_PATH;
-        if (get_property(hPackage,cszSourceDir,check,&size) != ERROR_SUCCESS )
-            set_property(hPackage, cszSourceDir, pth);
+        if (MsiGetPropertyW(hPackage,cszSourceDir,check,&size) != ERROR_SUCCESS )
+            MsiSetPropertyW(hPackage, cszSourceDir, pth);
     }
 
-    rc = MsiDatabaseOpenViewA(hPackage, ExecSeqQuery, &view);
+    db = MsiGetActiveDatabase(hPackage);
+    rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
+    MsiCloseHandle(db);
     
     if (rc == ERROR_SUCCESS)
     {
@@ -456,7 +209,6 @@
     }
 
 end:
-    blitz_propertytable();
     return rc;
 }
 
@@ -588,10 +340,15 @@
     WCHAR source[0x100];
     WCHAR target[0x200];
     WCHAR *deformated=NULL;
+    MSIHANDLE db;
 
     strcatW(ExecSeqQuery,action);
     strcatW(ExecSeqQuery,end);
-    rc = MsiDatabaseOpenViewW(hPackage, ExecSeqQuery, &view);
+
+    db = MsiGetActiveDatabase(hPackage);
+    rc = MsiDatabaseOpenViewW(db, ExecSeqQuery, &view);
+    MsiCloseHandle(db);
+
     if (rc != ERROR_SUCCESS)
         return rc;
 
@@ -633,7 +390,7 @@
         case 35: /* Directory set with formatted text. */
         case 51: /* Property set with formatted text. */
             deformat_string(hPackage,target,&deformated);
-            set_property(hPackage,source,deformated);
+            MsiSetPropertyW(hPackage,source,deformated);
             HeapFree(GetProcessHeap(),0,deformated);
             break;
         default:
@@ -654,7 +411,7 @@
     static const WCHAR TF[]= {'T','e','m','p','F','o','l','d','e','r',0};
     DWORD sz=MAX_PATH;
 
-    if (get_property(hPackage, TF,tmp_file, &sz) != ERROR_SUCCESS)
+    if (MsiGetPropertyW(hPackage, TF,tmp_file, &sz) != ERROR_SUCCESS)
         GetTempPathW(MAX_PATH,tmp_file);
 
     strcatW(tmp_file,source);
@@ -676,6 +433,7 @@
         static const WCHAR end[]={'`',0};
         HANDLE the_file;
         CHAR buffer[1024];
+        MSIHANDLE db;
 
         the_file = CreateFileW(tmp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
                            FILE_ATTRIBUTE_NORMAL, NULL);
@@ -685,7 +443,11 @@
 
         strcatW(Query,source);
         strcatW(Query,end);
-        rc = MsiDatabaseOpenViewW(hPackage, Query, &view);
+
+        db = MsiGetActiveDatabase(hPackage);
+        rc = MsiDatabaseOpenViewW(db, Query, &view);
+        MsiCloseHandle(db);
+
         if (rc != ERROR_SUCCESS)
             return rc;
 
@@ -782,7 +544,6 @@
     PROCESS_INFORMATION info;
     BOOL rc;
     WCHAR *deformated;
-    static const WCHAR c_collen[] = {'C',':','\\',0};
     static const WCHAR spc[] = {' ',0};
 
     memset(&si,0,sizeof(STARTUPINFOW));
@@ -875,8 +636,12 @@
     static const CHAR *ExecSeqQuery = "select * from CreateFolder";
     UINT rc;
     MSIHANDLE view;
+    MSIHANDLE db;
+
+    db = MsiGetActiveDatabase(hPackage);
+    rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
+    MsiCloseHandle(db);
 
-    rc = MsiDatabaseOpenViewA(hPackage, ExecSeqQuery, &view);
     if (rc != ERROR_SUCCESS)
         return rc;
 
@@ -913,7 +678,7 @@
         }
 
         sz = MAX_PATH;
-        rc = get_property(hPackage, dir,full_path,&sz);
+        rc = MsiGetPropertyW(hPackage, dir,full_path,&sz);
 
         if (rc != ERROR_SUCCESS)
         {
@@ -961,9 +726,10 @@
     MSIHANDLE row = 0;
     WCHAR full_path[MAX_PATH];
     WCHAR name_source[0x100];
+    MSIHANDLE db;
 
     sz = MAX_PATH; 
-    if (get_property(hPackage,dir,path,&sz)==ERROR_SUCCESS)
+    if (MsiGetPropertyW(hPackage,dir,path,&sz)==ERROR_SUCCESS)
         return ERROR_SUCCESS;
 
     TRACE("Working to resolve %s\n",debugstr_w(dir));
@@ -974,18 +740,14 @@
         if (!source)
         {
             sz = 0x100;
-            if(!get_property(hPackage,cszRootDrive,buffer,&sz))
+            if(!MsiGetPropertyW(hPackage,cszRootDrive,buffer,&sz))
             {
-                set_property(hPackage,cszTargetDir,buffer);
+                MsiSetPropertyW(hPackage,cszTargetDir,buffer);
                 strcpyW(path,buffer);
             }
             else
             {
-                ERR("No RootDrive property defined disaster!\n");
-                MsiCloseHandle(row);
-                MsiViewClose(view);
-                MsiCloseHandle(view);
-                return ERROR_FUNCTION_FAILED;
+                strcpyW(path,c_collen);
             }
         }
         else
@@ -996,7 +758,11 @@
 
     strcatW(Query,dir);
     strcatW(Query,end);
-    rc = MsiDatabaseOpenViewW(hPackage, Query, &view);
+
+    db = MsiGetActiveDatabase(hPackage);
+    rc = MsiDatabaseOpenViewW(db, Query, &view);
+    MsiCloseHandle(db);
+
     if (rc != ERROR_SUCCESS)
         return rc;
 
@@ -1068,7 +834,7 @@
             strcatW(full_path,targetdir);
             strcatW(full_path,cszbs);
         }
-        set_property(hPackage,dir,full_path);
+        MsiSetPropertyW(hPackage,dir,full_path);
         if (!source)
             strcpyW(path,full_path);
 
@@ -1087,7 +853,7 @@
         
         strcpyW(name_source,dir);
         strcatW(name_source,cszsrc);
-        set_property(hPackage,name_source,full_path);
+        MsiSetPropertyW(hPackage,name_source,full_path);
         if (source)
             strcpyW(path,full_path);
     }
@@ -1122,15 +888,14 @@
     static const CHAR *ExecSeqQuery = "select * from Directory";
     UINT rc;
     MSIHANDLE view;
-
-    /* According to MSDN these properties are set when CostFinalize is run  
-     * or MsiSetInstallLevel is called */
-    TRACE("Setting installer properties\n");
-    set_installer_properties(hPackage);    
+    MSIHANDLE db;
 
     TRACE("Building Directory properties\n");
 
-    rc = MsiDatabaseOpenViewA(hPackage, ExecSeqQuery, &view);
+    db = MsiGetActiveDatabase(hPackage);
+    rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
+    MsiCloseHandle(db);
+
     if (rc != ERROR_SUCCESS)
         return rc;
 
@@ -1184,14 +949,17 @@
     UINT    size;
     DWORD   write;
     HANDLE  the_file;
+    MSIHANDLE db;
 
-    rc = read_raw_stream_data(hPackage,stream_name,&data,&size); 
+    db = MsiGetActiveDatabase(hPackage);
+    rc = read_raw_stream_data(db,stream_name,&data,&size); 
+    MsiCloseHandle(db);
 
     if (rc != ERROR_SUCCESS)
         return rc;
 
     write = 0x100;
-    if (get_property(hPackage, cszSourceDir, source, &write))
+    if (MsiGetPropertyW(hPackage, cszSourceDir, source, &write))
     {
         ERR("No Source dir defined \n");
         rc = ERROR_FUNCTION_FAILED;
@@ -1271,6 +1039,7 @@
     DWORD sz=0x100;
     INT seq;
     static INT last_sequence = 0; 
+    MSIHANDLE db;
 
     if (sequence <= last_sequence)
     {
@@ -1280,7 +1049,10 @@
 
     sprintf(Query,ExecSeqQuery,sequence);
 
-    rc = MsiDatabaseOpenViewA(hPackage, Query, &view);
+    db = MsiGetActiveDatabase(hPackage);
+    rc = MsiDatabaseOpenViewA(db, Query, &view);
+    MsiCloseHandle(db);
+
     if (rc != ERROR_SUCCESS)
         return rc;
 
@@ -1316,7 +1088,7 @@
         else
         {
             sz = 0x100;
-            if (get_property(hPackage, cszSourceDir, source, &sz))
+            if (MsiGetPropertyW(hPackage, cszSourceDir, source, &sz))
             {
                 ERR("No Source dir defined \n");
                 rc = ERROR_FUNCTION_FAILED;
@@ -1358,11 +1130,14 @@
     static const WCHAR end[]={'`',0};
     WCHAR dir[0x100];
     DWORD sz=0x100;
+    MSIHANDLE db;
 
     strcatW(ExecSeqQuery,component);
     strcatW(ExecSeqQuery,end);
 
-    rc = MsiDatabaseOpenViewW(hPackage, ExecSeqQuery, &view);
+    db = MsiGetActiveDatabase(hPackage);
+    rc = MsiDatabaseOpenViewW(db, ExecSeqQuery, &view);
+    MsiCloseHandle(db);
 
     if (rc != ERROR_SUCCESS)
         return rc;
@@ -1387,7 +1162,7 @@
     sz=0x100;
     MsiRecordGetStringW(row,3,dir,&sz);
     sz=MAX_PATH;
-    rc = get_property(hPackage, dir, install_path, &sz);
+    rc = MsiGetPropertyW(hPackage, dir, install_path, &sz);
 
     MsiCloseHandle(row);
     MsiViewClose(view);
@@ -1402,6 +1177,7 @@
     MSIHANDLE row = 0;
     static const CHAR *ExecSeqQuery = 
         "select * from File order by Sequence";
+    MSIHANDLE db;
 
     /* REALLY what we want to do is go through all the enabled
      * features and check all the components of that feature and
@@ -1410,8 +1186,10 @@
      * but for sheer gratification I am going to just brute force
      * install all the files
      */
+    db = MsiGetActiveDatabase(hPackage);
+    rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
+    MsiCloseHandle(db);
 
-    rc = MsiDatabaseOpenViewA(hPackage, ExecSeqQuery, &view);
     if (rc != ERROR_SUCCESS)
         return rc;
 
@@ -1497,7 +1275,7 @@
         }
 
         /* for future use lets keep track of this file and where it went */
-        set_property(hPackage,sourcename,install_path);
+        MsiSetPropertyW(hPackage,sourcename,install_path);
 
         MsiCloseHandle(row);
     }
@@ -1513,14 +1291,17 @@
     MSIHANDLE view;
     MSIHANDLE row = 0;
     static const CHAR *ExecSeqQuery = "select * from DuplicateFile";
+    MSIHANDLE db;
 
 
     /*
      * Yes we should only do this for componenets that are installed
      * but again I need to do that went I track components.
      */
+    db = MsiGetActiveDatabase(hPackage);
+    rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
+    MsiCloseHandle(db);
 
-    rc = MsiDatabaseOpenViewA(hPackage, ExecSeqQuery, &view);
     if (rc != ERROR_SUCCESS)
         return rc;
 
@@ -1558,7 +1339,7 @@
         }
 
         sz = 0x100;
-        rc = get_property(hPackage,file_key,file_source,&sz);
+        rc = MsiGetPropertyW(hPackage,file_key,file_source,&sz);
         if (rc != ERROR_SUCCESS)
         {
             ERR("Original file unknown %s\n",debugstr_w(file_key));
@@ -1586,7 +1367,7 @@
             sz=0x100;
             MsiRecordGetStringW(row,5,destkey,&sz);
             sz = 0x100;
-            rc = get_property(hPackage, destkey, dest_path, &sz);
+            rc = MsiGetPropertyW(hPackage, destkey, dest_path, &sz);
             if (rc != ERROR_SUCCESS)
             {
                 ERR("Unable to get destination folder\n");
@@ -1700,12 +1481,15 @@
     MSIHANDLE view;
     MSIHANDLE row = 0;
     static const CHAR *ExecSeqQuery = "select * from Registry";
+    MSIHANDLE db;
 
     /* Again here we want to key off of the components being installed...
      * oh well
      */
-    
-    rc = MsiDatabaseOpenViewA(hPackage, ExecSeqQuery, &view);
+    db = MsiGetActiveDatabase(hPackage);
+    rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
+    MsiCloseHandle(db);
+
     if (rc != ERROR_SUCCESS)
         return rc;
 
@@ -1851,7 +1635,7 @@
     mark++;
     TRACE("Current %s .. %s\n",debugstr_w(*data),debugstr_w(mark));
     sz = 0x100;
-    if (get_property(hPackage, key, value,&sz) == ERROR_SUCCESS)
+    if (MsiGetPropertyW(hPackage, key, value,&sz) == ERROR_SUCCESS)
     {
         LPWSTR newdata;
         chunk = (strlenW(value)+1) * sizeof(WCHAR);
@@ -1953,7 +1737,7 @@
                                 szPathBuf, DWORD* pcchPathBuf) 
 {
     TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf);
-    return get_property(hInstall,szFolder,szPathBuf,pcchPathBuf);
+    return MsiGetPropertyW(hInstall,szFolder,szPathBuf,pcchPathBuf);
 }
 
 
@@ -2007,11 +1791,11 @@
                     (strlenW(szFolder)+8)*sizeof(WCHAR));
         strcpyW(newfolder,szFolder);
         strcatW(newfolder,cszsrc);
-        rc = get_property(hInstall,newfolder,szPathBuf,pcchPathBuf);
+        rc = MsiGetPropertyW(hInstall,newfolder,szPathBuf,pcchPathBuf);
         HeapFree(GetProcessHeap(),0,newfolder);
     }
     else
-        rc = get_property(hInstall,szFolder,szPathBuf,pcchPathBuf);
+        rc = MsiGetPropertyW(hInstall,szFolder,szPathBuf,pcchPathBuf);
     return rc;
 }
 
@@ -2028,8 +1812,12 @@
     MSIHANDLE view;
     MSIHANDLE row = 0;
     static const CHAR *ExecSeqQuery;
+    MSIHANDLE db;
+
+    db = MsiGetActiveDatabase(hPackage);
+    rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
+    MsiCloseHandle(db);
 
-    rc = MsiDatabaseOpenViewA(hPackage, ExecSeqQuery, &view);
     if (rc != ERROR_SUCCESS)
         return rc;
 
diff -ur dlls/msi.old/cond.y dlls/msi/cond.y
--- dlls/msi.old/cond.y	2004-06-29 07:27:41.000000000 -0500
+++ dlls/msi/cond.y	2004-06-29 07:29:03.000000000 -0500
@@ -449,11 +449,9 @@
             $$ = HeapAlloc( GetProcessHeap(), 0, 0x100*sizeof (WCHAR) );
 
             /* Lookup the identifier */
-            /* This will not really work until we have write access to the table*/
-            /* HACK ALERT HACK ALERT... */
 
             sz=0x100;
-            if (get_property(cond->hInstall,$1,$$,&sz) != ERROR_SUCCESS)
+            if (MsiGetPropertyW(cond->hInstall,$1,$$,&sz) != ERROR_SUCCESS)
             {
                 $$[0]=0;
             }
diff -ur dlls/msi.old/msi.c dlls/msi/msi.c
--- dlls/msi.old/msi.c	2004-06-29 07:27:41.000000000 -0500
+++ dlls/msi/msi.c	2004-06-29 07:32:19.000000000 -0500
@@ -375,32 +375,6 @@
     return r;
 }
 
-UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
-{
-    FIXME("%s %p\n",debugstr_a(szPackage), phPackage);
-    return ERROR_CALL_NOT_IMPLEMENTED;
-}
-
-UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
-{
-    UINT rc;
-    FIXME("%s %p\n",debugstr_w(szPackage), phPackage);
-    rc = MsiOpenDatabaseW(szPackage,MSIDBOPEN_READONLY,phPackage);
-    return rc;
-}
-
-UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
-{
-    FIXME("%s 0x%08lx %p\n",debugstr_a(szPackage), dwOptions, phPackage);
-    return ERROR_CALL_NOT_IMPLEMENTED;
-}
-
-UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
-{
-    FIXME("%s 0x%08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage);
-    return ERROR_CALL_NOT_IMPLEMENTED;
-}
-
 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, LPCSTR szTransforms, LANGID lgidLanguage)
 {
     FIXME("%s %s %s 0x%08x\n",debugstr_a(szPackagePath), debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
@@ -466,7 +440,7 @@
 
 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
 {
-   MSIHANDLE dbhandle;
+   MSIHANDLE packagehandle;
     UINT rc = ERROR_SUCCESS; 
 
     FIXME("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
@@ -475,13 +449,13 @@
     if (rc != ERROR_SUCCESS)
         return rc;
 
-    rc = MsiOpenDatabaseW(szPackagePath,MSIDBOPEN_READONLY,&dbhandle);
+    rc = MsiOpenPackageW(szPackagePath,&packagehandle);
     if (rc != ERROR_SUCCESS)
         return rc;
 
-    ACTION_DoTopLevelINSTALL(dbhandle, szPackagePath, szCommandLine);
+    ACTION_DoTopLevelINSTALL(packagehandle, szPackagePath, szCommandLine);
 
-    MsiCloseHandle(dbhandle);
+    MsiCloseHandle(packagehandle);
     return rc;
 }
 
@@ -1224,151 +1198,6 @@
   return S_FALSE;
 }
 
-/* property code */
-UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue)
-{
-    FIXME("STUB until write access is done: (%s %s)\n", szName,
-          szValue);
-
-    if (!hInstall)
-        return ERROR_INVALID_HANDLE;
-
-    return ERROR_SUCCESS;
-}
-
-UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
-{
-    FIXME("STUB until write access is done: (%s %s)\n",debugstr_w(szName),
-          debugstr_w(szValue));
-
-    if (!hInstall)
-        return ERROR_INVALID_HANDLE;
-
-    return ERROR_SUCCESS;
-}
-
-UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPSTR szValueBuf, DWORD* pchValueBuf) 
-{
-    LPWSTR szwName = NULL, szwValueBuf = NULL;
-    UINT hr = ERROR_INSTALL_FAILURE;
-
-    if (0 == hInstall) {
-      return ERROR_INVALID_HANDLE;
-    }
-    if (NULL == szName) {
-      return ERROR_INVALID_PARAMETER;
-    }
-
-    FIXME("%lu %s %lu\n", hInstall, debugstr_a(szName), *pchValueBuf);
-
-    if (NULL != szValueBuf && NULL == pchValueBuf) {
-      return ERROR_INVALID_PARAMETER;
-    }
-    if( szName )
-    {
-        UINT len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
-        szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
-        if( !szwName )
-            goto end;
-        MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
-    } else {
-      return ERROR_INVALID_PARAMETER;
-    }
-    if( szValueBuf )
-    {
-        szwValueBuf = HeapAlloc( GetProcessHeap(), 0, (*pchValueBuf) * sizeof(WCHAR) );
-        if( !szwValueBuf )	 
-            goto end;
-    }
-
-    hr = MsiGetPropertyW( hInstall, szwName, szwValueBuf, pchValueBuf );
-
-    if( ERROR_SUCCESS == hr )
-    {
-        WideCharToMultiByte(CP_ACP, 0, szwValueBuf, -1, szValueBuf, *pchValueBuf, NULL, NULL);
-    }
-
-end:
-    if( szwName )
-        HeapFree( GetProcessHeap(), 0, szwName );
-    if( szwValueBuf )
-        HeapFree( GetProcessHeap(), 0, szwValueBuf );
-
-    return hr;
-}
-
-UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName, 
-                           LPWSTR szValueBuf, DWORD* pchValueBuf)
-{
-    MSIHANDLE view,row;
-    UINT rc;
-    WCHAR Query[1024]=
-        {'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' '
-         ,'P','r','o','p','e','r','t','y',' ','w','h','e','r','e',' ','`'
-         ,'P','r','o','p','e','r','t','y','`','=','`',0};
-
-    static const WCHAR szEnd[]={'`',0};
-
-    if (0 == hInstall) {
-      return ERROR_INVALID_HANDLE;
-    }
-    if (NULL == szName) {
-      return ERROR_INVALID_PARAMETER;
-    }
-
-    strcatW(Query,szName);
-    strcatW(Query,szEnd);
-    
-    rc = MsiDatabaseOpenViewW(hInstall, Query, &view);
-    if (rc == ERROR_SUCCESS)
-    {
-        DWORD sz;
-        WCHAR value[0x100];
-
-        rc = MsiViewExecute(view, 0);
-        if (rc != ERROR_SUCCESS)
-        {
-            MsiViewClose(view);
-            MsiCloseHandle(view);
-            return rc;
-        }
-
-        rc = MsiViewFetch(view,&row);
-        if (rc == ERROR_SUCCESS)
-        {
-            sz=0x100;
-            rc = MsiRecordGetStringW(row,2,value,&sz);
-            strncpyW(szValueBuf,value,min(sz+1,*pchValueBuf));
-            *pchValueBuf = sz+1;
-            MsiCloseHandle(row);
-        }
-        MsiViewClose(view);
-        MsiCloseHandle(view);
-    }
-
-    if (rc == ERROR_SUCCESS)
-        TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
-            debugstr_w(szName));
-
-    return rc;
-}
-
-
-INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
-                              MSIHANDLE hRecord)
-{
-    FIXME("STUB: \n");
-    return ERROR_SUCCESS;
-}
-
-
-MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
-{
-    FIXME("Is this correct?\n");
-    msihandle_addref(hInstall);
-    return hInstall;
-}
-
 UINT WINAPI MsiEnumRelatedProductsA (LPCSTR lpUpgradeCode, DWORD dwReserved,
                                     DWORD iProductIndex, LPSTR lpProductBuf)
 {
diff -ur dlls/msi.old/msipriv.h dlls/msi/msipriv.h
--- dlls/msi.old/msipriv.h	2004-06-29 07:27:41.000000000 -0500
+++ dlls/msi/msipriv.h	2004-06-29 07:29:10.000000000 -0500
@@ -145,6 +145,7 @@
 #define MSIHANDLETYPE_SUMMARYINFO 2
 #define MSIHANDLETYPE_VIEW 3
 #define MSIHANDLETYPE_RECORD 4
+#define MSIHANDLETYPE_PACKAGE 5
 
 #define MSI_MAJORVERSION 1
 #define MSI_MINORVERSION 10
--- /dev/null	1994-07-17 18:46:18.000000000 -0500
+++ dlls/msi/package.c	2004-06-29 07:35:58.000000000 -0500
@@ -0,0 +1,541 @@
+/*
+ * Implementation of the Microsoft Installer (msi.dll)
+ *
+ * Copyright 2004 Aric Stewart 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
+ */
+
+#define NONAMELESSUNION
+
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "winnls.h"
+#include "shlwapi.h"
+#include "wine/debug.h"
+#include "msi.h"
+#include "msiquery.h"
+#include "msipriv.h"
+#include "objidl.h"
+#include "wincrypt.h"
+#include "winuser.h"
+#include "shlobj.h"
+#include "wine/unicode.h"
+#include "objbase.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msi);
+
+/*
+ * The MSVC headers define the MSIDBOPEN_* macros cast to LPCTSTR,
+ *  which is a problem because LPCTSTR isn't defined when compiling wine.
+ * To work around this problem, we need to define LPCTSTR as LPCWSTR here,
+ *  and make sure to only use it in W functions.
+ */
+#define LPCTSTR LPCWSTR
+
+void MSI_FreePackage( VOID *arg);
+
+typedef struct tagMSIPACKAGE
+{
+    MSIHANDLE db;
+} MSIPACKAGE;
+
+void MSI_FreePackage( VOID *arg)
+{
+    MSIPACKAGE *package= arg;
+
+    MsiCloseHandle(package->db);
+}
+
+UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
+{
+    LPWSTR szwPack = NULL;
+    UINT len, ret;
+
+    TRACE("%s %p\n",debugstr_a(szPackage), phPackage);
+
+    if( szPackage )
+    {
+        len = MultiByteToWideChar( CP_ACP, 0, szPackage, -1, NULL, 0 );
+        szwPack = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
+        if( szwPack )
+            MultiByteToWideChar( CP_ACP, 0, szPackage, -1, szwPack, len );
+    }
+
+    ret = MsiOpenPackageW( szwPack, phPackage );
+
+    if( szwPack )
+        HeapFree( GetProcessHeap(), 0, szwPack );
+
+    return ret;
+}
+
+
+static const void clone_properties(MSIHANDLE db)
+{
+    MSIHANDLE view;
+    UINT rc;
+    static const CHAR CreateSql[] = "CREATE TABLE `_Property` ( `_Property` "
+"CHAR(56) NOT NULL, `Value` CHAR(98) NOT NULL PRIMARY KEY `_Property`)";
+    static const CHAR Query[] = "SELECT * from Property";
+    static const CHAR Insert[] = 
+      "INSERT into `_Property` (`_Property`,`Value`) VALUES (?)";
+
+    /* create the temporary properties table */
+    MsiDatabaseOpenViewA(db, CreateSql, &view);
+    MsiViewExecute(view,0);   
+    MsiViewClose(view);
+    MsiCloseHandle(view); 
+
+    /* clone the existing properties */
+    MsiDatabaseOpenViewA(db, Query, &view);
+
+    MsiViewExecute(view, 0);
+    while (1)
+    {
+        MSIHANDLE row;
+        MSIHANDLE view2;
+
+        rc = MsiViewFetch(view,&row);
+        if (rc != ERROR_SUCCESS)
+            break;
+
+        MsiDatabaseOpenViewA(db,Insert,&view2);  
+        MsiViewExecute(view2,row);
+        MsiViewClose(view2);
+        MsiCloseHandle(view2);
+ 
+        MsiCloseHandle(row); 
+    }
+    MsiViewClose(view);
+    MsiCloseHandle(view);
+    
+}
+
+/*
+ * There are a whole slew of these we need to set
+ *
+ *
+http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/properties.asp
+ */
+static VOID set_installer_properties(MSIHANDLE hPackage)
+{
+    WCHAR pth[MAX_PATH];
+
+    static const WCHAR cszbs[]={'\\',0};
+    static const WCHAR CFF[] = 
+{'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
+    static const WCHAR PFF[] = 
+{'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
+    static const WCHAR CADF[] = 
+{'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
+    static const WCHAR ATF[] = 
+{'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
+    static const WCHAR ADF[] = 
+{'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
+    static const WCHAR SF[] = 
+{'S','y','s','t','e','m','F','o','l','d','e','r',0};
+    static const WCHAR LADF[] = 
+{'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
+    static const WCHAR MPF[] = 
+{'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
+    static const WCHAR PF[] = 
+{'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
+    static const WCHAR WF[] = 
+{'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
+    static const WCHAR TF[]=
+{'T','e','m','p','F','o','l','d','e','r',0};
+
+/* Not yet set ...  but needed by iTunes
+ *
+DesktopFolder
+FavoritesFolder
+FontsFolder
+PrimaryVolumePath
+ProgramFiles64Folder
+ProgramMenuFolder
+SendToFolder
+StartMenuFolder
+StartupFolder
+System16Folder
+System64Folder
+TemplateFolder
+ */
+
+/* asked for by iTunes ... but are they installer set? 
+ *
+ *  GlobalAssemblyCache
+ */
+
+/*
+ * Other things i notice set
+ *
+ScreenY
+ScreenX
+SystemLanguageID
+ComputerName
+UserLanguageID
+LogonUser
+VirtualMemory
+PhysicalMemory
+Intel
+ShellAdvSupport
+ServicePackLevel
+WindowsBuild
+Version9x
+Version95
+VersionNT
+AdminUser
+DefaultUIFont
+VersionMsi
+VersionDatabase
+PackagecodeChanging
+ProductState
+CaptionHeight
+BorderTop
+BorderSide
+TextHeight
+ColorBits
+RedirectedDllSupport
+Time
+Date
+Privilaged
+DATABASE
+OriginalDatabase
+UILevel
+*/
+
+    SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
+    strcatW(pth,cszbs);
+    MsiSetPropertyW(hPackage, CFF, pth);
+
+    SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
+    strcatW(pth,cszbs);
+    MsiSetPropertyW(hPackage, PFF, pth);
+
+    SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
+    strcatW(pth,cszbs);
+    MsiSetPropertyW(hPackage, CADF, pth);
+
+    SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
+    strcatW(pth,cszbs);
+    MsiSetPropertyW(hPackage, ATF, pth);
+
+    SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
+    strcatW(pth,cszbs);
+    MsiSetPropertyW(hPackage, ADF, pth);
+
+    SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
+    strcatW(pth,cszbs);
+    MsiSetPropertyW(hPackage, SF, pth);
+
+    SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
+    strcatW(pth,cszbs);
+    MsiSetPropertyW(hPackage, LADF, pth);
+
+    SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
+    strcatW(pth,cszbs);
+    MsiSetPropertyW(hPackage, MPF, pth);
+
+    SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
+    strcatW(pth,cszbs);
+    MsiSetPropertyW(hPackage, PF, pth);
+
+    SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
+    strcatW(pth,cszbs);
+    MsiSetPropertyW(hPackage, WF, pth);
+
+    GetTempPathW(MAX_PATH,pth);
+    MsiSetPropertyW(hPackage, TF, pth);
+}
+
+
+UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
+{
+    UINT rc;
+    MSIHANDLE handle;
+    MSIHANDLE db;
+    MSIPACKAGE *package;
+
+    static const WCHAR OriginalDatabase[] =
+{'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
+    static const WCHAR Database[] =
+{'D','A','T','A','B','A','S','E',0};
+
+    TRACE("%s %p\n",debugstr_w(szPackage), phPackage);
+
+    rc = MsiOpenDatabaseW(szPackage, MSIDBOPEN_READONLY, &db);
+
+    if (rc != ERROR_SUCCESS)
+        return ERROR_FUNCTION_FAILED;
+
+    handle = alloc_msihandle(MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
+                             MSI_FreePackage, (void**)&package);
+
+    if (!handle)
+    {
+        MsiCloseHandle(db);
+        return ERROR_FUNCTION_FAILED;
+    }
+
+    package->db = db;
+
+    /* ok here is where we do a slew of things to the database to 
+     * prep for all that is to come as a package */
+
+    clone_properties(db);
+    set_installer_properties(handle);
+    MsiSetPropertyW(handle, OriginalDatabase, szPackage);
+    MsiSetPropertyW(handle, Database, szPackage);
+
+    *phPackage = handle;
+
+    return ERROR_SUCCESS;
+}
+
+UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
+{
+    FIXME("%s 0x%08lx %p\n",debugstr_a(szPackage), dwOptions, phPackage);
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
+{
+    FIXME("%s 0x%08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage);
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
+{
+    MSIPACKAGE *package;
+
+    TRACE("(%i)\n",(INT)hInstall);
+
+    package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
+
+    if( !package)
+        return ERROR_INVALID_HANDLE;
+
+    msihandle_addref(package->db);
+    return package->db;
+}
+
+INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
+                              MSIHANDLE hRecord)
+{
+    FIXME("STUB: \n");
+    return ERROR_SUCCESS;
+}
+
+/* property code */
+UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue)
+{
+    LPWSTR szwName = NULL, szwValue = NULL;
+    UINT hr = ERROR_INSTALL_FAILURE;
+    UINT len;
+
+    if (0 == hInstall) {
+      return ERROR_INVALID_HANDLE;
+    }
+    if (NULL == szName) {
+      return ERROR_INVALID_PARAMETER;
+    }
+    if (NULL == szValue) {
+      return ERROR_INVALID_PARAMETER;
+    }
+
+    len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
+    szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
+    if( !szwName )
+        goto end;
+    MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
+
+    len = MultiByteToWideChar( CP_ACP, 0, szValue, -1, NULL, 0 );
+    szwValue = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
+    if( !szwValue)
+        goto end;
+    MultiByteToWideChar( CP_ACP, 0, szValue , -1, szwValue, len );
+
+    hr = MsiSetPropertyW( hInstall, szwName, szwValue);
+
+end:
+    if( szwName )
+        HeapFree( GetProcessHeap(), 0, szwName );
+    if( szwValue )
+        HeapFree( GetProcessHeap(), 0, szwValue );
+
+    return hr;
+}
+
+UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
+{
+    MSIPACKAGE *package;
+    MSIHANDLE view,row;
+    UINT rc;
+    DWORD sz = 0;
+    static const CHAR Insert[]=
+     "INSERT into `_Property` (`_Property`,`Value`) VALUES (?)";
+
+    TRACE("Setting property (%s %s)\n",debugstr_w(szName),
+          debugstr_w(szValue));
+
+    if (!hInstall)
+        return ERROR_INVALID_HANDLE;
+
+    if (MsiGetPropertyW(hInstall,szName,0,&sz)==ERROR_MORE_DATA)
+    {
+        FIXME("Cannot set exising properties! FIXME MIKE!\n");
+        return ERROR_FUNCTION_FAILED;
+    }
+
+    package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
+    if( !package)
+        return ERROR_INVALID_HANDLE;
+
+    rc = MsiDatabaseOpenViewA(package->db,Insert,&view);
+    if (rc!= ERROR_SUCCESS)
+        return rc;
+
+    row = MsiCreateRecord(2);
+    MsiRecordSetStringW(row,1,szName);
+    MsiRecordSetStringW(row,2,szValue);
+
+    rc = MsiViewExecute(view,row);
+
+    MsiCloseHandle(row);
+    MsiViewClose(view);
+    MsiCloseHandle(view);
+
+    return rc;
+}
+
+UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPSTR szValueBuf, DWORD* pchValueBuf) 
+{
+    LPWSTR szwName = NULL, szwValueBuf = NULL;
+    UINT hr = ERROR_INSTALL_FAILURE;
+
+    if (0 == hInstall) {
+      return ERROR_INVALID_HANDLE;
+    }
+    if (NULL == szName) {
+      return ERROR_INVALID_PARAMETER;
+    }
+
+    TRACE("%lu %s %lu\n", hInstall, debugstr_a(szName), *pchValueBuf);
+
+    if (NULL != szValueBuf && NULL == pchValueBuf) {
+      return ERROR_INVALID_PARAMETER;
+    }
+    if( szName )
+    {
+        UINT len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
+        szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
+        if( !szwName )
+            goto end;
+        MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
+    } else {
+      return ERROR_INVALID_PARAMETER;
+    }
+    if( szValueBuf )
+    {
+        szwValueBuf = HeapAlloc( GetProcessHeap(), 0, (*pchValueBuf) * sizeof(WCHAR) );
+        if( !szwValueBuf )	 
+            goto end;
+    }
+
+    hr = MsiGetPropertyW( hInstall, szwName, szwValueBuf, pchValueBuf );
+
+    if(  *pchValueBuf > 0 )
+    {
+        WideCharToMultiByte(CP_ACP, 0, szwValueBuf, -1, szValueBuf, *pchValueBuf, NULL, NULL);
+    }
+
+end:
+    if( szwName )
+        HeapFree( GetProcessHeap(), 0, szwName );
+    if( szwValueBuf )
+        HeapFree( GetProcessHeap(), 0, szwValueBuf );
+
+    return hr;
+}
+
+UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName, 
+                           LPWSTR szValueBuf, DWORD* pchValueBuf)
+{
+    MSIHANDLE view,row;
+    UINT rc;
+    WCHAR Query[1024]=
+    {'s','e','l','e','c','t',' ','V','a','l','u','e',' ','f','r','o','m',' '
+     ,'_','P','r','o','p','e','r','t','y',' ','w','h','e','r','e',' '
+     ,'_','P','r','o','p','e','r','t','y','=','`',0};
+
+    static const WCHAR szEnd[]={'`',0};
+    MSIPACKAGE *package;
+
+    if (0 == hInstall) {
+      return ERROR_INVALID_HANDLE;
+    }
+    if (NULL == szName) {
+      return ERROR_INVALID_PARAMETER;
+    }
+
+    package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
+    if( !package)
+        return ERROR_INVALID_HANDLE;
+
+    strcatW(Query,szName);
+    strcatW(Query,szEnd);
+    
+    rc = MsiDatabaseOpenViewW(package->db, Query, &view);
+    if (rc == ERROR_SUCCESS)
+    {
+        DWORD sz;
+        WCHAR value[0x100];
+
+        rc = MsiViewExecute(view, 0);
+        if (rc != ERROR_SUCCESS)
+        {
+            MsiViewClose(view);
+            MsiCloseHandle(view);
+            return rc;
+        }
+
+        rc = MsiViewFetch(view,&row);
+        if (rc == ERROR_SUCCESS)
+        {
+            sz=0x100;
+            rc = MsiRecordGetStringW(row,1,value,&sz);
+            strncpyW(szValueBuf,value,min(sz+1,*pchValueBuf));
+            *pchValueBuf = sz+1;
+            MsiCloseHandle(row);
+        }
+        MsiViewClose(view);
+        MsiCloseHandle(view);
+    }
+
+    if (rc == ERROR_SUCCESS)
+        TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
+            debugstr_w(szName));
+    else
+    {
+        *pchValueBuf = 0;
+        TRACE("property not found\n");
+    }
+
+    return rc;
+}
+


More information about the wine-patches mailing list