Sync to Wine-20050930:
Aric Stewart <aric@codeweavers.com>
- Add the GUID for Patch files so that they can be opened as well. Looks
  like the database structure is pretty much the same.
- Implement MsiReinstallFeature.
- Be sure to null terminate the string in MsiGetProductInfoA after the
  W->A conversion using MsiGetProductInfoW if there is space.
- Added stub implementations for MsiEnumPatchesA/W.
Alexandre Julliard <julliard@winehq.org>
- We are no longer generating .dbg.c files.
- Use a more portable scheme for storing the name of a critical
  section.
- Get rid of a couple of non-portable long long constants.
- Fixed memory leak introduced in previous change.
- Avoid non-portable va_list manipulations.
Milko Krachounov <milko@3mhz.net>
- Bulgarian resources for mpr, msi, user, commdlg, oleaut32, shdocvw,
  shell32, comctl32, msrle32, mshtml, winspool, wineps, serialui,
  setupapi, wininet, regedit, uninstaller, notepad, winecfg and
  winhelp.
Jan Van Buggenhout <Chipzz@ULYSSIS.Org>
- implement stubs for MsiSequence[AW].
Dmitry Timoshkov <dmitry@codeweavers.com>
- COLOR_3DFACE is a better choice for the dialog background.
- Fix the usage of COLOR_xxx constants in the place of the window's
  class hbrBackground.
Mike McCormack <mike@codeweavers.com>
- Stub implementation of the RemoveIniValues action.
- Fix various memory leaks.
- Simplify the ProcessComponents action a little.
- Make build_icon_path return the path directly.
- Implement MsiSequenceA/W.
- Simplify the InstallValidate action a little.
- Added memory allocation inline functions (part 2).
- Fix a bug in a previous patch spotted by Dieter Komendera.
- Convert progids to a standard list.
- convert verbs into a standard list
- remove limitation of 100 verbs
- use pointers to verbs rather than indexes
- Rename load_dynamic_property and remove its unused 3rd argument.
- Create a macro to write a value to a subkey.
- Use the new msi_reg_set* macros where possible.
- Create a macro function to write registry values.
- fix a bug introduced by the progid list conversion
- make a fixme a little less alarmist
- Add objects to lists at the right time.
- Fix some simple memory leaks.
- Fix an error introduced when converting dialog lists to standard
  lists.
- Added memory allocation inline functions (part 1).
- Make sure not to free a a pointer that has been modified.
  Check that the text identifier doesn't contain invalid characters.
- Don't quote numbers in a query, as it doesn't parse correctly.
- Read the MaskEdit template from the correct db field.
- Don't create MSI handles unless we have to pass one through the API.
- Convert the list of dialog controls to a standard list.
- Deformat all dialog text strings before using them.
- Load riched20.dll on demand, and unload it after it's used (based on a
  patch by Rob Shearman).
- Make sure to release the package we grabbed on the error path.
- Fix and test MsiViewGetColumnInfo and binary fields.
- Skip dash characters in the PIDMask for a MaskedEdit control.
- Don't refcount tables.
- Fix an uninitialized variable problem.
- Fix memory leaks in the table code.
- Fix memory leaks.
- Remove some unused values in the object header.
- Fill out the stubs for MsiApplyTransformA/W a bit more.
- Fix various query related memory leaks.
- Make sure to set the minimum size before allocating string table
  memory.
- Don't include the terminating nul in the length in
  MsiSummaryInfoGetPropertyW.
- fix MsiSummaryInfoGetProperty to return ERROR_MORE_DATA if the
  buffer is too small (based on a patch by Aric Stewart)
- add a test case to show correct behaviour
- Create a function to determine the table's row size and use it.
  Fix a memory leak in the table code.
- Eliminate fixed length buffers from the MSIFEATURE structure.
- Fix more fixed length buffers.
- Reduce the indent level of a function.
- Allocate memory rather than using fixed length buffers.
- Remove an unnecessary level of indent.
- Keep temporary files in a seperate list.
- Rename ACTION_DoTopLevelINSTALL to MSI_InstallPackage, remove its
  duplicate 4th parameter.
  Split the code to copy a package into a separate function.
- Avoid fixed length buffers for conditions.
- Fix a memory leak.
- Create a function to read a property as an integer.
- Make some fixme messages less alarmist.
- Fix if's that are followed by semicolons.
- Add some more action stubs, remove forward declarations.
- Eliminate yet more fixed length buffers.
- Convert RunningActions array into a list.
- Split command line parsing from MSI_InstallPackage into a separate
  function.
- Move a fixed size buffer to the heap.
- Fix memory leaks in custom actions.
- Make a macro function for unimplemented actions.
  Add some more unimplemented action stubs.
- Make load_string_table return the string table.
- Stub implementation of the IsolateComponents action.
- Convert the list of tables to a standard list.
- Add a stub implementation of the BindImage action.
- Avoid UpdateWindow, it causes trouble with WS_EX_TRANSPARENT.
- Stub implementation of the PatchFiles action.
- Fix another memory leak.
- Add the progress control.
- Stub implementation of the MoveFiles action.
- Avoid using static variables in the InstallFiles action.
- Take advantage of the msi_get_deformatted_field function to simplify
  some code.
- Improve a fixme message a little.
- Skip the first character of a font identifier if it's \ or &.
- Make sure not to access invalid components or features.
- Fix the handling of MsiGetTargetPath args (with test case).
- Fix the handling of MsiDoAction args (with test case).
- Fixes for MsiGetSourcePath parameter handling.
- Load a table's column information separately from the table itself.
- Handle copying of the install package to a temporary file in one place
  only.
- Implement MsiGetShortcutTargetA.
- Fix the stub for MsiConfigureFeature.
Alexander N. Sørnes <alex@thehandofagony.com>
- Added Norwegian translations.
Kimmo Myllyvirta <kimmo.myllyvirta@gmail.com>
- Added Finnish resources.
Modified: trunk/reactos/lib/msi/action.c
Modified: trunk/reactos/lib/msi/action.h
Modified: trunk/reactos/lib/msi/appsearch.c
Modified: trunk/reactos/lib/msi/classes.c
Modified: trunk/reactos/lib/msi/cond.tab.c
Modified: trunk/reactos/lib/msi/cond.tab.h
Modified: trunk/reactos/lib/msi/cond.y
Modified: trunk/reactos/lib/msi/create.c
Modified: trunk/reactos/lib/msi/custom.c
Modified: trunk/reactos/lib/msi/database.c
Modified: trunk/reactos/lib/msi/delete.c
Modified: trunk/reactos/lib/msi/dialog.c
Modified: trunk/reactos/lib/msi/distinct.c
Modified: trunk/reactos/lib/msi/events.c
Modified: trunk/reactos/lib/msi/files.c
Modified: trunk/reactos/lib/msi/format.c
Modified: trunk/reactos/lib/msi/handle.c
Modified: trunk/reactos/lib/msi/helpers.c
Modified: trunk/reactos/lib/msi/insert.c
Modified: trunk/reactos/lib/msi/install.c
Modified: trunk/reactos/lib/msi/msi.c
Modified: trunk/reactos/lib/msi/msi.rc
Modified: trunk/reactos/lib/msi/msi.spec
Added: trunk/reactos/lib/msi/msi_Bg.rc
Modified: trunk/reactos/lib/msi/msi_En.rc
Added: trunk/reactos/lib/msi/msi_Fi.rc
Added: trunk/reactos/lib/msi/msi_No.rc
Modified: trunk/reactos/lib/msi/msi_Ru.rc
Modified: trunk/reactos/lib/msi/msipriv.h
Modified: trunk/reactos/lib/msi/msiquery.c
Modified: trunk/reactos/lib/msi/order.c
Modified: trunk/reactos/lib/msi/package.c
Modified: trunk/reactos/lib/msi/preview.c
Modified: trunk/reactos/lib/msi/record.c
Modified: trunk/reactos/lib/msi/registry.c
Modified: trunk/reactos/lib/msi/select.c
Modified: trunk/reactos/lib/msi/source.c
Modified: trunk/reactos/lib/msi/sql.tab.c
Modified: trunk/reactos/lib/msi/sql.tab.h
Modified: trunk/reactos/lib/msi/sql.y
Modified: trunk/reactos/lib/msi/string.c
Modified: trunk/reactos/lib/msi/suminfo.c
Modified: trunk/reactos/lib/msi/table.c
Modified: trunk/reactos/lib/msi/update.c
Modified: trunk/reactos/lib/msi/upgrade.c
Modified: trunk/reactos/lib/msi/version.rc
Modified: trunk/reactos/lib/msi/where.c
Modified: trunk/reactos/w32api/include/msiquery.h

Modified: trunk/reactos/lib/msi/action.c
--- trunk/reactos/lib/msi/action.c	2005-10-08 13:34:21 UTC (rev 18332)
+++ trunk/reactos/lib/msi/action.c	2005-10-08 13:45:19 UTC (rev 18333)
@@ -55,36 +55,6 @@
 static UINT ACTION_ProcessUISequence(MSIPACKAGE *package);
 static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI);
 
-/* 
- * action handlers
- */
-typedef UINT (*STANDARDACTIONHANDLER)(MSIPACKAGE*);
-
-static UINT ACTION_LaunchConditions(MSIPACKAGE *package);
-static UINT ACTION_CostInitialize(MSIPACKAGE *package);
-static UINT ACTION_CreateFolders(MSIPACKAGE *package);
-static UINT ACTION_CostFinalize(MSIPACKAGE *package);
-static UINT ACTION_FileCost(MSIPACKAGE *package);
-static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package);
-static UINT ACTION_InstallInitialize(MSIPACKAGE *package);
-static UINT ACTION_InstallValidate(MSIPACKAGE *package);
-static UINT ACTION_ProcessComponents(MSIPACKAGE *package);
-static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package);
-static UINT ACTION_RegisterUser(MSIPACKAGE *package);
-static UINT ACTION_CreateShortcuts(MSIPACKAGE *package);
-static UINT ACTION_PublishProduct(MSIPACKAGE *package);
-static UINT ACTION_WriteIniValues(MSIPACKAGE *package);
-static UINT ACTION_SelfRegModules(MSIPACKAGE *package);
-static UINT ACTION_PublishFeatures(MSIPACKAGE *package);
-static UINT ACTION_RegisterProduct(MSIPACKAGE *package);
-static UINT ACTION_InstallExecute(MSIPACKAGE *package);
-static UINT ACTION_InstallFinalize(MSIPACKAGE *package);
-static UINT ACTION_ForceReboot(MSIPACKAGE *package);
-static UINT ACTION_ResolveSource(MSIPACKAGE *package);
-static UINT ACTION_ExecuteAction(MSIPACKAGE *package);
-static UINT ACTION_RegisterFonts(MSIPACKAGE *package);
-static UINT ACTION_PublishComponents(MSIPACKAGE *package);
-
 /*
  * consts and values used
  */
@@ -262,89 +232,15 @@
     {'W','r','i','t','e','E','n','v','i','r','o','n','m','e','n','t',
             'S','t','r','i','n','g','s',0};
 
+/* action handlers */
+typedef UINT (*STANDARDACTIONHANDLER)(MSIPACKAGE*);
+
 struct _actions {
     LPCWSTR action;
     STANDARDACTIONHANDLER handler;
 };
 
-static struct _actions StandardActions[] = {
-    { szAllocateRegistrySpace, NULL},
-    { szAppSearch, ACTION_AppSearch },
-    { szBindImage, NULL},
-    { szCCPSearch, NULL},
-    { szCostFinalize, ACTION_CostFinalize },
-    { szCostInitialize, ACTION_CostInitialize },
-    { szCreateFolders, ACTION_CreateFolders },
-    { szCreateShortcuts, ACTION_CreateShortcuts },
-    { szDeleteServices, NULL},
-    { szDisableRollback, NULL},
-    { szDuplicateFiles, ACTION_DuplicateFiles },
-    { szExecuteAction, ACTION_ExecuteAction },
-    { szFileCost, ACTION_FileCost },
-    { szFindRelatedProducts, ACTION_FindRelatedProducts },
-    { szForceReboot, ACTION_ForceReboot },
-    { szInstallAdminPackage, NULL},
-    { szInstallExecute, ACTION_InstallExecute },
-    { szInstallExecuteAgain, ACTION_InstallExecute },
-    { szInstallFiles, ACTION_InstallFiles},
-    { szInstallFinalize, ACTION_InstallFinalize },
-    { szInstallInitialize, ACTION_InstallInitialize },
-    { szInstallSFPCatalogFile, NULL},
-    { szInstallValidate, ACTION_InstallValidate },
-    { szIsolateComponents, NULL},
-    { szLaunchConditions, ACTION_LaunchConditions },
-    { szMigrateFeatureStates, NULL},
-    { szMoveFiles, NULL},
-    { szMsiPublishAssemblies, NULL},
-    { szMsiUnpublishAssemblies, NULL},
-    { szInstallODBC, NULL},
-    { szInstallServices, NULL},
-    { szPatchFiles, NULL},
-    { szProcessComponents, ACTION_ProcessComponents },
-    { szPublishComponents, ACTION_PublishComponents },
-    { szPublishFeatures, ACTION_PublishFeatures },
-    { szPublishProduct, ACTION_PublishProduct },
-    { szRegisterClassInfo, ACTION_RegisterClassInfo },
-    { szRegisterComPlus, NULL},
-    { szRegisterExtensionInfo, ACTION_RegisterExtensionInfo },
-    { szRegisterFonts, ACTION_RegisterFonts },
-    { szRegisterMIMEInfo, ACTION_RegisterMIMEInfo },
-    { szRegisterProduct, ACTION_RegisterProduct },
-    { szRegisterProgIdInfo, ACTION_RegisterProgIdInfo },
-    { szRegisterTypeLibraries, ACTION_RegisterTypeLibraries },
-    { szRegisterUser, ACTION_RegisterUser},
-    { szRemoveDuplicateFiles, NULL},
-    { szRemoveEnvironmentStrings, NULL},
-    { szRemoveExistingProducts, NULL},
-    { szRemoveFiles, NULL},
-    { szRemoveFolders, NULL},
-    { szRemoveIniValues, NULL},
-    { szRemoveODBC, NULL},
-    { szRemoveRegistryValues, NULL},
-    { szRemoveShortcuts, NULL},
-    { szResolveSource, ACTION_ResolveSource},
-    { szRMCCPSearch, NULL},
-    { szScheduleReboot, NULL},
-    { szSelfRegModules, ACTION_SelfRegModules },
-    { szSelfUnregModules, NULL},
-    { szSetODBCFolders, NULL},
-    { szStartServices, NULL},
-    { szStopServices, NULL},
-    { szUnpublishComponents, NULL},
-    { szUnpublishFeatures, NULL},
-    { szUnregisterClassInfo, NULL},
-    { szUnregisterComPlus, NULL},
-    { szUnregisterExtensionInfo, NULL},
-    { szUnregisterFonts, NULL},
-    { szUnregisterMIMEInfo, NULL},
-    { szUnregisterProgIdInfo, NULL},
-    { szUnregisterTypeLibraries, NULL},
-    { szValidateProductID, NULL},
-    { szWriteEnvironmentStrings, NULL},
-    { szWriteIniValues, ACTION_WriteIniValues },
-    { szWriteRegistryValues, ACTION_WriteRegistryValues},
-    { NULL, NULL},
-};
+static struct _actions StandardActions[];
 
 
 /********************************************************
@@ -399,7 +295,7 @@
  
     MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONSTART, row);
     msiobj_release(&row->hdr);
-    HeapFree(GetProcessHeap(),0,deformated);
+    msi_free(deformated);
 }
 
 static void ui_actioninfo(MSIPACKAGE *package, LPCWSTR action, BOOL start, 
@@ -431,15 +327,90 @@
     msiobj_release(&row->hdr);
 }
 
+static int msi_get_property_int( MSIPACKAGE *package, LPCWSTR prop, int def )
+{
+    LPWSTR str = msi_dup_property( package, prop );
+    int val = str ? atoiW( str ) : def;
+    msi_free( str );
+    return val;
+}
+
+static UINT msi_parse_command_line( MSIPACKAGE *package, LPCWSTR szCommandLine )
+{
+    LPCWSTR ptr,ptr2;
+    BOOL quote;
+    DWORD len;
+    LPWSTR prop = NULL, val = NULL;
+
+    if (!szCommandLine)
+        return ERROR_SUCCESS;
+
+    ptr = szCommandLine;
+       
+    while (*ptr)
+    {
+        if (*ptr==' ')
+        {
+            ptr++;
+            continue;
+        }
+
+        TRACE("Looking at %s\n",debugstr_w(ptr));
+
+        ptr2 = strchrW(ptr,'=');
+        if (!ptr2)
+        {
+            ERR("command line contains unknown string : %s\n", debugstr_w(ptr));
+            break;
+        }
+ 
+        quote = FALSE;
+
+        len = ptr2-ptr;
+        prop = msi_alloc((len+1)*sizeof(WCHAR));
+        memcpy(prop,ptr,len*sizeof(WCHAR));
+        prop[len]=0;
+        ptr2++;
+       
+        len = 0; 
+        ptr = ptr2; 
+        while (*ptr && (quote || (!quote && *ptr!=' ')))
+        {
+            if (*ptr == '"')
+                quote = !quote;
+            ptr++;
+            len++;
+        }
+       
+        if (*ptr2=='"')
+        {
+            ptr2++;
+            len -= 2;
+        }
+        val = msi_alloc((len+1)*sizeof(WCHAR));
+        memcpy(val,ptr2,len*sizeof(WCHAR));
+        val[len] = 0;
+
+        if (lstrlenW(prop) > 0)
+        {
+            TRACE("Found commandline property (%s) = (%s)\n", 
+                   debugstr_w(prop), debugstr_w(val));
+            MSI_SetPropertyW(package,prop,val);
+        }
+        msi_free(val);
+        msi_free(prop);
+    }
+
+    return ERROR_SUCCESS;
+}
+
 /****************************************************
  * TOP level entry points 
  *****************************************************/
 
-UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath,
-                              LPCWSTR szCommandLine, LPCWSTR msiFilePath)
+UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
+                         LPCWSTR szCommandLine )
 {
-    DWORD sz;
-    WCHAR buffer[10];
     UINT rc;
     BOOL ui = FALSE;
     static const WCHAR szUILevel[] = {'U','I','L','e','v','e','l',0};
@@ -448,13 +419,11 @@
 
     MSI_SetPropertyW(package, szAction, szInstall);
 
-    package->script = HeapAlloc(GetProcessHeap(),0,sizeof(MSISCRIPT));
+    package->script = msi_alloc(sizeof(MSISCRIPT));
     memset(package->script,0,sizeof(MSISCRIPT));
 
     package->script->InWhatSequence = SEQUENCE_INSTALL;
 
-    package->msiFilePath= strdupW(msiFilePath);
-
     if (szPackagePath)   
     {
         LPWSTR p, check, path;
@@ -469,94 +438,31 @@
         }
         else
         {
-            HeapFree(GetProcessHeap(),0,path);
-            path = HeapAlloc(GetProcessHeap(),0,MAX_PATH*sizeof(WCHAR));
+            msi_free(path);
+            path = msi_alloc(MAX_PATH*sizeof(WCHAR));
             GetCurrentDirectoryW(MAX_PATH,path);
             strcatW(path,cszbs);
         }
 
-        check = load_dynamic_property(package, cszSourceDir,NULL);
+        check = msi_dup_property( package, cszSourceDir );
         if (!check)
             MSI_SetPropertyW(package, cszSourceDir, path);
-        else
-            HeapFree(GetProcessHeap(), 0, check);
-
-        HeapFree(GetProcessHeap(), 0, path);
+        msi_free(check);
+        msi_free(path);
     }
 
-    if (szCommandLine)
-    {
-        LPWSTR ptr,ptr2;
-        ptr = (LPWSTR)szCommandLine;
-       
-        while (*ptr)
-        {
-            WCHAR *prop = NULL;
-            WCHAR *val = NULL;
+    msi_parse_command_line( package, szCommandLine );
 
-            TRACE("Looking at %s\n",debugstr_w(ptr));
-
-            ptr2 = strchrW(ptr,'=');
-            if (ptr2)
-            {
-                BOOL quote=FALSE;
-                DWORD len = 0;
-
-                while (*ptr == ' ') ptr++;
-                len = ptr2-ptr;
-                prop = HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
-                memcpy(prop,ptr,len*sizeof(WCHAR));
-                prop[len]=0;
-                ptr2++;
-           
-                len = 0; 
-                ptr = ptr2; 
-                while (*ptr && (quote || (!quote && *ptr!=' ')))
-                {
-                    if (*ptr == '"')
-                        quote = !quote;
-                    ptr++;
-                    len++;
-                }
-               
-                if (*ptr2=='"')
-                {
-                    ptr2++;
-                    len -= 2;
-                }
-                val = HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
-                memcpy(val,ptr2,len*sizeof(WCHAR));
-                val[len] = 0;
-
-                if (strlenW(prop) > 0)
-                {
-                    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++;
-        }
-    }
-  
-    sz = 10; 
-    if (MSI_GetPropertyW(package,szUILevel,buffer,&sz) == ERROR_SUCCESS)
+    if ( msi_get_property_int(package, szUILevel, 0) >= INSTALLUILEVEL_REDUCED )
     {
-        if (atoiW(buffer) >= INSTALLUILEVEL_REDUCED)
+        package->script->InWhatSequence |= SEQUENCE_UI;
+        rc = ACTION_ProcessUISequence(package);
+        ui = TRUE;
+        if (rc == ERROR_SUCCESS)
         {
-            package->script->InWhatSequence |= SEQUENCE_UI;
-            rc = ACTION_ProcessUISequence(package);
-            ui = TRUE;
-            if (rc == ERROR_SUCCESS)
-            {
-                package->script->InWhatSequence |= SEQUENCE_EXEC;
-                rc = ACTION_ProcessExecSequence(package,TRUE);
-            }
+            package->script->InWhatSequence |= SEQUENCE_EXEC;
+            rc = ACTION_ProcessExecSequence(package,TRUE);
         }
-        else
-            rc = ACTION_ProcessExecSequence(package,FALSE);
     }
     else
         rc = ACTION_ProcessExecSequence(package,FALSE);
@@ -692,6 +598,40 @@
     return rc;
 }
 
+UINT MSI_Sequence( MSIPACKAGE *package, LPCWSTR szTable, INT iSequenceMode )
+{
+    MSIQUERY * view;
+    UINT r;
+    static const WCHAR query[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','%','s','`',
+         ' ','W','H','E','R','E',' ', 
+         '`','S','e','q','u','e','n','c','e','`',' ',
+         '>',' ','0',' ','O','R','D','E','R',' ','B','Y',' ',
+         '`','S','e','q','u','e','n','c','e','`',0};
+    iterate_action_param iap;
+
+    /*
+     * FIXME: probably should be checking UILevel in the
+     *       ACTION_PerformUIAction/ACTION_PerformAction
+     *       rather than saving the UI level here. Those
+     *       two functions can be merged too.
+     */
+    iap.package = package;
+    iap.UI = TRUE;
+
+    TRACE("%p %s %i\n", package, debugstr_w(szTable), iSequenceMode );
+
+    r = MSI_OpenQuery( package->db, &view, query, szTable );
+    if (r == ERROR_SUCCESS)
+    {
+        r = MSI_IterateRecords( view, NULL, ITERATE_Actions, &iap );
+        msiobj_release(&view->hdr);
+    }
+
+    return r;
+}
+
 static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran)
 {
     MSIQUERY * view;
@@ -818,7 +758,7 @@
                 }
                 else
                 {
-                    FIXME("UNHANDLED Standard Action %s\n",debugstr_w(action));
+                    FIXME("unhandled standard action %s\n",debugstr_w(action));
                     *rc = ERROR_SUCCESS;
                 }
             }
@@ -868,7 +808,7 @@
 
     if (!handled)
     {
-        FIXME("UNHANDLED MSI ACTION %s\n",debugstr_w(action));
+        FIXME("unhandled msi action %s\n",debugstr_w(action));
         rc = ERROR_FUNCTION_NOT_CALLED;
     }
 
@@ -892,7 +832,7 @@
 
     if (!handled)
     {
-        FIXME("UNHANDLED MSI ACTION %s\n",debugstr_w(action));
+        FIXME("unhandled msi action %s\n",debugstr_w(action));
         rc = ERROR_FUNCTION_NOT_CALLED;
     }
 
@@ -939,7 +879,7 @@
 
     folder->State = 3;
 
-    HeapFree(GetProcessHeap(),0,full_path);
+    msi_free(full_path);
     return ERROR_SUCCESS;
 }
 
@@ -971,34 +911,22 @@
 static MSICOMPONENT* load_component( MSIRECORD * row )
 {
     MSICOMPONENT *comp;
-    DWORD sz;
 
-    comp = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MSICOMPONENT) );
+    comp = msi_alloc_zero( sizeof(MSICOMPONENT) );
     if (!comp)
         return comp;
 
     /* fill in the data */
-    sz = IDENTIFIER_SIZE;       
-    MSI_RecordGetStringW(row,1,comp->Component,&sz);
+    comp->Component = load_dynamic_stringW( row, 1 );
 
-    TRACE("Loading Component %s\n",
-           debugstr_w(comp->Component));
+    TRACE("Loading Component %s\n", debugstr_w(comp->Component));
 
-    sz = 0x100;
-    if (!MSI_RecordIsNull(row,2))
-        MSI_RecordGetStringW(row,2,comp->ComponentId,&sz);
-            
-    sz = IDENTIFIER_SIZE;       
-    MSI_RecordGetStringW(row,3,comp->Directory,&sz);
-
+    comp->ComponentId = load_dynamic_stringW( row, 2 );
+    comp->Directory = load_dynamic_stringW( row, 3 );
     comp->Attributes = MSI_RecordGetInteger(row,4);
+    comp->Condition = load_dynamic_stringW( row, 5 );
+    comp->KeyPath = load_dynamic_stringW( row, 6 );
 
-    sz = 0x100;       
-    MSI_RecordGetStringW(row,5,comp->Condition,&sz);
-
-    sz = IDENTIFIER_SIZE;       
-    MSI_RecordGetStringW(row,6,comp->KeyPath,&sz);
-
     comp->Installed = INSTALLSTATE_ABSENT;
     comp->Action = INSTALLSTATE_UNKNOWN;
     comp->ActionRequest = INSTALLSTATE_UNKNOWN;
@@ -1017,7 +945,7 @@
 {
     ComponentList *cl;
 
-    cl = HeapAlloc( GetProcessHeap(), 0, sizeof (*cl) );
+    cl = msi_alloc( sizeof (*cl) );
     if ( !cl )
         return ERROR_NOT_ENOUGH_MEMORY;
     cl->component = comp;
@@ -1084,7 +1012,6 @@
 {
     MSIPACKAGE* package = (MSIPACKAGE*)param;
     MSIFEATURE* feature;
-    DWORD sz;
     static const WCHAR Query1[] = 
         {'S','E','L','E','C','T',' ',
          '`','C','o','m','p','o','n','e','n','t','_','`',
@@ -1098,38 +1025,25 @@
 
     /* fill in the data */
 
-    feature = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (MSIFEATURE) );
+    feature = msi_alloc_zero( sizeof (MSIFEATURE) );
     if (!feature)
         return ERROR_NOT_ENOUGH_MEMORY;
 
     list_init( &feature->Components );
     
-    sz = IDENTIFIER_SIZE;       
-    MSI_RecordGetStringW(row,1,feature->Feature,&sz);
+    feature->Feature = load_dynamic_stringW( row, 1 );
 
     TRACE("Loading feature %s\n",debugstr_w(feature->Feature));
 
-    sz = IDENTIFIER_SIZE;
-    if (!MSI_RecordIsNull(row,2))
-        MSI_RecordGetStringW(row,2,feature->Feature_Parent,&sz);
+    feature->Feature_Parent = load_dynamic_stringW( row, 2 );
+    feature->Title = load_dynamic_stringW( row, 3 );
+    feature->Description = load_dynamic_stringW( row, 4 );
 
-    sz = 0x100;
-    if (!MSI_RecordIsNull(row,3))
-        MSI_RecordGetStringW(row,3,feature->Title,&sz);
-
-    sz = 0x100;
-    if (!MSI_RecordIsNull(row,4))
-        MSI_RecordGetStringW(row,4,feature->Description,&sz);
-
     if (!MSI_RecordIsNull(row,5))
         feature->Display = MSI_RecordGetInteger(row,5);
   
     feature->Level= MSI_RecordGetInteger(row,6);
-
-    sz = IDENTIFIER_SIZE;
-    if (!MSI_RecordIsNull(row,7))
-        MSI_RecordGetStringW(row,7,feature->Directory,&sz);
-
+    feature->Directory = load_dynamic_stringW( row, 7 );
     feature->Attributes = MSI_RecordGetInteger(row,8);
 
     feature->Installed = INSTALLSTATE_ABSENT;
@@ -1161,7 +1075,7 @@
 
     /* fill in the data */
 
-    file = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (MSIFILE) );
+    file = msi_alloc_zero( sizeof (MSIFILE) );
     if (!file)
         return ERROR_NOT_ENOUGH_MEMORY;
  
@@ -1185,7 +1099,6 @@
     file->Attributes = MSI_RecordGetInteger( row, 7 );
     file->Sequence = MSI_RecordGetInteger( row, 8 );
 
-    file->Temporary = FALSE;
     file->State = 0;
 
     TRACE("File Loaded (%s)\n",debugstr_w(file->File));  
@@ -1277,11 +1190,11 @@
         ui_actionstart(package, action);
         TRACE("Executing Action (%s)\n",debugstr_w(action));
         rc = ACTION_PerformAction(package, action, TRUE);
-        HeapFree(GetProcessHeap(),0,package->script->Actions[script][i]);
+        msi_free(package->script->Actions[script][i]);
         if (rc != ERROR_SUCCESS)
             break;
     }
-    HeapFree(GetProcessHeap(),0,package->script->Actions[script]);
+    msi_free(package->script->Actions[script]);
 
     package->script->ActionCount[script] = 0;
     package->script->Actions[script] = NULL;
@@ -1316,7 +1229,7 @@
 
     TRACE("Working to load %s\n",debugstr_w(dir));
 
-    folder = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (MSIFOLDER) );
+    folder = msi_alloc_zero( sizeof (MSIFOLDER) );
     if (!folder)
         return NULL;
 
@@ -1360,7 +1273,7 @@
     if (targetdir)
     {
         TRACE("   TargetDefault = %s\n",debugstr_w(targetdir));
-        HeapFree(GetProcessHeap(),0, folder->TargetDefault);
+        msi_free( folder->TargetDefault);
         folder->TargetDefault = strdupW(targetdir);
     }
 
@@ -1370,7 +1283,7 @@
         folder->SourceDefault = strdupW(shortname);
     else if (targetdir)
         folder->SourceDefault = strdupW(targetdir);
-    HeapFree(GetProcessHeap(), 0, ptargetdir);
+    msi_free(ptargetdir);
         TRACE("   SourceDefault = %s\n", debugstr_w( folder->SourceDefault ));
 
     parent = MSI_RecordGetString(row,2);
@@ -1384,7 +1297,7 @@
             ERR("failed to load parent folder %s\n", debugstr_w(parent));
     }
 
-    folder->Property = load_dynamic_property( package, dir, NULL );
+    folder->Property = msi_dup_property( package, dir );
 
     msiobj_release(&row->hdr);
 
@@ -1439,56 +1352,52 @@
                                     INSTALLSTATE state)
 {
     static const WCHAR all[]={'A','L','L',0};
-    LPWSTR override = NULL;
-    BOOL rc = FALSE;
+    LPWSTR override;
     MSIFEATURE *feature;
 
-    override = load_dynamic_property(package, property, NULL);
-    if (override)
+    override = msi_dup_property( package, property );
+    if (!override)
+        return FALSE;
+ 
+    LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
     {
-        rc = TRUE;
-        LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
+        if (strcmpiW(override,all)==0)
         {
-            if (strcmpiW(override,all)==0)
+            feature->ActionRequest= state;
+            feature->Action = state;
+        }
+        else
+        {
+            LPWSTR ptr = override;
+            LPWSTR ptr2 = strchrW(override,',');
+
+            while (ptr)
             {
-                feature->ActionRequest= state;
-                feature->Action = state;
-            }
-            else
-            {
-                LPWSTR ptr = override;
-                LPWSTR ptr2 = strchrW(override,',');
-
-                while (ptr)
+                if ((ptr2 && strncmpW(ptr,feature->Feature, ptr2-ptr)==0)
+                    || (!ptr2 && strcmpW(ptr,feature->Feature)==0))
                 {
-                    if ((ptr2 && 
-                        strncmpW(ptr,feature->Feature, ptr2-ptr)==0)
-                        || (!ptr2 && strcmpW(ptr,feature->Feature)==0))
-                    {
-                        feature->ActionRequest= state;
-                        feature->Action = state;
-                        break;
-                    }
-                    if (ptr2)
-                    {
-                        ptr=ptr2+1;
-                        ptr2 = strchrW(ptr,',');
-                    }
-                    else
-                        break;
+                    feature->ActionRequest= state;
+                    feature->Action = state;
+                    break;
                 }
+                if (ptr2)
+                {
+                    ptr=ptr2+1;
+                    ptr2 = strchrW(ptr,',');
+                }
+                else
+                    break;
             }
         }
-        HeapFree(GetProcessHeap(),0,override);
     } 
+    msi_free(override);
 
-    return rc;
+    return TRUE;
 }
 
 static UINT SetFeatureStates(MSIPACKAGE *package)
 {
-    LPWSTR level;
-    INT install_level;
+    int install_level;
     static const WCHAR szlevel[] =
         {'I','N','S','T','A','L','L','L','E','V','E','L',0};
     static const WCHAR szAddLocal[] =
@@ -1504,14 +1413,7 @@
 
     TRACE("Checking Install Level\n");
 
-    level = load_dynamic_property(package,szlevel,NULL);
-    if (level)
-    {
-        install_level = atoiW(level);
-        HeapFree(GetProcessHeap(), 0, level);
-    }
-    else
-        install_level = 1;
+    install_level = msi_get_property_int( package, szlevel, 1 );
 
     /* ok hereis the _real_ rub
      * all these activation/deactivation things happen in order and things
@@ -1659,7 +1561,7 @@
     load_folder(package,name);
     path = resolve_folder(package,name,FALSE,TRUE,NULL);
     TRACE("resolves to %s\n",debugstr_w(path));
-    HeapFree( GetProcessHeap(), 0, path);
+    msi_free(path);
 
     return ERROR_SUCCESS;
 }
@@ -1736,81 +1638,74 @@
 
     LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
     {
-        MSICOMPONENT* comp = NULL;
+        MSICOMPONENT* comp = file->Component;
+        LPWSTR p;
 
-        comp = file->Component;
-
-        if (file->Temporary == TRUE)
+        if (!comp)
             continue;
 
-        if (comp)
-        {
-            LPWSTR p;
+        /* calculate target */
+        p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL);
 
-            /* calculate target */
-            p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL);
+        msi_free(file->TargetPath);
 
-            HeapFree(GetProcessHeap(),0,file->TargetPath);
+        TRACE("file %s is named %s\n",
+               debugstr_w(file->File),debugstr_w(file->FileName));       
 
-            TRACE("file %s is named %s\n",
-                   debugstr_w(file->File),debugstr_w(file->FileName));       
+        file->TargetPath = build_directory_name(2, p, file->FileName);
 
-            file->TargetPath = build_directory_name(2, p, file->FileName);
+        msi_free(p);
 
-            HeapFree(GetProcessHeap(),0,p);
+        TRACE("file %s resolves to %s\n",
+               debugstr_w(file->File),debugstr_w(file->TargetPath));       
 
-            TRACE("file %s resolves to %s\n",
-                   debugstr_w(file->File),debugstr_w(file->TargetPath));       
+        if (GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES)
+        {
+            file->State = 1;
+            comp->Cost += file->FileSize;
+            continue;
+        }
 
-            if (GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES)
-            {
-                file->State = 1;
-                comp->Cost += file->FileSize;
-            }
-            else
-            {
-                if (file->Version)
-                {
-                    DWORD handle;
-                    DWORD versize;
-                    UINT sz;
-                    LPVOID version;
-                    static const WCHAR name[] = 
-                        {'\\',0};
-                    static const WCHAR name_fmt[] = 
-                        {'%','u','.','%','u','.','%','u','.','%','u',0};
-                    WCHAR filever[0x100];
-                    VS_FIXEDFILEINFO *lpVer;
+        if (file->Version)
+        {
+            DWORD handle;
+            DWORD versize;
+            UINT sz;
+            LPVOID version;
+            static const WCHAR name[] = 
+                {'\\',0};
+            static const WCHAR name_fmt[] = 
+                {'%','u','.','%','u','.','%','u','.','%','u',0};
+            WCHAR filever[0x100];
+            VS_FIXEDFILEINFO *lpVer;
 
-                    TRACE("Version comparison.. \n");
-                    versize = GetFileVersionInfoSizeW(file->TargetPath,&handle);
-                    version = HeapAlloc(GetProcessHeap(),0,versize);
-                    GetFileVersionInfoW(file->TargetPath, 0, versize, version);
+            TRACE("Version comparison.. \n");
+            versize = GetFileVersionInfoSizeW(file->TargetPath,&handle);
+            version = msi_alloc(versize);
+            GetFileVersionInfoW(file->TargetPath, 0, versize, version);
 
-                    VerQueryValueW(version, (LPWSTR)name, (LPVOID*)&lpVer, &sz);
+            VerQueryValueW(version, (LPWSTR)name, (LPVOID*)&lpVer, &sz);
 
-                    sprintfW(filever,name_fmt,
-                        HIWORD(lpVer->dwFileVersionMS),
-                        LOWORD(lpVer->dwFileVersionMS),
-                        HIWORD(lpVer->dwFileVersionLS),
-                        LOWORD(lpVer->dwFileVersionLS));
+            sprintfW(filever,name_fmt,
+                HIWORD(lpVer->dwFileVersionMS),
+                LOWORD(lpVer->dwFileVersionMS),
+                HIWORD(lpVer->dwFileVersionLS),
+                LOWORD(lpVer->dwFileVersionLS));
 
-                    TRACE("new %s old %s\n", debugstr_w(file->Version),
-                          debugstr_w(filever));
-                    if (strcmpiW(filever,file->Version)<0)
-                    {
-                        file->State = 2;
-                        FIXME("cost should be diff in size\n");
-                        comp->Cost += file->FileSize;
-                    }
-                    else
-                        file->State = 3;
-                    HeapFree(GetProcessHeap(),0,version);
-                }
-                else
-                    file->State = 3;
+            TRACE("new %s old %s\n", debugstr_w(file->Version),
+                  debugstr_w(filever));
+            if (strcmpiW(filever,file->Version)<0)
+            {
+                file->State = 2;
+                FIXME("cost should be diff in size\n");
+                comp->Cost += file->FileSize;
             }
-        } 
+            else
+                file->State = 3;
+            msi_free(version);
+        }
+        else
+            file->State = 3;
     }
 
     TRACE("Evaluating Condition Table\n");
@@ -1826,7 +1721,7 @@
     TRACE("Enabling or Disabling Components\n");
     LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
     {
-        if (comp->Condition[0])
+        if (comp->Condition)
         {
             if (MSI_EvaluateConditionW(package,
                 comp->Condition) == MSICONDITION_FALSE)
@@ -1839,11 +1734,10 @@
 
     MSI_SetPropertyW(package,szCosting,szOne);
     /* set default run level if not set */
-    level = load_dynamic_property(package,szlevel,NULL);
+    level = msi_dup_property( package, szlevel );
     if (!level)
         MSI_SetPropertyW(package,szlevel, szOne);
-    else
-        HeapFree(GetProcessHeap(),0,level);
+    msi_free(level);
 
     ACTION_UpdateInstallStates(package);
 
@@ -1875,7 +1769,7 @@
             else
                 *size = strlenW(ptr)/2;
 
-            data = HeapAlloc(GetProcessHeap(),0,*size);
+            data = msi_alloc(*size);
 
             byte[0] = '0'; 
             byte[1] = 'x'; 
@@ -1900,7 +1794,7 @@
                 data[count] = (BYTE)strtol(byte,NULL,0);
                 count ++;
             }
-            HeapFree(GetProcessHeap(),0,deformated);
+            msi_free(deformated);
 
             TRACE("Data %li bytes(%i)\n",*size,count);
         }
@@ -1913,7 +1807,7 @@
 
             *type=REG_DWORD; 
             *size = sizeof(DWORD);
-            data = HeapAlloc(GetProcessHeap(),0,*size);
+            data = msi_alloc(*size);
             p = deformated;
             if (*p == '-')
                 p++;
@@ -1930,7 +1824,7 @@
             *(LPDWORD)data = d;
             TRACE("DWORD %li\n",*(LPDWORD)data);
 
-            HeapFree(GetProcessHeap(),0,deformated);
+            msi_free(deformated);
         }
     }
     else
@@ -2032,7 +1926,7 @@
         case -1: 
             {
                 static const WCHAR szALLUSER[] = {'A','L','L','U','S','E','R','S',0};
-                LPWSTR all_users = load_dynamic_property(package, szALLUSER, NULL);
+                LPWSTR all_users = msi_dup_property( package, szALLUSER );
                 if (all_users && all_users[0] == '1')
                 {
                     root_key = HKEY_LOCAL_MACHINE;
@@ -2043,7 +1937,7 @@
                     root_key = HKEY_CURRENT_USER;
                     szRoot = szHCU;
                 }
-                HeapFree(GetProcessHeap(),0,all_users);
+                msi_free(all_users);
             }
                  break;
         case 0:  root_key = HKEY_CLASSES_ROOT; 
@@ -2069,18 +1963,18 @@
 
     deformat_string(package, key , &deformated);
     size = strlenW(deformated) + strlenW(szRoot) + 1;
-    uikey = HeapAlloc(GetProcessHeap(), 0, size*sizeof(WCHAR));
+    uikey = msi_alloc(size*sizeof(WCHAR));
     strcpyW(uikey,szRoot);
     strcatW(uikey,deformated);
 
     if (RegCreateKeyW( root_key, deformated, &hkey))
     {
         ERR("Could not create key %s\n",debugstr_w(deformated));
-        HeapFree(GetProcessHeap(),0,deformated);
-        HeapFree(GetProcessHeap(),0,uikey);
+        msi_free(deformated);
+        msi_free(uikey);
         return ERROR_SUCCESS;
     }
-    HeapFree(GetProcessHeap(),0,deformated);
+    msi_free(deformated);
 
     value = MSI_RecordGetString(row,5);
     if (value)
@@ -2136,9 +2030,9 @@
     ui_actiondata(package,szWriteRegistryValues,uirow);
     msiobj_release( &uirow->hdr );
 
-    HeapFree(GetProcessHeap(),0,value_data);
-    HeapFree(GetProcessHeap(),0,deformated);
-    HeapFree(GetProcessHeap(),0,uikey);
+    msi_free(value_data);
+    msi_free(deformated);
+    msi_free(uikey);
 
     return ERROR_SUCCESS;
 }
@@ -2185,47 +2079,25 @@
          '`','R','e','g','i','s','t','r','y','`',0};
     UINT rc;
     MSIQUERY * view;
-    MSIRECORD * row = 0;
     MSIFEATURE *feature;
     MSIFILE *file;
 
-    TRACE(" InstallValidate \n");
+    TRACE("InstallValidate\n");
 
     rc = MSI_DatabaseOpenViewW(package->db, q1, &view);
-    if (rc != ERROR_SUCCESS)
-        return ERROR_SUCCESS;
-
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
+    if (rc == ERROR_SUCCESS)
     {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
+        MSI_IterateRecords( view, &progress, NULL, package );
+        msiobj_release( &view->hdr );
+        total += progress * REG_PROGRESS_VALUE;
     }
-    while (1)
-    {
-        rc = MSI_ViewFetch(view,&row);
[truncated at 1000 lines; 19151 more skipped]