Sync to Wine-0_9_1:
Ivan Leo Puoti <ivanleo@gmail.com>
- Fix some wrong prototypes.
Thomas Weidenmueller <wine-patches@reactsoft.com>
- Passing NULL as the last two parameters to ReadFile is illegal and
  actually causes a crash on windows. The attached patch fixes this.
Aric Stewart <aric@codeweavers.com>
- Force files to install if the REINSTALL property is set.
Mike McCormack <mike@codeweavers.com>
- Some installers don't call the CreateFolders action before the
  InstallFiles action as MSDN specifies, but it still seems to work, so
  make sure that we create component directories in the InstallFiles
  action anyway.
- Create component folders in the CreateFolders action.
- If an action fails, print out its name as well as the error code.  Use
  %d for error codes so it's easy to match them up to something in
  winerror.h.
- Rename load_dynamic_stringW to msi_dup_record_field to better describe
  what it does, and replace a few instances with MSI_RecordGetString to
  avoid allocating memory.
- Tidy up the RegisterProduct action a little.
- Create a stub function to apply a single table transform and call it
  where we need to apply transforms.
- Enumerate the substorage transforms for any patches that are passed on
  the command line with PATCH=.  Need to implement
  table_apply_transform() before this will do anything interesting.
- Simplify register_progid() and remove a fixed length buffer.
- Make enter and escape trigger the default and cancel buttons in
  dialogs.
- Switch back to using IPicture to load images.  LoadImage did the
  resizing for us, but doesn't handle jpeg files and requires us writing
  a temp file, whereas IPicture handles jpeg files and can load directly
  from a stream.
- Remove unused package parameter of register_progid_base().
- Remove an incorrect comment and check for 0 being an invalid file
  handle.
- Add missing semicolons that caused compile trouble on FreeBSD.
- Extract file directly to their target location, bypassing the need to
  use temporary files and move files.
- Put the UI update code for cabinet file into a separate function.
- Translate INVALID_HANDLE_VALUE to zero for cabinet handles.
- Fix a memory leak in the cabinet extracting code.
- Fix passing of NULL pointers to MsiDecomposeDescriptor and add a
  test.
- Fix parameter handling in MsiSetTargetPath, and add a test for it.
- Deleted two buggy functions that incorrectly and inefficiently check
  whether a row already exists in a table, and replaced them with a call
  to an existing working function that does the same thing correctly.
- Fix and test MsiGetProperty and MsiSetProperty.
- Add a stub implementation of msi.MsiSetMode.
- NULL and empty strings are the same in conditions.
- Add a bunch of tests for MsiEvaluateCondition and make them pass.
- Fix error handling in MsiEvaluateCondition.
- Create the +msidb debug channel for msi database code.
- Implement transforms.  This still includes some debugging code which
  can be enabled by setting debug_transform to 1 in the relevant
  places.
- Define NONAMELESSUNION and NONAMELESSSTRUCT for older compilers.
- Remove some redundant null pointer checks.
- Make sure to unregister all the classes that were registered when msi
  is unloaded, so we can register again cleanly.
- Fix a memory leak.
- Implement the RemoveFiles action.
- Add a read-only implementation of the SelectionTree control.
- Make sure we only CoUninitialize after successfully initializing.
  Fix the address of the returned IShellLinkDataList interface.
- Use an enumeration for file states.
- Handle MaskEdit masks containing dashes and other constant
  characters.
- Stub implementation for MsiAdvertiseScriptA/W.
- Add a stub for the AllocateRegistrySpace action.
- Explicitly check for MSICONDITION_TRUE being returned from
  MsiEvaluateCondition.
- Stub implementation for MsiGetFileHashA/W.
- Define MSIDBOPEN_ constants using LPCWSTR when compiling Wine.
- Improve MsiUseFeatureEx and MsiGetFeatureState a little, add some
  simple test cases.
- Use msi_get_property_int() in a few more places.
- Implement MsiGetFeatureUsageA and MsiUseFeature(Ex)A using their W
  versions.
- Use "static const" rather than "const static" as gcc -W complains
  about the former.
- Add an implementation for MsiGetShortcutTargetA/W.
- Don't change the UI level during ExecuteAction.
- Return an error in MsiGetComponentPathW if passed a null component.
- Remove the unused 1st parameter of ACTION_VerifyComponentForAction.
- Fix MsiGetPropertyA/W spec declarations.
- Create an internal handle-free api for reading MSI database summary
  information.
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.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/files.c
Modified: trunk/reactos/lib/msi/format.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_Ko.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/record.c
Modified: trunk/reactos/lib/msi/registry.c
Modified: trunk/reactos/lib/msi/select.c
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/where.c
Modified: trunk/reactos/w32api/include/msi.h
Modified: trunk/reactos/w32api/include/msiquery.h

Modified: trunk/reactos/lib/msi/action.c
--- trunk/reactos/lib/msi/action.c	2005-11-17 20:33:50 UTC (rev 19306)
+++ trunk/reactos/lib/msi/action.c	2005-11-17 20:49:37 UTC (rev 19307)
@@ -60,119 +60,119 @@
  */
 static const WCHAR c_colon[] = {'C',':','\\',0};
 
-const static WCHAR szCreateFolders[] =
+static const WCHAR szCreateFolders[] =
     {'C','r','e','a','t','e','F','o','l','d','e','r','s',0};
-const static WCHAR szCostFinalize[] =
+static const WCHAR szCostFinalize[] =
     {'C','o','s','t','F','i','n','a','l','i','z','e',0};
 const WCHAR szInstallFiles[] =
     {'I','n','s','t','a','l','l','F','i','l','e','s',0};
 const WCHAR szDuplicateFiles[] =
     {'D','u','p','l','i','c','a','t','e','F','i','l','e','s',0};
-const static WCHAR szWriteRegistryValues[] =
+static const WCHAR szWriteRegistryValues[] =
     {'W','r','i','t','e','R','e','g','i','s','t','r','y',
             'V','a','l','u','e','s',0};
-const static WCHAR szCostInitialize[] =
+static const WCHAR szCostInitialize[] =
     {'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0};
-const static WCHAR szFileCost[] = 
+static const WCHAR szFileCost[] = 
     {'F','i','l','e','C','o','s','t',0};
-const static WCHAR szInstallInitialize[] = 
+static const WCHAR szInstallInitialize[] = 
     {'I','n','s','t','a','l','l','I','n','i','t','i','a','l','i','z','e',0};
-const static WCHAR szInstallValidate[] = 
+static const WCHAR szInstallValidate[] = 
     {'I','n','s','t','a','l','l','V','a','l','i','d','a','t','e',0};
-const static WCHAR szLaunchConditions[] = 
+static const WCHAR szLaunchConditions[] = 
     {'L','a','u','n','c','h','C','o','n','d','i','t','i','o','n','s',0};
-const static WCHAR szProcessComponents[] = 
+static const WCHAR szProcessComponents[] = 
     {'P','r','o','c','e','s','s','C','o','m','p','o','n','e','n','t','s',0};
-const static WCHAR szRegisterTypeLibraries[] = 
+static const WCHAR szRegisterTypeLibraries[] = 
     {'R','e','g','i','s','t','e','r','T','y','p','e',
             'L','i','b','r','a','r','i','e','s',0};
 const WCHAR szRegisterClassInfo[] = 
     {'R','e','g','i','s','t','e','r','C','l','a','s','s','I','n','f','o',0};
 const WCHAR szRegisterProgIdInfo[] = 
     {'R','e','g','i','s','t','e','r','P','r','o','g','I','d','I','n','f','o',0};
-const static WCHAR szCreateShortcuts[] = 
+static const WCHAR szCreateShortcuts[] = 
     {'C','r','e','a','t','e','S','h','o','r','t','c','u','t','s',0};
-const static WCHAR szPublishProduct[] = 
+static const WCHAR szPublishProduct[] = 
     {'P','u','b','l','i','s','h','P','r','o','d','u','c','t',0};
-const static WCHAR szWriteIniValues[] = 
+static const WCHAR szWriteIniValues[] = 
     {'W','r','i','t','e','I','n','i','V','a','l','u','e','s',0};
-const static WCHAR szSelfRegModules[] = 
+static const WCHAR szSelfRegModules[] = 
     {'S','e','l','f','R','e','g','M','o','d','u','l','e','s',0};
-const static WCHAR szPublishFeatures[] = 
+static const WCHAR szPublishFeatures[] = 
     {'P','u','b','l','i','s','h','F','e','a','t','u','r','e','s',0};
-const static WCHAR szRegisterProduct[] = 
+static const WCHAR szRegisterProduct[] = 
     {'R','e','g','i','s','t','e','r','P','r','o','d','u','c','t',0};
-const static WCHAR szInstallExecute[] = 
+static const WCHAR szInstallExecute[] = 
     {'I','n','s','t','a','l','l','E','x','e','c','u','t','e',0};
-const static WCHAR szInstallExecuteAgain[] = 
+static const WCHAR szInstallExecuteAgain[] = 
     {'I','n','s','t','a','l','l','E','x','e','c','u','t','e',
             'A','g','a','i','n',0};
-const static WCHAR szInstallFinalize[] = 
+static const WCHAR szInstallFinalize[] = 
     {'I','n','s','t','a','l','l','F','i','n','a','l','i','z','e',0};
-const static WCHAR szForceReboot[] = 
+static const WCHAR szForceReboot[] = 
     {'F','o','r','c','e','R','e','b','o','o','t',0};
-const static WCHAR szResolveSource[] =
+static const WCHAR szResolveSource[] =
     {'R','e','s','o','l','v','e','S','o','u','r','c','e',0};
 const WCHAR szAppSearch[] = 
     {'A','p','p','S','e','a','r','c','h',0};
-const static WCHAR szAllocateRegistrySpace[] = 
+static const WCHAR szAllocateRegistrySpace[] = 
     {'A','l','l','o','c','a','t','e','R','e','g','i','s','t','r','y',
             'S','p','a','c','e',0};
-const static WCHAR szBindImage[] = 
+static const WCHAR szBindImage[] = 
     {'B','i','n','d','I','m','a','g','e',0};
-const static WCHAR szCCPSearch[] = 
+static const WCHAR szCCPSearch[] = 
     {'C','C','P','S','e','a','r','c','h',0};
-const static WCHAR szDeleteServices[] = 
+static const WCHAR szDeleteServices[] = 
     {'D','e','l','e','t','e','S','e','r','v','i','c','e','s',0};
-const static WCHAR szDisableRollback[] = 
+static const WCHAR szDisableRollback[] = 
     {'D','i','s','a','b','l','e','R','o','l','l','b','a','c','k',0};
-const static WCHAR szExecuteAction[] = 
+static const WCHAR szExecuteAction[] = 
     {'E','x','e','c','u','t','e','A','c','t','i','o','n',0};
 const WCHAR szFindRelatedProducts[] = 
     {'F','i','n','d','R','e','l','a','t','e','d',
             'P','r','o','d','u','c','t','s',0};
-const static WCHAR szInstallAdminPackage[] = 
+static const WCHAR szInstallAdminPackage[] = 
     {'I','n','s','t','a','l','l','A','d','m','i','n',
             'P','a','c','k','a','g','e',0};
-const static WCHAR szInstallSFPCatalogFile[] = 
+static const WCHAR szInstallSFPCatalogFile[] = 
     {'I','n','s','t','a','l','l','S','F','P','C','a','t','a','l','o','g',
             'F','i','l','e',0};
-const static WCHAR szIsolateComponents[] = 
+static const WCHAR szIsolateComponents[] = 
     {'I','s','o','l','a','t','e','C','o','m','p','o','n','e','n','t','s',0};
 const WCHAR szMigrateFeatureStates[] = 
     {'M','i','g','r','a','t','e','F','e','a','t','u','r','e',
             'S','t','a','t','e','s',0};
 const WCHAR szMoveFiles[] = 
     {'M','o','v','e','F','i','l','e','s',0};
-const static WCHAR szMsiPublishAssemblies[] = 
+static const WCHAR szMsiPublishAssemblies[] = 
     {'M','s','i','P','u','b','l','i','s','h',
             'A','s','s','e','m','b','l','i','e','s',0};
-const static WCHAR szMsiUnpublishAssemblies[] = 
+static const WCHAR szMsiUnpublishAssemblies[] = 
     {'M','s','i','U','n','p','u','b','l','i','s','h',
             'A','s','s','e','m','b','l','i','e','s',0};
-const static WCHAR szInstallODBC[] = 
+static const WCHAR szInstallODBC[] = 
     {'I','n','s','t','a','l','l','O','D','B','C',0};
-const static WCHAR szInstallServices[] = 
+static const WCHAR szInstallServices[] = 
     {'I','n','s','t','a','l','l','S','e','r','v','i','c','e','s',0};
 const WCHAR szPatchFiles[] = 
     {'P','a','t','c','h','F','i','l','e','s',0};
-const static WCHAR szPublishComponents[] = 
+static const WCHAR szPublishComponents[] = 
     {'P','u','b','l','i','s','h','C','o','m','p','o','n','e','n','t','s',0};
-const static WCHAR szRegisterComPlus[] =
+static const WCHAR szRegisterComPlus[] =
     {'R','e','g','i','s','t','e','r','C','o','m','P','l','u','s',0};
 const WCHAR szRegisterExtensionInfo[] =
     {'R','e','g','i','s','t','e','r','E','x','t','e','n','s','i','o','n',
             'I','n','f','o',0};
-const static WCHAR szRegisterFonts[] =
+static const WCHAR szRegisterFonts[] =
     {'R','e','g','i','s','t','e','r','F','o','n','t','s',0};
 const WCHAR szRegisterMIMEInfo[] =
     {'R','e','g','i','s','t','e','r','M','I','M','E','I','n','f','o',0};
-const static WCHAR szRegisterUser[] =
+static const WCHAR szRegisterUser[] =
     {'R','e','g','i','s','t','e','r','U','s','e','r',0};
 const WCHAR szRemoveDuplicateFiles[] =
     {'R','e','m','o','v','e','D','u','p','l','i','c','a','t','e',
             'F','i','l','e','s',0};
-const static WCHAR szRemoveEnvironmentStrings[] =
+static const WCHAR szRemoveEnvironmentStrings[] =
     {'R','e','m','o','v','e','E','n','v','i','r','o','n','m','e','n','t',
             'S','t','r','i','n','g','s',0};
 const WCHAR szRemoveExistingProducts[] =
@@ -180,55 +180,55 @@
             'P','r','o','d','u','c','t','s',0};
 const WCHAR szRemoveFiles[] =
     {'R','e','m','o','v','e','F','i','l','e','s',0};
-const static WCHAR szRemoveFolders[] =
+static const WCHAR szRemoveFolders[] =
     {'R','e','m','o','v','e','F','o','l','d','e','r','s',0};
-const static WCHAR szRemoveIniValues[] =
+static const WCHAR szRemoveIniValues[] =
     {'R','e','m','o','v','e','I','n','i','V','a','l','u','e','s',0};
-const static WCHAR szRemoveODBC[] =
+static const WCHAR szRemoveODBC[] =
     {'R','e','m','o','v','e','O','D','B','C',0};
-const static WCHAR szRemoveRegistryValues[] =
+static const WCHAR szRemoveRegistryValues[] =
     {'R','e','m','o','v','e','R','e','g','i','s','t','r','y',
             'V','a','l','u','e','s',0};
-const static WCHAR szRemoveShortcuts[] =
+static const WCHAR szRemoveShortcuts[] =
     {'R','e','m','o','v','e','S','h','o','r','t','c','u','t','s',0};
-const static WCHAR szRMCCPSearch[] =
+static const WCHAR szRMCCPSearch[] =
     {'R','M','C','C','P','S','e','a','r','c','h',0};
-const static WCHAR szScheduleReboot[] =
+static const WCHAR szScheduleReboot[] =
     {'S','c','h','e','d','u','l','e','R','e','b','o','o','t',0};
-const static WCHAR szSelfUnregModules[] =
+static const WCHAR szSelfUnregModules[] =
     {'S','e','l','f','U','n','r','e','g','M','o','d','u','l','e','s',0};
-const static WCHAR szSetODBCFolders[] =
+static const WCHAR szSetODBCFolders[] =
     {'S','e','t','O','D','B','C','F','o','l','d','e','r','s',0};
-const static WCHAR szStartServices[] =
+static const WCHAR szStartServices[] =
     {'S','t','a','r','t','S','e','r','v','i','c','e','s',0};
-const static WCHAR szStopServices[] =
+static const WCHAR szStopServices[] =
     {'S','t','o','p','S','e','r','v','i','c','e','s',0};
-const static WCHAR szUnpublishComponents[] =
+static const WCHAR szUnpublishComponents[] =
     {'U','n','p','u','b','l','i','s','h',
             'C','o','m','p','o','n','e','n','t','s',0};
-const static WCHAR szUnpublishFeatures[] =
+static const WCHAR szUnpublishFeatures[] =
     {'U','n','p','u','b','l','i','s','h','F','e','a','t','u','r','e','s',0};
 const WCHAR szUnregisterClassInfo[] =
     {'U','n','r','e','g','i','s','t','e','r','C','l','a','s','s',
             'I','n','f','o',0};
-const static WCHAR szUnregisterComPlus[] =
+static const WCHAR szUnregisterComPlus[] =
     {'U','n','r','e','g','i','s','t','e','r','C','o','m','P','l','u','s',0};
 const WCHAR szUnregisterExtensionInfo[] =
     {'U','n','r','e','g','i','s','t','e','r',
             'E','x','t','e','n','s','i','o','n','I','n','f','o',0};
-const static WCHAR szUnregisterFonts[] =
+static const WCHAR szUnregisterFonts[] =
     {'U','n','r','e','g','i','s','t','e','r','F','o','n','t','s',0};
 const WCHAR szUnregisterMIMEInfo[] =
     {'U','n','r','e','g','i','s','t','e','r','M','I','M','E','I','n','f','o',0};
 const WCHAR szUnregisterProgIdInfo[] =
     {'U','n','r','e','g','i','s','t','e','r','P','r','o','g','I','d',
             'I','n','f','o',0};
-const static WCHAR szUnregisterTypeLibraries[] =
+static const WCHAR szUnregisterTypeLibraries[] =
     {'U','n','r','e','g','i','s','t','e','r','T','y','p','e',
             'L','i','b','r','a','r','i','e','s',0};
-const static WCHAR szValidateProductID[] =
+static const WCHAR szValidateProductID[] =
     {'V','a','l','i','d','a','t','e','P','r','o','d','u','c','t','I','D',0};
-const static WCHAR szWriteEnvironmentStrings[] =
+static const WCHAR szWriteEnvironmentStrings[] =
     {'W','r','i','t','e','E','n','v','i','r','o','n','m','e','n','t',
             'S','t','r','i','n','g','s',0};
 
@@ -404,6 +404,171 @@
     return ERROR_SUCCESS;
 }
 
+
+static LPWSTR* msi_split_string( LPCWSTR str, WCHAR sep )
+{
+    LPWSTR p, *ret = NULL;
+    UINT count = 0;
+
+    if (!str)
+        return ret;
+
+    /* count the number of substrings */
+    for ( p = (LPWSTR)str, count = 0; p; count++ )
+    {
+        p = strchrW( p, sep );
+        if (p)
+            p++;
+    }
+
+    /* allocate space for an array of substring pointers and the substrings */
+    ret = msi_alloc( (count+1) * sizeof (LPWSTR) +
+                     (lstrlenW(str)+1) * sizeof(WCHAR) );
+    if (!ret)
+        return ret;
+
+    /* copy the string and set the pointers */
+    p = (LPWSTR) &ret[count+1];
+    lstrcpyW( p, str );
+    for( count = 0; (ret[count] = p); count++ )
+    {
+        p = strchrW( p, sep );
+        if (p)
+            *p++ = 0;
+    }
+
+    return ret;
+}
+
+static UINT msi_apply_substorage_transform( MSIPACKAGE *package,
+                                 MSIDATABASE *patch_db, LPCWSTR name )
+{
+    UINT ret = ERROR_FUNCTION_FAILED;
+    IStorage *stg = NULL;
+    HRESULT r;
+
+    TRACE("%p %s\n", package, debugstr_w(name) );
+
+    if (*name++ != ':')
+    {
+        ERR("expected a colon in %s\n", debugstr_w(name));
+        return ERROR_FUNCTION_FAILED;
+    }
+
+    r = IStorage_OpenStorage( patch_db->storage, name, NULL, STGM_SHARE_EXCLUSIVE, NULL, 0, &stg );
+    if (SUCCEEDED(r))
+    {
+        ret = msi_table_apply_transform( package->db, stg );
+        IStorage_Release( stg );
+        ret = ERROR_SUCCESS;
+    }
+    else
+        ERR("failed to open substorage %s\n", debugstr_w(name));
+
+    return ret;
+}
+
+static UINT msi_check_patch_applicable( MSIPACKAGE *package, MSISUMMARYINFO *si )
+{
+    static const WCHAR szProdID[] = { 'P','r','o','d','u','c','t','I','D',0 };
+    LPWSTR guid_list, *guids, product_id;
+    UINT i, ret = ERROR_FUNCTION_FAILED;
+
+    product_id = msi_dup_property( package, szProdID );
+    if (!product_id)
+    {
+        /* FIXME: the property ProductID should be written into the DB somewhere */
+        ERR("no product ID to check\n");
+        return ERROR_SUCCESS;
+    }
+
+    guid_list = msi_suminfo_dup_string( si, PID_TEMPLATE );
+    guids = msi_split_string( guid_list, ';' );
+    for ( i = 0; guids[i] && ret != ERROR_SUCCESS; i++ )
+    {
+        if (!lstrcmpW( guids[i], product_id ))
+            ret = ERROR_SUCCESS;
+    }
+    msi_free( guids );
+    msi_free( guid_list );
+    msi_free( product_id );
+
+    return ret;
+}
+
+static UINT msi_parse_patch_summary( MSIPACKAGE *package, MSIDATABASE *patch_db )
+{
+    MSISUMMARYINFO *si;
+    LPWSTR str, *substorage;
+    UINT i, r = ERROR_SUCCESS;
+
+    si = MSI_GetSummaryInformationW( patch_db, 0 );
+    if (!si)
+        return ERROR_FUNCTION_FAILED;
+
+    msi_check_patch_applicable( package, si );
+
+    /* enumerate the substorage */
+    str = msi_suminfo_dup_string( si, PID_LASTAUTHOR );
+    substorage = msi_split_string( str, ';' );
+    for ( i = 0; substorage && substorage[i] && r == ERROR_SUCCESS; i++ )
+        r = msi_apply_substorage_transform( package, patch_db, substorage[i] );
+    msi_free( substorage );
+    msi_free( str );
+
+    /* FIXME: parse the sources in PID_REVNUMBER and do something with them... */
+
+    msiobj_release( &si->hdr );
+
+    return r;
+}
+
+static UINT msi_apply_patch_package( MSIPACKAGE *package, LPCWSTR file )
+{
+    MSIDATABASE *patch_db = NULL;
+    UINT r;
+
+    TRACE("%p %s\n", package, debugstr_w( file ) );
+
+    /* FIXME:
+     *  We probably want to make sure we only open a patch collection here.
+     *  Patch collections (.msp) and databases (.msi) have different GUIDs
+     *  but currently MSI_OpenDatabaseW will accept both.
+     */
+    r = MSI_OpenDatabaseW( file, MSIDBOPEN_READONLY, &patch_db );
+    if ( r != ERROR_SUCCESS )
+    {
+        ERR("failed to open patch collection %s\n", debugstr_w( file ) );
+        return r;
+    }
+
+    msi_parse_patch_summary( package, patch_db );
+    msiobj_release( &patch_db->hdr );
+
+    return ERROR_SUCCESS;
+}
+
+/* get the PATCH property, and apply all the patches it specifies */
+static UINT msi_apply_patches( MSIPACKAGE *package )
+{
+    static const WCHAR szPatch[] = { 'P','A','T','C','H',0 };
+    LPWSTR patch_list, *patches;
+    UINT i, r = ERROR_SUCCESS;
+
+    patch_list = msi_dup_property( package, szPatch );
+
+    TRACE("patches to be applied: %s\n", debugstr_w( patch_list ) );
+
+    patches = msi_split_string( patch_list, ';' );
+    for( i=0; patches && patches[i] && r == ERROR_SUCCESS; i++ )
+        r = msi_apply_patch_package( package, patches[i] );
+
+    msi_free( patches );
+    msi_free( patch_list );
+
+    return r;
+}
+
 /****************************************************
  * TOP level entry points 
  *****************************************************/
@@ -453,6 +618,8 @@
 
     msi_parse_command_line( package, szCommandLine );
 
+    msi_apply_patches( package );
+
     if ( msi_get_property_int(package, szUILevel, 0) >= INSTALLUILEVEL_REDUCED )
     {
         package->script->InWhatSequence |= SEQUENCE_UI;
@@ -593,7 +760,7 @@
         rc = ERROR_SUCCESS;
 
     if (rc != ERROR_SUCCESS)
-        ERR("Execution halted due to error (%i)\n",rc);
+        ERR("Execution halted, action %s returned %i\n", debugstr_w(action), rc);
 
     return rc;
 }
@@ -708,7 +875,7 @@
     
     if (rc == ERROR_SUCCESS)
     {
-        TRACE("Running the actions \n"); 
+        TRACE("Running the actions\n"); 
 
         rc = MSI_IterateRecords(view, NULL, ITERATE_Actions, &iap);
         msiobj_release(&view->hdr);
@@ -727,6 +894,12 @@
     BOOL run = force;
     int i;
 
+    if (!package)
+    {
+        ERR("package was null!\n");
+        return FALSE;
+    }
+
     if (!run && !package->script->CurrentlyScripting)
         run = TRUE;
    
@@ -855,7 +1028,7 @@
     dir = MSI_RecordGetString(row,1);
     if (!dir)
     {
-        ERR("Unable to get folder id \n");
+        ERR("Unable to get folder id\n");
         return ERROR_SUCCESS;
     }
 
@@ -883,7 +1056,43 @@
     return ERROR_SUCCESS;
 }
 
+/* FIXME: probably should merge this with the above function */
+static UINT msi_create_directory( MSIPACKAGE* package, LPCWSTR dir )
+{
+    UINT rc = ERROR_SUCCESS;
+    MSIFOLDER *folder;
+    LPWSTR install_path;
 
+    install_path = resolve_folder(package, dir, FALSE, FALSE, &folder);
+    if (!install_path)
+        return ERROR_FUNCTION_FAILED; 
+
+    /* create the path */
+    if (folder->State == 0)
+    {
+        create_full_pathW(install_path);
+        folder->State = 2;
+    }
+    msi_free(install_path);
+
+    return rc;
+}
+
+UINT msi_create_component_directories( MSIPACKAGE *package )
+{
+    MSICOMPONENT *comp;
+
+    /* create all the folders required by the components are going to install */
+    LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
+    {
+        if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL))
+            continue;
+        msi_create_directory( package, comp->Directory );
+    }
+
+    return ERROR_SUCCESS;
+}
+
 /*
  * Also we cannot enable/disable components either, so for now I am just going 
  * to do all the directories for all the components.
@@ -898,13 +1107,16 @@
     UINT rc;
     MSIQUERY *view;
 
+    /* create all the empty folders specified in the CreateFolder table */
     rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view );
     if (rc != ERROR_SUCCESS)
         return ERROR_SUCCESS;
 
     rc = MSI_IterateRecords(view, NULL, ITERATE_CreateFolders, package);
     msiobj_release(&view->hdr);
-   
+
+    msi_create_component_directories( package );
+
     return rc;
 }
 
@@ -917,15 +1129,15 @@
         return comp;
 
     /* fill in the data */
-    comp->Component = load_dynamic_stringW( row, 1 );
+    comp->Component = msi_dup_record_field( row, 1 );
 
     TRACE("Loading Component %s\n", debugstr_w(comp->Component));
 
-    comp->ComponentId = load_dynamic_stringW( row, 2 );
-    comp->Directory = load_dynamic_stringW( row, 3 );
+    comp->ComponentId = msi_dup_record_field( row, 2 );
+    comp->Directory = msi_dup_record_field( row, 3 );
     comp->Attributes = MSI_RecordGetInteger(row,4);
-    comp->Condition = load_dynamic_stringW( row, 5 );
-    comp->KeyPath = load_dynamic_stringW( row, 6 );
+    comp->Condition = msi_dup_record_field( row, 5 );
+    comp->KeyPath = msi_dup_record_field( row, 6 );
 
     comp->Installed = INSTALLSTATE_ABSENT;
     comp->Action = INSTALLSTATE_UNKNOWN;
@@ -1031,19 +1243,19 @@
 
     list_init( &feature->Components );
     
-    feature->Feature = load_dynamic_stringW( row, 1 );
+    feature->Feature = msi_dup_record_field( row, 1 );
 
     TRACE("Loading feature %s\n",debugstr_w(feature->Feature));
 
-    feature->Feature_Parent = load_dynamic_stringW( row, 2 );
-    feature->Title = load_dynamic_stringW( row, 3 );
-    feature->Description = load_dynamic_stringW( row, 4 );
+    feature->Feature_Parent = msi_dup_record_field( row, 2 );
+    feature->Title = msi_dup_record_field( row, 3 );
+    feature->Description = msi_dup_record_field( row, 4 );
 
     if (!MSI_RecordIsNull(row,5))
         feature->Display = MSI_RecordGetInteger(row,5);
   
     feature->Level= MSI_RecordGetInteger(row,6);
-    feature->Directory = load_dynamic_stringW( row, 7 );
+    feature->Directory = msi_dup_record_field( row, 7 );
     feature->Attributes = MSI_RecordGetInteger(row,8);
 
     feature->Installed = INSTALLSTATE_ABSENT;
@@ -1079,7 +1291,7 @@
     if (!file)
         return ERROR_NOT_ENOUGH_MEMORY;
  
-    file->File = load_dynamic_stringW( row, 1 );
+    file->File = msi_dup_record_field( row, 1 );
 
     component = MSI_RecordGetString( row, 2 );
     file->Component = get_loaded_component( package, component );
@@ -1087,19 +1299,19 @@
     if (!file->Component)
         ERR("Unfound Component %s\n",debugstr_w(component));
 
-    file->FileName = load_dynamic_stringW( row, 3 );
+    file->FileName = msi_dup_record_field( row, 3 );
     reduce_to_longfilename( file->FileName );
 
-    file->ShortName = load_dynamic_stringW( row, 3 );
+    file->ShortName = msi_dup_record_field( row, 3 );
     reduce_to_shortfilename( file->ShortName );
     
     file->FileSize = MSI_RecordGetInteger( row, 4 );
-    file->Version = load_dynamic_stringW( row, 5 );
-    file->Language = load_dynamic_stringW( row, 6 );
+    file->Version = msi_dup_record_field( row, 5 );
+    file->Language = msi_dup_record_field( row, 6 );
     file->Attributes = MSI_RecordGetInteger( row, 7 );
     file->Sequence = MSI_RecordGetInteger( row, 8 );
 
-    file->State = 0;
+    file->state = msifs_invalid;
 
     TRACE("File Loaded (%s)\n",debugstr_w(file->File));  
 
@@ -1154,11 +1366,8 @@
     static const WCHAR szCosting[] =
         {'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 };
     static const WCHAR szZero[] = { '0', 0 };
-    WCHAR buffer[3];
-    DWORD sz = 3;
 
-    MSI_GetPropertyW(package, szCosting, buffer, &sz);
-    if (buffer[0]=='1')
+    if ( 1 == msi_get_property_int( package, szCosting, 0 ) )
         return ERROR_SUCCESS;
     
     MSI_SetPropertyW(package, szCosting, szZero);
@@ -1239,7 +1448,7 @@
     if (!row)
         return NULL;
 
-    ptargetdir = targetdir = load_dynamic_stringW(row,3);
+    ptargetdir = targetdir = msi_dup_record_field(row,3);
 
     /* split src and target dir */
     if (strchrW(targetdir,':'))
@@ -1404,6 +1613,8 @@
         {'A','D','D','L','O','C','A','L',0};
     static const WCHAR szRemove[] =
         {'R','E','M','O','V','E',0};
+    static const WCHAR szReinstall[] =
+        {'R','E','I','N','S','T','A','L','L',0};
     BOOL override = FALSE;
     MSICOMPONENT* component;
     MSIFEATURE *feature;
@@ -1439,6 +1650,7 @@
      */
     override |= process_state_property(package,szAddLocal,INSTALLSTATE_LOCAL);
     override |= process_state_property(package,szRemove,INSTALLSTATE_ABSENT);
+    override |= process_state_property(package,szReinstall,INSTALLSTATE_LOCAL);
 
     if (!override)
     {
@@ -1617,13 +1829,10 @@
     UINT rc;
     MSIQUERY * view;
     LPWSTR level;
-    DWORD sz = 3;
-    WCHAR buffer[3];
 
-    MSI_GetPropertyW(package, szCosting, buffer, &sz);
-    if (buffer[0]=='1')
+    if ( 1 == msi_get_property_int( package, szCosting, 0 ) )
         return ERROR_SUCCESS;
-
+    
     TRACE("Building Directory properties\n");
 
     rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
@@ -1661,7 +1870,7 @@
 
         if (GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES)
         {
-            file->State = 1;
+            file->state = msifs_missing;
             comp->Cost += file->FileSize;
             continue;
         }
@@ -1672,14 +1881,13 @@
             DWORD versize;
             UINT sz;
             LPVOID version;
-            static const WCHAR name[] = 
-                {'\\',0};
+            static WCHAR name[] = {'\\',0};
             static const WCHAR name_fmt[] = 
                 {'%','u','.','%','u','.','%','u','.','%','u',0};
             WCHAR filever[0x100];
             VS_FIXEDFILEINFO *lpVer;
 
-            TRACE("Version comparison.. \n");
+            TRACE("Version comparison..\n");
             versize = GetFileVersionInfoSizeW(file->TargetPath,&handle);
             version = msi_alloc(versize);
             GetFileVersionInfoW(file->TargetPath, 0, versize, version);
@@ -1696,16 +1904,16 @@
                   debugstr_w(filever));
             if (strcmpiW(filever,file->Version)<0)
             {
-                file->State = 2;
-                FIXME("cost should be diff in size\n");
+                file->state = msifs_overwrite;
+                /* FIXME: cost should be diff in size */
                 comp->Cost += file->FileSize;
             }
             else
-                file->State = 3;
+                file->state = msifs_present;
             msi_free(version);
         }
         else
-            file->State = 3;
+            file->state = msifs_present;
     }
 
     TRACE("Evaluating Condition Table\n");
@@ -1893,7 +2101,7 @@
     if (!comp)
         return ERROR_SUCCESS;
 
-    if (!ACTION_VerifyComponentForAction(package, comp, INSTALLSTATE_LOCAL))
+    if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL))
     {
         TRACE("Skipping write due to disabled component %s\n",
                         debugstr_w(component));
@@ -2349,9 +2557,6 @@
     MSICOMPONENT *comp;
     HKEY hkey=0,hkey2=0;
 
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
     /* writes the Component and Features values to the registry */
 
     rc = MSIREG_OpenComponents(&hkey);
@@ -2385,8 +2590,7 @@
             * Write the keypath out if the component is to be registered
             * and delete the key if the component is to be deregistered
             */
-            if (ACTION_VerifyComponentForAction(package, comp,
-                                    INSTALLSTATE_LOCAL))
+            if (ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL))
             {
                 rc = RegCreateKeyW(hkey,squished_cc,&hkey2);
                 if (rc != ERROR_SUCCESS)
@@ -2417,8 +2621,7 @@
                     msiobj_release( &uirow->hdr );
                }
             }
-            else if (ACTION_VerifyComponentForAction(package, comp,
-                                    INSTALLSTATE_ABSENT))
+            else if (ACTION_VerifyComponentForAction( comp, INSTALLSTATE_ABSENT))
             {
                 DWORD res;
 
@@ -2523,7 +2726,7 @@
     if (!comp)
         return ERROR_SUCCESS;
 
-    if (!ACTION_VerifyComponentForAction(package, comp, INSTALLSTATE_LOCAL))
+    if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL))
     {
         TRACE("Skipping typelib reg due to disabled component\n");
 
@@ -2539,19 +2742,18 @@
         return ERROR_SUCCESS;
 
     module = LoadLibraryExW( file->TargetPath, NULL, LOAD_LIBRARY_AS_DATAFILE );
-    if (module != NULL)
+    if (module)
     {
-        LPWSTR guid;
-        guid = load_dynamic_stringW(row,1);
-        CLSIDFromString(guid, &tl_struct.clsid);
-        msi_free(guid);
+        LPCWSTR guid;
+        guid = MSI_RecordGetString(row,1);
+        CLSIDFromString((LPWSTR)guid, &tl_struct.clsid);
         tl_struct.source = strdupW( file->TargetPath );
         tl_struct.path = NULL;
 
         EnumResourceNamesW(module, szTYPELIB, Typelib_EnumResNameProc,
                         (LONG_PTR)&tl_struct);
 
-        if (tl_struct.path != NULL)
+        if (tl_struct.path)
         {
             LPWSTR help = NULL;
             LPCWSTR helpid;
@@ -2604,9 +2806,6 @@
         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
          '`','T','y','p','e','L','i','b','`',0};
 
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
     rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
     if (rc != ERROR_SUCCESS)
         return ERROR_SUCCESS;
@@ -2634,7 +2833,7 @@
     if (!comp)
         return ERROR_SUCCESS;
 
-    if (!ACTION_VerifyComponentForAction(package, comp, INSTALLSTATE_LOCAL))
+    if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL ))
     {
         TRACE("Skipping shortcut creation due to disabled component\n");
 
@@ -2755,9 +2954,6 @@
         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
          '`','S','h','o','r','t','c','u','t','`',0};
 
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
     rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
     if (rc != ERROR_SUCCESS)
         return ERROR_SUCCESS;
@@ -2856,9 +3052,6 @@
     DWORD size;
     MSIHANDLE hDb, hSumInfo;
 
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
     /* write out icon files */
 
     rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
@@ -2925,7 +3118,7 @@
         }
         else
         {
-            ERR("Unable to query Revision_Number... \n");
+            ERR("Unable to query Revision_Number...\n");
             rc = ERROR_SUCCESS;
         }
         MsiCloseHandle(hSumInfo);
@@ -2959,7 +3152,7 @@
     component = MSI_RecordGetString(row, 8);
     comp = get_loaded_component(package,component);
 
-    if (!ACTION_VerifyComponentForAction(package, comp, INSTALLSTATE_LOCAL))
+    if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL))
     {
         TRACE("Skipping ini file due to disabled component %s\n",
                         debugstr_w(component));
@@ -3133,9 +3326,6 @@
     HKEY hkey=0;
     HKEY hukey=0;
     
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
     rc = MSIREG_OpenFeaturesKey(package->ProductCode,&hkey,TRUE);
     if (rc != ERROR_SUCCESS)
         goto end;
@@ -3281,55 +3471,54 @@
     return ERROR_SUCCESS;
 }
 
+static UINT msi_write_uninstall_property_vals( MSIPACKAGE *package, HKEY hkey )
+{
+    LPWSTR prop, val, key;
+    static const LPCSTR propval[] = {
+        "ARPAUTHORIZEDCDFPREFIX", "AuthorizedCDFPrefix",
+        "ARPCONTACT",             "Contact",
+        "ARPCOMMENTS",            "Comments",
+        "ProductName",            "DisplayName",
+        "ProductVersion",         "DisplayVersion",
+        "ARPHELPLINK",            "HelpLink",
+        "ARPHELPTELEPHONE",       "HelpTelephone",
+        "ARPINSTALLLOCATION",     "InstallLocation",
+        "SourceDir",              "InstallSource",
+        "Manufacturer",           "Publisher",
+        "ARPREADME",              "Readme",
+        "ARPSIZE",                "Size",
+        "ARPURLINFOABOUT",        "URLInfoAbout",
+        "ARPURLUPDATEINFO",       "URLUpdateInfo",
+        NULL,
+    };
+    const LPCSTR *p = propval;
+
+    while( *p )
+    {
+        prop = strdupAtoW( *p++ );
+        key = strdupAtoW( *p++ );
+        val = msi_dup_property( package, prop );
+        msi_reg_set_val_str( hkey, key, val );
+        msi_free(val);
+        msi_free(key);
+        msi_free(prop);
+    }
+    return ERROR_SUCCESS;
+}
+
 static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
 {
     HKEY hkey=0;
     LPWSTR buffer = NULL;
-    UINT rc,i;
+    UINT rc;
     DWORD size, langid;
     static const WCHAR szWindowsInstaller[] = 
-    {'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
-    static const WCHAR szPropKeys[][80] = 
-    {
-{'A','R','P','A','U','T','H','O','R','I','Z','E','D','C','D','F','P','R','E','F','I','X',0},
-{'A','R','P','C','O','N','T','A','C','T',0},
-{'A','R','P','C','O','M','M','E','N','T','S',0},
-{'P','r','o','d','u','c','t','N','a','m','e',0},
-{'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0},
-{'A','R','P','H','E','L','P','L','I','N','K',0},
-{'A','R','P','H','E','L','P','T','E','L','E','P','H','O','N','E',0},
-{'A','R','P','I','N','S','T','A','L','L','L','O','C','A','T','I','O','N',0},
-{'S','o','u','r','c','e','D','i','r',0},
-{'M','a','n','u','f','a','c','t','u','r','e','r',0},
-{'A','R','P','R','E','A','D','M','E',0},
-{'A','R','P','S','I','Z','E',0},
-{'A','R','P','U','R','L','I','N','F','O','A','B','O','U','T',0},
-{'A','R','P','U','R','L','U','P','D','A','T','E','I','N','F','O',0},
-{0},
-    };
-
-    static const WCHAR szRegKeys[][80] = 
-    {
-{'A','u','t','h','o','r','i','z','e','d','C','D','F','P','r','e','f','i','x',0},
-{'C','o','n','t','a','c','t',0},
-{'C','o','m','m','e','n','t','s',0},
-{'D','i','s','p','l','a','y','N','a','m','e',0},
-{'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0},
-{'H','e','l','p','L','i','n','k',0},
-{'H','e','l','p','T','e','l','e','p','h','o','n','e',0},
-{'I','n','s','t','a','l','l','L','o','c','a','t','i','o','n',0},
-{'I','n','s','t','a','l','l','S','o','u','r','c','e',0},
-{'P','u','b','l','i','s','h','e','r',0},
-{'R','e','a','d','m','e',0},
-{'S','i','z','e',0},
-{'U','R','L','I','n','f','o','A','b','o','u','t',0},
-{'U','R','L','U','p','d','a','t','e','I','n','f','o',0},
-{0},
-    };
+        {'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
     static const WCHAR szUpgradeCode[] = 
         {'U','p','g','r','a','d','e','C','o','d','e',0};
     static const WCHAR modpath_fmt[] = 
-        {'M','s','i','E','x','e','c','.','e','x','e',' ','/','I','[','P','r','o','d','u','c','t','C','o','d','e',']',0};
+        {'M','s','i','E','x','e','c','.','e','x','e',' ',
+         '/','I','[','P','r','o','d','u','c','t','C','o','d','e',']',0};
     static const WCHAR szModifyPath[] = 
         {'M','o','d','i','f','y','P','a','t','h',0};
     static const WCHAR szUninstallString[] = 
@@ -3344,23 +3533,16 @@
     SYSTEMTIME systime;
     static const WCHAR date_fmt[] = {'%','i','%','i','%','i',0};
     LPWSTR upgrade_code;
+    WCHAR szDate[9]; 
 
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
     rc = MSIREG_OpenUninstallKey(package->ProductCode,&hkey,TRUE);
     if (rc != ERROR_SUCCESS)
-        goto end;
+        return rc;
 
     /* dump all the info i can grab */
-    FIXME("Flesh out more information \n");
+    FIXME("Flesh out more information\n");
 
-    for( i=0; szPropKeys[i][0]; i++ )
-    {
-        buffer = msi_dup_property( package, szPropKeys[i] );
-        msi_reg_set_val_str( hkey, szRegKeys[i], buffer );
-        msi_free(buffer);
-    }
+    msi_write_uninstall_property_vals( package, hkey );
 
     msi_reg_set_val_dword( hkey, szWindowsInstaller, 1 );
     
@@ -3376,11 +3558,8 @@
     msi_reg_set_val_dword( hkey, szEstimatedSize, 0 );
    
     GetLocalTime(&systime);
-    size = 9*sizeof(WCHAR);
-    buffer= msi_alloc(size);
-    sprintfW(buffer,date_fmt,systime.wYear,systime.wMonth,systime.wDay);
-    msi_reg_set_val_str( hkey, INSTALLPROPERTY_INSTALLDATEW, buffer );
-    msi_free(buffer);
+    sprintfW(szDate,date_fmt,systime.wYear,systime.wMonth,systime.wDay);
+    msi_reg_set_val_str( hkey, INSTALLPROPERTY_INSTALLDATEW, szDate );
    
     langid = msi_get_property_int( package, szProductLanguage, 0 );
     msi_reg_set_val_dword( hkey, INSTALLPROPERTY_LANGUAGEW, langid );
@@ -3414,7 +3593,6 @@
         msi_free(upgrade_code);
     }
     
-end:
     RegCloseKey(hkey);
 
     return ERROR_SUCCESS;
@@ -3422,23 +3600,13 @@
 
 static UINT ACTION_InstallExecute(MSIPACKAGE *package)
 {
-    UINT rc;
-
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
-    rc = execute_script(package,INSTALL_SCRIPT);
-
-    return rc;
+    return execute_script(package,INSTALL_SCRIPT);
[truncated at 1000 lines; 5268 more skipped]