Sync to Wine-20050628:
authorGé van Geldorp <ge@gse.nl>
Wed, 3 Aug 2005 22:12:15 +0000 (22:12 +0000)
committerGé van Geldorp <ge@gse.nl>
Wed, 3 Aug 2005 22:12:15 +0000 (22:12 +0000)
Mike McCormack <mike@codeweavers.com>
- Repaint the area behind the "transparent" text control when it
  changes.
- Implement transparency in the text control.
- Make the MSI icon control work.
- Make tabs work in msi dialogs.
- Added support for the MSI MaskEdit control.
- Use a richedit control for license text.
- Fix radio button groups. Don't add the WS_GROUP style to every
  window.
- Use standard lists in the event subscription code.
- Take the dialog frame into account when calculating the dialog size.
- Use MSI_QueryGetRecord in one more place.
- Create a helper function to fetch a single record from a query.
- More -Wmissing-declarations and -Wwrite-strings warning fixes.
- Get rid of some redundant parser types.
- Use the new helper function MSI_QueryGetRecord.
- Use MSI_RecordGetString in more actions.
- Use MSI_RecordGetString where possible.
- Fixes for -Wmissing-declarations and -Wwrite-strings warnings.
- Remove some unused code.
- Add and correct some function declarations.
- Improve number parsing and avoid unicode.h.
- avoid unicode.h
- add a missing function prototype
- Create a stub implementation for MsiViewGetError.
- Remove more types from the parser.
- Test and fix the size of stream fields in a record.
- Clean up headers and make some functions static.
Marcus Meissner <meissner@suse.de>
- Use a simpler expression for the "RichEdit20W" string to workaround
  compiler bug.
- Remove cszbs from msi/action.h.
Aric Stewart <aric@codeweavers.com>
Mike McCormack <mike@codeweavers.com>
- Allow dialog controls to subscribe to installer events.
- Fix handling of checkbox properties.
- Implement dialog events and hook up the dialog code.
Aric Stewart <aric@codeweavers.com>
- Break out all the file related actions and helper functions into
  files.c
- Break out all the top level apis into install.c.
- Break out all the class registration actions into classes.c. This
  includes RegisterClassInfo, RegisterProgIds, RegisterExtensions and
  RegisterMIMETypes.
- Break out all the helper functions into helpers.c.
- Added module upgrade.c and implemented FindRelatedProducts.
- A long overdue fix to MSI_SetTargetPath. This should fix an error with
  some installers that where unable to change the target path.
- Add functions to add the User UpgradeCodes.
- A simple cleanup to only track the temp file if we need to have it
  laying around because the action is going on asynchronously. Otherwise
  clean up the temp file as the action finishes.
- Introduce really basic scripting of actions. This is primarily to get
  the order of execution of the action correct since some custom actions
  can be scripted and others are run during the script building phase.
- Perform ExecuteAction at UILevel 2.
- Rework CreateShortcuts to use MSI_IterateRecords.
- Properly handle -1 as a registry key root.
- Rework SelfRegModules to use MSI_IterateRecords.
- Rework component, feature and file loading to use MSI_IterateRecords.
- Rework RegisterFonts to use MSI_IterateRecords.
- Rework WriteIniValues to use MSI_IterateRecords.
- Rework PublishProduct to use MSI_IterateRecords.
- Rework RegisterTypeLibraries to use MSI_IterateR
- Rework LaunchConditions to use MSI_IterateRecord
- Rework CostFinalize to use MSI_IterateRecords.
- Rework WriteRegistryValues to use MSI_IterateRecords.
- Rework CreateFolders to use MSI_IterateRecords.
- Use MSI_IterateRecords for processing actions.
  Some whitespace cleanup and replace a comment block I did not want to
  remove.
- Flesh out the remaining keys in RegisterProduct.
- Extending upon Mike McCormack's cleanup to use MSI_RecordGetString.
- Register the Product Version also.
  Also help plug some memory leaks pointed out by Mike McCormack.
- Avoid a loop where a parent's parent refers to itself as its parent.
- Added module upgrade.c and implemented FindRelatedProducts.
- Set the Preselected property if appropriate (relevant to
  MigrateFeatureStates when implemented).
- Write out Product Language and Product Icon to the registry.
- Write out UpgradeCodes to the registry to allow for future upgrades.
- Don't get caught in loops on parent progids.
- Since multiple progids can refer to 1 class we need to check if that
  class is isntalled instead of just relying on having it set the
  InstallMe variable.
- Add install_on_demand for Extension servers also. currently defaulting
  to TRUE.
- Extension need to have 1 verb to mark the given progid to be
  installed.
- Do not loop if a ProgId's Parent Index it itself.
- Add a VersionIndIndex for tracking version independent fields for the
  ProgIds properly.
- Print a message for skipped actions in ProcessExecSequence like in the
  UISequence.
- Do not change a features state to Advertise if it explicitly disallows
  it.
- For typelibs index 1 do not add \\1 to the path. This cleans up
  registry diffs with native MSI.
- Register the FileType and correct short vs long path problems with
  InprocServer32. Also add install_on_demand boolean for future
  expansion.
- First pass at writing out CurVer keys for ProgIds. Also print a
  message for the actions we skip. Lines up with native MSI output logs
  for ease of comparison.
- A big rewrite of the whole RegisterClass, RegisterProgId,
  RegisterExtension and RegisterMIME actions. We now handle verbs
  properly, handle dependancies and such properly and keep track of what
  we need to register and what we do not properly.
- Allow control events to return codes to halt the processing of event.
  Needed for the SetTargetPath Event.
- Fix situations where TARGETDIR is set to a non \ terminated
  path. Fixes a few installers.
- Redo how we extract files from a cabinet in order to dramatically
  improve performance, especially if picking and choosing files out of
  the cabinet.
- Duplicate files should not fail if unable to get Destination
  Directory.
- Use MSI_IterateRecords for DuplicateFiles.
- Add UI messages to FindRelatedProducts.
- Reduce unneeded includes.
- A "1" is returned not a 1 for AssignmentType. Also as a bit more to
  the FIXME message.
- Add Language to the values we can query with MsiGetProductInfo.
- Correct a crash if the length buffer is NULL.
- Locate where a buffer size is not being set and correctly handle the
  buffer size conversion from W to A (with help from Robert Shearman).
- Make sure the TRACE statements do not spew garbage by using
  debugstr_wn.
- Restrict deformating of nested index keys [[1]].
- Introduce the beginning of group deformating {}.
- Implement the [!file] format to produce the short filename.
Stefan Huehner <stefan@huehner.org>
- Fix more -Wstrict-prototypes warnings.
Francois Gouget <fgouget@free.fr>
- Assorted spelling fixes.
Dmitry Timoshkov <dmitry@codeweavers.com>
- Make more of the OLE interface vtables const.

svn path=/trunk/; revision=17034

42 files changed:
reactos/include/wine/msvcrt/fcntl.h [new file with mode: 0644]
reactos/lib/msi/Makefile.in
reactos/lib/msi/action.c
reactos/lib/msi/action.h
reactos/lib/msi/classes.c [new file with mode: 0644]
reactos/lib/msi/cond.tab.c
reactos/lib/msi/cond.tab.h
reactos/lib/msi/cond.y
reactos/lib/msi/create.c
reactos/lib/msi/custom.c
reactos/lib/msi/database.c
reactos/lib/msi/dialog.c
reactos/lib/msi/events.c [new file with mode: 0644]
reactos/lib/msi/files.c [new file with mode: 0644]
reactos/lib/msi/format.c
reactos/lib/msi/helpers.c [new file with mode: 0644]
reactos/lib/msi/insert.c
reactos/lib/msi/install.c [new file with mode: 0644]
reactos/lib/msi/msi.c
reactos/lib/msi/msi.spec
reactos/lib/msi/msi.xml
reactos/lib/msi/msipriv.h
reactos/lib/msi/msiquery.c
reactos/lib/msi/order.c
reactos/lib/msi/package.c
reactos/lib/msi/preview.c
reactos/lib/msi/query.h
reactos/lib/msi/record.c
reactos/lib/msi/registry.c
reactos/lib/msi/select.c
reactos/lib/msi/sql.tab.c
reactos/lib/msi/sql.tab.h
reactos/lib/msi/sql.y
reactos/lib/msi/suminfo.c
reactos/lib/msi/table.c
reactos/lib/msi/tokenize.c
reactos/lib/msi/update.c
reactos/lib/msi/upgrade.c [new file with mode: 0644]
reactos/lib/msi/where.c
reactos/w32api/include/msi.h
reactos/w32api/include/msidefs.h
reactos/w32api/include/msiquery.h

diff --git a/reactos/include/wine/msvcrt/fcntl.h b/reactos/include/wine/msvcrt/fcntl.h
new file mode 100644 (file)
index 0000000..f914f08
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __WINE_MSVCRT_FCNTL_H
+#define __WINE_MSVCRT_FCNTL_H
+
+/*
+ * Compatibility header
+ */
+
+#include <fcntl.h>
+
+#endif /* __WINE_MSVCRT_FCNTL_H */
index 12f85fd..38098fa 100644 (file)
@@ -4,21 +4,26 @@ SRCDIR    = @srcdir@
 VPATH     = @srcdir@\r
 MODULE    = msi.dll\r
 IMPORTLIB = libmsi.$(IMPLIBEXT)\r
-IMPORTS   = shell32 cabinet oleaut32 ole32 version user32 gdi32 advapi32 kernel32\r
+IMPORTS   = shell32 shlwapi cabinet oleaut32 ole32 version user32 gdi32 advapi32 kernel32\r
 EXTRALIBS = -luuid $(LIBUNICODE)\r
 \r
 C_SRCS = \\r
        action.c \\r
        appsearch.c \\r
+       classes.c \\r
        create.c \\r
        custom.c \\r
        database.c \\r
        delete.c \\r
        dialog.c \\r
        distinct.c \\r
+       events.c \\r
+       files.c \\r
        format.c \\r
        handle.c \\r
+       helpers.c \\r
        insert.c \\r
+       install.c \\r
        msi.c \\r
        msiquery.c \\r
        order.c \\r
@@ -33,6 +38,7 @@ C_SRCS = \
        table.c \\r
        tokenize.c \\r
        update.c \\r
+       upgrade.c \\r
        where.c\r
 \r
 RC_SRCS = msi.rc\r
index 336a4a8..6f6ca2e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Implementation of the Microsoft Installer (msi.dll)
  *
- * Copyright 2004 Aric Stewart for CodeWeavers
+ * Copyright 2004,2005 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
@@ -27,7 +27,6 @@ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/stand
  */
 
 #include <stdarg.h>
-#include <stdio.h>
 
 #define COBJMACROS
 
@@ -36,15 +35,8 @@ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/stand
 #include "winerror.h"
 #include "winreg.h"
 #include "wine/debug.h"
-#include "fdi.h"
-#include "msi.h"
-#include "msiquery.h"
 #include "msidefs.h"
-#include "fcntl.h"
-#include "objbase.h"
-#include "objidl.h"
 #include "msipriv.h"
-#include "winnls.h"
 #include "winuser.h"
 #include "shlobj.h"
 #include "wine/unicode.h"
@@ -62,8 +54,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
 static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran);
 static UINT ACTION_ProcessUISequence(MSIPACKAGE *package);
 static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI);
-static UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name, 
-                            LPWSTR *FilePath);
 
 /* 
  * action handlers
@@ -75,17 +65,11 @@ 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_InstallFiles(MSIPACKAGE *package);
-static UINT ACTION_DuplicateFiles(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_RegisterClassInfo(MSIPACKAGE *package);
-static UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package);
-static UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package);
-static UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package);
 static UINT ACTION_RegisterUser(MSIPACKAGE *package);
 static UINT ACTION_CreateShortcuts(MSIPACKAGE *package);
 static UINT ACTION_PublishProduct(MSIPACKAGE *package);
@@ -101,26 +85,18 @@ static UINT ACTION_ExecuteAction(MSIPACKAGE *package);
 static UINT ACTION_RegisterFonts(MSIPACKAGE *package);
 static UINT ACTION_PublishComponents(MSIPACKAGE *package);
 
 /*
  * consts and values used
  */
-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 cszTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0};
-static const WCHAR cszDatabase[]={'D','A','T','A','B','A','S','E',0};
 static const WCHAR c_colon[] = {'C',':','\\',0};
-static const WCHAR szProductCode[]=
-    {'P','r','o','d','u','c','t','C','o','d','e',0};
-static const WCHAR cszbs[]={'\\',0};
+
 const static WCHAR szCreateFolders[] =
     {'C','r','e','a','t','e','F','o','l','d','e','r','s',0};
 const static WCHAR szCostFinalize[] =
     {'C','o','s','t','F','i','n','a','l','i','z','e',0};
-const static WCHAR szInstallFiles[] =
+const WCHAR szInstallFiles[] =
     {'I','n','s','t','a','l','l','F','i','l','e','s',0};
-const static WCHAR szDuplicateFiles[] =
+const WCHAR szDuplicateFiles[] =
     {'D','u','p','l','i','c','a','t','e','F','i','l','e','s',0};
 const static WCHAR szWriteRegistryValues[] =
     {'W','r','i','t','e','R','e','g','i','s','t','r','y',
@@ -140,9 +116,9 @@ const static WCHAR szProcessComponents[] =
 const static 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 static WCHAR szRegisterClassInfo[] = 
+const WCHAR szRegisterClassInfo[] = 
     {'R','e','g','i','s','t','e','r','C','l','a','s','s','I','n','f','o',0};
-const static WCHAR szRegisterProgIdInfo[] = 
+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[] = 
     {'C','r','e','a','t','e','S','h','o','r','t','c','u','t','s',0};
@@ -167,7 +143,7 @@ const static WCHAR szForceReboot[] =
     {'F','o','r','c','e','R','e','b','o','o','t',0};
 const static WCHAR szResolveSource[] =
     {'R','e','s','o','l','v','e','S','o','u','r','c','e',0};
-const static WCHAR szAppSearch[] = 
+const WCHAR szAppSearch[] = 
     {'A','p','p','S','e','a','r','c','h',0};
 const static WCHAR szAllocateRegistrySpace[] = 
     {'A','l','l','o','c','a','t','e','R','e','g','i','s','t','r','y',
@@ -182,7 +158,7 @@ const static WCHAR szDisableRollback[] =
     {'D','i','s','a','b','l','e','R','o','l','l','b','a','c','k',0};
 const static WCHAR szExecuteAction[] = 
     {'E','x','e','c','u','t','e','A','c','t','i','o','n',0};
-const static WCHAR szFindRelatedProducts[] = 
+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[] = 
@@ -193,10 +169,10 @@ const static WCHAR szInstallSFPCatalogFile[] =
             'F','i','l','e',0};
 const static WCHAR szIsolateComponents[] = 
     {'I','s','o','l','a','t','e','C','o','m','p','o','n','e','n','t','s',0};
-const static WCHAR szMigrateFeatureStates[] = 
+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 static WCHAR szMoveFiles[] = 
+const WCHAR szMoveFiles[] = 
     {'M','o','v','e','F','i','l','e','s',0};
 const static WCHAR szMsiPublishAssemblies[] = 
     {'M','s','i','P','u','b','l','i','s','h',
@@ -208,31 +184,31 @@ const static WCHAR szInstallODBC[] =
     {'I','n','s','t','a','l','l','O','D','B','C',0};
 const static WCHAR szInstallServices[] = 
     {'I','n','s','t','a','l','l','S','e','r','v','i','c','e','s',0};
-const static WCHAR szPatchFiles[] = 
+const WCHAR szPatchFiles[] = 
     {'P','a','t','c','h','F','i','l','e','s',0};
 const static WCHAR szPublishComponents[] = 
     {'P','u','b','l','i','s','h','C','o','m','p','o','n','e','n','t','s',0};
 const static WCHAR szRegisterComPlus[] =
     {'R','e','g','i','s','t','e','r','C','o','m','P','l','u','s',0};
-const static WCHAR szRegisterExtensionInfo[] =
+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[] =
     {'R','e','g','i','s','t','e','r','F','o','n','t','s',0};
-const static WCHAR szRegisterMIMEInfo[] =
+const WCHAR szRegisterMIMEInfo[] =
     {'R','e','g','i','s','t','e','r','M','I','M','E','I','n','f','o',0};
 const static WCHAR szRegisterUser[] =
     {'R','e','g','i','s','t','e','r','U','s','e','r',0};
-const static WCHAR szRemoveDuplicateFiles[] =
+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[] =
     {'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 static WCHAR szRemoveExistingProducts[] =
+const WCHAR szRemoveExistingProducts[] =
     {'R','e','m','o','v','e','E','x','i','s','t','i','n','g',
             'P','r','o','d','u','c','t','s',0};
-const static WCHAR szRemoveFiles[] =
+const WCHAR szRemoveFiles[] =
     {'R','e','m','o','v','e','F','i','l','e','s',0};
 const static WCHAR szRemoveFolders[] =
     {'R','e','m','o','v','e','F','o','l','d','e','r','s',0};
@@ -262,19 +238,19 @@ const static WCHAR szUnpublishComponents[] =
             'C','o','m','p','o','n','e','n','t','s',0};
 const static WCHAR szUnpublishFeatures[] =
     {'U','n','p','u','b','l','i','s','h','F','e','a','t','u','r','e','s',0};
-const static WCHAR szUnregisterClassInfo[] =
+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[] =
     {'U','n','r','e','g','i','s','t','e','r','C','o','m','P','l','u','s',0};
-const static WCHAR szUnregisterExtensionInfo[] =
+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[] =
     {'U','n','r','e','g','i','s','t','e','r','F','o','n','t','s',0};
-const static WCHAR szUnregisterMIMEInfo[] =
+const WCHAR szUnregisterMIMEInfo[] =
     {'U','n','r','e','g','i','s','t','e','r','M','I','M','E','I','n','f','o',0};
-const static WCHAR szUnregisterProgIdInfo[] =
+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[] =
@@ -305,7 +281,7 @@ static struct _actions StandardActions[] = {
     { szDuplicateFiles, ACTION_DuplicateFiles },
     { szExecuteAction, ACTION_ExecuteAction },
     { szFileCost, ACTION_FileCost },
-    { szFindRelatedProducts, NULL},
+    { szFindRelatedProducts, ACTION_FindRelatedProducts },
     { szForceReboot, ACTION_ForceReboot },
     { szInstallAdminPackage, NULL},
     { szInstallExecute, ACTION_InstallExecute },
@@ -371,343 +347,22 @@ static struct _actions StandardActions[] = {
 };
 
 
-/******************************************************** 
- * helper functions to get around current HACKS and such
+/********************************************************
+ * helper functions
  ********************************************************/
-inline static void reduce_to_longfilename(WCHAR* filename)
-{
-    LPWSTR p = strchrW(filename,'|');
-    if (p)
-        memmove(filename, p+1, (strlenW(p+1)+1)*sizeof(WCHAR));
-}
-
-inline static void reduce_to_shortfilename(WCHAR* filename)
-{
-    LPWSTR p = strchrW(filename,'|');
-    if (p)
-        *p = 0;
-}
-
-WCHAR *load_dynamic_stringW(MSIRECORD *row, INT index)
-{
-    UINT rc;
-    DWORD sz;
-    LPWSTR ret;
-   
-    sz = 0; 
-    if (MSI_RecordIsNull(row,index))
-        return NULL;
-
-    rc = MSI_RecordGetStringW(row,index,NULL,&sz);
-
-    /* having an empty string is different than NULL */
-    if (sz == 0)
-    {
-        ret = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR));
-        ret[0] = 0;
-        return ret;
-    }
-
-    sz ++;
-    ret = HeapAlloc(GetProcessHeap(),0,sz * sizeof (WCHAR));
-    rc = MSI_RecordGetStringW(row,index,ret,&sz);
-    if (rc!=ERROR_SUCCESS)
-    {
-        ERR("Unable to load dynamic string\n");
-        HeapFree(GetProcessHeap(), 0, ret);
-        ret = NULL;
-    }
-    return ret;
-}
-
-LPWSTR load_dynamic_property(MSIPACKAGE *package, LPCWSTR prop, UINT* rc)
-{
-    DWORD sz = 0;
-    LPWSTR str;
-    UINT r;
-
-    r = MSI_GetPropertyW(package, prop, NULL, &sz);
-    if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
-    {
-        if (rc)
-            *rc = r;
-        return NULL;
-    }
-    sz++;
-    str = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));
-    r = MSI_GetPropertyW(package, prop, str, &sz);
-    if (r != ERROR_SUCCESS)
-    {
-        HeapFree(GetProcessHeap(),0,str);
-        str = NULL;
-    }
-    if (rc)
-        *rc = r;
-    return str;
-}
-
-int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component )
-{
-    int rc = -1;
-    DWORD i;
-
-    for (i = 0; i < package->loaded_components; i++)
-    {
-        if (strcmpW(Component,package->components[i].Component)==0)
-        {
-            rc = i;
-            break;
-        }
-    }
-    return rc;
-}
-
-int get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature )
-{
-    int rc = -1;
-    DWORD i;
-
-    for (i = 0; i < package->loaded_features; i++)
-    {
-        if (strcmpW(Feature,package->features[i].Feature)==0)
-        {
-            rc = i;
-            break;
-        }
-    }
-    return rc;
-}
-
-int get_loaded_file(MSIPACKAGE* package, LPCWSTR file)
-{
-    int rc = -1;
-    DWORD i;
-
-    for (i = 0; i < package->loaded_files; i++)
-    {
-        if (strcmpW(file,package->files[i].File)==0)
-        {
-            rc = i;
-            break;
-        }
-    }
-    return rc;
-}
-
-int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path)
-{
-    DWORD i;
-    DWORD index;
-
-    if (!package)
-        return -2;
-
-    for (i=0; i < package->loaded_files; i++)
-        if (strcmpW(package->files[i].File,name)==0)
-            return -1;
-
-    index = package->loaded_files;
-    package->loaded_files++;
-    if (package->loaded_files== 1)
-        package->files = HeapAlloc(GetProcessHeap(),0,sizeof(MSIFILE));
-    else
-        package->files = HeapReAlloc(GetProcessHeap(),0,
-            package->files , package->loaded_files * sizeof(MSIFILE));
-
-    memset(&package->files[index],0,sizeof(MSIFILE));
-
-    package->files[index].File = strdupW(name);
-    package->files[index].TargetPath = strdupW(path);
-    package->files[index].Temporary = TRUE;
-
-    TRACE("Tracking tempfile (%s)\n",debugstr_w(package->files[index].File));  
-
-    return 0;
-}
-
-static void remove_tracked_tempfiles(MSIPACKAGE* package)
-{
-    DWORD i;
-
-    if (!package)
-        return;
-
-    for (i = 0; i < package->loaded_files; i++)
-    {
-        if (package->files[i].Temporary)
-        {
-            TRACE("Cleaning up %s\n",debugstr_w(package->files[i].TargetPath));
-            DeleteFileW(package->files[i].TargetPath);
-        }
-
-    }
-}
-
-/* wrapper to resist a need for a full rewrite right now */
-DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data )
-{
-    if (ptr)
-    {
-        MSIRECORD *rec = MSI_CreateRecord(1);
-        DWORD size = 0;
-
-        MSI_RecordSetStringW(rec,0,ptr);
-        MSI_FormatRecordW(package,rec,NULL,&size);
-        if (size >= 0)
-        {
-            size++;
-            *data = HeapAlloc(GetProcessHeap(),0,size*sizeof(WCHAR));
-            if (size > 1)
-                MSI_FormatRecordW(package,rec,*data,&size);
-            else
-                *data[0] = 0;
-            msiobj_release( &rec->hdr );
-            return sizeof(WCHAR)*size;
-        }
-        msiobj_release( &rec->hdr );
-    }
-
-    *data = NULL;
-    return 0;
-}
-
-/* Called when the package is being closed */
-void ACTION_free_package_structures( MSIPACKAGE* package)
-{
-    INT i;
-    
-    TRACE("Freeing package action data\n");
-
-    remove_tracked_tempfiles(package);
-
-    /* No dynamic buffers in features */
-    if (package->features && package->loaded_features > 0)
-        HeapFree(GetProcessHeap(),0,package->features);
-
-    for (i = 0; i < package->loaded_folders; i++)
-    {
-        HeapFree(GetProcessHeap(),0,package->folders[i].Directory);
-        HeapFree(GetProcessHeap(),0,package->folders[i].TargetDefault);
-        HeapFree(GetProcessHeap(),0,package->folders[i].SourceDefault);
-        HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedTarget);
-        HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedSource);
-        HeapFree(GetProcessHeap(),0,package->folders[i].Property);
-    }
-    if (package->folders && package->loaded_folders > 0)
-        HeapFree(GetProcessHeap(),0,package->folders);
-
-    for (i = 0; i < package->loaded_components; i++)
-        HeapFree(GetProcessHeap(),0,package->components[i].FullKeypath);
-
-    if (package->components && package->loaded_components > 0)
-        HeapFree(GetProcessHeap(),0,package->components);
 
-    for (i = 0; i < package->loaded_files; i++)
-    {
-        HeapFree(GetProcessHeap(),0,package->files[i].File);
-        HeapFree(GetProcessHeap(),0,package->files[i].FileName);
-        HeapFree(GetProcessHeap(),0,package->files[i].ShortName);
-        HeapFree(GetProcessHeap(),0,package->files[i].Version);
-        HeapFree(GetProcessHeap(),0,package->files[i].Language);
-        HeapFree(GetProcessHeap(),0,package->files[i].SourcePath);
-        HeapFree(GetProcessHeap(),0,package->files[i].TargetPath);
-    }
-
-    if (package->files && package->loaded_files > 0)
-        HeapFree(GetProcessHeap(),0,package->files);
-
-    for (i = 0; i < package->DeferredActionCount; i++)
-        HeapFree(GetProcessHeap(),0,package->DeferredAction[i]);
-    HeapFree(GetProcessHeap(),0,package->DeferredAction);
-
-    for (i = 0; i < package->CommitActionCount; i++)
-        HeapFree(GetProcessHeap(),0,package->CommitAction[i]);
-    HeapFree(GetProcessHeap(),0,package->CommitAction);
-
-    HeapFree(GetProcessHeap(),0,package->PackagePath);
-}
-
-static void ui_progress(MSIPACKAGE *package, int a, int b, int c, int d )
-{
-    MSIRECORD * row;
-
-    row = MSI_CreateRecord(4);
-    MSI_RecordSetInteger(row,1,a);
-    MSI_RecordSetInteger(row,2,b);
-    MSI_RecordSetInteger(row,3,c);
-    MSI_RecordSetInteger(row,4,d);
-    MSI_ProcessMessage(package, INSTALLMESSAGE_PROGRESS, row);
-    msiobj_release(&row->hdr);
-
-    msi_dialog_check_messages(NULL);
-}
-
-static void ui_actiondata(MSIPACKAGE *package, LPCWSTR action, MSIRECORD * record)
+static void ce_actiontext(MSIPACKAGE* package, LPCWSTR action)
 {
-    static const WCHAR Query_t[] = 
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','A','c','t','i','o', 'n','T','e','x','t','`',' ',
-         'W','H','E','R','E',' ', '`','A','c','t','i','o','n','`',' ','=', 
-         ' ','\'','%','s','\'',0};
-    WCHAR message[1024];
-    UINT rc;
-    MSIQUERY * view;
-    MSIRECORD * row = 0;
-    DWORD size;
-
-    if (!package->LastAction || strcmpW(package->LastAction,action))
-    {
-        rc = MSI_OpenQuery(package->db, &view, Query_t, action);
-        if (rc != ERROR_SUCCESS)
-            return;
-
-        rc = MSI_ViewExecute(view, 0);
-        if (rc != ERROR_SUCCESS)
-        {
-            MSI_ViewClose(view);
-            msiobj_release(&view->hdr);
-            return;
-        }
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            MSI_ViewClose(view);
-            msiobj_release(&view->hdr);
-            return;
-        }
-
-        if (MSI_RecordIsNull(row,3))
-        {
-            msiobj_release(&row->hdr);
-            MSI_ViewClose(view);
-            msiobj_release(&view->hdr);
-            return;
-        }
-
-        /* update the cached actionformat */
-        HeapFree(GetProcessHeap(),0,package->ActionFormat);
-        package->ActionFormat = load_dynamic_stringW(row,3);
-
-        HeapFree(GetProcessHeap(),0,package->LastAction);
-        package->LastAction = strdupW(action);
-
-        msiobj_release(&row->hdr);
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-    }
-
-    MSI_RecordSetStringW(record,0,package->ActionFormat);
-    size = 1024;
-    MSI_FormatRecordW(package,record,message,&size);
+    static const WCHAR szActionText[] = 
+        {'A','c','t','i','o','n','T','e','x','t',0};
+    MSIRECORD *row;
 
     row = MSI_CreateRecord(1);
-    MSI_RecordSetStringW(row,1,message);
-    MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, row);
+    MSI_RecordSetStringW(row,1,action);
+    ControlEvent_FireSubscribedEvent(package,szActionText, row);
     msiobj_release(&row->hdr);
 }
 
-
 static void ui_actionstart(MSIPACKAGE *package, LPCWSTR action)
 {
     static const WCHAR template_s[]=
@@ -722,44 +377,25 @@ static void ui_actionstart(MSIPACKAGE *package, LPCWSTR action)
          ' ','\'','%','s','\'',0};
     WCHAR message[1024];
     WCHAR timet[0x100];
-    UINT rc;
-    MSIQUERY * view;
     MSIRECORD * row = 0;
-    WCHAR *ActionText=NULL;
+    LPCWSTR ActionText;
 
     GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);
 
-    rc = MSI_OpenQuery(package->db, &view, Query_t, action);
-    if (rc != ERROR_SUCCESS)
-        return;
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return;
-    }
-    rc = MSI_ViewFetch(view,&row);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
+    row = MSI_QueryGetRecord( package->db, Query_t, action );
+    if (!row)
         return;
-    }
 
-    ActionText = load_dynamic_stringW(row,2);
-    msiobj_release(&row->hdr);
-    MSI_ViewClose(view);
-    msiobj_release(&view->hdr);
+    ActionText = MSI_RecordGetString(row,2);
 
     sprintfW(message,template_s,timet,action,ActionText);
+    msiobj_release(&row->hdr);
 
     row = MSI_CreateRecord(1);
     MSI_RecordSetStringW(row,1,message);
  
     MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONSTART, row);
     msiobj_release(&row->hdr);
-    HeapFree(GetProcessHeap(),0,ActionText);
 }
 
 static void ui_actioninfo(MSIPACKAGE *package, LPCWSTR action, BOOL start, 
@@ -791,82 +427,6 @@ static void ui_actioninfo(MSIPACKAGE *package, LPCWSTR action, BOOL start,
     msiobj_release(&row->hdr);
 }
 
-/*
- *  build_directory_name()
- *
- *  This function is to save messing round with directory names
- *  It handles adding backslashes between path segments, 
- *   and can add \ at the end of the directory name if told to.
- *
- *  It takes a variable number of arguments.
- *  It always allocates a new string for the result, so make sure
- *   to free the return value when finished with it.
- *
- *  The first arg is the number of path segments that follow.
- *  The arguments following count are a list of path segments.
- *  A path segment may be NULL.
- *
- *  Path segments will be added with a \ separating them.
- *  A \ will not be added after the last segment, however if the
- *    last segment is NULL, then the last character will be a \
- * 
- */
-static LPWSTR build_directory_name(DWORD count, ...)
-{
-    DWORD sz = 1, i;
-    LPWSTR dir;
-    va_list va;
-
-    va_start(va,count);
-    for(i=0; i<count; i++)
-    {
-        LPCWSTR str = va_arg(va,LPCWSTR);
-        if (str)
-            sz += strlenW(str) + 1;
-    }
-    va_end(va);
-
-    dir = HeapAlloc(GetProcessHeap(), 0, sz*sizeof(WCHAR));
-    dir[0]=0;
-
-    va_start(va,count);
-    for(i=0; i<count; i++)
-    {
-        LPCWSTR str = va_arg(va,LPCWSTR);
-        if (!str)
-            continue;
-        strcatW(dir, str);
-        if( ((i+1)!=count) && dir[strlenW(dir)-1]!='\\')
-            strcatW(dir, cszbs);
-    }
-    return dir;
-}
-
-static BOOL ACTION_VerifyComponentForAction(MSIPACKAGE* package, INT index, 
-                                            INSTALLSTATE check )
-{
-    if (package->components[index].Installed == check)
-        return FALSE;
-
-    if (package->components[index].ActionRequest == check)
-        return TRUE;
-    else
-        return FALSE;
-}
-
-static BOOL ACTION_VerifyFeatureForAction(MSIPACKAGE* package, INT index, 
-                                            INSTALLSTATE check )
-{
-    if (package->features[index].Installed == check)
-        return FALSE;
-
-    if (package->features[index].ActionRequest == check)
-        return TRUE;
-    else
-        return FALSE;
-}
-
-
 /****************************************************
  * TOP level entry points 
  *****************************************************/
@@ -883,7 +443,9 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath,
     static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0};
 
     MSI_SetPropertyW(package, szAction, szInstall);
-    package->ExecuteSequenceRun = FALSE;
+
+    package->script = HeapAlloc(GetProcessHeap(),0,sizeof(MSISCRIPT));
+    memset(package->script,0,sizeof(MSISCRIPT));
 
     if (szPackagePath)   
     {
@@ -993,15 +555,17 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath,
         rc = ERROR_SUCCESS;
     }
 
+    package->script->CurrentlyScripting= FALSE;
+
     /* process the ending type action */
     if (rc == ERROR_SUCCESS)
         ACTION_PerformActionSequence(package,-1,ui);
     else if (rc == ERROR_INSTALL_USEREXIT) 
         ACTION_PerformActionSequence(package,-2,ui);
-    else if (rc == ERROR_FUNCTION_FAILED) 
-        ACTION_PerformActionSequence(package,-3,ui);
     else if (rc == ERROR_INSTALL_SUSPEND) 
         ACTION_PerformActionSequence(package,-4,ui);
+    else  /* failed */
+        ACTION_PerformActionSequence(package,-3,ui);
 
     /* finish up running custom actions */
     ACTION_FinishCustomActions(package);
@@ -1011,10 +575,7 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath,
 
 static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI)
 {
-    MSIQUERY * view;
-    UINT rc;
-    WCHAR buffer[0x100];
-    DWORD sz = 0x100;
+    UINT rc = ERROR_SUCCESS;
     MSIRECORD * row = 0;
     static const WCHAR ExecSeqQuery[] =
         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
@@ -1029,71 +590,88 @@ static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI)
         ' ', '=',' ','%','i',0};
 
     if (UI)
-        rc = MSI_OpenQuery(package->db, &view, UISeqQuery, seq);
+        row = MSI_QueryGetRecord(package->db, UISeqQuery, seq);
     else
-        rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, seq);
+        row = MSI_QueryGetRecord(package->db, ExecSeqQuery, seq);
 
-    if (rc == ERROR_SUCCESS)
+    if (row)
     {
-        rc = MSI_ViewExecute(view, 0);
+        LPCWSTR action, cond;
 
-        if (rc != ERROR_SUCCESS)
-        {
-            MSI_ViewClose(view);
-            msiobj_release(&view->hdr);
-            goto end;
-        }
-       
         TRACE("Running the actions\n"); 
 
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
+        /* check conditions */
+        cond = MSI_RecordGetString(row,2);
+        if (cond)
         {
-            rc = ERROR_SUCCESS;
-            goto end;
+            /* this is a hack to skip errors in the condition code */
+            if (MSI_EvaluateConditionW(package, cond) == MSICONDITION_FALSE)
+                goto end;
         }
 
-        /* check conditions */
-        if (!MSI_RecordIsNull(row,2))
+        action = MSI_RecordGetString(row,1);
+        if (!action)
         {
-            LPWSTR cond = NULL;
-            cond = load_dynamic_stringW(row,2);
-
-            if (cond)
-            {
-                /* this is a hack to skip errors in the condition code */
-                if (MSI_EvaluateConditionW(package, cond) == MSICONDITION_FALSE)
-                {
-                    HeapFree(GetProcessHeap(),0,cond);
-                    msiobj_release(&row->hdr);
-                    goto end;
-                }
-                else
-                    HeapFree(GetProcessHeap(),0,cond);
-            }
-        }
-
-        sz=0x100;
-        rc =  MSI_RecordGetStringW(row,1,buffer,&sz);
-        if (rc != ERROR_SUCCESS)
-        {
-            ERR("Error is %x\n",rc);
-            msiobj_release(&row->hdr);
-            goto end;
-        }
+            ERR("failed to fetch action\n");
+            rc = ERROR_FUNCTION_FAILED;
+            goto end;
+        }
 
         if (UI)
-            rc = ACTION_PerformUIAction(package,buffer);
+            rc = ACTION_PerformUIAction(package,action);
         else
-            rc = ACTION_PerformAction(package,buffer);
-        msiobj_release(&row->hdr);
+            rc = ACTION_PerformAction(package,action,FALSE);
 end:
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
+        msiobj_release(&row->hdr);
+    }
+    else
+        rc = ERROR_SUCCESS;
+
+    return rc;
+}
+
+typedef struct {
+    MSIPACKAGE* package;
+    BOOL UI;
+} iterate_action_param;
+
+static UINT ITERATE_Actions(MSIRECORD *row, LPVOID param)
+{
+    iterate_action_param *iap= (iterate_action_param*)param;
+    UINT rc;
+    LPCWSTR cond, action;
+
+    action = MSI_RecordGetString(row,1);
+    if (!action)
+    {
+        ERR("Error is retrieving action name\n");
+        return  ERROR_FUNCTION_FAILED;
+    }
+
+    /* check conditions */
+    cond = MSI_RecordGetString(row,2);
+    if (cond)
+    {
+        /* this is a hack to skip errors in the condition code */
+        if (MSI_EvaluateConditionW(iap->package, cond) == MSICONDITION_FALSE)
+        {
+            TRACE("Skipping action: %s (condition is false)\n",
+                            debugstr_w(action));
+            return ERROR_SUCCESS;
+        }
     }
+
+    if (iap->UI)
+        rc = ACTION_PerformUIAction(iap->package,action);
     else
+        rc = ACTION_PerformAction(iap->package,action,FALSE);
+
+    if (rc == ERROR_FUNCTION_NOT_CALLED)
         rc = ERROR_SUCCESS;
 
+    if (rc != ERROR_SUCCESS)
+        ERR("Execution halted due to error (%i)\n",rc);
+
     return rc;
 }
 
@@ -1117,122 +695,41 @@ static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran)
          ' ','\'', 'I','n','s','t','a','l','l',
          'V','a','l','i','d','a','t','e','\'', 0};
     INT seq = 0;
+    iterate_action_param iap;
 
+    iap.package = package;
+    iap.UI = FALSE;
 
-    if (package->ExecuteSequenceRun)
+    if (package->script->ExecuteSequenceRun)
     {
         TRACE("Execute Sequence already Run\n");
         return ERROR_SUCCESS;
     }
 
-    package->ExecuteSequenceRun = TRUE;
-    
+    package->script->ExecuteSequenceRun = TRUE;
+
     /* get the sequence number */
     if (UIran)
     {
-        rc = MSI_DatabaseOpenViewW(package->db, IVQuery, &view);
-        if (rc != ERROR_SUCCESS)
-            return rc;
-        rc = MSI_ViewExecute(view, 0);
-        if (rc != ERROR_SUCCESS)
-        {
-            MSI_ViewClose(view);
-            msiobj_release(&view->hdr);
-            return rc;
-        }
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            MSI_ViewClose(view);
-            msiobj_release(&view->hdr);
-            return rc;
-        }
+        row = MSI_QueryGetRecord(package->db, IVQuery);
+        if( !row )
+            return ERROR_FUNCTION_FAILED;
         seq = MSI_RecordGetInteger(row,1);
         msiobj_release(&row->hdr);
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
     }
 
     rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, seq);
     if (rc == ERROR_SUCCESS)
     {
-        rc = MSI_ViewExecute(view, 0);
-
-        if (rc != ERROR_SUCCESS)
-        {
-            MSI_ViewClose(view);
-            msiobj_release(&view->hdr);
-            goto end;
-        }
-       
-        TRACE("Running the actions\n"); 
-
-        while (1)
-        {
-            WCHAR buffer[0x100];
-            DWORD sz = 0x100;
-
-            rc = MSI_ViewFetch(view,&row);
-            if (rc != ERROR_SUCCESS)
-            {
-                rc = ERROR_SUCCESS;
-                break;
-            }
-
-            /* check conditions */
-            if (!MSI_RecordIsNull(row,2))
-            {
-                LPWSTR cond = NULL;
-                cond = load_dynamic_stringW(row,2);
-
-                if (cond)
-                {
-                    /* this is a hack to skip errors in the condition code */
-                    if (MSI_EvaluateConditionW(package, cond) ==
-                            MSICONDITION_FALSE)
-                    {
-                        HeapFree(GetProcessHeap(),0,cond);
-                        msiobj_release(&row->hdr);
-                        continue; 
-                    }
-                    else
-                        HeapFree(GetProcessHeap(),0,cond);
-                }
-            }
-
-            sz=0x100;
-            rc =  MSI_RecordGetStringW(row,1,buffer,&sz);
-            if (rc != ERROR_SUCCESS)
-            {
-                ERR("Error is %x\n",rc);
-                msiobj_release(&row->hdr);
-                break;
-            }
-
-            rc = ACTION_PerformAction(package,buffer);
-
-            if (rc == ERROR_FUNCTION_NOT_CALLED)
-                rc = ERROR_SUCCESS;
-
-            if (rc != ERROR_SUCCESS)
-            {
-                ERR("Execution halted due to error (%i)\n",rc);
-                msiobj_release(&row->hdr);
-                break;
-            }
-
-            msiobj_release(&row->hdr);
-        }
+        TRACE("Running the actions\n");
 
-        MSI_ViewClose(view);
+        rc = MSI_IterateRecords(view, NULL, ITERATE_Actions, &iap);
         msiobj_release(&view->hdr);
     }
 
-end:
     return rc;
 }
 
-
 static UINT ACTION_ProcessUISequence(MSIPACKAGE *package)
 {
     MSIQUERY * view;
@@ -1245,113 +742,70 @@ static UINT ACTION_ProcessUISequence(MSIPACKAGE *package)
          '`','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;
+
+    iap.package = package;
+    iap.UI = TRUE;
+
     rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
     
     if (rc == ERROR_SUCCESS)
     {
-        rc = MSI_ViewExecute(view, 0);
-
-        if (rc != ERROR_SUCCESS)
-        {
-            MSI_ViewClose(view);
-            msiobj_release(&view->hdr);
-            goto end;
-        }
-       
         TRACE("Running the actions \n"); 
 
-        while (1)
-        {
-            WCHAR buffer[0x100];
-            DWORD sz = 0x100;
-            MSIRECORD * row = 0;
-
-            rc = MSI_ViewFetch(view,&row);
-            if (rc != ERROR_SUCCESS)
-            {
-                rc = ERROR_SUCCESS;
-                break;
-            }
-
-            /* check conditions */
-            if (!MSI_RecordIsNull(row,2))
-            {
-                LPWSTR cond = NULL;
-                cond = load_dynamic_stringW(row,2);
-
-                if (cond)
-                {
-                    /* this is a hack to skip errors in the condition code */
-                    if (MSI_EvaluateConditionW(package, cond) ==
-                            MSICONDITION_FALSE)
-                    {
-                        HeapFree(GetProcessHeap(),0,cond);
-                        msiobj_release(&row->hdr);
-                        continue; 
-                    }
-                    else
-                        HeapFree(GetProcessHeap(),0,cond);
-                }
-            }
-
-            sz=0x100;
-            rc =  MSI_RecordGetStringW(row,1,buffer,&sz);
-            if (rc != ERROR_SUCCESS)
-            {
-                ERR("Error is %x\n",rc);
-                msiobj_release(&row->hdr);
-                break;
-            }
-
-            rc = ACTION_PerformUIAction(package,buffer);
-
-            if (rc == ERROR_FUNCTION_NOT_CALLED)
-                rc = ERROR_SUCCESS;
-
-            if (rc != ERROR_SUCCESS)
-            {
-                ERR("Execution halted due to error (%i)\n",rc);
-                msiobj_release(&row->hdr);
-                break;
-            }
-
-            msiobj_release(&row->hdr);
-        }
-
-        MSI_ViewClose(view);
+        rc = MSI_IterateRecords(view, NULL, ITERATE_Actions, &iap);
         msiobj_release(&view->hdr);
     }
 
-end:
     return rc;
 }
 
 /********************************************************
  * ACTION helper functions and functions that perform the actions
  *******************************************************/
-BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action, UINT* rc)
+static BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action, 
+                                        UINT* rc, BOOL force )
 {
     BOOL ret = FALSE; 
-
+    BOOL run = force;
     int i;
+
+    if (!run && !package->script->CurrentlyScripting)
+        run = TRUE;
+   
+    if (!run)
+    {
+        if (strcmpW(action,szInstallFinalize) == 0 ||
+            strcmpW(action,szInstallExecute) == 0 ||
+            strcmpW(action,szInstallExecuteAgain) == 0) 
+                run = TRUE;
+    }
+    
     i = 0;
     while (StandardActions[i].action != NULL)
     {
         if (strcmpW(StandardActions[i].action, action)==0)
         {
-            ui_actioninfo(package, action, TRUE, 0);
-            ui_actionstart(package, action);
-            if (StandardActions[i].handler)
+            ce_actiontext(package, action);
+            if (!run)
             {
-                *rc = StandardActions[i].handler(package);
+                ui_actioninfo(package, action, TRUE, 0);
+                *rc = schedule_action(package,INSTALL_SCRIPT,action);
+                ui_actioninfo(package, action, FALSE, *rc);
             }
             else
             {
-                FIXME("UNHANDLED Standard Action %s\n",debugstr_w(action));
-                *rc = ERROR_SUCCESS;
+                ui_actionstart(package, action);
+                if (StandardActions[i].handler)
+                {
+                    *rc = StandardActions[i].handler(package);
+                }
+                else
+                {
+                    FIXME("UNHANDLED Standard Action %s\n",debugstr_w(action));
+                    *rc = ERROR_SUCCESS;
+                }
             }
-            ui_actioninfo(package, action, FALSE, *rc);
             ret = TRUE;
             break;
         }
@@ -1360,28 +814,25 @@ BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action, UINT* rc)
     return ret;
 }
 
-BOOL ACTION_HandleDialogBox(MSIPACKAGE *package, LPCWSTR dialog, UINT* rc)
+static BOOL ACTION_HandleDialogBox( MSIPACKAGE *package, LPCWSTR dialog, UINT* rc )
 {
     BOOL ret = FALSE;
 
-    /*
-     * for the UI when we get that working
-     *
     if (ACTION_DialogBox(package,dialog) == ERROR_SUCCESS)
     {
         *rc = package->CurrentInstallState;
         ret = TRUE;
     }
-    */
     return ret;
 }
 
-BOOL ACTION_HandleCustomAction(MSIPACKAGE* package, LPCWSTR action, UINT* rc)
+static BOOL ACTION_HandleCustomAction( MSIPACKAGE* package, LPCWSTR action,
+                                       UINT* rc, BOOL force )
 {
     BOOL ret=FALSE;
     UINT arc;
 
-    arc = ACTION_CustomAction(package,action,FALSE);
+    arc = ACTION_CustomAction(package,action, force);
 
     if (arc != ERROR_CALL_NOT_IMPLEMENTED)
     {
@@ -1399,17 +850,17 @@ BOOL ACTION_HandleCustomAction(MSIPACKAGE* package, LPCWSTR action, UINT* rc)
  * But until I get write access to the database that is hard, so I am going to
  * hack it to see if I can get something to run.
  */
-UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action)
+UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action, BOOL force)
 {
     UINT rc = ERROR_SUCCESS; 
     BOOL handled;
 
     TRACE("Performing action (%s)\n",debugstr_w(action));
 
-    handled = ACTION_HandleStandardAction(package, action, &rc);
+    handled = ACTION_HandleStandardAction(package, action, &rc, force);
 
     if (!handled)
-        handled = ACTION_HandleCustomAction(package, action, &rc);
+        handled = ACTION_HandleCustomAction(package, action, &rc, force);
 
     if (!handled)
     {
@@ -1428,10 +879,10 @@ UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action)
 
     TRACE("Performing action (%s)\n",debugstr_w(action));
 
-    handled = ACTION_HandleStandardAction(package, action, &rc);
+    handled = ACTION_HandleStandardAction(package, action, &rc,TRUE);
 
     if (!handled)
-        handled = ACTION_HandleCustomAction(package, action, &rc);
+        handled = ACTION_HandleCustomAction(package, action, &rc, FALSE);
 
     if (!handled)
         handled = ACTION_HandleDialogBox(package, action, &rc);
@@ -1448,60 +899,51 @@ UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action)
     return rc;
 }
 
-/***********************************************************************
- *            create_full_pathW
- *
- * Recursively create all directories in the path.
- *
- * shamelessly stolen from setupapi/queue.c
- */
-static BOOL create_full_pathW(const WCHAR *path)
-{
-    BOOL ret = TRUE;
-    int len;
-    WCHAR *new_path;
 
-    new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) *
-                                              sizeof(WCHAR));
+/*
+ * Actual Action Handlers
+ */
 
-    strcpyW(new_path, path);
+static UINT ITERATE_CreateFolders(MSIRECORD *row, LPVOID param)
+{
+    MSIPACKAGE *package = (MSIPACKAGE*)param;
+    LPCWSTR dir;
+    LPWSTR full_path;
+    MSIRECORD *uirow;
+    MSIFOLDER *folder;
 
-    while((len = strlenW(new_path)) && new_path[len - 1] == '\\')
-    new_path[len - 1] = 0;
+    dir = MSI_RecordGetString(row,1);
+    if (!dir)
+    {
+        ERR("Unable to get folder id \n");
+        return ERROR_SUCCESS;
+    }
 
-    while(!CreateDirectoryW(new_path, NULL))
+    full_path = resolve_folder(package,dir,FALSE,FALSE,&folder);
+    if (!full_path)
     {
-        WCHAR *slash;
-        DWORD last_error = GetLastError();
-        if(last_error == ERROR_ALREADY_EXISTS)
-            break;
+        ERR("Unable to resolve folder id %s\n",debugstr_w(dir));
+        return ERROR_SUCCESS;
+    }
 
-        if(last_error != ERROR_PATH_NOT_FOUND)
-        {
-            ret = FALSE;
-            break;
-        }
+    TRACE("Folder is %s\n",debugstr_w(full_path));
 
-        if(!(slash = strrchrW(new_path, '\\')))
-        {
-            ret = FALSE;
-            break;
-        }
+    /* UI stuff */
+    uirow = MSI_CreateRecord(1);
+    MSI_RecordSetStringW(uirow,1,full_path);
+    ui_actiondata(package,szCreateFolders,uirow);
+    msiobj_release( &uirow->hdr );
 
-        len = slash - new_path;
-        new_path[len] = 0;
-        if(!create_full_pathW(new_path))
-        {
-            ret = FALSE;
-            break;
-        }
-        new_path[len] = '\\';
-    }
+    if (folder->State == 0)
+        create_full_pathW(full_path);
 
-    HeapFree(GetProcessHeap(), 0, new_path);
-    return ret;
+    folder->State = 3;
+
+    HeapFree(GetProcessHeap(),0,full_path);
+    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.
@@ -1515,70 +957,12 @@ static UINT ACTION_CreateFolders(MSIPACKAGE *package)
          '`','C','r','e','a','t','e','F','o','l','d','e','r','`',0 };
     UINT rc;
     MSIQUERY *view;
-    MSIFOLDER *folder;
 
     rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view );
     if (rc != ERROR_SUCCESS)
         return ERROR_SUCCESS;
 
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
-    }
-    
-    while (1)
-    {
-        WCHAR dir[0x100];
-        LPWSTR full_path;
-        DWORD sz;
-        MSIRECORD *row = NULL, *uirow;
-
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            rc = ERROR_SUCCESS;
-            break;
-        }
-
-        sz=0x100;
-        rc = MSI_RecordGetStringW(row,1,dir,&sz);
-
-        if (rc!= ERROR_SUCCESS)
-        {
-            ERR("Unable to get folder id \n");
-            msiobj_release(&row->hdr);
-            continue;
-        }
-
-        sz = MAX_PATH;
-        full_path = resolve_folder(package,dir,FALSE,FALSE,&folder);
-        if (!full_path)
-        {
-            ERR("Unable to resolve folder id %s\n",debugstr_w(dir));
-            msiobj_release(&row->hdr);
-            continue;
-        }
-
-        TRACE("Folder is %s\n",debugstr_w(full_path));
-
-        /* UI stuff */
-        uirow = MSI_CreateRecord(1);
-        MSI_RecordSetStringW(uirow,1,full_path);
-        ui_actiondata(package,szCreateFolders,uirow);
-        msiobj_release( &uirow->hdr );
-
-        if (folder->State == 0)
-            create_full_pathW(full_path);
-
-        folder->State = 3;
-
-        msiobj_release(&row->hdr);
-        HeapFree(GetProcessHeap(),0,full_path);
-    }
-    MSI_ViewClose(view);
+    rc = MSI_IterateRecords(view, NULL, ITERATE_CreateFolders, package);
     msiobj_release(&view->hdr);
    
     return rc;
@@ -1602,7 +986,7 @@ static int load_component(MSIPACKAGE* package, MSIRECORD * row)
 
     memset(&package->components[index],0,sizeof(MSICOMPONENT));
 
-    sz = 96;       
+    sz = IDENTIFIER_SIZE;       
     MSI_RecordGetStringW(row,1,package->components[index].Component,&sz);
 
     TRACE("Loading Component %s\n",
@@ -1612,7 +996,7 @@ static int load_component(MSIPACKAGE* package, MSIRECORD * row)
     if (!MSI_RecordIsNull(row,2))
         MSI_RecordGetStringW(row,2,package->components[index].ComponentId,&sz);
             
-    sz = 96;       
+    sz = IDENTIFIER_SIZE;       
     MSI_RecordGetStringW(row,3,package->components[index].Directory,&sz);
 
     package->components[index].Attributes = MSI_RecordGetInteger(row,4);
@@ -1620,7 +1004,7 @@ static int load_component(MSIPACKAGE* package, MSIRECORD * row)
     sz = 0x100;       
     MSI_RecordGetStringW(row,5,package->components[index].Condition,&sz);
 
-    sz = 96;       
+    sz = IDENTIFIER_SIZE;       
     MSI_RecordGetStringW(row,6,package->components[index].KeyPath,&sz);
 
     package->components[index].Installed = INSTALLSTATE_ABSENT;
@@ -1632,8 +1016,68 @@ static int load_component(MSIPACKAGE* package, MSIRECORD * row)
     return index;
 }
 
-static void load_feature(MSIPACKAGE* package, MSIRECORD * row)
+typedef struct {
+    MSIPACKAGE *package;
+    INT index;
+    INT cnt;
+} _ilfs;
+
+static UINT iterate_component_check(MSIRECORD *row, LPVOID param)
+{
+    _ilfs* ilfs= (_ilfs*)param;
+    INT c_indx;
+
+    c_indx = load_component(ilfs->package,row);
+
+    ilfs->package->features[ilfs->index].Components[ilfs->cnt] = c_indx;
+    ilfs->package->features[ilfs->index].ComponentCount ++;
+    TRACE("Loaded new component to index %i\n",c_indx);
+
+    return ERROR_SUCCESS;
+}
+
+static UINT iterate_load_featurecomponents(MSIRECORD *row, LPVOID param)
+{
+    _ilfs* ilfs= (_ilfs*)param;
+    LPCWSTR component;
+    DWORD rc;
+    INT c_indx;
+    INT cnt = ilfs->package->features[ilfs->index].ComponentCount;
+    MSIQUERY * view;
+    static const WCHAR Query[] = 
+        {'S','E','L','E','C','T',' ','*',' ','F','R', 'O','M',' ', 
+         '`','C','o','m','p','o','n','e','n','t','`',' ',
+         'W','H','E','R','E',' ', 
+         '`','C','o','m','p','o','n','e','n','t','`',' ',
+         '=','\'','%','s','\'',0};
+
+    component = MSI_RecordGetString(row,1);
+
+    /* check to see if the component is already loaded */
+    c_indx = get_loaded_component(ilfs->package,component);
+    if (c_indx != -1)
+    {
+        TRACE("Component %s already loaded at %i\n", debugstr_w(component),
+                        c_indx);
+        ilfs->package->features[ilfs->index].Components[cnt] = c_indx;
+        ilfs->package->features[ilfs->index].ComponentCount ++;
+        return ERROR_SUCCESS;
+    }
+
+    rc = MSI_OpenQuery(ilfs->package->db, &view, Query, component);
+    if (rc != ERROR_SUCCESS)
+        return ERROR_SUCCESS;
+
+    ilfs->cnt = cnt;
+    rc = MSI_IterateRecords(view, NULL, iterate_component_check, ilfs);
+    msiobj_release( &view->hdr );
+
+    return ERROR_SUCCESS;
+}
+
+static UINT load_feature(MSIRECORD * row, LPVOID param)
 {
+    MSIPACKAGE* package = (MSIPACKAGE*)param;
     int index = package->loaded_features;
     DWORD sz;
     static const WCHAR Query1[] = 
@@ -1643,17 +1087,12 @@ static void load_feature(MSIPACKAGE* package, MSIRECORD * row)
          'C','o','m','p','o','n','e','n','t','s','`',' ',
          'W','H','E','R','E',' ',
          '`','F','e', 'a','t','u','r','e','_','`',' ','=','\'','%','s','\'',0};
-    static const WCHAR Query2[] = 
-        {'S','E','L','E','C','T',' ','*',' ','F','R', 'O','M',' ', 
-         '`','C','o','m','p','o','n','e','n','t','`',' ',
-         'W','H','E','R','E',' ', 
-         '`','C','o','m','p','o','n','e','n','t','`',' ',
-         '=','\'','%','s','\'',0};
     MSIQUERY * view;
-    MSIQUERY * view2;
-    MSIRECORD * row2;
-    MSIRECORD * row3;
     UINT    rc;
+    _ilfs ilfs;
+
+    ilfs.package = package;
+    ilfs.index = index;
 
     /* fill in the data */
 
@@ -1666,12 +1105,12 @@ static void load_feature(MSIPACKAGE* package, MSIRECORD * row)
 
     memset(&package->features[index],0,sizeof(MSIFEATURE));
     
-    sz = 96;       
+    sz = IDENTIFIER_SIZE;       
     MSI_RecordGetStringW(row,1,package->features[index].Feature,&sz);
 
     TRACE("Loading feature %s\n",debugstr_w(package->features[index].Feature));
 
-    sz = 96;
+    sz = IDENTIFIER_SIZE;
     if (!MSI_RecordIsNull(row,2))
         MSI_RecordGetStringW(row,2,package->features[index].Feature_Parent,&sz);
 
@@ -1688,7 +1127,7 @@ static void load_feature(MSIPACKAGE* package, MSIRECORD * row)
   
     package->features[index].Level= MSI_RecordGetInteger(row,6);
 
-     sz = 96;
+     sz = IDENTIFIER_SIZE;
      if (!MSI_RecordIsNull(row,7))
         MSI_RecordGetStringW(row,7,package->features[index].Directory,&sz);
 
@@ -1700,84 +1139,22 @@ static void load_feature(MSIPACKAGE* package, MSIRECORD * row)
 
     /* load feature components */
 
-    rc = MSI_OpenQuery(package->db, &view, Query1, package->features[index].Feature);
-    if (rc != ERROR_SUCCESS)
-        return;
-    rc = MSI_ViewExecute(view,0);
+    rc = MSI_OpenQuery(package->db, &view, Query1, 
+                    package->features[index].Feature);
     if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return;
-    }
-    while (1)
-    {
-        DWORD sz = 0x100;
-        WCHAR buffer[0x100];
-        DWORD rc;
-        INT c_indx;
-        INT cnt = package->features[index].ComponentCount;
-
-        rc = MSI_ViewFetch(view,&row2);
-        if (rc != ERROR_SUCCESS)
-            break;
+        return ERROR_SUCCESS;
 
-        sz = 0x100;
-        MSI_RecordGetStringW(row2,1,buffer,&sz);
+    MSI_IterateRecords(view, NULL, iterate_load_featurecomponents , &ilfs);
+    msiobj_release(&view->hdr);
 
-        /* check to see if the component is already loaded */
-        c_indx = get_loaded_component(package,buffer);
-        if (c_indx != -1)
-        {
-            TRACE("Component %s already loaded at %i\n", debugstr_w(buffer),
-                  c_indx);
-            package->features[index].Components[cnt] = c_indx;
-            package->features[index].ComponentCount ++;
-            msiobj_release( &row2->hdr );
-            continue;
-        }
-
-        rc = MSI_OpenQuery(package->db, &view2, Query2, buffer);
-        if (rc != ERROR_SUCCESS)
-        {
-            msiobj_release( &row2->hdr );
-            continue;
-        }
-        rc = MSI_ViewExecute(view2,0);
-        if (rc != ERROR_SUCCESS)
-        {
-            msiobj_release( &row2->hdr );
-            MSI_ViewClose(view2);
-            msiobj_release( &view2->hdr );  
-            continue;
-        }
-        while (1)
-        {
-            DWORD rc;
-
-            rc = MSI_ViewFetch(view2,&row3);
-            if (rc != ERROR_SUCCESS)
-                break;
-            c_indx = load_component(package,row3);
-            msiobj_release( &row3->hdr );
-
-            package->features[index].Components[cnt] = c_indx;
-            package->features[index].ComponentCount ++;
-            TRACE("Loaded new component to index %i\n",c_indx);
-        }
-        MSI_ViewClose(view2);
-        msiobj_release( &view2->hdr );
-        msiobj_release( &row2->hdr );
-    }
-    MSI_ViewClose(view);
-    msiobj_release(&view->hdr);
+    return ERROR_SUCCESS;
 }
 
-static UINT load_file(MSIPACKAGE* package, MSIRECORD * row)
+static UINT load_file(MSIRECORD *row, LPVOID param)
 {
+    MSIPACKAGE* package = (MSIPACKAGE*)param;
     DWORD index = package->loaded_files;
-    DWORD i;
-    LPWSTR buffer;
+    LPCWSTR component;
 
     /* fill in the data */
 
@@ -1791,18 +1168,13 @@ static UINT load_file(MSIPACKAGE* package, MSIRECORD * row)
     memset(&package->files[index],0,sizeof(MSIFILE));
  
     package->files[index].File = load_dynamic_stringW(row, 1);
-    buffer = load_dynamic_stringW(row, 2);
 
-    package->files[index].ComponentIndex = -1;
-    for (i = 0; i < package->loaded_components; i++)
-        if (strcmpW(package->components[i].Component,buffer)==0)
-        {
-            package->files[index].ComponentIndex = i;
-            break;
-        }
+    component = MSI_RecordGetString(row, 2);
+    package->files[index].ComponentIndex = get_loaded_component(package,
+                    component);
+
     if (package->files[index].ComponentIndex == -1)
-        ERR("Unfound Component %s\n",debugstr_w(buffer));
-    HeapFree(GetProcessHeap(), 0, buffer);
+        ERR("Unfound Component %s\n",debugstr_w(component));
 
     package->files[index].FileName = load_dynamic_stringW(row,3);
     reduce_to_longfilename(package->files[index].FileName);
@@ -1827,7 +1199,6 @@ static UINT load_file(MSIPACKAGE* package, MSIRECORD * row)
 static UINT load_all_files(MSIPACKAGE *package)
 {
     MSIQUERY * view;
-    MSIRECORD * row;
     UINT rc;
     static const WCHAR Query[] =
         {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
@@ -1840,27 +1211,8 @@ static UINT load_all_files(MSIPACKAGE *package)
     rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
     if (rc != ERROR_SUCCESS)
         return ERROR_SUCCESS;
-   
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return ERROR_SUCCESS;
-    }
 
-    while (1)
-    {
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            rc = ERROR_SUCCESS;
-            break;
-        }
-        load_file(package,row);
-        msiobj_release(&row->hdr);
-    }
-    MSI_ViewClose(view);
+    rc = MSI_IterateRecords(view, NULL, load_file, package);
     msiobj_release(&view->hdr);
 
     return ERROR_SUCCESS;
@@ -1883,7 +1235,6 @@ static UINT load_all_files(MSIPACKAGE *package)
 static UINT ACTION_CostInitialize(MSIPACKAGE *package)
 {
     MSIQUERY * view;
-    MSIRECORD * row;
     UINT rc;
     static const WCHAR Query_all[] =
         {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
@@ -1904,25 +1255,8 @@ static UINT ACTION_CostInitialize(MSIPACKAGE *package)
     rc = MSI_DatabaseOpenViewW(package->db,Query_all,&view);
     if (rc != ERROR_SUCCESS)
         return rc;
-    rc = MSI_ViewExecute(view,0);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
-    }
-    while (1)
-    {
-        DWORD rc;
 
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-            break;
-       
-        load_feature(package,row); 
-        msiobj_release(&row->hdr);
-    }
-    MSI_ViewClose(view);
+    rc = MSI_IterateRecords(view, NULL, load_feature, package);
     msiobj_release(&view->hdr);
 
     load_all_files(package);
@@ -1930,6 +1264,31 @@ static UINT ACTION_CostInitialize(MSIPACKAGE *package)
     return ERROR_SUCCESS;
 }
 
+static UINT execute_script(MSIPACKAGE *package, UINT script )
+{
+    int i;
+    UINT rc = ERROR_SUCCESS;
+
+    TRACE("Executing Script %i\n",script);
+
+    for (i = 0; i < package->script->ActionCount[script]; i++)
+    {
+        LPWSTR action;
+        action = package->script->Actions[script][i];
+        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]);
+        if (rc != ERROR_SUCCESS)
+            break;
+    }
+    HeapFree(GetProcessHeap(),0,package->script->Actions[script]);
+
+    package->script->ActionCount[script] = 0;
+    package->script->Actions[script] = NULL;
+    return rc;
+}
+
 static UINT ACTION_FileCost(MSIPACKAGE *package)
 {
     return ERROR_SUCCESS;
@@ -1944,9 +1303,8 @@ static INT load_folder(MSIPACKAGE *package, const WCHAR* dir)
          'W','H','E','R','E',' ', '`', 'D','i','r','e','c','t', 'o','r','y','`',
          ' ','=',' ','\'','%','s','\'',
          0};
-    UINT rc;
-    MSIQUERY * view;
-    LPWSTR ptargetdir, targetdir, parent, srcdir;
+    LPWSTR ptargetdir, targetdir, srcdir;
+    LPCWSTR parent;
     LPWSTR shortname = NULL;
     MSIRECORD * row = 0;
     INT index = -1;
@@ -1978,25 +1336,9 @@ static INT load_folder(MSIPACKAGE *package, const WCHAR* dir)
 
     package->folders[index].Directory = strdupW(dir);
 
-    rc = MSI_OpenQuery(package->db, &view, Query, dir);
-    if (rc != ERROR_SUCCESS)
-        return -1;
-
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return -1;
-    }
-
-    rc = MSI_ViewFetch(view,&row);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
+    row = MSI_QueryGetRecord(package->db, Query, dir);
+    if (!row)
         return -1;
-    }
 
     ptargetdir = targetdir = load_dynamic_stringW(row,3);
 
@@ -2048,7 +1390,7 @@ static INT load_folder(MSIPACKAGE *package, const WCHAR* dir)
     HeapFree(GetProcessHeap(), 0, ptargetdir);
         TRACE("   SourceDefault = %s\n",debugstr_w(package->folders[index].SourceDefault));
 
-    parent = load_dynamic_stringW(row,2);
+    parent = MSI_RecordGetString(row,2);
     if (parent) 
     {
         i = load_folder(package,parent);
@@ -2060,138 +1402,16 @@ static INT load_folder(MSIPACKAGE *package, const WCHAR* dir)
     }
     else
         package->folders[index].ParentIndex = -2;
-    HeapFree(GetProcessHeap(), 0, parent);
 
     package->folders[index].Property = load_dynamic_property(package, dir,NULL);
 
     msiobj_release(&row->hdr);
-    MSI_ViewClose(view);
-    msiobj_release(&view->hdr);
     TRACE(" %s retuning on index %i\n",debugstr_w(dir),index);
     return index;
 }
 
-
-LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source, 
-                      BOOL set_prop, MSIFOLDER **folder)
-{
-    DWORD i;
-    LPWSTR p, path = NULL;
-
-    TRACE("Working to resolve %s\n",debugstr_w(name));
-
-    /* special resolving for Target and Source root dir */
-    if (strcmpW(name,cszTargetDir)==0 || strcmpW(name,cszSourceDir)==0)
-    {
-        if (!source)
-        {
-            path = load_dynamic_property(package,cszTargetDir,NULL);
-            if (!path)
-            {
-                path = load_dynamic_property(package,cszRootDrive,NULL);
-                if (set_prop)
-                    MSI_SetPropertyW(package,cszTargetDir,path);
-            }
-            if (folder)
-            {
-                for (i = 0; i < package->loaded_folders; i++)
-                {
-                    if (strcmpW(package->folders[i].Directory,name)==0)
-                        break;
-                }
-                *folder = &(package->folders[i]);
-            }
-            return path;
-        }
-        else
-        {
-            path = load_dynamic_property(package,cszSourceDir,NULL);
-            if (!path)
-            {
-                path = load_dynamic_property(package,cszDatabase,NULL);
-                if (path)
-                {
-                    p = strrchrW(path,'\\');
-                    if (p)
-                        *(p+1) = 0;
-                }
-            }
-            if (folder)
-            {
-                for (i = 0; i < package->loaded_folders; i++)
-                {
-                    if (strcmpW(package->folders[i].Directory,name)==0)
-                        break;
-                }
-                *folder = &(package->folders[i]);
-            }
-            return path;
-        }
-    }
-
-    for (i = 0; i < package->loaded_folders; i++)
-    {
-        if (strcmpW(package->folders[i].Directory,name)==0)
-            break;
-    }
-
-    if (i >= package->loaded_folders)
-        return NULL;
-
-    if (folder)
-        *folder = &(package->folders[i]);
-
-    if (!source && package->folders[i].ResolvedTarget)
-    {
-        path = strdupW(package->folders[i].ResolvedTarget);
-        TRACE("   already resolved to %s\n",debugstr_w(path));
-        return path;
-    }
-    else if (source && package->folders[i].ResolvedSource)
-    {
-        path = strdupW(package->folders[i].ResolvedSource);
-        TRACE("   (source)already resolved to %s\n",debugstr_w(path));
-        return path;
-    }
-    else if (!source && package->folders[i].Property)
-    {
-        path = build_directory_name(2, package->folders[i].Property, NULL);
-                    
-        TRACE("   internally set to %s\n",debugstr_w(path));
-        if (set_prop)
-            MSI_SetPropertyW(package,name,path);
-        return path;
-    }
-
-    if (package->folders[i].ParentIndex >= 0)
-    {
-        LPWSTR parent = package->folders[package->folders[i].ParentIndex].Directory;
-
-        TRACE(" ! Parent is %s\n", debugstr_w(parent));
-
-        p = resolve_folder(package, parent, source, set_prop, NULL);
-        if (!source)
-        {
-            TRACE("   TargetDefault = %s\n",debugstr_w(package->folders[i].TargetDefault));
-            path = build_directory_name(3, p, package->folders[i].TargetDefault, NULL);
-            package->folders[i].ResolvedTarget = strdupW(path);
-            TRACE("   resolved into %s\n",debugstr_w(path));
-            if (set_prop)
-                MSI_SetPropertyW(package,name,path);
-        }
-        else 
-        {
-            path = build_directory_name(3, p, package->folders[i].SourceDefault, NULL);
-            TRACE("   (source)resolved into %s\n",debugstr_w(path));
-            package->folders[i].ResolvedSource = strdupW(path);
-        }
-        HeapFree(GetProcessHeap(),0,p);
-    }
-    return path;
-}
-
 /* scan for and update current install states */
-void ACTION_UpdateInstallStates(MSIPACKAGE *package)
+static void ACTION_UpdateInstallStates(MSIPACKAGE *package)
 {
     int i;
     LPWSTR productcode;
@@ -2230,72 +1450,6 @@ void ACTION_UpdateInstallStates(MSIPACKAGE *package)
     }
 }
 
-/* update compoennt state based on a feature change */
-void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
-{
-    int i;
-    INSTALLSTATE newstate;
-    MSIFEATURE *feature;
-
-    i = get_loaded_feature(package,szFeature);
-    if (i < 0)
-        return;
-
-    feature = &package->features[i];
-    newstate = feature->ActionRequest;
-
-    for( i = 0; i < feature->ComponentCount; i++)
-    {
-        MSICOMPONENT* component = &package->components[feature->Components[i]];
-
-        TRACE("MODIFYING(%i): Component %s (Installed %i, Action %i, Request %i)\n",
-            newstate, debugstr_w(component->Component), component->Installed, 
-            component->Action, component->ActionRequest);
-        
-        if (!component->Enabled)
-            continue;
-        else
-        {
-            if (newstate == INSTALLSTATE_LOCAL)
-            {
-                component->ActionRequest = INSTALLSTATE_LOCAL;
-                component->Action = INSTALLSTATE_LOCAL;
-            }
-            else 
-            {
-                int j,k;
-
-                component->ActionRequest = newstate;
-                component->Action = newstate;
-
-                /*if any other feature wants is local we need to set it local*/
-                for (j = 0; 
-                     j < package->loaded_features &&
-                     component->ActionRequest != INSTALLSTATE_LOCAL; 
-                     j++)
-                {
-                    for (k = 0; k < package->features[j].ComponentCount; k++)
-                        if ( package->features[j].Components[k] ==
-                             feature->Components[i] )
-                        {
-                            if (package->features[j].ActionRequest == 
-                                INSTALLSTATE_LOCAL)
-                            {
-                                TRACE("Saved by %s\n", debugstr_w(package->features[j].Feature));
-                                component->ActionRequest = INSTALLSTATE_LOCAL;
-                                component->Action = INSTALLSTATE_LOCAL;
-                            }
-                            break;
-                        }
-                }
-            }
-        }
-        TRACE("Result (%i): Component %s (Installed %i, Action %i, Request %i)\n",
-            newstate, debugstr_w(component->Component), component->Installed, 
-            component->Action, component->ActionRequest);
-    } 
-}
-
 static BOOL process_state_property (MSIPACKAGE* package, LPCWSTR property, 
                                     INSTALLSTATE state)
 {
@@ -2429,6 +1583,14 @@ static UINT SetFeatureStates(MSIPACKAGE *package)
             }
         }
     }
+    else
+    {
+        /* set the Preselected Property */
+        static const WCHAR szPreselected[] = {'P','r','e','s','e','l','e','c','t','e','d',0};
+        static const WCHAR szOne[] = { '1', 0 };
+
+        MSI_SetPropertyW(package,szPreselected,szOne);
+    }
 
     /*
      * now we want to enable or disable components base on feature 
@@ -2504,6 +1666,52 @@ static UINT SetFeatureStates(MSIPACKAGE *package)
     return ERROR_SUCCESS;
 }
 
+static UINT ITERATE_CostFinalizeDirectories(MSIRECORD *row, LPVOID param)
+{
+    MSIPACKAGE *package = (MSIPACKAGE*)param;
+    LPCWSTR name;
+    LPWSTR path;
+
+    name = MSI_RecordGetString(row,1);
+
+    /* This helper function now does ALL the work */
+    TRACE("Dir %s ...\n",debugstr_w(name));
+    load_folder(package,name);
+    path = resolve_folder(package,name,FALSE,TRUE,NULL);
+    TRACE("resolves to %s\n",debugstr_w(path));
+    HeapFree( GetProcessHeap(), 0, path);
+
+    return ERROR_SUCCESS;
+}
+
+static UINT ITERATE_CostFinalizeConditions(MSIRECORD *row, LPVOID param)
+{
+    MSIPACKAGE *package = (MSIPACKAGE*)param;
+    LPCWSTR Feature;
+    int feature_index;
+
+    Feature = MSI_RecordGetString(row,1);
+
+    feature_index = get_loaded_feature(package,Feature);
+    if (feature_index < 0)
+        ERR("FAILED to find loaded feature %s\n",debugstr_w(Feature));
+    else
+    {
+        LPCWSTR Condition;
+        Condition = MSI_RecordGetString(row,3);
+
+        if (MSI_EvaluateConditionW(package,Condition) == MSICONDITION_TRUE)
+        {
+            int level = MSI_RecordGetInteger(row,2);
+            TRACE("Reseting feature %s to level %i\n", debugstr_w(Feature),
+                            level);
+            package->features[feature_index].Level = level;
+        }
+    }
+    return ERROR_SUCCESS;
+}
+
+
 /* 
  * A lot is done in this function aside from just the costing.
  * The costing needs to be implemented at some point but for now I am going
@@ -2539,41 +1747,8 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
     rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
     if (rc == ERROR_SUCCESS)
     {
-        rc = MSI_ViewExecute(view, 0);
-        if (rc != ERROR_SUCCESS)
-        {
-            MSI_ViewClose(view);
-            msiobj_release(&view->hdr);
-            return rc;
-        }
-
-        while (1)
-        {
-            WCHAR name[0x100];
-            LPWSTR path;
-            MSIRECORD * row = 0;
-            DWORD sz;
-
-            rc = MSI_ViewFetch(view,&row);
-            if (rc != ERROR_SUCCESS)
-            {
-                rc = ERROR_SUCCESS;
-                break;
-            }
-
-            sz=0x100;
-            MSI_RecordGetStringW(row,1,name,&sz);
-
-            /* This helper function now does ALL the work */
-            TRACE("Dir %s ...\n",debugstr_w(name));
-            load_folder(package,name);
-            path = resolve_folder(package,name,FALSE,TRUE,NULL);
-            TRACE("resolves to %s\n",debugstr_w(path));
-            HeapFree( GetProcessHeap(), 0, path);
-
-            msiobj_release(&row->hdr);
-        }
-        MSI_ViewClose(view);
+        rc = MSI_IterateRecords(view, NULL, ITERATE_CostFinalizeDirectories,
+                        package);
         msiobj_release(&view->hdr);
     }
 
@@ -2666,54 +1841,8 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
     rc = MSI_DatabaseOpenViewW(package->db, ConditionQuery, &view);
     if (rc == ERROR_SUCCESS)
     {
-        rc = MSI_ViewExecute(view, 0);
-        if (rc != ERROR_SUCCESS)
-        {
-            MSI_ViewClose(view);
-            msiobj_release(&view->hdr);
-            return rc;
-        }
-    
-        while (1)
-        {
-            WCHAR Feature[0x100];
-            MSIRECORD * row = 0;
-            DWORD sz;
-            int feature_index;
-
-            rc = MSI_ViewFetch(view,&row);
-
-            if (rc != ERROR_SUCCESS)
-            {
-                rc = ERROR_SUCCESS;
-                break;
-            }
-
-            sz = 0x100;
-            MSI_RecordGetStringW(row,1,Feature,&sz);
-
-            feature_index = get_loaded_feature(package,Feature);
-            if (feature_index < 0)
-                ERR("FAILED to find loaded feature %s\n",debugstr_w(Feature));
-            else
-            {
-                LPWSTR Condition;
-                Condition = load_dynamic_stringW(row,3);
-
-                if (MSI_EvaluateConditionW(package,Condition) == 
-                    MSICONDITION_TRUE)
-                {
-                    int level = MSI_RecordGetInteger(row,2);
-                    TRACE("Reseting feature %s to level %i\n",
-                           debugstr_w(Feature), level);
-                    package->features[feature_index].Level = level;
-                }
-                HeapFree(GetProcessHeap(),0,Condition);
-            }
-
-            msiobj_release(&row->hdr);
-        }
-        MSI_ViewClose(view);
+        rc = MSI_IterateRecords(view, NULL, ITERATE_CostFinalizeConditions,
+                    package);
         msiobj_release(&view->hdr);
     }
 
@@ -2745,548 +1874,346 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
     return SetFeatureStates(package);
 }
 
-/*
- * This is a helper function for handling embedded cabinet media
- */
-static UINT writeout_cabinet_stream(MSIPACKAGE *package, WCHAR* stream_name,
-                                    WCHAR* source)
+/* OK this value is "interpreted" and then formatted based on the 
+   first few characters */
+static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type, 
+                         DWORD *size)
 {
-    UINT rc;
-    USHORT* data;
-    UINT    size;
-    DWORD   write;
-    HANDLE  the_file;
-    WCHAR tmp[MAX_PATH];
-
-    rc = read_raw_stream_data(package->db,stream_name,&data,&size); 
-    if (rc != ERROR_SUCCESS)
-        return rc;
-
-    write = MAX_PATH;
-    if (MSI_GetPropertyW(package, cszTempFolder, tmp, &write))
-        GetTempPathW(MAX_PATH,tmp);
-
-    GetTempFileNameW(tmp,stream_name,0,source);
-
-    track_tempfile(package,strrchrW(source,'\\'), source);
-    the_file = CreateFileW(source, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
-                           FILE_ATTRIBUTE_NORMAL, NULL);
-
-    if (the_file == INVALID_HANDLE_VALUE)
+    LPSTR data = NULL;
+    if (value[0]=='#' && value[1]!='#' && value[1]!='%')
     {
-        ERR("Unable to create file %s\n",debugstr_w(source));
-        rc = ERROR_FUNCTION_FAILED;
-        goto end;
-    }
+        if (value[1]=='x')
+        {
+            LPWSTR ptr;
+            CHAR byte[5];
+            LPWSTR deformated = NULL;
+            int count;
 
-    WriteFile(the_file,data,size,&write,NULL);
-    CloseHandle(the_file);
-    TRACE("wrote %li bytes to %s\n",write,debugstr_w(source));
-end:
-    HeapFree(GetProcessHeap(),0,data);
-    return rc;
-}
+            deformat_string(package, &value[2], &deformated);
 
+            /* binary value type */
+            ptr = deformated;
+            *type = REG_BINARY;
+            if (strlenW(ptr)%2)
+                *size = (strlenW(ptr)/2)+1;
+            else
+                *size = strlenW(ptr)/2;
 
-/* Support functions for FDI functions */
-typedef struct
-{
-    MSIPACKAGE* package;
-    LPCSTR cab_path;
-    LPCSTR file_name;
-} CabData;
+            data = HeapAlloc(GetProcessHeap(),0,*size);
 
-static void * cabinet_alloc(ULONG cb)
-{
-    return HeapAlloc(GetProcessHeap(), 0, cb);
-}
+            byte[0] = '0'; 
+            byte[1] = 'x'; 
+            byte[4] = 0; 
+            count = 0;
+            /* if uneven pad with a zero in front */
+            if (strlenW(ptr)%2)
+            {
+                byte[2]= '0';
+                byte[3]= *ptr;
+                ptr++;
+                data[count] = (BYTE)strtol(byte,NULL,0);
+                count ++;
+                TRACE("Uneven byte count\n");
+            }
+            while (*ptr)
+            {
+                byte[2]= *ptr;
+                ptr++;
+                byte[3]= *ptr;
+                ptr++;
+                data[count] = (BYTE)strtol(byte,NULL,0);
+                count ++;
+            }
+            HeapFree(GetProcessHeap(),0,deformated);
 
-static void cabinet_free(void *pv)
-{
-    HeapFree(GetProcessHeap(), 0, pv);
-}
+            TRACE("Data %li bytes(%i)\n",*size,count);
+        }
+        else
+        {
+            LPWSTR deformated;
+            LPWSTR p;
+            DWORD d = 0;
+            deformat_string(package, &value[1], &deformated);
 
-static INT_PTR cabinet_open(char *pszFile, int oflag, int pmode)
-{
-    DWORD dwAccess = 0;
-    DWORD dwShareMode = 0;
-    DWORD dwCreateDisposition = OPEN_EXISTING;
-    switch (oflag & _O_ACCMODE)
-    {
-    case _O_RDONLY:
-        dwAccess = GENERIC_READ;
-        dwShareMode = FILE_SHARE_READ | FILE_SHARE_DELETE;
-        break;
-    case _O_WRONLY:
-        dwAccess = GENERIC_WRITE;
-        dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
-        break;
-    case _O_RDWR:
-        dwAccess = GENERIC_READ | GENERIC_WRITE;
-        dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
-        break;
-    }
-    if ((oflag & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL))
-        dwCreateDisposition = CREATE_NEW;
-    else if (oflag & _O_CREAT)
-        dwCreateDisposition = CREATE_ALWAYS;
-    return (INT_PTR)CreateFileA(pszFile, dwAccess, dwShareMode, NULL, 
-                                dwCreateDisposition, 0, NULL);
-}
+            *type=REG_DWORD; 
+            *size = sizeof(DWORD);
+            data = HeapAlloc(GetProcessHeap(),0,*size);
+            p = deformated;
+            if (*p == '-')
+                p++;
+            while (*p)
+            {
+                if ( (*p < '0') || (*p > '9') )
+                    break;
+                d *= 10;
+                d += (*p - '0');
+                p++;
+            }
+            if (deformated[0] == '-')
+                d = -d;
+            *(LPDWORD)data = d;
+            TRACE("DWORD %li\n",*(LPDWORD)data);
 
-static UINT cabinet_read(INT_PTR hf, void *pv, UINT cb)
-{
-    DWORD dwRead;
-    if (ReadFile((HANDLE)hf, pv, cb, &dwRead, NULL))
-        return dwRead;
-    return 0;
-}
+            HeapFree(GetProcessHeap(),0,deformated);
+        }
+    }
+    else
+    {
+        static const WCHAR szMulti[] = {'[','~',']',0};
+        LPCWSTR ptr;
+        *type=REG_SZ;
 
-static UINT cabinet_write(INT_PTR hf, void *pv, UINT cb)
-{
-    DWORD dwWritten;
-    if (WriteFile((HANDLE)hf, pv, cb, &dwWritten, NULL))
-        return dwWritten;
-    return 0;
-}
+        if (value[0]=='#')
+        {
+            if (value[1]=='%')
+            {
+                ptr = &value[2];
+                *type=REG_EXPAND_SZ;
+            }
+            else
+                ptr = &value[1];
+         }
+         else
+            ptr=value;
 
-static int cabinet_close(INT_PTR hf)
-{
-    return CloseHandle((HANDLE)hf) ? 0 : -1;
-}
+        if (strstrW(value,szMulti))
+            *type = REG_MULTI_SZ;
 
-static long cabinet_seek(INT_PTR hf, long dist, int seektype)
-{
-    /* flags are compatible and so are passed straight through */
-    return SetFilePointer((HANDLE)hf, dist, NULL, seektype);
+        *size = deformat_string(package, ptr,(LPWSTR*)&data);
+    }
+    return data;
 }
 
-static INT_PTR cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
+static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
 {
-    /* FIXME: try to do more processing in this function */
-    switch (fdint)
-    {
-    case fdintCOPY_FILE:
-    {
-        CabData *data = (CabData*) pfdin->pv;
-        ULONG len = strlen(data->cab_path) + strlen(pfdin->psz1);
-        char *file;
-
-        LPWSTR trackname;
-        LPWSTR trackpath;
-        LPWSTR tracknametmp;
-        static const WCHAR tmpprefix[] = {'C','A','B','T','M','P','_',0};
-       
-        if (data->file_name && lstrcmpiA(data->file_name,pfdin->psz1))
-                return 0;
-        
-        file = cabinet_alloc((len+1)*sizeof(char));
-        strcpy(file, data->cab_path);
-        strcat(file, pfdin->psz1);
+    MSIPACKAGE *package = (MSIPACKAGE*)param;
+    static const WCHAR szHCR[] = 
+        {'H','K','E','Y','_','C','L','A','S','S','E','S','_',
+         'R','O','O','T','\\',0};
+    static const WCHAR szHCU[] =
+        {'H','K','E','Y','_','C','U','R','R','E','N','T','_',
+         'U','S','E','R','\\',0};
+    static const WCHAR szHLM[] =
+        {'H','K','E','Y','_','L','O','C','A','L','_',
+         'M','A','C','H','I','N','E','\\',0};
+    static const WCHAR szHU[] =
+        {'H','K','E','Y','_','U','S','E','R','S','\\',0};
+
+    LPSTR value_data = NULL;
+    HKEY  root_key, hkey;
+    DWORD type,size;
+    LPWSTR  deformated;
+    LPCWSTR szRoot, component, name, key, value;
+    INT component_index;
+    MSIRECORD * uirow;
+    LPWSTR uikey;
+    INT   root;
+    BOOL check_first = FALSE;
+    UINT rc;
 
-        TRACE("file: %s\n", debugstr_a(file));
+    ui_progress(package,2,0,0,0);
 
-        /* track this file so it can be deleted if not installed */
-        trackpath=strdupAtoW(file);
-        tracknametmp=strdupAtoW(strrchr(file,'\\')+1);
-        trackname = HeapAlloc(GetProcessHeap(),0,(strlenW(tracknametmp) + 
-                                  strlenW(tmpprefix)+1) * sizeof(WCHAR));
+    value = NULL;
+    key = NULL;
+    uikey = NULL;
+    name = NULL;
 
-        strcpyW(trackname,tmpprefix);
-        strcatW(trackname,tracknametmp);
+    component = MSI_RecordGetString(row, 6);
+    component_index = get_loaded_component(package,component);
 
-        track_tempfile(data->package, trackname, trackpath);
+    if (!ACTION_VerifyComponentForAction(package, component_index,
+                            INSTALLSTATE_LOCAL))
+    {
+        TRACE("Skipping write due to disabled component %s\n",
+                        debugstr_w(component));
 
-        HeapFree(GetProcessHeap(),0,trackpath);
-        HeapFree(GetProcessHeap(),0,trackname);
-        HeapFree(GetProcessHeap(),0,tracknametmp);
+        package->components[component_index].Action =
+                package->components[component_index].Installed;
 
-        return cabinet_open(file, _O_WRONLY | _O_CREAT, 0);
-    }
-    case fdintCLOSE_FILE_INFO:
-    {
-        FILETIME ft;
-           FILETIME ftLocal;
-        if (!DosDateTimeToFileTime(pfdin->date, pfdin->time, &ft))
-            return -1;
-        if (!LocalFileTimeToFileTime(&ft, &ftLocal))
-            return -1;
-        if (!SetFileTime((HANDLE)pfdin->hf, &ftLocal, 0, &ftLocal))
-            return -1;
-
-        cabinet_close(pfdin->hf);
-        return 1;
-    }
-    default:
-        return 0;
+        return ERROR_SUCCESS;
     }
-}
 
-/***********************************************************************
- *            extract_cabinet_file
- *
- * Extract files from a cab file.
- */
-static BOOL extract_a_cabinet_file(MSIPACKAGE* package, const WCHAR* source, 
-                                 const WCHAR* path, const WCHAR* file)
-{
-    HFDI hfdi;
-    ERF erf;
-    BOOL ret;
-    char *cabinet;
-    char *cab_path;
-    char *file_name;
-    CabData data;
-
-    TRACE("Extracting %s (%s) to %s\n",debugstr_w(source), 
-                    debugstr_w(file), debugstr_w(path));
-
-    hfdi = FDICreate(cabinet_alloc,
-                     cabinet_free,
-                     cabinet_open,
-                     cabinet_read,
-                     cabinet_write,
-                     cabinet_close,
-                     cabinet_seek,
-                     0,
-                     &erf);
-    if (!hfdi)
-    {
-        ERR("FDICreate failed\n");
-        return FALSE;
-    }
+    package->components[component_index].Action = INSTALLSTATE_LOCAL;
 
-    if (!(cabinet = strdupWtoA( source )))
-    {
-        FDIDestroy(hfdi);
-        return FALSE;
-    }
-    if (!(cab_path = strdupWtoA( path )))
+    name = MSI_RecordGetString(row, 4);
+    if( MSI_RecordIsNull(row,5) && name )
     {
-        FDIDestroy(hfdi);
-        HeapFree(GetProcessHeap(), 0, cabinet);
-        return FALSE;
+        /* null values can have special meanings */
+        if (name[0]=='-' && name[1] == 0)
+                return ERROR_SUCCESS;
+        else if ((name[0]=='+' && name[1] == 0) || 
+                 (name[0] == '*' && name[1] == 0))
+                name = NULL;
+        check_first = TRUE;
     }
 
-    data.package = package;
-    data.cab_path = cab_path;
-    if (file)
-        file_name = strdupWtoA(file);
-    else
-        file_name = NULL;
-    data.file_name = file_name;
-
-    ret = FDICopy(hfdi, cabinet, "", 0, cabinet_notify, NULL, &data);
-
-    if (!ret)
-        ERR("FDICopy failed\n");
+    root = MSI_RecordGetInteger(row,2);
+    key = MSI_RecordGetString(row, 3);
 
-    FDIDestroy(hfdi);
-
-    HeapFree(GetProcessHeap(), 0, cabinet);
-    HeapFree(GetProcessHeap(), 0, cab_path);
-    HeapFree(GetProcessHeap(), 0, file_name);
+    /* get the root key */
+    switch (root)
+    {
+        case -1: 
+            {
+                static const WCHAR szALLUSER[] = {'A','L','L','U','S','E','R','S',0};
+                LPWSTR all_users = load_dynamic_property(package, szALLUSER, NULL);
+                if (all_users && all_users[0] == '1')
+                {
+                    root_key = HKEY_LOCAL_MACHINE;
+                    szRoot = szHLM;
+                }
+                else
+                {
+                    root_key = HKEY_CURRENT_USER;
+                    szRoot = szHCU;
+                }
+                HeapFree(GetProcessHeap(),0,all_users);
+            }
+                 break;
+        case 0:  root_key = HKEY_CLASSES_ROOT; 
+                 szRoot = szHCR;
+                 break;
+        case 1:  root_key = HKEY_CURRENT_USER;
+                 szRoot = szHCU;
+                 break;
+        case 2:  root_key = HKEY_LOCAL_MACHINE;
+                 szRoot = szHLM;
+                 break;
+        case 3:  root_key = HKEY_USERS; 
+                 szRoot = szHU;
+                 break;
+        default:
+                 ERR("Unknown root %i\n",root);
+                 root_key=NULL;
+                 szRoot = NULL;
+                 break;
+    }
+    if (!root_key)
+        return ERROR_SUCCESS;
 
-    return ret;
-}
+    deformat_string(package, key , &deformated);
+    size = strlenW(deformated) + strlenW(szRoot) + 1;
+    uikey = HeapAlloc(GetProcessHeap(), 0, size*sizeof(WCHAR));
+    strcpyW(uikey,szRoot);
+    strcatW(uikey,deformated);
 
-static UINT ready_media_for_file(MSIPACKAGE *package, WCHAR* path, 
-                                 MSIFILE* file)
-{
-    UINT rc;
-    MSIQUERY * view;
-    MSIRECORD * row = 0;
-    static WCHAR source[MAX_PATH];
-    static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
-         '`','M','e','d','i','a','`',' ','W','H','E','R','E',' ',
-         '`','L','a','s','t','S','e','q','u','e','n','c','e','`',' ','>','=',
-         ' ','%', 'i',' ','O','R','D','E','R',' ','B','Y',' ',
-         '`','L','a','s','t','S','e','q','u','e','n','c','e','`',0};
-    WCHAR Query[1024];
-    WCHAR cab[0x100];
-    DWORD sz=0x100;
-    INT seq;
-    static UINT last_sequence = 0; 
-
-    if (file->Attributes & msidbFileAttributesNoncompressed)
+    if (RegCreateKeyW( root_key, deformated, &hkey))
     {
-        TRACE("Uncompressed File, no media to ready.\n");
+        ERR("Could not create key %s\n",debugstr_w(deformated));
+        HeapFree(GetProcessHeap(),0,deformated);
+        HeapFree(GetProcessHeap(),0,uikey);
         return ERROR_SUCCESS;
     }
+    HeapFree(GetProcessHeap(),0,deformated);
 
-    if (file->Sequence <= last_sequence)
+    value = MSI_RecordGetString(row,5);
+    if (value)
+        value_data = parse_value(package, value, &type, &size); 
+    else
     {
-        TRACE("Media already ready (%u, %u)\n",file->Sequence,last_sequence);
-        /*extract_a_cabinet_file(package, source,path,file->File); */
-        return ERROR_SUCCESS;
+        static const WCHAR szEmpty[] = {0};
+        value_data = (LPSTR)strdupW(szEmpty);
+        size = 0;
+        type = REG_SZ;
     }
 
-    sprintfW(Query,ExecSeqQuery,file->Sequence);
-
-    rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
-    if (rc != ERROR_SUCCESS)
-        return rc;
+    deformat_string(package, name, &deformated);
 
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
-    }
+    /* get the double nulls to terminate SZ_MULTI */
+    if (type == REG_MULTI_SZ)
+        size +=sizeof(WCHAR);
 
-    rc = MSI_ViewFetch(view,&row);
-    if (rc != ERROR_SUCCESS)
+    if (!check_first)
     {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
+        TRACE("Setting value %s of %s\n",debugstr_w(deformated),
+                        debugstr_w(uikey));
+        RegSetValueExW(hkey, deformated, 0, type, value_data, size);
     }
-    seq = MSI_RecordGetInteger(row,2);
-    last_sequence = seq;
-
-    if (!MSI_RecordIsNull(row,4))
+    else
     {
-        sz=0x100;
-        MSI_RecordGetStringW(row,4,cab,&sz);
-        TRACE("Source is CAB %s\n",debugstr_w(cab));
-        /* the stream does not contain the # character */
-        if (cab[0]=='#')
+        DWORD sz = 0;
+        rc = RegQueryValueExW(hkey, deformated, NULL, NULL, NULL, &sz);
+        if (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA)
         {
-            writeout_cabinet_stream(package,&cab[1],source);
-            strcpyW(path,source);
-            *(strrchrW(path,'\\')+1)=0;
+            TRACE("value %s of %s checked already exists\n",
+                            debugstr_w(deformated), debugstr_w(uikey));
         }
         else
         {
-            sz = MAX_PATH;
-            if (MSI_GetPropertyW(package, cszSourceDir, source, &sz))
-            {
-                ERR("No Source dir defined \n");
-                rc = ERROR_FUNCTION_FAILED;
-            }
-            else
-            {
-                strcpyW(path,source);
-                strcatW(source,cab);
-                /* extract the cab file into a folder in the temp folder */
-                sz = MAX_PATH;
-                if (MSI_GetPropertyW(package, cszTempFolder,path, &sz) 
-                                    != ERROR_SUCCESS)
-                    GetTempPathW(MAX_PATH,path);
-            }
+            TRACE("Checked and setting value %s of %s\n",
+                            debugstr_w(deformated), debugstr_w(uikey));
+            if (deformated || size)
+                RegSetValueExW(hkey, deformated, 0, type, value_data, size);
         }
-        rc = !extract_a_cabinet_file(package, source,path,NULL);
-    }
-    else
-    {
-        sz = MAX_PATH;
-        MSI_GetPropertyW(package,cszSourceDir,source,&sz);
-        strcpyW(path,source);
     }
-    msiobj_release(&row->hdr);
-    MSI_ViewClose(view);
-    msiobj_release(&view->hdr);
-    return rc;
-}
+    RegCloseKey(hkey);
 
-inline static UINT create_component_directory ( MSIPACKAGE* package, INT component)
-{
-    UINT rc = ERROR_SUCCESS;
-    MSIFOLDER *folder;
-    LPWSTR install_path;
+    uirow = MSI_CreateRecord(3);
+    MSI_RecordSetStringW(uirow,2,deformated);
+    MSI_RecordSetStringW(uirow,1,uikey);
+
+    if (type == REG_SZ)
+        MSI_RecordSetStringW(uirow,3,(LPWSTR)value_data);
+    else
+        MSI_RecordSetStringW(uirow,3,value);
 
-    install_path = resolve_folder(package, package->components[component].Directory,
-                        FALSE, FALSE, &folder);
-    if (!install_path)
-        return ERROR_FUNCTION_FAILED; 
+    ui_actiondata(package,szWriteRegistryValues,uirow);
+    msiobj_release( &uirow->hdr );
 
-    /* create the path */
-    if (folder->State == 0)
-    {
-        create_full_pathW(install_path);
-        folder->State = 2;
-    }
-    HeapFree(GetProcessHeap(), 0, install_path);
+    HeapFree(GetProcessHeap(),0,value_data);
+    HeapFree(GetProcessHeap(),0,deformated);
+    HeapFree(GetProcessHeap(),0,uikey);
 
-    return rc;
+    return ERROR_SUCCESS;
 }
 
-static UINT ACTION_InstallFiles(MSIPACKAGE *package)
+static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package)
 {
-    UINT rc = ERROR_SUCCESS;
-    DWORD index;
-    MSIRECORD * uirow;
-    WCHAR uipath[MAX_PATH];
+    UINT rc;
+    MSIQUERY * view;
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','R','e','g','i','s','t','r','y','`',0 };
 
     if (!package)
         return ERROR_INVALID_HANDLE;
 
-    /* increment progress bar each time action data is sent */
-    ui_progress(package,1,1,0,0);
-
-    for (index = 0; index < package->loaded_files; index++)
-    {
-        WCHAR path_to_source[MAX_PATH];
-        MSIFILE *file;
-        
-        file = &package->files[index];
+    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
+    if (rc != ERROR_SUCCESS)
+        return ERROR_SUCCESS;
 
-        if (file->Temporary)
-            continue;
+    /* increment progress bar each time action data is sent */
+    ui_progress(package,1,REG_PROGRESS_VALUE,1,0);
 
+    rc = MSI_IterateRecords(view, NULL, ITERATE_WriteRegistryValues, package);
 
-        if (!ACTION_VerifyComponentForAction(package, file->ComponentIndex, 
-                                       INSTALLSTATE_LOCAL))
-        {
-            ui_progress(package,2,file->FileSize,0,0);
-            TRACE("File %s is not scheduled for install\n",
-                   debugstr_w(file->File));
+    msiobj_release(&view->hdr);
+    return rc;
+}
 
-            continue;
-        }
+static UINT ACTION_InstallInitialize(MSIPACKAGE *package)
+{
+    package->script->CurrentlyScripting = TRUE;
 
-        if ((file->State == 1) || (file->State == 2))
-        {
-            LPWSTR p;
-            MSICOMPONENT* comp = NULL;
-
-            TRACE("Installing %s\n",debugstr_w(file->File));
-            rc = ready_media_for_file(package, path_to_source, file);
-            /* 
-             * WARNING!
-             * our file table could change here because a new temp file
-             * may have been created
-             */
-            file = &package->files[index];
-            if (rc != ERROR_SUCCESS)
-            {
-                ERR("Unable to ready media\n");
-                rc = ERROR_FUNCTION_FAILED;
-                break;
-            }
+    return ERROR_SUCCESS;
+}
 
-            create_component_directory( package, file->ComponentIndex);
 
-            /* recalculate file paths because things may have changed */
-
-            if (file->ComponentIndex >= 0)
-                comp = &package->components[file->ComponentIndex];
-
-            p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL);
-            HeapFree(GetProcessHeap(),0,file->TargetPath);
-
-            file->TargetPath = build_directory_name(2, p, file->FileName);
-            HeapFree(GetProcessHeap(),0,p);
-
-            if (file->Attributes & msidbFileAttributesNoncompressed)
-            {
-                p = resolve_folder(package, comp->Directory, TRUE, FALSE, NULL);
-                file->SourcePath = build_directory_name(2, p, file->ShortName);
-                HeapFree(GetProcessHeap(),0,p);
-            }
-            else
-                file->SourcePath = build_directory_name(2, path_to_source, 
-                            file->File);
-
-
-            TRACE("file paths %s to %s\n",debugstr_w(file->SourcePath),
-                  debugstr_w(file->TargetPath));
-
-            /* the UI chunk */
-            uirow=MSI_CreateRecord(9);
-            MSI_RecordSetStringW(uirow,1,file->File);
-            strcpyW(uipath,file->TargetPath);
-            *(strrchrW(uipath,'\\')+1)=0;
-            MSI_RecordSetStringW(uirow,9,uipath);
-            MSI_RecordSetInteger(uirow,6,file->FileSize);
-            ui_actiondata(package,szInstallFiles,uirow);
-            msiobj_release( &uirow->hdr );
-            ui_progress(package,2,file->FileSize,0,0);
-
-            
-            if (file->Attributes & msidbFileAttributesNoncompressed)
-                rc = CopyFileW(file->SourcePath,file->TargetPath,FALSE);
-            else
-                rc = MoveFileW(file->SourcePath, file->TargetPath);
-
-            if (!rc)
-            {
-                rc = GetLastError();
-                ERR("Unable to move/copy file (%s -> %s) (error %d)\n",
-                     debugstr_w(file->SourcePath), debugstr_w(file->TargetPath),
-                      rc);
-                if (rc == ERROR_ALREADY_EXISTS && file->State == 2)
-                {
-                    if (!CopyFileW(file->SourcePath,file->TargetPath,FALSE))
-                        ERR("Unable to copy file (%s -> %s) (error %ld)\n",
-                            debugstr_w(file->SourcePath), 
-                            debugstr_w(file->TargetPath), GetLastError());
-                    if (!(file->Attributes & msidbFileAttributesNoncompressed))
-                        DeleteFileW(file->SourcePath);
-                    rc = 0;
-                }
-                else if (rc == ERROR_FILE_NOT_FOUND)
-                {
-                    ERR("Source File Not Found!  Continuing\n");
-                    rc = 0;
-                }
-                else if (file->Attributes & msidbFileAttributesVital)
-                {
-                    ERR("Ignoring Error and continuing (nonvital file)...\n");
-                    rc = 0;
-                }
-            }
-            else
-            {
-                file->State = 4;
-                rc = ERROR_SUCCESS;
-            }
-        }
-    }
-
-    return rc;
-}
-
-inline static UINT get_file_target(MSIPACKAGE *package, LPCWSTR file_key, 
-                                   LPWSTR* file_source)
-{
-    DWORD index;
-
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
-    for (index = 0; index < package->loaded_files; index ++)
-    {
-        if (strcmpW(file_key,package->files[index].File)==0)
-        {
-            if (package->files[index].State >= 2)
-            {
-                *file_source = strdupW(package->files[index].TargetPath);
-                return ERROR_SUCCESS;
-            }
-            else
-                return ERROR_FILE_NOT_FOUND;
-        }
-    }
-
-    return ERROR_FUNCTION_FAILED;
-}
-
-static UINT ACTION_DuplicateFiles(MSIPACKAGE *package)
+static UINT ACTION_InstallValidate(MSIPACKAGE *package)
 {
+    DWORD progress = 0;
+    DWORD total = 0;
+    static const WCHAR q1[]=
+        {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
+         '`','R','e','g','i','s','t','r','y','`',0};
     UINT rc;
     MSIQUERY * view;
     MSIRECORD * row = 0;
-    static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','D','u','p','l','i','c','a','t','e','F','i','l','e','`',0};
+    int i;
 
-    if (!package)
-        return ERROR_INVALID_HANDLE;
+    TRACE(" InstallValidate \n");
 
-    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
+    rc = MSI_DatabaseOpenViewW(package->db, q1, &view);
     if (rc != ERROR_SUCCESS)
         return ERROR_SUCCESS;
 
@@ -3297,574 +2224,78 @@ static UINT ACTION_DuplicateFiles(MSIPACKAGE *package)
         msiobj_release(&view->hdr);
         return rc;
     }
-
     while (1)
     {
-        WCHAR file_key[0x100];
-        WCHAR *file_source = NULL;
-        WCHAR dest_name[0x100];
-        LPWSTR dest_path, dest;
-        WCHAR component[0x100];
-        INT component_index;
-
-        DWORD sz=0x100;
-
         rc = MSI_ViewFetch(view,&row);
         if (rc != ERROR_SUCCESS)
         {
             rc = ERROR_SUCCESS;
             break;
         }
+        progress +=1;
 
-        sz=0x100;
-        rc = MSI_RecordGetStringW(row,2,component,&sz);
-        if (rc != ERROR_SUCCESS)
-        {
-            ERR("Unable to get component\n");
-            msiobj_release(&row->hdr);
-            break;
-        }
-
-        component_index = get_loaded_component(package,component);
-
-        if (!ACTION_VerifyComponentForAction(package, component_index, 
-                                       INSTALLSTATE_LOCAL))
-        {
-            TRACE("Skipping copy due to disabled component\n");
-
-            /* the action taken was the same as the current install state */        
-            package->components[component_index].Action =
-                package->components[component_index].Installed;
-
-            msiobj_release(&row->hdr);
-            continue;
-        }
-
-        package->components[component_index].Action = INSTALLSTATE_LOCAL;
-
-        sz=0x100;
-        rc = MSI_RecordGetStringW(row,3,file_key,&sz);
-        if (rc != ERROR_SUCCESS)
-        {
-            ERR("Unable to get file key\n");
-            msiobj_release(&row->hdr);
-            break;
-        }
-
-        rc = get_file_target(package,file_key,&file_source);
-
-        if (rc != ERROR_SUCCESS)
-        {
-            ERR("Original file unknown %s\n",debugstr_w(file_key));
-            msiobj_release(&row->hdr);
-            HeapFree(GetProcessHeap(),0,file_source);
-            continue;
-        }
-
-        if (MSI_RecordIsNull(row,4))
-        {
-            strcpyW(dest_name,strrchrW(file_source,'\\')+1);
-        }
-        else
-        {
-            sz=0x100;
-            MSI_RecordGetStringW(row,4,dest_name,&sz);
-            reduce_to_longfilename(dest_name);
-         }
-
-        if (MSI_RecordIsNull(row,5))
-        {
-            LPWSTR p;
-            dest_path = strdupW(file_source);
-            p = strrchrW(dest_path,'\\');
-            if (p)
-                *p=0;
-        }
-        else
-        {
-            WCHAR destkey[0x100];
-            sz=0x100;
-            MSI_RecordGetStringW(row,5,destkey,&sz);
-            sz = 0x100;
-            dest_path = resolve_folder(package, destkey, FALSE,FALSE,NULL);
-            if (!dest_path)
-            {
-                ERR("Unable to get destination folder\n");
-                msiobj_release(&row->hdr);
-                HeapFree(GetProcessHeap(),0,file_source);
-                break;
-            }
-        }
-
-        dest = build_directory_name(2, dest_path, dest_name);
-           
-        TRACE("Duplicating file %s to %s\n",debugstr_w(file_source),
-              debugstr_w(dest)); 
-        
-        if (strcmpW(file_source,dest))
-            rc = !CopyFileW(file_source,dest,TRUE);
-        else
-            rc = ERROR_SUCCESS;
-        
-        if (rc != ERROR_SUCCESS)
-            ERR("Failed to copy file %s -> %s, last error %ld\n", debugstr_w(file_source), debugstr_w(dest_path), GetLastError());
-
-        FIXME("We should track these duplicate files as well\n");   
         msiobj_release(&row->hdr);
-        HeapFree(GetProcessHeap(),0,dest_path);
-        HeapFree(GetProcessHeap(),0,dest);
-        HeapFree(GetProcessHeap(),0,file_source);
     }
     MSI_ViewClose(view);
     msiobj_release(&view->hdr);
-    return rc;
-}
 
+    total = total + progress * REG_PROGRESS_VALUE;
+    total = total + package->loaded_components * COMPONENT_PROGRESS_VALUE;
+    for (i=0; i < package->loaded_files; i++)
+        total += package->files[i].FileSize;
+    ui_progress(package,0,total,0,0);
 
-/* OK this value is "interpreted" and then formatted based on the 
-   first few characters */
-static LPSTR parse_value(MSIPACKAGE *package, WCHAR *value, DWORD *type, 
-                         DWORD *size)
-{
-    LPSTR data = NULL;
-    if (value[0]=='#' && value[1]!='#' && value[1]!='%')
+    for(i = 0; i < package->loaded_features; i++)
     {
-        if (value[1]=='x')
-        {
-            LPWSTR ptr;
-            CHAR byte[5];
-            LPWSTR deformated = NULL;
-            int count;
-
-            deformat_string(package, &value[2], &deformated);
-
-            /* binary value type */
-            ptr = deformated;
-            *type = REG_BINARY;
-            if (strlenW(ptr)%2)
-                *size = (strlenW(ptr)/2)+1;
-            else
-                *size = strlenW(ptr)/2;
-
-            data = HeapAlloc(GetProcessHeap(),0,*size);
-
-            byte[0] = '0'; 
-            byte[1] = 'x'; 
-            byte[4] = 0; 
-            count = 0;
-            /* if uneven pad with a zero in front */
-            if (strlenW(ptr)%2)
-            {
-                byte[2]= '0';
-                byte[3]= *ptr;
-                ptr++;
-                data[count] = (BYTE)strtol(byte,NULL,0);
-                count ++;
-                TRACE("Uneven byte count\n");
-            }
-            while (*ptr)
-            {
-                byte[2]= *ptr;
-                ptr++;
-                byte[3]= *ptr;
-                ptr++;
-                data[count] = (BYTE)strtol(byte,NULL,0);
-                count ++;
-            }
-            HeapFree(GetProcessHeap(),0,deformated);
-
-            TRACE("Data %li bytes(%i)\n",*size,count);
-        }
-        else
-        {
-            LPWSTR deformated;
-            LPWSTR p;
-            DWORD d = 0;
-            deformat_string(package, &value[1], &deformated);
-
-            *type=REG_DWORD; 
-            *size = sizeof(DWORD);
-            data = HeapAlloc(GetProcessHeap(),0,*size);
-            p = deformated;
-            if (*p == '-')
-                p++;
-            while (*p)
-            {
-                if ( (*p < '0') || (*p > '9') )
-                    break;
-                d *= 10;
-                d += (*p - '0');
-                p++;
-            }
-            if (deformated[0] == '-')
-                d = -d;
-            *(LPDWORD)data = d;
-            TRACE("DWORD %li\n",*(LPDWORD)data);
-
-            HeapFree(GetProcessHeap(),0,deformated);
-        }
+        MSIFEATURE* feature = &package->features[i];
+        TRACE("Feature: %s; Installed: %i; Action %i; Request %i\n",
+            debugstr_w(feature->Feature), feature->Installed, feature->Action,
+            feature->ActionRequest);
     }
-    else
-    {
-        static const WCHAR szMulti[] = {'[','~',']',0};
-        WCHAR *ptr;
-        *type=REG_SZ;
+    
+    return ERROR_SUCCESS;
+}
 
-        if (value[0]=='#')
-        {
-            if (value[1]=='%')
-            {
-                ptr = &value[2];
-                *type=REG_EXPAND_SZ;
-            }
-            else
-                ptr = &value[1];
-         }
-         else
-            ptr=value;
+static UINT ITERATE_LaunchConditions(MSIRECORD *row, LPVOID param)
+{
+    MSIPACKAGE* package = (MSIPACKAGE*)param;
+    LPCWSTR cond = NULL; 
+    LPCWSTR message = NULL;
+    static const WCHAR title[]=
+        {'I','n','s','t','a','l','l',' ','F','a', 'i','l','e','d',0};
 
-        if (strstrW(value,szMulti))
-            *type = REG_MULTI_SZ;
+    cond = MSI_RecordGetString(row,1);
 
-        *size = deformat_string(package, ptr,(LPWSTR*)&data);
+    if (MSI_EvaluateConditionW(package,cond) != MSICONDITION_TRUE)
+    {
+        LPWSTR deformated;
+        message = MSI_RecordGetString(row,2);
+        deformat_string(package,message,&deformated); 
+        MessageBoxW(NULL,deformated,title,MB_OK);
+        HeapFree(GetProcessHeap(),0,deformated);
+        return ERROR_FUNCTION_FAILED;
     }
-    return data;
+
+    return ERROR_SUCCESS;
 }
 
-static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package)
+static UINT ACTION_LaunchConditions(MSIPACKAGE *package)
 {
     UINT rc;
-    MSIQUERY * view;
-    MSIRECORD * row = 0;
+    MSIQUERY * view = NULL;
     static const WCHAR ExecSeqQuery[] =
         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','R','e','g','i','s','t','r','y','`',0 };
+         '`','L','a','u','n','c','h','C','o','n','d','i','t','i','o','n','`',0};
 
-    if (!package)
-        return ERROR_INVALID_HANDLE;
+    TRACE("Checking launch conditions\n");
 
     rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
     if (rc != ERROR_SUCCESS)
         return ERROR_SUCCESS;
 
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
-    }
-
-    /* increment progress bar each time action data is sent */
-    ui_progress(package,1,REG_PROGRESS_VALUE,1,0);
-
-    while (1)
-    {
-        static const WCHAR szHCR[] = 
-            {'H','K','E','Y','_','C','L','A','S','S','E','S','_',
-             'R','O','O','T','\\',0};
-        static const WCHAR szHCU[] =
-            {'H','K','E','Y','_','C','U','R','R','E','N','T','_',
-             'U','S','E','R','\\',0};
-        static const WCHAR szHLM[] =
-            {'H','K','E','Y','_','L','O','C','A','L','_',
-             'M','A','C','H','I','N','E','\\',0};
-        static const WCHAR szHU[] =
-            {'H','K','E','Y','_','U','S','E','R','S','\\',0};
-
-        LPSTR value_data = NULL;
-        HKEY  root_key, hkey;
-        DWORD type,size;
-        LPWSTR value, key, name, component, deformated;
-        LPCWSTR szRoot;
-        INT component_index;
-        MSIRECORD * uirow;
-        LPWSTR uikey;
-        INT   root;
-        BOOL check_first = FALSE;
-
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            rc = ERROR_SUCCESS;
-            break;
-        }
-        ui_progress(package,2,0,0,0);
-
-        value = NULL;
-        key = NULL;
-        uikey = NULL;
-        name = NULL;
-
-        component = load_dynamic_stringW(row, 6);
-        component_index = get_loaded_component(package,component);
-
-        if (!ACTION_VerifyComponentForAction(package, component_index, 
-                                       INSTALLSTATE_LOCAL))
-        {
-            TRACE("Skipping write due to disabled component\n");
-            msiobj_release(&row->hdr);
-
-            package->components[component_index].Action =
-                package->components[component_index].Installed;
-
-            goto next;
-        }
-
-        package->components[component_index].Action = INSTALLSTATE_LOCAL;
-
-        name = load_dynamic_stringW(row, 4);
-        if( MSI_RecordIsNull(row,5) && name )
-        {
-            /* null values can have special meanings */
-            if (name[0]=='-' && name[1] == 0)
-            {
-                msiobj_release(&row->hdr);
-                goto next;
-            }
-            else if ((name[0]=='+' && name[1] == 0) || 
-                     (name[0] == '*' && name[1] == 0))
-            {
-                HeapFree(GetProcessHeap(),0,name);
-                name = NULL;
-                check_first = TRUE;
-            }
-        }
-
-        root = MSI_RecordGetInteger(row,2);
-        key = load_dynamic_stringW(row, 3);
-      
-   
-        /* get the root key */
-        switch (root)
-        {
-            case 0:  root_key = HKEY_CLASSES_ROOT; 
-                     szRoot = szHCR;
-                     break;
-            case 1:  root_key = HKEY_CURRENT_USER;
-                     szRoot = szHCU;
-                     break;
-            case 2:  root_key = HKEY_LOCAL_MACHINE;
-                     szRoot = szHLM;
-                     break;
-            case 3:  root_key = HKEY_USERS; 
-                     szRoot = szHU;
-                     break;
-            default:
-                 ERR("Unknown root %i\n",root);
-                 root_key=NULL;
-                 szRoot = NULL;
-                 break;
-        }
-        if (!root_key)
-        {
-            msiobj_release(&row->hdr);
-            goto next;
-        }
-
-        deformat_string(package, key , &deformated);
-        size = strlenW(deformated) + strlenW(szRoot) + 1;
-        uikey = HeapAlloc(GetProcessHeap(), 0, 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));
-            msiobj_release(&row->hdr);
-            HeapFree(GetProcessHeap(),0,deformated);
-            goto next;
-        }
-        HeapFree(GetProcessHeap(),0,deformated);
-
-        value = load_dynamic_stringW(row,5);
-        if (value)
-            value_data = parse_value(package, value, &type, &size); 
-        else
-        {
-            static const WCHAR szEmpty[] = {0};
-            value_data = (LPSTR)strdupW(szEmpty);
-            size = 0;
-            type = REG_SZ;
-        }
-
-        deformat_string(package, name, &deformated);
-
-        /* get the double nulls to terminate SZ_MULTI */
-        if (type == REG_MULTI_SZ)
-            size +=sizeof(WCHAR);
-
-        if (!check_first)
-        {
-            TRACE("Setting value %s of %s\n",debugstr_w(deformated),
-                            debugstr_w(uikey));
-            RegSetValueExW(hkey, deformated, 0, type, value_data, size);
-        }
-        else
-        {
-            DWORD sz = 0;
-            rc = RegQueryValueExW(hkey, deformated, NULL, NULL, NULL, &sz);
-            if (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA)
-            {
-                TRACE("value %s of %s checked already exists\n",
-                                debugstr_w(deformated), debugstr_w(uikey));
-            }
-            else
-            {
-                TRACE("Checked and setting value %s of %s\n",
-                                debugstr_w(deformated), debugstr_w(uikey));
-                RegSetValueExW(hkey, deformated, 0, type, value_data, size);
-            }
-        }
-
-        uirow = MSI_CreateRecord(3);
-        MSI_RecordSetStringW(uirow,2,deformated);
-        MSI_RecordSetStringW(uirow,1,uikey);
-
-        if (type == REG_SZ)
-            MSI_RecordSetStringW(uirow,3,(LPWSTR)value_data);
-        else
-            MSI_RecordSetStringW(uirow,3,value);
-
-        ui_actiondata(package,szWriteRegistryValues,uirow);
-        msiobj_release( &uirow->hdr );
-
-        HeapFree(GetProcessHeap(),0,value_data);
-        HeapFree(GetProcessHeap(),0,value);
-        HeapFree(GetProcessHeap(),0,deformated);
-
-        msiobj_release(&row->hdr);
-        RegCloseKey(hkey);
-next:
-        HeapFree(GetProcessHeap(),0,uikey);
-        HeapFree(GetProcessHeap(),0,key);
-        HeapFree(GetProcessHeap(),0,name);
-        HeapFree(GetProcessHeap(),0,component);
-    }
-    MSI_ViewClose(view);
-    msiobj_release(&view->hdr);
-    return rc;
-}
-
-static UINT ACTION_InstallInitialize(MSIPACKAGE *package)
-{
-    return ERROR_SUCCESS;
-}
-
-
-static UINT ACTION_InstallValidate(MSIPACKAGE *package)
-{
-    DWORD progress = 0;
-    DWORD total = 0;
-    static const WCHAR q1[]=
-        {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
-         '`','R','e','g','i','s','t','r','y','`',0};
-    UINT rc;
-    MSIQUERY * view;
-    MSIRECORD * row = 0;
-    int i;
-
-    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)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
-    }
-    while (1)
-    {
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            rc = ERROR_SUCCESS;
-            break;
-        }
-        progress +=1;
-
-        msiobj_release(&row->hdr);
-    }
-    MSI_ViewClose(view);
+    rc = MSI_IterateRecords(view, NULL, ITERATE_LaunchConditions, package);
     msiobj_release(&view->hdr);
 
-    total = total + progress * REG_PROGRESS_VALUE;
-    total = total + package->loaded_components * COMPONENT_PROGRESS_VALUE;
-    for (i=0; i < package->loaded_files; i++)
-        total += package->files[i].FileSize;
-    ui_progress(package,0,total,0,0);
-
-    for(i = 0; i < package->loaded_features; i++)
-    {
-        MSIFEATURE* feature = &package->features[i];
-        TRACE("Feature: %s; Installed: %i; Action %i; Request %i\n",
-            debugstr_w(feature->Feature), feature->Installed, feature->Action,
-            feature->ActionRequest);
-    }
-    
-    return ERROR_SUCCESS;
-}
-
-static UINT ACTION_LaunchConditions(MSIPACKAGE *package)
-{
-    UINT rc;
-    MSIQUERY * view = NULL;
-    MSIRECORD * row = 0;
-    static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','L','a','u','n','c','h','C','o','n','d','i','t','i','o','n','`',0};
-    static const WCHAR title[]=
-        {'I','n','s','t','a','l','l',' ','F','a', 'i','l','e','d',0};
-
-    TRACE("Checking launch conditions\n");
-
-    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
-    if (rc != ERROR_SUCCESS)
-        return ERROR_SUCCESS;
-
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
-    }
-
-    rc = ERROR_SUCCESS;
-    while (rc == ERROR_SUCCESS)
-    {
-        LPWSTR cond = NULL; 
-        LPWSTR message = NULL;
-
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            rc = ERROR_SUCCESS;
-            break;
-        }
-
-        cond = load_dynamic_stringW(row,1);
-
-        if (MSI_EvaluateConditionW(package,cond) != MSICONDITION_TRUE)
-        {
-            LPWSTR deformated;
-            message = load_dynamic_stringW(row,2);
-            deformat_string(package,message,&deformated); 
-            MessageBoxW(NULL,deformated,title,MB_OK);
-            HeapFree(GetProcessHeap(),0,message);
-            HeapFree(GetProcessHeap(),0,deformated);
-            rc = ERROR_FUNCTION_FAILED;
-        }
-        HeapFree(GetProcessHeap(),0,cond);
-        msiobj_release(&row->hdr);
-    }
-    MSI_ViewClose(view);
-    msiobj_release(&view->hdr);
     return rc;
 }
 
@@ -3880,10 +2311,10 @@ static LPWSTR resolve_keypath( MSIPACKAGE* package, INT
     }
     if (cmp->Attributes & msidbComponentAttributesRegistryKeyPath)
     {
-        MSIQUERY * view;
         MSIRECORD * row = 0;
-        UINT rc,root,len;
-        LPWSTR key,deformated,buffer,name,deformated_name;
+        UINT root,len;
+        LPWSTR deformated,buffer,deformated_name;
+        LPCWSTR key,name;
         static const WCHAR ExecSeqQuery[] =
             {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
              '`','R','e','g','i','s','t','r','y','`',' ',
@@ -3893,30 +2324,13 @@ static LPWSTR resolve_keypath( MSIPACKAGE* package, INT
         static const WCHAR fmt2[]=
             {'%','0','2','i',':','\\','%','s','\\','%','s',0};
 
-        rc = MSI_OpenQuery(package->db,&view,ExecSeqQuery,cmp->KeyPath);
-
-        if (rc!=ERROR_SUCCESS)
+        row = MSI_QueryGetRecord(package->db, ExecSeqQuery,cmp->KeyPath);
+        if (!row)
             return NULL;
 
-        rc = MSI_ViewExecute(view, 0);
-        if (rc != ERROR_SUCCESS)
-        {
-            MSI_ViewClose(view);
-            msiobj_release(&view->hdr);
-            return NULL;
-        }
-
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            MSI_ViewClose(view);
-            msiobj_release(&view->hdr);
-            return NULL;
-        }
-
         root = MSI_RecordGetInteger(row,2);
-        key = load_dynamic_stringW(row, 3);
-        name = load_dynamic_stringW(row, 4);
+        key = MSI_RecordGetString(row, 3);
+        name = MSI_RecordGetString(row, 4);
         deformat_string(package, key , &deformated);
         deformat_string(package, name, &deformated_name);
 
@@ -3931,13 +2345,9 @@ static LPWSTR resolve_keypath( MSIPACKAGE* package, INT
         else
             sprintfW(buffer,fmt,root,deformated);
 
-        HeapFree(GetProcessHeap(),0,key);
         HeapFree(GetProcessHeap(),0,deformated);
-        HeapFree(GetProcessHeap(),0,name);
         HeapFree(GetProcessHeap(),0,deformated_name);
         msiobj_release(&row->hdr);
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
 
         return buffer;
     }
@@ -3960,7 +2370,7 @@ static LPWSTR resolve_keypath( MSIPACKAGE* package, INT
     return NULL;
 }
 
-static HKEY openSharedDLLsKey()
+static HKEY openSharedDLLsKey(void)
 {
     HKEY hkey=0;
     static const WCHAR path[] =
@@ -4214,7 +2624,7 @@ typedef struct {
     ITypeLib    *ptLib;
 } typelib_struct;
 
-BOOL CALLBACK Typelib_EnumResNameProc( HMODULE hModule, LPCWSTR lpszType, 
+static BOOL CALLBACK Typelib_EnumResNameProc( HMODULE hModule, LPCWSTR lpszType, 
                                        LPWSTR lpszName, LONG_PTR lParam)
 {
     TLIBATTR *attr;
@@ -4232,8 +2642,13 @@ BOOL CALLBACK Typelib_EnumResNameProc( HMODULE hModule, LPCWSTR lpszType,
     sz = strlenW(tl_struct->source)+4;
     sz *= sizeof(WCHAR);
 
-    tl_struct->path = HeapAlloc(GetProcessHeap(),0,sz);
-    sprintfW(tl_struct->path,fmt,tl_struct->source, lpszName);
+    if ((INT)lpszName == 1)
+        tl_struct->path = strdupW(tl_struct->source);
+    else
+    {
+        tl_struct->path = HeapAlloc(GetProcessHeap(),0,sz);
+        sprintfW(tl_struct->path,fmt,tl_struct->source, lpszName);
+    }
 
     TRACE("trying %s\n", debugstr_w(tl_struct->path));
     res = LoadTypeLib(tl_struct->path,&tl_struct->ptLib);
@@ -4261,6 +2676,91 @@ BOOL CALLBACK Typelib_EnumResNameProc( HMODULE hModule, LPCWSTR lpszType,
     return TRUE;
 }
 
+static UINT ITERATE_RegisterTypeLibraries(MSIRECORD *row, LPVOID param)
+{
+    MSIPACKAGE* package = (MSIPACKAGE*)param;
+    LPCWSTR component;
+    INT index;
+    typelib_struct tl_struct;
+    HMODULE module;
+    static const WCHAR szTYPELIB[] = {'T','Y','P','E','L','I','B',0};
+
+    component = MSI_RecordGetString(row,3);
+    index = get_loaded_component(package,component);
+    if (index < 0)
+        return ERROR_SUCCESS;
+
+    if (!ACTION_VerifyComponentForAction(package, index, INSTALLSTATE_LOCAL))
+    {
+        TRACE("Skipping typelib reg due to disabled component\n");
+
+        package->components[index].Action =
+            package->components[index].Installed;
+
+        return ERROR_SUCCESS;
+    }
+
+    package->components[index].Action = INSTALLSTATE_LOCAL;
+
+    index = get_loaded_file(package,package->components[index].KeyPath); 
+
+    if (index < 0)
+        return ERROR_SUCCESS;
+
+    module = LoadLibraryExW(package->files[index].TargetPath, NULL,
+                    LOAD_LIBRARY_AS_DATAFILE);
+    if (module != NULL)
+    {
+        LPWSTR guid;
+        guid = load_dynamic_stringW(row,1);
+        CLSIDFromString(guid, &tl_struct.clsid);
+        HeapFree(GetProcessHeap(),0,guid);
+        tl_struct.source = strdupW(package->files[index].TargetPath);
+        tl_struct.path = NULL;
+
+        EnumResourceNamesW(module, szTYPELIB, Typelib_EnumResNameProc,
+                        (LONG_PTR)&tl_struct);
+
+        if (tl_struct.path != NULL)
+        {
+            LPWSTR help = NULL;
+            LPCWSTR helpid;
+            HRESULT res;
+
+            helpid = MSI_RecordGetString(row,6);
+
+            if (helpid)
+                help = resolve_folder(package,helpid,FALSE,FALSE,NULL);
+            res = RegisterTypeLib(tl_struct.ptLib,tl_struct.path,help);
+            HeapFree(GetProcessHeap(),0,help);
+
+            if (!SUCCEEDED(res))
+                ERR("Failed to register type library %s\n",
+                        debugstr_w(tl_struct.path));
+            else
+            {
+                ui_actiondata(package,szRegisterTypeLibraries,row);
+
+                TRACE("Registered %s\n", debugstr_w(tl_struct.path));
+            }
+
+            ITypeLib_Release(tl_struct.ptLib);
+            HeapFree(GetProcessHeap(),0,tl_struct.path);
+        }
+        else
+            ERR("Failed to load type library %s\n",
+                    debugstr_w(tl_struct.source));
+
+        FreeLibrary(module);
+        HeapFree(GetProcessHeap(),0,tl_struct.source);
+    }
+    else
+        ERR("Could not load file! %s\n",
+                debugstr_w(package->files[index].TargetPath));
+
+    return ERROR_SUCCESS;
+}
+
 static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package)
 {
     /* 
@@ -4271,7 +2771,6 @@ static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package)
      */
     UINT rc;
     MSIQUERY * view;
-    MSIRECORD * row = 0;
     static const WCHAR Query[] =
         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
          '`','T','y','p','e','L','i','b','`',0};
@@ -4283,2916 +2782,1381 @@ static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package)
     if (rc != ERROR_SUCCESS)
         return ERROR_SUCCESS;
 
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
-    }
-
-    while (1)
-    {   
-        WCHAR component[0x100];
-        DWORD sz;
-        INT index;
-        LPWSTR guid;
-        typelib_struct tl_struct;
-        HMODULE module;
-        static const WCHAR szTYPELIB[] = {'T','Y','P','E','L','I','B',0};
+    rc = MSI_IterateRecords(view, NULL, ITERATE_RegisterTypeLibraries, package);
+    msiobj_release(&view->hdr);
+    return rc;
+}
 
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            rc = ERROR_SUCCESS;
-            break;
-        }
+static UINT ITERATE_CreateShortcuts(MSIRECORD *row, LPVOID param)
+{
+    MSIPACKAGE *package = (MSIPACKAGE*)param;
+    LPWSTR target_file, target_folder;
+    LPCWSTR buffer;
+    WCHAR filename[0x100];
+    DWORD sz;
+    DWORD index;
+    static const WCHAR szlnk[]={'.','l','n','k',0};
+    IShellLinkW *sl;
+    IPersistFile *pf;
+    HRESULT res;
 
-        sz = 0x100;
-        MSI_RecordGetStringW(row,3,component,&sz);
+    buffer = MSI_RecordGetString(row,4);
+    index = get_loaded_component(package,buffer);
 
-        index = get_loaded_component(package,component);
-        if (index < 0)
-        {
-            msiobj_release(&row->hdr);
-            continue;
-        }
+    if (index < 0)
+        return ERROR_SUCCESS;
 
-        if (!ACTION_VerifyComponentForAction(package, index,
-                                INSTALLSTATE_LOCAL))
-        {
-            TRACE("Skipping typelib reg due to disabled component\n");
-            msiobj_release(&row->hdr);
+    if (!ACTION_VerifyComponentForAction(package, index, INSTALLSTATE_LOCAL))
+    {
+        TRACE("Skipping shortcut creation due to disabled component\n");
 
-            package->components[index].Action =
+        package->components[index].Action =
                 package->components[index].Installed;
 
-            continue;
-        }
-
-        package->components[index].Action = INSTALLSTATE_LOCAL;
-
-        index = get_loaded_file(package,package->components[index].KeyPath); 
-   
-        if (index < 0)
-        {
-            msiobj_release(&row->hdr);
-            continue;
-        }
-
-        guid = load_dynamic_stringW(row,1);
-        module = LoadLibraryExW(package->files[index].TargetPath, NULL,
-                        LOAD_LIBRARY_AS_DATAFILE);
-        if (module != NULL)
-        {
-            CLSIDFromString(guid, &tl_struct.clsid);
-            tl_struct.source = strdupW(package->files[index].TargetPath);
-            tl_struct.path = NULL;
-
-            EnumResourceNamesW(module, szTYPELIB, Typelib_EnumResNameProc, 
-                               (LONG_PTR)&tl_struct);
-
-            if (tl_struct.path != NULL)
-            {
-                LPWSTR help;
-                WCHAR helpid[0x100];
-                HRESULT res;
-
-                sz = 0x100;
-                MSI_RecordGetStringW(row,6,helpid,&sz);
-
-                help = resolve_folder(package,helpid,FALSE,FALSE,NULL);
-                res = RegisterTypeLib(tl_struct.ptLib,tl_struct.path,help);
-                HeapFree(GetProcessHeap(),0,help);
-
-                if (!SUCCEEDED(res))
-                    ERR("Failed to register type library %s\n", 
-                            debugstr_w(tl_struct.path));
-                else
-                {
-                    ui_actiondata(package,szRegisterTypeLibraries,row);
-                
-                    TRACE("Registered %s\n", debugstr_w(tl_struct.path));
-                }
-
-                ITypeLib_Release(tl_struct.ptLib);
-                HeapFree(GetProcessHeap(),0,tl_struct.path);
-            }
-            else
-                ERR("Failed to load type library %s\n", 
-                    debugstr_w(tl_struct.source));
-       
-            FreeLibrary(module);
-            HeapFree(GetProcessHeap(),0,tl_struct.source);
-        }
-        else
-            ERR("Could not load file! %s\n",
-                    debugstr_w(package->files[index].TargetPath));
-        msiobj_release(&row->hdr);
+        return ERROR_SUCCESS;
     }
-    MSI_ViewClose(view);
-    msiobj_release(&view->hdr);
-    return rc;
-}
 
-static UINT register_appid(MSIPACKAGE *package, LPCWSTR clsid, LPCWSTR app )
-{
-    static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
-    UINT rc;
-    MSIQUERY * view;
-    MSIRECORD * row = 0;
-    static const WCHAR ExecSeqQuery[] = 
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','A','p','p','I' ,'d','`',' ','W','H','E','R','E',' ',
-         '`','A','p','p','I','d','`',' ','=','\'','%','s','\'',0};
-    HKEY hkey2,hkey3;
-    LPWSTR buffer=0;
+    package->components[index].Action = INSTALLSTATE_LOCAL;
 
-    if (!package)
-        return ERROR_INVALID_HANDLE;
+    ui_actiondata(package,szCreateShortcuts,row);
 
-    rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, clsid);
-    if (rc != ERROR_SUCCESS)
-        return rc;
+    res = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
+                    &IID_IShellLinkW, (LPVOID *) &sl );
 
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
+    if (FAILED(res))
     {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
+        ERR("Is IID_IShellLink\n");
+        return ERROR_SUCCESS;
     }
 
-    RegCreateKeyW(HKEY_CLASSES_ROOT,szAppID,&hkey2);
-    RegCreateKeyW(hkey2,clsid,&hkey3);
-    RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)app,
-                   (strlenW(app)+1)*sizeof(WCHAR));
-
-    rc = MSI_ViewFetch(view,&row);
-    if (rc != ERROR_SUCCESS)
+    res = IShellLinkW_QueryInterface( sl, &IID_IPersistFile,(LPVOID*) &pf );
+    if( FAILED( res ) )
     {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
+        ERR("Is IID_IPersistFile\n");
+        return ERROR_SUCCESS;
     }
 
-    if (!MSI_RecordIsNull(row,2)) 
-    {
-        LPWSTR deformated=0;
-        UINT size; 
-        static const WCHAR szRemoteServerName[] =
-             {'R','e','m','o','t','e','S','e','r','v','e','r','N','a','m','e',
-              0};
-        buffer = load_dynamic_stringW(row,2);
-        size = deformat_string(package,buffer,&deformated);
-        RegSetValueExW(hkey3,szRemoteServerName,0,REG_SZ,(LPVOID)deformated,
-                       size);
+    buffer = MSI_RecordGetString(row,2);
+    target_folder = resolve_folder(package, buffer,FALSE,FALSE,NULL);
+
+    /* may be needed because of a bug somehwere else */
+    create_full_pathW(target_folder);
+
+    sz = 0x100;
+    MSI_RecordGetStringW(row,3,filename,&sz);
+    reduce_to_longfilename(filename);
+    if (!strchrW(filename,'.') || strcmpiW(strchrW(filename,'.'),szlnk))
+        strcatW(filename,szlnk);
+    target_file = build_directory_name(2, target_folder, filename);
+    HeapFree(GetProcessHeap(),0,target_folder);
+
+    buffer = MSI_RecordGetString(row,5);
+    if (strchrW(buffer,'['))
+    {
+        LPWSTR deformated;
+        deformat_string(package,buffer,&deformated);
+        IShellLinkW_SetPath(sl,deformated);
         HeapFree(GetProcessHeap(),0,deformated);
-        HeapFree(GetProcessHeap(),0,buffer);
     }
-
-    if (!MSI_RecordIsNull(row,3)) 
+    else
     {
-        static const WCHAR szLocalService[] =
-             {'L','o','c','a','l','S','e','r','v','i','c','e',0};
-        UINT size;
-        buffer = load_dynamic_stringW(row,3);
-        size = (strlenW(buffer)+1) * sizeof(WCHAR);
-        RegSetValueExW(hkey3,szLocalService,0,REG_SZ,(LPVOID)buffer,size);
-        HeapFree(GetProcessHeap(),0,buffer);
+        LPWSTR keypath;
+        FIXME("poorly handled shortcut format, advertised shortcut\n");
+        keypath = strdupW(package->components[index].FullKeypath);
+        IShellLinkW_SetPath(sl,keypath);
+        HeapFree(GetProcessHeap(),0,keypath);
     }
 
-    if (!MSI_RecordIsNull(row,4)) 
+    if (!MSI_RecordIsNull(row,6))
     {
-        static const WCHAR szService[] =
-             {'S','e','r','v','i','c','e',
-              'P','a','r','a','m','e','t','e','r','s',0};
-        UINT size;
-        buffer = load_dynamic_stringW(row,4);
-        size = (strlenW(buffer)+1) * sizeof(WCHAR);
-        RegSetValueExW(hkey3,szService,0,REG_SZ,(LPVOID)buffer,size);
-        HeapFree(GetProcessHeap(),0,buffer);
+        LPWSTR deformated;
+        buffer = MSI_RecordGetString(row,6);
+        deformat_string(package,buffer,&deformated);
+        IShellLinkW_SetArguments(sl,deformated);
+        HeapFree(GetProcessHeap(),0,deformated);
     }
 
-    if (!MSI_RecordIsNull(row,5)) 
+    if (!MSI_RecordIsNull(row,7))
     {
-        static const WCHAR szDLL[] =
-             {'D','l','l','S','u','r','r','o','g','a','t','e',0};
-        UINT size;
-        buffer = load_dynamic_stringW(row,5);
-        size = (strlenW(buffer)+1) * sizeof(WCHAR);
-        RegSetValueExW(hkey3,szDLL,0,REG_SZ,(LPVOID)buffer,size);
-        HeapFree(GetProcessHeap(),0,buffer);
+        buffer = MSI_RecordGetString(row,7);
+        IShellLinkW_SetDescription(sl,buffer);
     }
 
-    if (!MSI_RecordIsNull(row,6)) 
+    if (!MSI_RecordIsNull(row,8))
+        IShellLinkW_SetHotkey(sl,MSI_RecordGetInteger(row,8));
+
+    if (!MSI_RecordIsNull(row,9))
     {
-        static const WCHAR szActivate[] =
-             {'A','c','t','i','v','a','t','e','A','s',
-              'S','t','o','r','a','g','e',0};
-        static const WCHAR szY[] = {'Y',0};
+        WCHAR *Path = NULL;
+        INT index; 
 
-        if (MSI_RecordGetInteger(row,6))
-            RegSetValueExW(hkey3,szActivate,0,REG_SZ,(LPVOID)szY,4);
+        buffer = MSI_RecordGetString(row,9);
+
+        build_icon_path(package,buffer,&Path);
+        index = MSI_RecordGetInteger(row,10);
+
+        IShellLinkW_SetIconLocation(sl,Path,index);
+        HeapFree(GetProcessHeap(),0,Path);
     }
 
-    if (!MSI_RecordIsNull(row,7)) 
-    {
-        static const WCHAR szRunAs[] = {'R','u','n','A','s',0};
-        static const WCHAR szUser[] = 
-             {'I','n','t','e','r','a','c','t','i','v','e',' ',
-              'U','s','e','r',0};
+    if (!MSI_RecordIsNull(row,11))
+        IShellLinkW_SetShowCmd(sl,MSI_RecordGetInteger(row,11));
 
-        if (MSI_RecordGetInteger(row,7))
-            RegSetValueExW(hkey3,szRunAs,0,REG_SZ,(LPVOID)szUser,34);
+    if (!MSI_RecordIsNull(row,12))
+    {
+        LPWSTR Path;
+        buffer = MSI_RecordGetString(row,12);
+        Path = resolve_folder(package, buffer, FALSE, FALSE, NULL);
+        IShellLinkW_SetWorkingDirectory(sl,Path);
+        HeapFree(GetProcessHeap(), 0, Path);
     }
 
-    msiobj_release(&row->hdr);
-    MSI_ViewClose(view);
-    msiobj_release(&view->hdr);
-    RegCloseKey(hkey3);
-    RegCloseKey(hkey2);
-    return rc;
+    TRACE("Writing shortcut to %s\n",debugstr_w(target_file));
+    IPersistFile_Save(pf,target_file,FALSE);
+
+    HeapFree(GetProcessHeap(),0,target_file);    
+
+    IPersistFile_Release( pf );
+    IShellLinkW_Release( sl );
+
+    return ERROR_SUCCESS;
 }
 
-static UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
+static UINT ACTION_CreateShortcuts(MSIPACKAGE *package)
 {
-    /* 
-     * Again I am assuming the words, "Whose key file represents" when referring
-     * to a Component as to meaning that Components KeyPath file
-     *
-     * Also there is a very strong connection between ClassInfo and ProgID
-     * that I am mostly glossing over.  
-     * What would be more propper is to load the ClassInfo and the ProgID info
-     * into memory data structures and then be able to enable and disable them
-     * based on component. 
-     */
-    
     UINT rc;
+    HRESULT res;
     MSIQUERY * view;
-    MSIRECORD * row = 0;
-    static const WCHAR ExecSeqQuery[] =
+    static const WCHAR Query[] =
         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','C','l','a','s','s','`',0};
-    static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
-    static const WCHAR szProgID[] = { 'P','r','o','g','I','D',0 };
-    static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
-    static const WCHAR szSpace[] = {' ',0};
-    HKEY hkey,hkey2,hkey3;
-    LPWSTR argument,deformated;
+         '`','S','h','o','r','t','c','u','t','`',0};
 
     if (!package)
         return ERROR_INVALID_HANDLE;
 
-    rc = RegCreateKeyW(HKEY_CLASSES_ROOT,szCLSID,&hkey);
-    if (rc != ERROR_SUCCESS)
-        return ERROR_FUNCTION_FAILED;
-
-    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
+    rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
     if (rc != ERROR_SUCCESS)
-    {
-        rc = ERROR_SUCCESS;
-        goto end;
-    }
+        return ERROR_SUCCESS;
 
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
+    res = CoInitialize( NULL );
+    if (FAILED (res))
     {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        goto end;
+        ERR("CoInitialize failed\n");
+        return ERROR_FUNCTION_FAILED;
     }
 
-    while (1)
-    {
-        WCHAR clsid[0x100];
-        WCHAR buffer[0x100];
-        WCHAR desc[0x100];
-        DWORD sz;
-        INT index;
-        DWORD size;
-     
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            rc = ERROR_SUCCESS;
-            break;
-        }
+    rc = MSI_IterateRecords(view, NULL, ITERATE_CreateShortcuts, package);
+    msiobj_release(&view->hdr);
 
-        sz=0x100;
-        MSI_RecordGetStringW(row,3,buffer,&sz);
+    CoUninitialize();
 
-        index = get_loaded_component(package,buffer);
+    return rc;
+}
 
-        if (index < 0)
-        {
-            msiobj_release(&row->hdr);
-            continue;
-        }
+static UINT ITERATE_PublishProduct(MSIRECORD *row, LPVOID param)
+{
+    MSIPACKAGE* package = (MSIPACKAGE*)param;
+    HANDLE the_file;
+    LPWSTR FilePath=NULL;
+    LPCWSTR FileName=NULL;
+    CHAR buffer[1024];
+    DWORD sz;
+    UINT rc;
 
-        if ((!ACTION_VerifyComponentForAction(package, index,
-                                INSTALLSTATE_LOCAL)) &&
-            (!ACTION_VerifyComponentForAction(package, index,
-                                INSTALLSTATE_ADVERTISED)))
-        {
-            TRACE("Skipping class reg due to disabled component\n");
-            msiobj_release(&row->hdr);
+    FileName = MSI_RecordGetString(row,1);
+    if (!FileName)
+    {
+        ERR("Unable to get FileName\n");
+        return ERROR_SUCCESS;
+    }
 
-            package->components[index].Action =
-                package->components[index].Installed;
+    build_icon_path(package,FileName,&FilePath);
 
-            continue;
-        }
+    TRACE("Creating icon file at %s\n",debugstr_w(FilePath));
 
-        package->components[index].Action = INSTALLSTATE_LOCAL;
+    the_file = CreateFileW(FilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+                        FILE_ATTRIBUTE_NORMAL, NULL);
 
-        sz=0x100;
-        MSI_RecordGetStringW(row,1,clsid,&sz);
-        RegCreateKeyW(hkey,clsid,&hkey2);
+    if (the_file == INVALID_HANDLE_VALUE)
+    {
+        ERR("Unable to create file %s\n",debugstr_w(FilePath));
+        HeapFree(GetProcessHeap(),0,FilePath);
+        return ERROR_SUCCESS;
+    }
 
-        if (!MSI_RecordIsNull(row,5))
+    do 
+    {
+        DWORD write;
+        sz = 1024;
+        rc = MSI_RecordReadStream(row,2,buffer,&sz);
+        if (rc != ERROR_SUCCESS)
         {
-            sz=0x100;
-            MSI_RecordGetStringW(row,5,desc,&sz);
-
-            RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)desc,
-                           (strlenW(desc)+1)*sizeof(WCHAR));
+            ERR("Failed to get stream\n");
+            CloseHandle(the_file);  
+            DeleteFileW(FilePath);
+            break;
         }
-        else
-            desc[0]=0;
+        WriteFile(the_file,buffer,sz,&write,NULL);
+    } while (sz == 1024);
 
-        sz=0x100;
-        MSI_RecordGetStringW(row,2,buffer,&sz);
+    HeapFree(GetProcessHeap(),0,FilePath);
 
-        RegCreateKeyW(hkey2,buffer,&hkey3);
+    CloseHandle(the_file);
+    return ERROR_SUCCESS;
+}
 
-        index = get_loaded_file(package,package->components[index].KeyPath);
+/*
+ * 99% of the work done here is only done for 
+ * advertised installs. However this is where the
+ * Icon table is processed and written out
+ * so that is what I am going to do here.
+ */
+static UINT ACTION_PublishProduct(MSIPACKAGE *package)
+{
+    UINT rc;
+    MSIQUERY * view;
+    static const WCHAR Query[]=
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','I','c','o','n','`',0};
+    /* for registry stuff */
+    LPWSTR productcode;
+    HKEY hkey=0;
+    HKEY hukey=0;
+    static const WCHAR szProductName[] =
+        {'P','r','o','d','u','c','t','N','a','m','e',0};
+    static const WCHAR szPackageCode[] =
+        {'P','a','c','k','a','g','e','C','o','d','e',0};
+    static const WCHAR szLanguage[] =
+        {'L','a','n','g','u','a','g','e',0};
+    static const WCHAR szProductLanguage[] =
+        {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
+    static const WCHAR szProductIcon[] =
+        {'P','r','o','d','u','c','t','I','c','o','n',0};
+    static const WCHAR szARPProductIcon[] =
+        {'A','R','P','P','R','O','D','U','C','T','I','C','O','N',0};
+    static const WCHAR szProductVersion[] =
+        {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
+    static const WCHAR szVersion[] =
+        {'V','e','r','s','i','o','n',0};
+    DWORD langid;
+    LPWSTR buffer;
+    DWORD size;
+    MSIHANDLE hDb, hSumInfo;
 
-        argument = load_dynamic_stringW(row,11); 
-        size = deformat_string(package,argument,&deformated);
-        if (deformated)
-            size+=sizeof(WCHAR);
-        HeapFree(GetProcessHeap(),0,argument);
-        size += (strlenW(package->files[index].TargetPath))*sizeof(WCHAR);
+    if (!package)
+        return ERROR_INVALID_HANDLE;
 
-        argument = HeapAlloc(GetProcessHeap(),0,size+sizeof(WCHAR));
-        strcpyW(argument,package->files[index].TargetPath);
-        if (deformated)
-        {
-            strcatW(argument,szSpace);
-            strcatW(argument,deformated);
-        }
+    /* write out icon files */
 
-        RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)argument, size);
-        HeapFree(GetProcessHeap(),0,deformated);
-        HeapFree(GetProcessHeap(),0,argument);
+    rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
+    if (rc == ERROR_SUCCESS)
+    {
+        MSI_IterateRecords(view, NULL, ITERATE_PublishProduct, package);
+        msiobj_release(&view->hdr);
+    }
 
-        RegCloseKey(hkey3);
+    /* ok there is a lot more done here but i need to figure out what */
 
-        if (!MSI_RecordIsNull(row,4))
-        {
-            sz=0x100;
-            MSI_RecordGetStringW(row,4,buffer,&sz);
+    productcode = load_dynamic_property(package,szProductCode,&rc);
+    if (!productcode)
+        return rc;
 
-            RegCreateKeyW(hkey2,szProgID,&hkey3);
-    
-            RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)buffer,
-                       (strlenW(buffer)+1)*sizeof(WCHAR));
+    rc = MSIREG_OpenProductsKey(productcode,&hkey,TRUE);
+    if (rc != ERROR_SUCCESS)
+        goto end;
 
-            RegCloseKey(hkey3);
-        }
+    rc = MSIREG_OpenUserProductsKey(productcode,&hukey,TRUE);
+    if (rc != ERROR_SUCCESS)
+        goto end;
 
-        if (!MSI_RecordIsNull(row,6))
-        { 
-            sz=0x100;
-            MSI_RecordGetStringW(row,6,buffer,&sz);
 
-            RegSetValueExW(hkey2,szAppID,0,REG_SZ,(LPVOID)buffer,
-                       (strlenW(buffer)+1)*sizeof(WCHAR));
+    buffer = load_dynamic_property(package,szProductName,NULL);
+    size = strlenW(buffer)*sizeof(WCHAR);
+    RegSetValueExW(hukey,szProductName,0,REG_SZ, (BYTE *)buffer,size);
+    HeapFree(GetProcessHeap(),0,buffer);
 
-            register_appid(package,buffer,desc);
-        }
+    buffer = load_dynamic_property(package,szProductLanguage,NULL);
+    size = sizeof(DWORD);
+    langid = atoiW(buffer);
+    RegSetValueExW(hukey,szLanguage,0,REG_DWORD, (BYTE *)&langid,size);
+    HeapFree(GetProcessHeap(),0,buffer);
 
+    buffer = load_dynamic_property(package,szARPProductIcon,NULL);
+    if (buffer)
+    {
+        LPWSTR path;
+        build_icon_path(package,buffer,&path);
+        size = strlenW(path) * sizeof(WCHAR);
+        RegSetValueExW(hukey,szProductIcon,0,REG_SZ, (BYTE *)path,size);
+    }
+    HeapFree(GetProcessHeap(),0,buffer);
 
-        if (!MSI_RecordIsNull(row,7))
+    buffer = load_dynamic_property(package,szProductVersion,NULL);
+    if (buffer)
+    {
+        DWORD verdword = build_version_dword(buffer);
+        size = sizeof(DWORD);
+        RegSetValueExW(hukey,szVersion,0,REG_DWORD, (BYTE *)&verdword,size);
+    }
+    HeapFree(GetProcessHeap(),0,buffer);
+    
+    FIXME("Need to write more keys to the user registry\n");
+  
+    hDb= alloc_msihandle( &package->db->hdr );
+    rc = MsiGetSummaryInformationW(hDb, NULL, 0, &hSumInfo); 
+    MsiCloseHandle(hDb);
+    if (rc == ERROR_SUCCESS)
+    {
+        WCHAR guidbuffer[0x200];
+        size = 0x200;
+        rc = MsiSummaryInfoGetPropertyW(hSumInfo, 9, NULL, NULL, NULL,
+                                        guidbuffer, &size);
+        if (rc == ERROR_SUCCESS)
         {
-            FIXME("Process field 7\n");
+            WCHAR squashed[GUID_SIZE];
+            /* for now we only care about the first guid */
+            LPWSTR ptr = strchrW(guidbuffer,';');
+            if (ptr) *ptr = 0;
+            squash_guid(guidbuffer,squashed);
+            size = strlenW(squashed)*sizeof(WCHAR);
+            RegSetValueExW(hukey,szPackageCode,0,REG_SZ, (LPSTR)squashed,
+                           size);
         }
-
-        if (!MSI_RecordIsNull(row,8))
-        {
-            static const WCHAR szDefaultIcon[] = 
-                {'D','e','f','a','u','l','t','I','c','o','n',0};
-
-            LPWSTR FileName = load_dynamic_stringW(row,8);
-            LPWSTR FilePath;
-            INT index;
-
-            RegCreateKeyW(hkey2,szDefaultIcon,&hkey3);
-            build_icon_path(package,FileName,&FilePath);
-            if (!MSI_RecordIsNull(row,9))
-            {
-                static const WCHAR index_fmt[] = {',','%','i',0};
-                WCHAR index_buf[20];
-                index = MSI_RecordGetInteger(row,9);
-                sprintfW(index_buf,index_fmt,index);
-                size = strlenW(FilePath)+strlenW(index_buf)+1;
-                size *= sizeof(WCHAR);
-                HeapReAlloc(GetProcessHeap(),0,FilePath,size);
-            }
-            RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)FilePath,
-                           (strlenW(FilePath)+1) * sizeof(WCHAR));
-            HeapFree(GetProcessHeap(),0,FilePath);
-            HeapFree(GetProcessHeap(),0,FileName);
-            RegCloseKey(hkey3);
-        }
-
-        if (!MSI_RecordIsNull(row,10))
+        else
         {
-            static const WCHAR szInproc32[] =
-                {'I','n','p','r','o','c','H','a','n','d','l','e','r','3','2',
-                 0};
-            static const WCHAR szInproc[] =
-                {'I','n','p','r','o','c','H','a','n','d','l','e','r',0};
-            INT i = MSI_RecordGetInteger(row,10);
-            if (i != MSI_NULL_INTEGER && i > 0 &&  i < 4)
-            {
-                static const WCHAR ole2[] = {'o','l','e','2','.','d','l','l',0};
-                static const WCHAR ole32[] =
-                    {'o','l','e','3','2','.','d','l','l',0};
-                switch(i)
-                {
-                    case 1:
-                        size = strlenW(ole2) * sizeof(WCHAR);
-                        RegCreateKeyW(hkey2,szInproc,&hkey3);
-                        RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)ole2, size);
-                        RegCloseKey(hkey3);
-                        break;
-                    case 2:
-                        size = strlenW(ole32) * sizeof(WCHAR);
-                        RegCreateKeyW(hkey2,szInproc32,&hkey3);
-                        RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)ole32,size);
-                        RegCloseKey(hkey3);
-                        break;
-                    case 3:
-                        size = strlenW(ole2) * sizeof(WCHAR);
-                        RegCreateKeyW(hkey2,szInproc,&hkey3);
-                        RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)ole2, size);
-                        RegCloseKey(hkey3);
-                        size = strlenW(ole32) * sizeof(WCHAR);
-                        RegCreateKeyW(hkey2,szInproc32,&hkey3);
-                        RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)ole32,size);
-                        RegCloseKey(hkey3);
-                        break;
-                }
-                
-            }
-            else
-            {
-                RegCreateKeyW(hkey2,szInproc32,&hkey3);
-                argument = load_dynamic_stringW(row,10);
-                reduce_to_longfilename(argument);
-                size = strlenW(argument)*sizeof(WCHAR);
-
-                RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)argument, size);
-                HeapFree(GetProcessHeap(),0,argument);
-
-                RegCloseKey(hkey3);
-            }
+            ERR("Unable to query Revision_Number... \n");
+            rc = ERROR_SUCCESS;
         }
-
-        RegCloseKey(hkey2);
-
-        ui_actiondata(package,szRegisterClassInfo,row);
-
-        msiobj_release(&row->hdr);
+        MsiCloseHandle(hSumInfo);
+    }
+    else
+    {
+        ERR("Unable to open Summary Information\n");
+        rc = ERROR_SUCCESS;
     }
-    MSI_ViewClose(view);
-    msiobj_release(&view->hdr);
 
 end:
+
+    HeapFree(GetProcessHeap(),0,productcode);    
     RegCloseKey(hkey);
+    RegCloseKey(hukey);
+
     return rc;
 }
 
-static UINT register_progid_base(MSIPACKAGE* package, MSIRECORD * row, 
-                                LPWSTR clsid)
+static UINT ITERATE_WriteIniValues(MSIRECORD *row, LPVOID param)
 {
-    static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
-    static const WCHAR szDefaultIcon[] =
-        {'D','e','f','a','u','l','t','I','c','o','n',0};
-    HKEY hkey,hkey2;
-    WCHAR buffer[0x100];
-    DWORD sz;
-
+    MSIPACKAGE *package = (MSIPACKAGE*)param;
+    LPCWSTR component,section,key,value,identifier,filename,dirproperty;
+    LPWSTR deformated_section, deformated_key, deformated_value;
+    LPWSTR folder, fullname = NULL;
+    MSIRECORD * uirow;
+    INT component_index,action;
+    static const WCHAR szWindowsFolder[] =
+          {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
 
-    sz = 0x100;
-    MSI_RecordGetStringW(row,1,buffer,&sz);
-    RegCreateKeyW(HKEY_CLASSES_ROOT,buffer,&hkey);
+    component = MSI_RecordGetString(row, 8);
+    component_index = get_loaded_component(package,component);
 
-    if (!MSI_RecordIsNull(row,4))
+    if (!ACTION_VerifyComponentForAction(package, component_index,
+                            INSTALLSTATE_LOCAL))
     {
-        sz = 0x100;
-        MSI_RecordGetStringW(row,4,buffer,&sz);
-        RegSetValueExW(hkey,NULL,0,REG_SZ,(LPVOID)buffer, (strlenW(buffer)+1) *
-                       sizeof(WCHAR));
+        TRACE("Skipping ini file due to disabled component %s\n",
+                        debugstr_w(component));
+
+        package->components[component_index].Action =
+            package->components[component_index].Installed;
+
+        return ERROR_SUCCESS;
     }
 
-    if (!MSI_RecordIsNull(row,3))
-    {   
-        sz = 0x100;
-    
-        MSI_RecordGetStringW(row,3,buffer,&sz);
-        RegCreateKeyW(hkey,szCLSID,&hkey2);
-        RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)buffer, (strlenW(buffer)+1) *
-                       sizeof(WCHAR));
+    package->components[component_index].Action = INSTALLSTATE_LOCAL;
 
-        if (clsid)
-            strcpyW(clsid,buffer);
+    identifier = MSI_RecordGetString(row,1); 
+    filename = MSI_RecordGetString(row,2);
+    dirproperty = MSI_RecordGetString(row,3);
+    section = MSI_RecordGetString(row,4);
+    key = MSI_RecordGetString(row,5);
+    value = MSI_RecordGetString(row,6);
+    action = MSI_RecordGetInteger(row,7);
 
-        RegCloseKey(hkey2);
+    deformat_string(package,section,&deformated_section);
+    deformat_string(package,key,&deformated_key);
+    deformat_string(package,value,&deformated_value);
+
+    if (dirproperty)
+    {
+        folder = resolve_folder(package, dirproperty, FALSE, FALSE, NULL);
+        if (!folder)
+            folder = load_dynamic_property(package,dirproperty,NULL);
     }
     else
+        folder = load_dynamic_property(package, szWindowsFolder, NULL);
+
+    if (!folder)
     {
-        FIXME("UNHANDLED case, Parent progid but classid is NULL\n");
-        return ERROR_FUNCTION_FAILED;
+        ERR("Unable to resolve folder! (%s)\n",debugstr_w(dirproperty));
+        goto cleanup;
     }
-    if (!MSI_RecordIsNull(row,5))
-    {
-        INT index = MSI_RecordGetInteger(row,6); 
-        LPWSTR FileName = load_dynamic_stringW(row,5);
-        LPWSTR FilePath,IconPath;
-        static const WCHAR fmt[] = {'%','s',',','%','i',0};
 
-        RegCreateKeyW(hkey,szDefaultIcon,&hkey2);
-        build_icon_path(package,FileName,&FilePath);
-       
-        IconPath = HeapAlloc(GetProcessHeap(),0,(strlenW(FilePath)+5)*
-                    sizeof(WCHAR));
+    fullname = build_directory_name(3, folder, filename, NULL);
 
-        sprintfW(IconPath,fmt,FilePath,index);
-        RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)IconPath,
-                           (strlenW(IconPath)+1) * sizeof(WCHAR));
-        HeapFree(GetProcessHeap(),0,FilePath);
-        HeapFree(GetProcessHeap(),0,FileName);
-        RegCloseKey(hkey2);
+    if (action == 0)
+    {
+        TRACE("Adding value %s to section %s in %s\n",
+                debugstr_w(deformated_key), debugstr_w(deformated_section),
+                debugstr_w(fullname));
+        WritePrivateProfileStringW(deformated_section, deformated_key,
+                                   deformated_value, fullname);
+    }
+    else if (action == 1)
+    {
+        WCHAR returned[10];
+        GetPrivateProfileStringW(deformated_section, deformated_key, NULL,
+                                 returned, 10, fullname);
+        if (returned[0] == 0)
+        {
+            TRACE("Adding value %s to section %s in %s\n",
+                    debugstr_w(deformated_key), debugstr_w(deformated_section),
+                    debugstr_w(fullname));
+
+            WritePrivateProfileStringW(deformated_section, deformated_key,
+                                       deformated_value, fullname);
+        }
     }
+    else if (action == 3)
+        FIXME("Append to existing section not yet implemented\n");
+
+    uirow = MSI_CreateRecord(4);
+    MSI_RecordSetStringW(uirow,1,identifier);
+    MSI_RecordSetStringW(uirow,2,deformated_section);
+    MSI_RecordSetStringW(uirow,3,deformated_key);
+    MSI_RecordSetStringW(uirow,4,deformated_value);
+    ui_actiondata(package,szWriteIniValues,uirow);
+    msiobj_release( &uirow->hdr );
+cleanup:
+    HeapFree(GetProcessHeap(),0,fullname);
+    HeapFree(GetProcessHeap(),0,folder);
+    HeapFree(GetProcessHeap(),0,deformated_key);
+    HeapFree(GetProcessHeap(),0,deformated_value);
+    HeapFree(GetProcessHeap(),0,deformated_section);
     return ERROR_SUCCESS;
 }
 
-static UINT register_progid(MSIPACKAGE *package, MSIRECORD * row, LPWSTR clsid);
-
-static UINT register_parent_progid(MSIPACKAGE *package, LPCWSTR parent, 
-                                   LPWSTR clsid)
+static UINT ACTION_WriteIniValues(MSIPACKAGE *package)
 {
     UINT rc;
     MSIQUERY * view;
-    MSIRECORD * row = 0;
-    static const WCHAR Query_t[] = 
+    static const WCHAR ExecSeqQuery[] = 
         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','P','r','o','g' ,'I','d','`',' ','W','H','E','R','E',' ',
-         '`','P','r','o','g','I','d','`',' ','=',' ','\'' ,'%','s','\'',0};
-
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
-    rc = MSI_OpenQuery(package->db, &view, Query_t, parent);
-    if (rc != ERROR_SUCCESS)
-        return rc;
-
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
-    }
+         '`','I','n','i','F','i','l','e','`',0};
 
-    rc = MSI_ViewFetch(view,&row);
+    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
     if (rc != ERROR_SUCCESS)
     {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
+        TRACE("no IniFile table\n");
+        return ERROR_SUCCESS;
     }
 
-    register_progid(package,row,clsid);
-
-    msiobj_release(&row->hdr);
-    MSI_ViewClose(view);
+    rc = MSI_IterateRecords(view, NULL, ITERATE_WriteIniValues, package);
     msiobj_release(&view->hdr);
     return rc;
 }
 
-static UINT register_progid(MSIPACKAGE *package, MSIRECORD * row, LPWSTR clsid)
+static UINT ITERATE_SelfRegModules(MSIRECORD *row, LPVOID param)
 {
-    UINT rc = ERROR_SUCCESS; 
+    MSIPACKAGE *package = (MSIPACKAGE*)param;
+    LPCWSTR filename;
+    LPWSTR FullName;
+    INT index;
+    DWORD len;
+    static const WCHAR ExeStr[] =
+        {'r','e','g','s','v','r','3','2','.','e','x','e',' ','\"',0};
+    static const WCHAR close[] =  {'\"',0};
+    STARTUPINFOW si;
+    PROCESS_INFORMATION info;
+    BOOL brc;
 
-    if (MSI_RecordIsNull(row,2))
-        rc = register_progid_base(package,row,clsid);
-    else
-    {
-        WCHAR buffer[0x1000];
-        DWORD sz, disp;
-        HKEY hkey,hkey2;
-        static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
-        static const WCHAR szDefaultIcon[] =
-            {'D','e','f','a','u','l','t','I','c','o','n',0};
-
-        /* check if already registered */
-        sz = 0x100;
-        MSI_RecordGetStringW(row,1,buffer,&sz);
-        RegCreateKeyExW(HKEY_CLASSES_ROOT, buffer, 0, NULL, 0,
-                        KEY_ALL_ACCESS, NULL, &hkey, &disp );
-        if (disp == REG_OPENED_EXISTING_KEY)
-        {
-            TRACE("Key already registered\n");
-            RegCloseKey(hkey);
-            return rc;
-        }
+    memset(&si,0,sizeof(STARTUPINFOW));
 
-        sz = 0x100;
-        MSI_RecordGetStringW(row,2,buffer,&sz);
-        rc = register_parent_progid(package,buffer,clsid);
+    filename = MSI_RecordGetString(row,1);
+    index = get_loaded_file(package,filename);
 
-        /* clsid is same as parent */
-        RegCreateKeyW(hkey,szCLSID,&hkey2);
-        RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)clsid, (strlenW(clsid)+1) *
-                       sizeof(WCHAR));
+    if (index < 0)
+    {
+        ERR("Unable to find file id %s\n",debugstr_w(filename));
+        return ERROR_SUCCESS;
+    }
 
-        RegCloseKey(hkey2);
+    len = strlenW(ExeStr);
+    len += strlenW(package->files[index].TargetPath);
+    len +=2;
 
+    FullName = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
+    strcpyW(FullName,ExeStr);
+    strcatW(FullName,package->files[index].TargetPath);
+    strcatW(FullName,close);
 
-        if (!MSI_RecordIsNull(row,4))
-        {
-            sz = 0x100;
-            MSI_RecordGetStringW(row,4,buffer,&sz);
-            RegSetValueExW(hkey,NULL,0,REG_SZ,(LPVOID)buffer,
-                           (strlenW(buffer)+1) * sizeof(WCHAR));
-        }
+    TRACE("Registering %s\n",debugstr_w(FullName));
+    brc = CreateProcessW(NULL, FullName, NULL, NULL, FALSE, 0, NULL, c_colon,
+                    &si, &info);
 
-        if (!MSI_RecordIsNull(row,5))
-        {
-            LPWSTR FileName = load_dynamic_stringW(row,5);
-            LPWSTR FilePath;
-            RegCreateKeyW(hkey,szDefaultIcon,&hkey2);
-            build_icon_path(package,FileName,&FilePath);
-            RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)FilePath,
-                           (strlenW(FilePath)+1) * sizeof(WCHAR));
-            HeapFree(GetProcessHeap(),0,FilePath);
-            HeapFree(GetProcessHeap(),0,FileName);
-            RegCloseKey(hkey2);
-        }
+    if (brc)
+        msi_dialog_check_messages(info.hProcess);
 
-        RegCloseKey(hkey);
-    }
-    return rc;
+    HeapFree(GetProcessHeap(),0,FullName);
+    return ERROR_SUCCESS;
 }
 
-static UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package)
+static UINT ACTION_SelfRegModules(MSIPACKAGE *package)
 {
-    /* 
-     * Sigh, here I am just brute force registering all progids
-     * this needs to be linked to the Classes that have been registered
-     * but the easiest way to do that is to load all these stuff into
-     * memory for easy checking.
-     *
-     * Gives me something to continue to work toward.
-     */
     UINT rc;
     MSIQUERY * view;
-    MSIRECORD * row = 0;
-    static const WCHAR Query[] =
-        {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
-         '`','P','r','o','g','I','d','`',0};
-
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
-    rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
-    if (rc != ERROR_SUCCESS)
-        return ERROR_SUCCESS;
+    static const WCHAR ExecSeqQuery[] = 
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','S','e','l','f','R','e','g','`',0};
 
-    rc = MSI_ViewExecute(view, 0);
+    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
     if (rc != ERROR_SUCCESS)
     {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
+        TRACE("no SelfReg table\n");
+        return ERROR_SUCCESS;
     }
 
-    while (1)
-    {
-        WCHAR clsid[0x1000];
-
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            rc = ERROR_SUCCESS;
-            break;
-        }
-        
-        register_progid(package,row,clsid);
-        ui_actiondata(package,szRegisterProgIdInfo,row);
-
-        msiobj_release(&row->hdr);
-    }
-    MSI_ViewClose(view);
+    MSI_IterateRecords(view, NULL, ITERATE_SelfRegModules, package);
     msiobj_release(&view->hdr);
-    return rc;
-}
 
-static UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name, 
-                            LPWSTR *FilePath)
-{
-    LPWSTR ProductCode;
-    LPWSTR SystemFolder;
-    LPWSTR dest;
-    UINT rc;
-
-    static const WCHAR szInstaller[] = 
-        {'I','n','s','t','a','l','l','e','r','\\',0};
-    static const WCHAR szFolder[] =
-        {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
-
-    ProductCode = load_dynamic_property(package,szProductCode,&rc);
-    if (!ProductCode)
-        return rc;
-
-    SystemFolder = load_dynamic_property(package,szFolder,NULL);
-
-    dest = build_directory_name(3, SystemFolder, szInstaller, ProductCode);
-
-    create_full_pathW(dest);
-
-    *FilePath = build_directory_name(2, dest, icon_name);
-
-    HeapFree(GetProcessHeap(),0,SystemFolder);
-    HeapFree(GetProcessHeap(),0,ProductCode);
-    HeapFree(GetProcessHeap(),0,dest);
     return ERROR_SUCCESS;
 }
 
-static UINT ACTION_CreateShortcuts(MSIPACKAGE *package)
+static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
 {
+    LPWSTR productcode;
     UINT rc;
-    MSIQUERY * view;
-    MSIRECORD * row = 0;
-    static const WCHAR Query[] =
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','S','h','o','r','t','c','u','t','`',0};
-    IShellLinkW *sl;
-    IPersistFile *pf;
-    HRESULT res;
-
+    DWORD i;
+    HKEY hkey=0;
+    HKEY hukey=0;
+    
     if (!package)
         return ERROR_INVALID_HANDLE;
 
-    res = CoInitialize( NULL );
-    if (FAILED (res))
-    {
-        ERR("CoInitialize failed\n");
-        return ERROR_FUNCTION_FAILED;
-    }
+    productcode = load_dynamic_property(package,szProductCode,&rc);
+    if (!productcode)
+        return rc;
 
-    rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
+    rc = MSIREG_OpenFeaturesKey(productcode,&hkey,TRUE);
     if (rc != ERROR_SUCCESS)
-        return ERROR_SUCCESS;
+        goto end;
 
-    rc = MSI_ViewExecute(view, 0);
+    rc = MSIREG_OpenUserFeaturesKey(productcode,&hukey,TRUE);
     if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
-    }
+        goto end;
 
-    while (1)
+    /* here the guids are base 85 encoded */
+    for (i = 0; i < package->loaded_features; i++)
     {
-        LPWSTR target_file, target_folder;
-        WCHAR buffer[0x100];
-        DWORD sz;
-        DWORD index;
-        static const WCHAR szlnk[]={'.','l','n','k',0};
+        LPWSTR data = NULL;
+        GUID clsid;
+        int j;
+        INT size;
+        BOOL absent = FALSE;
 
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            rc = ERROR_SUCCESS;
-            break;
-        }
-        
-        sz = 0x100;
-        MSI_RecordGetStringW(row,4,buffer,&sz);
+        if (!ACTION_VerifyFeatureForAction(package,i,INSTALLSTATE_LOCAL) &&
+            !ACTION_VerifyFeatureForAction(package,i,INSTALLSTATE_SOURCE) &&
+            !ACTION_VerifyFeatureForAction(package,i,INSTALLSTATE_ADVERTISED))
+            absent = TRUE;
 
-        index = get_loaded_component(package,buffer);
+        size = package->features[i].ComponentCount*21;
+        size +=1;
+        if (package->features[i].Feature_Parent[0])
+            size += strlenW(package->features[i].Feature_Parent)+2;
 
-        if (index < 0)
-        {
-            msiobj_release(&row->hdr);
-            continue;
-        }
+        data = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
 
-        if (!ACTION_VerifyComponentForAction(package, index,
-                                INSTALLSTATE_LOCAL))
+        data[0] = 0;
+        for (j = 0; j < package->features[i].ComponentCount; j++)
         {
-            TRACE("Skipping shortcut creation due to disabled component\n");
-            msiobj_release(&row->hdr);
-
-            package->components[index].Action =
-                package->components[index].Installed;
-
-            continue;
-        }
-
-        package->components[index].Action = INSTALLSTATE_LOCAL;
-
-        ui_actiondata(package,szCreateShortcuts,row);
-
-        res = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
-                              &IID_IShellLinkW, (LPVOID *) &sl );
-
-        if (FAILED(res))
-        {
-            ERR("Is IID_IShellLink\n");
-            msiobj_release(&row->hdr);
-            continue;
+            WCHAR buf[21];
+            memset(buf,0,sizeof(buf));
+            if (package->components
+                [package->features[i].Components[j]].ComponentId[0]!=0)
+            {
+                TRACE("From %s\n",debugstr_w(package->components
+                            [package->features[i].Components[j]].ComponentId));
+                CLSIDFromString(package->components
+                            [package->features[i].Components[j]].ComponentId,
+                            &clsid);
+                encode_base85_guid(&clsid,buf);
+                TRACE("to %s\n",debugstr_w(buf));
+                strcatW(data,buf);
+            }
         }
-
-        res = IShellLinkW_QueryInterface( sl, &IID_IPersistFile,(LPVOID*) &pf );
-        if( FAILED( res ) )
+        if (package->features[i].Feature_Parent[0])
         {
-            ERR("Is IID_IPersistFile\n");
-            msiobj_release(&row->hdr);
-            continue;
+            static const WCHAR sep[] = {'\2',0};
+            strcatW(data,sep);
+            strcatW(data,package->features[i].Feature_Parent);
         }
 
-        sz = 0x100;
-        MSI_RecordGetStringW(row,2,buffer,&sz);
-        target_folder = resolve_folder(package, buffer,FALSE,FALSE,NULL);
-
-        /* may be needed because of a bug somehwere else */
-        create_full_pathW(target_folder);
-
-        sz = 0x100;
-        MSI_RecordGetStringW(row,3,buffer,&sz);
-        reduce_to_longfilename(buffer);
-        if (!strchrW(buffer,'.') || strcmpiW(strchrW(buffer,'.'),szlnk))
-            strcatW(buffer,szlnk);
-        target_file = build_directory_name(2, target_folder, buffer);
-        HeapFree(GetProcessHeap(),0,target_folder);
+        size = (strlenW(data)+1)*sizeof(WCHAR);
+        RegSetValueExW(hkey,package->features[i].Feature,0,REG_SZ,
+                       (LPSTR)data,size);
+        HeapFree(GetProcessHeap(),0,data);
 
-        sz = 0x100;
-        MSI_RecordGetStringW(row,5,buffer,&sz);
-        if (strchrW(buffer,'['))
+        if (!absent)
         {
-            LPWSTR deformated;
-            deformat_string(package,buffer,&deformated);
-            IShellLinkW_SetPath(sl,deformated);
-            HeapFree(GetProcessHeap(),0,deformated);
+            size = strlenW(package->features[i].Feature_Parent)*sizeof(WCHAR);
+            RegSetValueExW(hukey,package->features[i].Feature,0,REG_SZ,
+                       (LPSTR)package->features[i].Feature_Parent,size);
         }
         else
         {
-            LPWSTR keypath;
-            FIXME("poorly handled shortcut format, advertised shortcut\n");
-            keypath = strdupW(package->components[index].FullKeypath);
-            IShellLinkW_SetPath(sl,keypath);
-            HeapFree(GetProcessHeap(),0,keypath);
-        }
-
-        if (!MSI_RecordIsNull(row,6))
-        {
-            LPWSTR deformated;
-            sz = 0x100;
-            MSI_RecordGetStringW(row,6,buffer,&sz);
-            deformat_string(package,buffer,&deformated);
-            IShellLinkW_SetArguments(sl,deformated);
-            HeapFree(GetProcessHeap(),0,deformated);
-        }
-
-        if (!MSI_RecordIsNull(row,7))
-        {
-            LPWSTR deformated;
-            deformated = load_dynamic_stringW(row,7);
-            IShellLinkW_SetDescription(sl,deformated);
-            HeapFree(GetProcessHeap(),0,deformated);
-        }
-
-        if (!MSI_RecordIsNull(row,8))
-            IShellLinkW_SetHotkey(sl,MSI_RecordGetInteger(row,8));
-
-        if (!MSI_RecordIsNull(row,9))
-        {
-            WCHAR *Path = NULL;
-            INT index; 
-
-            sz = 0x100;
-            MSI_RecordGetStringW(row,9,buffer,&sz);
-
-            build_icon_path(package,buffer,&Path);
-            index = MSI_RecordGetInteger(row,10);
-
-            IShellLinkW_SetIconLocation(sl,Path,index);
-            HeapFree(GetProcessHeap(),0,Path);
-        }
-
-        if (!MSI_RecordIsNull(row,11))
-            IShellLinkW_SetShowCmd(sl,MSI_RecordGetInteger(row,11));
-
-        if (!MSI_RecordIsNull(row,12))
-        {
-            LPWSTR Path;
-            sz = 0x100;
-            MSI_RecordGetStringW(row,12,buffer,&sz);
-            Path = resolve_folder(package, buffer, FALSE, FALSE, NULL);
-            IShellLinkW_SetWorkingDirectory(sl,Path);
-            HeapFree(GetProcessHeap(), 0, Path);
+            size = (strlenW(package->features[i].Feature_Parent)+2)*
+                    sizeof(WCHAR);
+            data = HeapAlloc(GetProcessHeap(),0,size);
+            data[0] = 0x6;
+            strcpyW(&data[1],package->features[i].Feature_Parent);
+            RegSetValueExW(hukey,package->features[i].Feature,0,REG_SZ,
+                       (LPSTR)data,size);
+            HeapFree(GetProcessHeap(),0,data);
         }
-
-        TRACE("Writing shortcut to %s\n",debugstr_w(target_file));
-        IPersistFile_Save(pf,target_file,FALSE);
-    
-        HeapFree(GetProcessHeap(),0,target_file);    
-
-        IPersistFile_Release( pf );
-        IShellLinkW_Release( sl );
-
-        msiobj_release(&row->hdr);
     }
-    MSI_ViewClose(view);
-    msiobj_release(&view->hdr);
-
-
-    CoUninitialize();
 
+end:
+    RegCloseKey(hkey);
+    RegCloseKey(hukey);
+    HeapFree(GetProcessHeap(), 0, productcode);
     return rc;
 }
 
-
-/*
- * 99% of the work done here is only done for 
- * advertised installs. However this is where the
- * Icon table is processed and written out
- * so that is what I am going to do here.
- */
-static UINT ACTION_PublishProduct(MSIPACKAGE *package)
+static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
 {
-    UINT rc;
-    MSIQUERY * view;
-    MSIRECORD * row = 0;
-    static const WCHAR Query[]=
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','I','c','o','n','`',0};
-    DWORD sz;
-    /* for registry stuff */
-    LPWSTR productcode;
     HKEY hkey=0;
-    HKEY hukey=0;
-    static const WCHAR szProductName[] =
-        {'P','r','o','d','u','c','t','N','a','m','e',0};
-    static const WCHAR szPackageCode[] =
-        {'P','a','c','k','a','g','e','C','o','d','e',0};
-    LPWSTR buffer;
+    LPWSTR buffer = NULL;
+    LPWSTR productcode;
+    UINT rc,i;
     DWORD size;
-    MSIHANDLE hDb, hSumInfo;
+    static WCHAR szNONE[] = {0};
+    static const WCHAR szWindowsInstaler[] = 
+    {'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},
+    };
+
+    static const WCHAR installerPathFmt[] = {
+    '%','s','\\',
+    'I','n','s','t','a','l','l','e','r','\\',0};
+    static const WCHAR fmt[] = {
+    '%','s','\\',
+    'I','n','s','t','a','l','l','e','r','\\',
+    '%','x','.','m','s','i',0};
+    static const WCHAR szLocalPackage[]=
+         {'L','o','c','a','l','P','a','c','k','a','g','e',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};
+    static const WCHAR szModifyPath[] = 
+        {'M','o','d','i','f','y','P','a','t','h',0};
+    static const WCHAR szUninstallString[] = 
+        {'U','n','i','n','s','t','a','l','l','S','t','r','i','n','g',0};
+    static const WCHAR szEstimatedSize[] = 
+        {'E','s','t','i','m','a','t','e','d','S','i','z','e',0};
+    static const WCHAR szInstallDate[] = 
+        {'I','n','s','t','a','l','l','D','a','t','e',0};
+    static const WCHAR szLanguage[] =
+        {'L','a','n','g','u','a','g','e',0};
+    static const WCHAR szProductLanguage[] =
+        {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
+    static const WCHAR szProductVersion[] =
+        {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
+    static const WCHAR szVersion[] =
+        {'V','e','r','s','i','o','n',0};
+    static const WCHAR szVersionMajor[] =
+        {'V','e','r','s','i','o','n','M','a','j','o','r',0};
+    static const WCHAR szVersionMinor[] =
+        {'V','e','r','s','i','o','n','M','i','n','o','r',0};
+
+    SYSTEMTIME systime;
+    static const WCHAR date_fmt[] = {'%','i','%','i','%','i',0};
+    LPWSTR upgrade_code;
+    WCHAR windir[MAX_PATH], path[MAX_PATH], packagefile[MAX_PATH];
+    INT num,start;
 
     if (!package)
         return ERROR_INVALID_HANDLE;
 
-    rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
-    if (rc != ERROR_SUCCESS)
-        goto next;
+    productcode = load_dynamic_property(package,szProductCode,&rc);
+    if (!productcode)
+        return rc;
 
-    rc = MSI_ViewExecute(view, 0);
+    rc = MSIREG_OpenUninstallKey(productcode,&hkey,TRUE);
     if (rc != ERROR_SUCCESS)
+        goto end;
+
+    /* dump all the info i can grab */
+    FIXME("Flesh out more information \n");
+
+    i = 0;
+    while (szPropKeys[i][0]!=0)
     {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        goto next;
+        buffer = load_dynamic_property(package,szPropKeys[i],&rc);
+        if (rc != ERROR_SUCCESS)
+            buffer = szNONE;
+        size = strlenW(buffer)*sizeof(WCHAR);
+        RegSetValueExW(hkey,szRegKeys[i],0,REG_SZ,(LPSTR)buffer,size);
+        HeapFree(GetProcessHeap(),0,buffer);
+        i++;
     }
 
-    while (1)
+    rc = 0x1;
+    size = sizeof(rc);
+    RegSetValueExW(hkey,szWindowsInstaler,0,REG_DWORD,(LPSTR)&rc,size);
+    
+    /* copy the package locally */
+    num = GetTickCount() & 0xffff;
+    if (!num) 
+        num = 1;
+    start = num;
+    GetWindowsDirectoryW(windir, sizeof(windir) / sizeof(windir[0]));
+    snprintfW(packagefile,sizeof(packagefile)/sizeof(packagefile[0]),fmt,
+     windir,num);
+    do 
     {
-        HANDLE the_file;
-        WCHAR *FilePath=NULL;
-        WCHAR *FileName=NULL;
-        CHAR buffer[1024];
-
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
+        HANDLE handle = CreateFileW(packagefile,GENERIC_WRITE, 0, NULL,
+                                  CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
+        if (handle != INVALID_HANDLE_VALUE)
         {
-            rc = ERROR_SUCCESS;
+            CloseHandle(handle);
             break;
         }
-    
-        FileName = load_dynamic_stringW(row,1);
-        if (!FileName)
-        {
-            ERR("Unable to get FileName\n");
-            msiobj_release(&row->hdr);
-            continue;
-        }
-
-        build_icon_path(package,FileName,&FilePath);
-
-        HeapFree(GetProcessHeap(),0,FileName);
-
-        TRACE("Creating icon file at %s\n",debugstr_w(FilePath));
-        
-        the_file = CreateFileW(FilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
-                           FILE_ATTRIBUTE_NORMAL, NULL);
-
-        if (the_file == INVALID_HANDLE_VALUE)
-        {
-            ERR("Unable to create file %s\n",debugstr_w(FilePath));
-            msiobj_release(&row->hdr);
-            HeapFree(GetProcessHeap(),0,FilePath);
-            continue;
-        }
+        if (GetLastError() != ERROR_FILE_EXISTS &&
+            GetLastError() != ERROR_SHARING_VIOLATION)
+            break;
+        if (!(++num & 0xffff)) num = 1;
+        sprintfW(packagefile,fmt,num);
+    } while (num != start);
 
-        do 
-        {
-            DWORD write;
-            sz = 1024;
-            rc = MSI_RecordReadStream(row,2,buffer,&sz);
-            if (rc != ERROR_SUCCESS)
-            {
-                ERR("Failed to get stream\n");
-                CloseHandle(the_file);  
-                DeleteFileW(FilePath);
-                break;
-            }
-            WriteFile(the_file,buffer,sz,&write,NULL);
-        } while (sz == 1024);
+    snprintfW(path,sizeof(path)/sizeof(path[0]),installerPathFmt,windir);
+    create_full_pathW(path);
+    TRACE("Copying to local package %s\n",debugstr_w(packagefile));
+    if (!CopyFileW(package->PackagePath,packagefile,FALSE))
+        ERR("Unable to copy package (%s -> %s) (error %ld)\n",
+            debugstr_w(package->PackagePath), debugstr_w(packagefile),
+            GetLastError());
+    size = strlenW(packagefile)*sizeof(WCHAR);
+    RegSetValueExW(hkey,szLocalPackage,0,REG_SZ,(LPSTR)packagefile,size);
 
-        HeapFree(GetProcessHeap(),0,FilePath);
+    /* do ModifyPath and UninstallString */
+    size = deformat_string(package,modpath_fmt,&buffer);
+    RegSetValueExW(hkey,szModifyPath,0,REG_EXPAND_SZ,(LPSTR)buffer,size);
+    RegSetValueExW(hkey,szUninstallString,0,REG_EXPAND_SZ,(LPSTR)buffer,size);
+    HeapFree(GetProcessHeap(),0,buffer);
 
-        CloseHandle(the_file);
-        msiobj_release(&row->hdr);
+    FIXME("Write real Estimated Size when we have it\n");
+    size = 0;
+    RegSetValueExW(hkey,szEstimatedSize,0,REG_DWORD,(LPSTR)&size,sizeof(DWORD));
+   
+    GetLocalTime(&systime);
+    size = 9*sizeof(WCHAR);
+    buffer= HeapAlloc(GetProcessHeap(),0,size);
+    sprintfW(buffer,date_fmt,systime.wYear,systime.wMonth,systime.wDay);
+    size = strlenW(buffer)*sizeof(WCHAR);
+    RegSetValueExW(hkey,szInstallDate,0,REG_SZ,(LPSTR)buffer,size);
+    HeapFree(GetProcessHeap(),0,buffer);
+   
+    buffer = load_dynamic_property(package,szProductLanguage,NULL);
+    size = atoiW(buffer);
+    RegSetValueExW(hkey,szLanguage,0,REG_DWORD, (LPSTR)&size,sizeof(DWORD));
+    HeapFree(GetProcessHeap(),1,buffer);
+
+    buffer = load_dynamic_property(package,szProductVersion,NULL);
+    if (buffer)
+    {
+        DWORD verdword = build_version_dword(buffer);
+        DWORD vermajor = verdword>>24;
+        DWORD verminor = (verdword>>16)&0x00FF;
+        size = sizeof(DWORD);
+        RegSetValueExW(hkey,szVersion,0,REG_DWORD,(LPSTR)&verdword,size);
+        RegSetValueExW(hkey,szVersionMajor,0,REG_DWORD,(LPSTR)&vermajor,size);
+        RegSetValueExW(hkey,szVersionMinor,0,REG_DWORD,(LPSTR)&verminor,size);
     }
-    MSI_ViewClose(view);
-    msiobj_release(&view->hdr);
-
-next:
-    /* ok there is a lot more done here but i need to figure out what */
-    productcode = load_dynamic_property(package,szProductCode,&rc);
-    if (!productcode)
-        return rc;
+    HeapFree(GetProcessHeap(),0,buffer);
+    
+    /* Handle Upgrade Codes */
+    upgrade_code = load_dynamic_property(package,szUpgradeCode, NULL);
+    if (upgrade_code)
+    {
+        HKEY hkey2;
+        WCHAR squashed[33];
+        MSIREG_OpenUpgradeCodesKey(upgrade_code, &hkey2, TRUE);
+        squash_guid(productcode,squashed);
+        RegSetValueExW(hkey2, squashed, 0,REG_SZ,NULL,0);
+        RegCloseKey(hkey2);
+        MSIREG_OpenUserUpgradeCodesKey(upgrade_code, &hkey2, TRUE);
+        squash_guid(productcode,squashed);
+        RegSetValueExW(hkey2, squashed, 0,REG_SZ,NULL,0);
+        RegCloseKey(hkey2);
 
-    rc = MSIREG_OpenProductsKey(productcode,&hkey,TRUE);
-    if (rc != ERROR_SUCCESS)
-        goto end;
-
-    rc = MSIREG_OpenUserProductsKey(productcode,&hukey,TRUE);
-    if (rc != ERROR_SUCCESS)
-        goto end;
-
-
-    buffer = load_dynamic_property(package,szProductName,NULL);
-    size = strlenW(buffer)*sizeof(WCHAR);
-    RegSetValueExW(hukey,szProductName,0,REG_SZ, (LPSTR)buffer,size);
-    HeapFree(GetProcessHeap(),0,buffer);
-    FIXME("Need to write more keys to the user registry\n");
-  
-    hDb= alloc_msihandle( &package->db->hdr );
-    rc = MsiGetSummaryInformationW(hDb, NULL, 0, &hSumInfo); 
-    MsiCloseHandle(hDb);
-    if (rc == ERROR_SUCCESS)
-    {
-        WCHAR guidbuffer[0x200];
-        size = 0x200;
-        rc = MsiSummaryInfoGetPropertyW(hSumInfo, 9, NULL, NULL, NULL,
-                                        guidbuffer, &size);
-        if (rc == ERROR_SUCCESS)
-        {
-            WCHAR squashed[GUID_SIZE];
-            /* for now we only care about the first guid */
-            LPWSTR ptr = strchrW(guidbuffer,';');
-            if (ptr) *ptr = 0;
-            squash_guid(guidbuffer,squashed);
-            size = strlenW(squashed)*sizeof(WCHAR);
-            RegSetValueExW(hukey,szPackageCode,0,REG_SZ, (LPSTR)squashed,
-                           size);
-        }
-        else
-        {
-            ERR("Unable to query Revision_Number... \n");
-            rc = ERROR_SUCCESS;
-        }
-        MsiCloseHandle(hSumInfo);
-    }
-    else
-    {
-        ERR("Unable to open Summary Information\n");
-        rc = ERROR_SUCCESS;
-    }
-
-end:
-
-    HeapFree(GetProcessHeap(),0,productcode);    
-    RegCloseKey(hkey);
-    RegCloseKey(hukey);
-
-    return rc;
-}
-
-static UINT ACTION_WriteIniValues(MSIPACKAGE *package)
-{
-    UINT rc;
-    MSIQUERY * view;
-    MSIRECORD * row = 0;
-    static const WCHAR ExecSeqQuery[] = 
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','I','n','i','F','i','l','e','`',0};
-    static const WCHAR szWindowsFolder[] =
-          {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
-
-    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
-    if (rc != ERROR_SUCCESS)
-    {
-        TRACE("no IniFile table\n");
-        return ERROR_SUCCESS;
-    }
-
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
-    }
-
-    while (1)
-    {
-        LPWSTR component,filename,dirproperty,section,key,value,identifier;
-        LPWSTR deformated_section, deformated_key, deformated_value;
-        LPWSTR folder, fullname = NULL;
-        MSIRECORD * uirow;
-        INT component_index,action;
-
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            rc = ERROR_SUCCESS;
-            break;
-        }
-
-        component = load_dynamic_stringW(row, 8);
-        component_index = get_loaded_component(package,component);
-        HeapFree(GetProcessHeap(),0,component);
-
-        if (!ACTION_VerifyComponentForAction(package, component_index,
-                                INSTALLSTATE_LOCAL))
-        {
-            TRACE("Skipping ini file due to disabled component\n");
-            msiobj_release(&row->hdr);
-
-            package->components[component_index].Action =
-                package->components[component_index].Installed;
-
-            continue;
-        }
-
-        package->components[component_index].Action = INSTALLSTATE_LOCAL;
-   
-        identifier = load_dynamic_stringW(row,1); 
-        filename = load_dynamic_stringW(row,2);
-        dirproperty = load_dynamic_stringW(row,3);
-        section = load_dynamic_stringW(row,4);
-        key = load_dynamic_stringW(row,5);
-        value = load_dynamic_stringW(row,6);
-        action = MSI_RecordGetInteger(row,7);
-
-        deformat_string(package,section,&deformated_section);
-        deformat_string(package,key,&deformated_key);
-        deformat_string(package,value,&deformated_value);
-
-        if (dirproperty)
-        {
-            folder = resolve_folder(package, dirproperty, FALSE, FALSE, NULL);
-            if (!folder)
-                folder = load_dynamic_property(package,dirproperty,NULL);
-        }
-        else
-            folder = load_dynamic_property(package, szWindowsFolder, NULL);
-
-        if (!folder)
-        {
-            ERR("Unable to resolve folder! (%s)\n",debugstr_w(dirproperty));
-            goto cleanup;
-        }
-
-        fullname = build_directory_name(3, folder, filename, NULL);
-
-        if (action == 0)
-        {
-            TRACE("Adding value %s to section %s in %s\n",
-                debugstr_w(deformated_key), debugstr_w(deformated_section),
-                debugstr_w(fullname));
-            WritePrivateProfileStringW(deformated_section, deformated_key,
-                                       deformated_value, fullname);
-        }
-        else if (action == 1)
-        {
-            WCHAR returned[10];
-            GetPrivateProfileStringW(deformated_section, deformated_key, NULL,
-                                     returned, 10, fullname);
-            if (returned[0] == 0)
-            {
-                TRACE("Adding value %s to section %s in %s\n",
-                    debugstr_w(deformated_key), debugstr_w(deformated_section),
-                    debugstr_w(fullname));
-
-                WritePrivateProfileStringW(deformated_section, deformated_key,
-                                       deformated_value, fullname);
-            }
-        }
-        else if (action == 3)
-        {
-            FIXME("Append to existing section not yet implemented\n");
-        }
-        
-        uirow = MSI_CreateRecord(4);
-        MSI_RecordSetStringW(uirow,1,identifier);
-        MSI_RecordSetStringW(uirow,2,deformated_section);
-        MSI_RecordSetStringW(uirow,3,deformated_key);
-        MSI_RecordSetStringW(uirow,4,deformated_value);
-        ui_actiondata(package,szWriteIniValues,uirow);
-        msiobj_release( &uirow->hdr );
-cleanup:
-        HeapFree(GetProcessHeap(),0,identifier);
-        HeapFree(GetProcessHeap(),0,fullname);
-        HeapFree(GetProcessHeap(),0,filename);
-        HeapFree(GetProcessHeap(),0,key);
-        HeapFree(GetProcessHeap(),0,value);
-        HeapFree(GetProcessHeap(),0,section);
-        HeapFree(GetProcessHeap(),0,dirproperty);
-        HeapFree(GetProcessHeap(),0,folder);
-        HeapFree(GetProcessHeap(),0,deformated_key);
-        HeapFree(GetProcessHeap(),0,deformated_value);
-        HeapFree(GetProcessHeap(),0,deformated_section);
-        msiobj_release(&row->hdr);
-    }
-    MSI_ViewClose(view);
-    msiobj_release(&view->hdr);
-    return rc;
-}
-
-static UINT ACTION_SelfRegModules(MSIPACKAGE *package)
-{
-    UINT rc;
-    MSIQUERY * view;
-    MSIRECORD * row = 0;
-    static const WCHAR ExecSeqQuery[] = 
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','S','e','l','f','R','e','g','`',0};
-
-    static const WCHAR ExeStr[] =
-        {'r','e','g','s','v','r','3','2','.','e','x','e',' ','\"',0};
-    static const WCHAR close[] =  {'\"',0};
-    STARTUPINFOW si;
-    PROCESS_INFORMATION info;
-    BOOL brc;
-
-    memset(&si,0,sizeof(STARTUPINFOW));
-
-    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
-    if (rc != ERROR_SUCCESS)
-    {
-        TRACE("no SelfReg table\n");
-        return ERROR_SUCCESS;
-    }
-
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
-    }
-
-    while (1)
-    {
-        LPWSTR filename;
-        INT index;
-        DWORD len;
-
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            rc = ERROR_SUCCESS;
-            break;
-        }
-
-        filename = load_dynamic_stringW(row,1);
-        index = get_loaded_file(package,filename);
-
-        if (index < 0)
-        {
-            ERR("Unable to find file id %s\n",debugstr_w(filename));
-            HeapFree(GetProcessHeap(),0,filename);
-            msiobj_release(&row->hdr);
-            continue;
-        }
-        HeapFree(GetProcessHeap(),0,filename);
-
-        len = strlenW(ExeStr);
-        len += strlenW(package->files[index].TargetPath);
-        len +=2;
-
-        filename = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
-        strcpyW(filename,ExeStr);
-        strcatW(filename,package->files[index].TargetPath);
-        strcatW(filename,close);
-
-        TRACE("Registering %s\n",debugstr_w(filename));
-        brc = CreateProcessW(NULL, filename, NULL, NULL, FALSE, 0, NULL,
-                  c_colon, &si, &info);
-
-        if (brc)
-            msi_dialog_check_messages(info.hProcess);
-        HeapFree(GetProcessHeap(),0,filename);
-        msiobj_release(&row->hdr);
-    }
-    MSI_ViewClose(view);
-    msiobj_release(&view->hdr);
-    return rc;
-}
-
-static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
-{
-    LPWSTR productcode;
-    UINT rc;
-    DWORD i;
-    HKEY hkey=0;
-    HKEY hukey=0;
-    
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
-    productcode = load_dynamic_property(package,szProductCode,&rc);
-    if (!productcode)
-        return rc;
-
-    rc = MSIREG_OpenFeaturesKey(productcode,&hkey,TRUE);
-    if (rc != ERROR_SUCCESS)
-        goto end;
-
-    rc = MSIREG_OpenUserFeaturesKey(productcode,&hukey,TRUE);
-    if (rc != ERROR_SUCCESS)
-        goto end;
-
-    /* here the guids are base 85 encoded */
-    for (i = 0; i < package->loaded_features; i++)
-    {
-        LPWSTR data = NULL;
-        GUID clsid;
-        int j;
-        INT size;
-        BOOL absent = FALSE;
-
-        if (!ACTION_VerifyFeatureForAction(package,i,INSTALLSTATE_LOCAL) &&
-            !ACTION_VerifyFeatureForAction(package,i,INSTALLSTATE_SOURCE) &&
-            !ACTION_VerifyFeatureForAction(package,i,INSTALLSTATE_ADVERTISED))
-            absent = TRUE;
-
-        size = package->features[i].ComponentCount*21;
-        size +=1;
-        if (package->features[i].Feature_Parent[0])
-            size += strlenW(package->features[i].Feature_Parent)+2;
-
-        data = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
-
-        data[0] = 0;
-        for (j = 0; j < package->features[i].ComponentCount; j++)
-        {
-            WCHAR buf[21];
-            memset(buf,0,sizeof(buf));
-            if (package->components
-                [package->features[i].Components[j]].ComponentId[0]!=0)
-            {
-                TRACE("From %s\n",debugstr_w(package->components
-                            [package->features[i].Components[j]].ComponentId));
-                CLSIDFromString(package->components
-                            [package->features[i].Components[j]].ComponentId,
-                            &clsid);
-                encode_base85_guid(&clsid,buf);
-                TRACE("to %s\n",debugstr_w(buf));
-                strcatW(data,buf);
-            }
-        }
-        if (package->features[i].Feature_Parent[0])
-        {
-            static const WCHAR sep[] = {'\2',0};
-            strcatW(data,sep);
-            strcatW(data,package->features[i].Feature_Parent);
-        }
-
-        size = (strlenW(data)+1)*sizeof(WCHAR);
-        RegSetValueExW(hkey,package->features[i].Feature,0,REG_SZ,
-                       (LPSTR)data,size);
-        HeapFree(GetProcessHeap(),0,data);
-
-        if (!absent)
-        {
-            size = strlenW(package->features[i].Feature_Parent)*sizeof(WCHAR);
-            RegSetValueExW(hukey,package->features[i].Feature,0,REG_SZ,
-                       (LPSTR)package->features[i].Feature_Parent,size);
-        }
-        else
-        {
-            size = (strlenW(package->features[i].Feature_Parent)+2)*
-                    sizeof(WCHAR);
-            data = HeapAlloc(GetProcessHeap(),0,size);
-            data[0] = 0x6;
-            strcpyW(&data[1],package->features[i].Feature_Parent);
-            RegSetValueExW(hukey,package->features[i].Feature,0,REG_SZ,
-                       (LPSTR)data,size);
-            HeapFree(GetProcessHeap(),0,data);
-        }
-    }
-
-end:
-    RegCloseKey(hkey);
-    RegCloseKey(hukey);
-    HeapFree(GetProcessHeap(), 0, productcode);
-    return rc;
-}
-
-static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
-{
-    HKEY hkey=0;
-    LPWSTR buffer;
-    LPWSTR productcode;
-    UINT rc,i;
-    DWORD size;
-    static WCHAR szNONE[] = {0};
-    static const WCHAR szWindowsInstaler[] = 
-    {'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},
-    };
-
-    static const WCHAR installerPathFmt[] = {
-    '%','s','\\',
-    'I','n','s','t','a','l','l','e','r','\\',0};
-    static const WCHAR fmt[] = {
-    '%','s','\\',
-    'I','n','s','t','a','l','l','e','r','\\',
-    '%','x','.','m','s','i',0};
-    static const WCHAR szLocalPackage[]=
-         {'L','o','c','a','l','P','a','c','k','a','g','e',0};
-    WCHAR windir[MAX_PATH], path[MAX_PATH], packagefile[MAX_PATH];
-    INT num,start;
-
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
-    productcode = load_dynamic_property(package,szProductCode,&rc);
-    if (!productcode)
-        return rc;
-
-    rc = MSIREG_OpenUninstallKey(productcode,&hkey,TRUE);
-    if (rc != ERROR_SUCCESS)
-        goto end;
-
-    /* dump all the info i can grab */
-    FIXME("Flesh out more information \n");
-
-    i = 0;
-    while (szPropKeys[i][0]!=0)
-    {
-        buffer = load_dynamic_property(package,szPropKeys[i],&rc);
-        if (rc != ERROR_SUCCESS)
-            buffer = szNONE;
-        size = strlenW(buffer)*sizeof(WCHAR);
-        RegSetValueExW(hkey,szRegKeys[i],0,REG_SZ,(LPSTR)buffer,size);
-        i++;
-    }
-
-    rc = 0x1;
-    size = sizeof(rc);
-    RegSetValueExW(hkey,szWindowsInstaler,0,REG_DWORD,(LPSTR)&rc,size);
-    
-    /* copy the package locally */
-    num = GetTickCount() & 0xffff;
-    if (!num) 
-        num = 1;
-    start = num;
-    GetWindowsDirectoryW(windir, sizeof(windir) / sizeof(windir[0]));
-    snprintfW(packagefile,sizeof(packagefile)/sizeof(packagefile[0]),fmt,
-     windir,num);
-    do 
-    {
-        HANDLE handle = CreateFileW(packagefile,GENERIC_WRITE, 0, NULL,
-                                  CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
-        if (handle != INVALID_HANDLE_VALUE)
-        {
-            CloseHandle(handle);
-            break;
-        }
-        if (GetLastError() != ERROR_FILE_EXISTS &&
-            GetLastError() != ERROR_SHARING_VIOLATION)
-            break;
-        if (!(++num & 0xffff)) num = 1;
-        sprintfW(packagefile,fmt,num);
-    } while (num != start);
-
-    snprintfW(path,sizeof(path)/sizeof(path[0]),installerPathFmt,windir);
-    create_full_pathW(path);
-    TRACE("Copying to local package %s\n",debugstr_w(packagefile));
-    if (!CopyFileW(package->PackagePath,packagefile,FALSE))
-        ERR("Unable to copy package (%s -> %s) (error %ld)\n",
-            debugstr_w(package->PackagePath), debugstr_w(packagefile),
-            GetLastError());
-    size = strlenW(packagefile)*sizeof(WCHAR);
-    RegSetValueExW(hkey,szLocalPackage,0,REG_SZ,(LPSTR)packagefile,size);
-    
-end:
-    HeapFree(GetProcessHeap(),0,productcode);
-    RegCloseKey(hkey);
-
-    return ERROR_SUCCESS;
-}
-
-static UINT ACTION_InstallExecute(MSIPACKAGE *package)
-{
-    int i;
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
-    for (i = 0; i < package->DeferredActionCount; i++)
-    {
-        LPWSTR action;
-        action = package->DeferredAction[i];
-        ui_actionstart(package, action);
-        TRACE("Executing Action (%s)\n",debugstr_w(action));
-        ACTION_CustomAction(package,action,TRUE);
-        HeapFree(GetProcessHeap(),0,package->DeferredAction[i]);
-    }
-    HeapFree(GetProcessHeap(),0,package->DeferredAction);
-
-    package->DeferredActionCount = 0;
-    package->DeferredAction = NULL;
-
-    return ERROR_SUCCESS;
-}
-
-static UINT ACTION_InstallFinalize(MSIPACKAGE *package)
-{
-    int i;
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
-    /* first do the same as an InstallExecute */
-    ACTION_InstallExecute(package);
-
-    /* then handle Commit Actions */
-    for (i = 0; i < package->CommitActionCount; i++)
-    {
-        LPWSTR action;
-        action = package->CommitAction[i];
-        ui_actionstart(package, action);
-        TRACE("Executing Commit Action (%s)\n",debugstr_w(action));
-        ACTION_CustomAction(package,action,TRUE);
-        HeapFree(GetProcessHeap(),0,package->CommitAction[i]);
-    }
-    HeapFree(GetProcessHeap(),0,package->CommitAction);
-
-    package->CommitActionCount = 0;
-    package->CommitAction = NULL;
-
-    return ERROR_SUCCESS;
-}
-
-static UINT ACTION_ForceReboot(MSIPACKAGE *package)
-{
-    static const WCHAR RunOnce[] = {
-    'S','o','f','t','w','a','r','e','\\',
-    'M','i','c','r','o','s','o','f','t','\\',
-    'W','i','n','d','o','w','s','\\',
-    'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
-    'R','u','n','O','n','c','e',0};
-    static const WCHAR InstallRunOnce[] = {
-    'S','o','f','t','w','a','r','e','\\',
-    'M','i','c','r','o','s','o','f','t','\\',
-    'W','i','n','d','o','w','s','\\',
-    'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
-    'I','n','s','t','a','l','l','e','r','\\',
-    'R','u','n','O','n','c','e','E','n','t','r','i','e','s',0};
-
-    static const WCHAR msiexec_fmt[] = {
-    '%','s',
-    '\\','M','s','i','E','x','e','c','.','e','x','e',' ','/','@',' ',
-    '\"','%','s','\"',0};
-    static const WCHAR install_fmt[] = {
-    '/','I',' ','\"','%','s','\"',' ',
-    'A','F','T','E','R','R','E','B','O','O','T','=','1',' ',
-    'R','U','N','O','N','C','E','E','N','T','R','Y','=','\"','%','s','\"',0};
-    WCHAR buffer[256], sysdir[MAX_PATH];
-    HKEY hkey,hukey;
-    LPWSTR productcode;
-    WCHAR  squished_pc[100];
-    INT rc;
-    DWORD size;
-    static const WCHAR szLUS[] = {
-         'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0};
-    static const WCHAR szSourceList[] = {
-         'S','o','u','r','c','e','L','i','s','t',0};
-    static const WCHAR szPackageName[] = { 
-        'P','a','c','k','a','g','e','N','a','m','e',0};
-
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
-    productcode = load_dynamic_property(package,szProductCode,&rc);
-    if (!productcode)
-        return rc;
-
-    squash_guid(productcode,squished_pc);
-
-    GetSystemDirectoryW(sysdir, sizeof(sysdir)/sizeof(sysdir[0]));
-    RegCreateKeyW(HKEY_LOCAL_MACHINE,RunOnce,&hkey);
-    snprintfW(buffer,sizeof(buffer)/sizeof(buffer[0]),msiexec_fmt,sysdir,
-     squished_pc);
-
-    size = strlenW(buffer)*sizeof(WCHAR);
-    RegSetValueExW(hkey,squished_pc,0,REG_SZ,(LPSTR)buffer,size);
-    RegCloseKey(hkey);
-
-    TRACE("Reboot command %s\n",debugstr_w(buffer));
-
-    RegCreateKeyW(HKEY_LOCAL_MACHINE,InstallRunOnce,&hkey);
-    sprintfW(buffer,install_fmt,productcode,squished_pc);
-
-    size = strlenW(buffer)*sizeof(WCHAR);
-    RegSetValueExW(hkey,squished_pc,0,REG_SZ,(LPSTR)buffer,size);
-    RegCloseKey(hkey);
-
-    rc = MSIREG_OpenUserProductsKey(productcode,&hukey,TRUE);
-    if (rc == ERROR_SUCCESS)
-    {
-        HKEY hukey2;
-        LPWSTR buf;
-        RegCreateKeyW(hukey, szSourceList, &hukey2);
-        buf = load_dynamic_property(package,cszSourceDir,NULL);
-        size = strlenW(buf)*sizeof(WCHAR);
-        RegSetValueExW(hukey2,szLUS,0,REG_SZ,(LPSTR)buf,size);
-        HeapFree(GetProcessHeap(),0,buf); 
-
-        buf = strrchrW(package->PackagePath,'\\');
-        if (buf)
-        {
-            buf++;
-            size = strlenW(buf)*sizeof(WCHAR);
-            RegSetValueExW(hukey2,szPackageName,0,REG_SZ,(LPSTR)buf,size);
-        }
-
-        RegCloseKey(hukey2);
-    }
-    HeapFree(GetProcessHeap(),0,productcode);
-
-    return ERROR_INSTALL_SUSPEND;
-}
-
-UINT ACTION_ResolveSource(MSIPACKAGE* package)
-{
-    /*
-     * we are currently doing what should be done here in the top level Install
-     * however for Adminastrative and uninstalls this step will be needed
-     */
-    return ERROR_SUCCESS;
-}
-
-
-static UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package)
-{
-    UINT rc;
-    MSIQUERY * view;
-    MSIRECORD * row = 0;
-    static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','E','x','t','e','n','s','i','o','n','`',0};
-    static const WCHAR szContentType[] = 
-        {'C','o','n','t','e','n','t',' ','T','y','p','e',0 };
-    HKEY hkey;
-
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
-    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
-    if (rc != ERROR_SUCCESS)
-    {
-        rc = ERROR_SUCCESS;
-        goto end;
-    }
-
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        goto end;
-    }
-
-    while (1)
-    {
-        WCHAR buffer[0x100];
-        WCHAR extension[257];
-        LPWSTR exten;
-        DWORD sz;
-        INT index;
-     
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            rc = ERROR_SUCCESS;
-            break;
-        }
-
-        sz=0x100;
-        MSI_RecordGetStringW(row,2,buffer,&sz);
-
-        index = get_loaded_component(package,buffer);
-
-        if (index < 0)
-        {
-            msiobj_release(&row->hdr);
-            continue;
-        }
-
-        if ((!ACTION_VerifyComponentForAction(package, index,
-                                INSTALLSTATE_LOCAL)) &&
-            (!ACTION_VerifyComponentForAction(package, index,
-                                INSTALLSTATE_ADVERTISED)))
-        {
-            TRACE("Skipping extension reg due to disabled component\n");
-            msiobj_release(&row->hdr);
-
-            package->components[index].Action =
-                package->components[index].Installed;
-
-            continue;
-        }
-
-        package->components[index].Action = INSTALLSTATE_LOCAL;
-
-        exten = load_dynamic_stringW(row,1);
-        extension[0] = '.';
-        extension[1] = 0;
-        strcatW(extension,exten);
-        HeapFree(GetProcessHeap(),0,exten);
-
-        RegCreateKeyW(HKEY_CLASSES_ROOT,extension,&hkey);
-
-        if (!MSI_RecordIsNull(row,4))
-        {
-            LPWSTR mime = load_dynamic_stringW(row,4);
-            RegSetValueExW(hkey,szContentType,0,REG_SZ,(LPVOID)mime,
-                           (strlenW(mime)+1)*sizeof(WCHAR));
-            HeapFree(GetProcessHeap(),0,mime);
-        }
-
-        if (!MSI_RecordIsNull(row,3))
-        {
-            static const WCHAR szSN[] = 
-                {'\\','S','h','e','l','l','N','e','w',0};
-            HKEY hkey2;
-            LPWSTR newkey;
-            LPWSTR progid= load_dynamic_stringW(row,3);
-
-            RegSetValueExW(hkey,NULL,0,REG_SZ,(LPVOID)progid,
-                           (strlenW(progid)+1)*sizeof(WCHAR));
-
-            newkey = HeapAlloc(GetProcessHeap(),0,
-                           (strlenW(progid)+strlenW(szSN)+1) * sizeof(WCHAR)); 
-
-            strcpyW(newkey,progid);
-            strcatW(newkey,szSN);
-            RegCreateKeyW(hkey,newkey,&hkey2);
-            RegCloseKey(hkey2);
-
-            HeapFree(GetProcessHeap(),0,progid);
-            HeapFree(GetProcessHeap(),0,newkey);
-        }
-
-
-        RegCloseKey(hkey);
-
-        ui_actiondata(package,szRegisterExtensionInfo,row);
-
-        msiobj_release(&row->hdr);
-    }
-    MSI_ViewClose(view);
-    msiobj_release(&view->hdr);
-
-end:
-    return rc;
-}
-
-static UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package)
-{
-    UINT rc;
-    MSIQUERY * view;
-    MSIRECORD * row = 0;
-    static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','M','I','M','E','`',0};
-    static const WCHAR szExten[] = 
-        {'E','x','t','e','n','s','i','o','n',0 };
-    HKEY hkey;
-
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
-    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
-    if (rc != ERROR_SUCCESS)
-    {
-        rc = ERROR_SUCCESS;
-        goto end;
-    }
-
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        goto end;
-    }
-
-    while (1)
-    {
-        WCHAR extension[257];
-        LPWSTR exten;
-        LPWSTR mime;
-        static const WCHAR fmt[] = 
-            {'M','I','M','E','\\','D','a','t','a','b','a','s','e','\\',
-             'C','o','n','t','e','n','t',' ','T','y','p','e','\\', '%','s',0};
-        LPWSTR key;
-     
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            rc = ERROR_SUCCESS;
-            break;
-        }
-
-        mime = load_dynamic_stringW(row,1);
-        exten = load_dynamic_stringW(row,2);
-        extension[0] = '.';
-        extension[1] = 0;
-        strcatW(extension,exten);
-        HeapFree(GetProcessHeap(),0,exten);
-
-        key = HeapAlloc(GetProcessHeap(),0,(strlenW(mime)+strlenW(fmt)+1) *
-                                            sizeof(WCHAR));
-        sprintfW(key,fmt,mime);
-        RegCreateKeyW(HKEY_CLASSES_ROOT,key,&hkey);
-        RegSetValueExW(hkey,szExten,0,REG_SZ,(LPVOID)extension,
-                           (strlenW(extension)+1)*sizeof(WCHAR));
-
-        HeapFree(GetProcessHeap(),0,mime);
-        HeapFree(GetProcessHeap(),0,key);
-
-        if (!MSI_RecordIsNull(row,3))
-        {
-            FIXME("Handle non null for field 3\n");
-        }
-
-        RegCloseKey(hkey);
-
-        ui_actiondata(package,szRegisterMIMEInfo,row);
-
-        msiobj_release(&row->hdr);
-    }
-    MSI_ViewClose(view);
-    msiobj_release(&view->hdr);
-
-end:
-    return rc;
-}
-
-static UINT ACTION_RegisterUser(MSIPACKAGE *package)
-{
-    static const WCHAR szProductID[]=
-         {'P','r','o','d','u','c','t','I','D',0};
-    HKEY hkey=0;
-    LPWSTR buffer;
-    LPWSTR productcode;
-    LPWSTR productid;
-    UINT rc,i;
-    DWORD size;
-
-    static const WCHAR szPropKeys[][80] = 
-    {
-        {'P','r','o','d','u','c','t','I','D',0},
-        {'U','S','E','R','N','A','M','E',0},
-        {'C','O','M','P','A','N','Y','N','A','M','E',0},
-        {0},
-    };
-
-    static const WCHAR szRegKeys[][80] = 
-    {
-        {'P','r','o','d','u','c','t','I','D',0},
-        {'R','e','g','O','w','n','e','r',0},
-        {'R','e','g','C','o','m','p','a','n','y',0},
-        {0},
-    };
-
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
-    productid = load_dynamic_property(package,szProductID,&rc);
-    if (!productid)
-        return ERROR_SUCCESS;
-
-    productcode = load_dynamic_property(package,szProductCode,&rc);
-    if (!productcode)
-        return rc;
-
-    rc = MSIREG_OpenUninstallKey(productcode,&hkey,TRUE);
-    if (rc != ERROR_SUCCESS)
-        goto end;
-
-    i = 0;
-    while (szPropKeys[i][0]!=0)
-    {
-        buffer = load_dynamic_property(package,szPropKeys[i],&rc);
-        if (rc == ERROR_SUCCESS)
-        {
-            size = strlenW(buffer)*sizeof(WCHAR);
-            RegSetValueExW(hkey,szRegKeys[i],0,REG_SZ,(LPSTR)buffer,size);
-        }
-        else
-            RegSetValueExW(hkey,szRegKeys[i],0,REG_SZ,NULL,0);
-        i++;
-    }
-
-end:
-    HeapFree(GetProcessHeap(),0,productcode);
-    HeapFree(GetProcessHeap(),0,productid);
-    RegCloseKey(hkey);
-
-    return ERROR_SUCCESS;
-}
-
-
-static UINT ACTION_ExecuteAction(MSIPACKAGE *package)
-{
-    UINT rc;
-    rc = ACTION_ProcessExecSequence(package,FALSE);
-    return rc;
-}
-
-
-/*
- * Code based off of code located here
- * http://www.codeproject.com/gdi/fontnamefromfile.asp
- *
- * Using string index 4 (full font name) instead of 1 (family name)
- */
-static LPWSTR load_ttfname_from(LPCWSTR filename)
-{
-    HANDLE handle;
-    LPWSTR ret = NULL;
-    int i;
-
-    typedef struct _tagTT_OFFSET_TABLE{
-        USHORT uMajorVersion;
-        USHORT uMinorVersion;
-        USHORT uNumOfTables;
-        USHORT uSearchRange;
-        USHORT uEntrySelector;
-        USHORT uRangeShift;
-    }TT_OFFSET_TABLE;
-
-    typedef struct _tagTT_TABLE_DIRECTORY{
-        char szTag[4]; /* table name */
-        ULONG uCheckSum; /* Check sum */
-        ULONG uOffset; /* Offset from beginning of file */
-        ULONG uLength; /* length of the table in bytes */
-    }TT_TABLE_DIRECTORY;
-
-    typedef struct _tagTT_NAME_TABLE_HEADER{
-    USHORT uFSelector; /* format selector. Always 0 */
-    USHORT uNRCount; /* Name Records count */
-    USHORT uStorageOffset; /* Offset for strings storage, 
-                            * from start of the table */
-    }TT_NAME_TABLE_HEADER;
-   
-    typedef struct _tagTT_NAME_RECORD{
-        USHORT uPlatformID;
-        USHORT uEncodingID;
-        USHORT uLanguageID;
-        USHORT uNameID;
-        USHORT uStringLength;
-        USHORT uStringOffset; /* from start of storage area */
-    }TT_NAME_RECORD;
-
-#define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
-#define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
-
-    handle = CreateFileW(filename ,GENERIC_READ, 0, NULL, OPEN_EXISTING,
-                    FILE_ATTRIBUTE_NORMAL, 0 );
-    if (handle != INVALID_HANDLE_VALUE)
-    {
-        TT_TABLE_DIRECTORY tblDir;
-        BOOL bFound = FALSE;
-        TT_OFFSET_TABLE ttOffsetTable;
-
-        ReadFile(handle,&ttOffsetTable, sizeof(TT_OFFSET_TABLE),NULL,NULL);
-        ttOffsetTable.uNumOfTables = SWAPWORD(ttOffsetTable.uNumOfTables);
-        ttOffsetTable.uMajorVersion = SWAPWORD(ttOffsetTable.uMajorVersion);
-        ttOffsetTable.uMinorVersion = SWAPWORD(ttOffsetTable.uMinorVersion);
-        
-        if (ttOffsetTable.uMajorVersion != 1 || 
-                        ttOffsetTable.uMinorVersion != 0)
-            return NULL;
-
-        for (i=0; i< ttOffsetTable.uNumOfTables; i++)
-        {
-            ReadFile(handle,&tblDir, sizeof(TT_TABLE_DIRECTORY),NULL,NULL);
-            if (strncmp(tblDir.szTag,"name",4)==0)
-            {
-                bFound = TRUE;
-                tblDir.uLength = SWAPLONG(tblDir.uLength);
-                tblDir.uOffset = SWAPLONG(tblDir.uOffset);
-                break;
-            }
-        }
-
-        if (bFound)
-        {
-            TT_NAME_TABLE_HEADER ttNTHeader;
-            TT_NAME_RECORD ttRecord;
-
-            SetFilePointer(handle, tblDir.uOffset, NULL, FILE_BEGIN);
-            ReadFile(handle,&ttNTHeader, sizeof(TT_NAME_TABLE_HEADER),
-                            NULL,NULL);
-
-            ttNTHeader.uNRCount = SWAPWORD(ttNTHeader.uNRCount);
-            ttNTHeader.uStorageOffset = SWAPWORD(ttNTHeader.uStorageOffset);
-            bFound = FALSE;
-            for(i=0; i<ttNTHeader.uNRCount; i++)
-            {
-                ReadFile(handle,&ttRecord, sizeof(TT_NAME_RECORD),NULL,NULL);
-                ttRecord.uNameID = SWAPWORD(ttRecord.uNameID);
-                /* 4 is the Full Font Name */
-                if(ttRecord.uNameID == 4)
-                {
-                    int nPos;
-                    LPSTR buf;
-                    static const LPSTR tt = " (TrueType)";
-
-                    ttRecord.uStringLength = SWAPWORD(ttRecord.uStringLength);
-                    ttRecord.uStringOffset = SWAPWORD(ttRecord.uStringOffset);
-                    nPos = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
-                    SetFilePointer(handle, tblDir.uOffset + 
-                                    ttRecord.uStringOffset + 
-                                    ttNTHeader.uStorageOffset,
-                                    NULL, FILE_BEGIN);
-                    buf = HeapAlloc(GetProcessHeap(), 0, 
-                                    ttRecord.uStringLength + 1 + strlen(tt));
-                    memset(buf, 0, ttRecord.uStringLength + 1 + strlen(tt));
-                    ReadFile(handle, buf, ttRecord.uStringLength, NULL, NULL);
-                    if (strlen(buf) > 0)
-                    {
-                        strcat(buf,tt);
-                        ret = strdupAtoW(buf);
-                        HeapFree(GetProcessHeap(),0,buf);
-                        break;
-                    }
-
-                    HeapFree(GetProcessHeap(),0,buf);
-                    SetFilePointer(handle,nPos, NULL, FILE_BEGIN);
-                }
-            }
-        }
-        CloseHandle(handle);
-    }
-    else
-        ERR("Unable to open font file %s\n", debugstr_w(filename));
-
-    TRACE("Returning fontname %s\n",debugstr_w(ret));
-    return ret;
-}
-
-static UINT ACTION_RegisterFonts(MSIPACKAGE *package)
-{
-    UINT rc;
-    MSIQUERY * view;
-    MSIRECORD * row = 0;
-    static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','F','o','n','t','`',0};
-    static const WCHAR regfont1[] =
-        {'S','o','f','t','w','a','r','e','\\',
-         'M','i','c','r','o','s','o','f','t','\\',
-         'W','i','n','d','o','w','s',' ','N','T','\\',
-         'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
-         'F','o','n','t','s',0};
-    static const WCHAR regfont2[] =
-        {'S','o','f','t','w','a','r','e','\\',
-         'M','i','c','r','o','s','o','f','t','\\',
-         'W','i','n','d','o','w','s','\\',
-         'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
-         'F','o','n','t','s',0};
-    HKEY hkey1;
-    HKEY hkey2;
-
-    TRACE("%p\n", package);
-
-    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
-    if (rc != ERROR_SUCCESS)
-    {
-        TRACE("MSI_DatabaseOpenViewW failed: %d\n", rc);
-        return ERROR_SUCCESS;
-    }
-
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        TRACE("MSI_ViewExecute returned %d\n", rc);
-        return ERROR_SUCCESS;
-    }
-
-    RegCreateKeyW(HKEY_LOCAL_MACHINE,regfont1,&hkey1);
-    RegCreateKeyW(HKEY_LOCAL_MACHINE,regfont2,&hkey2);
-    
-    while (1)
-    {
-        LPWSTR name;
-        LPWSTR file;
-        UINT index;
-        DWORD size;
-
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            rc = ERROR_SUCCESS;
-            break;
-        }
-
-        file = load_dynamic_stringW(row,1);
-        index = get_loaded_file(package,file);
-        if (index < 0)
-        {
-            ERR("Unable to load file\n");
-            HeapFree(GetProcessHeap(),0,file);
-            continue;
-        }
-
-        /* check to make sure that component is installed */
-        if (!ACTION_VerifyComponentForAction(package, 
-                package->files[index].ComponentIndex, INSTALLSTATE_LOCAL))
-        {
-            TRACE("Skipping: Component not scheduled for install\n");
-            HeapFree(GetProcessHeap(),0,file);
-
-            msiobj_release(&row->hdr);
-
-            continue;
-        }
-
-        if (MSI_RecordIsNull(row,2))
-            name = load_ttfname_from(package->files[index].TargetPath);
-        else
-            name = load_dynamic_stringW(row,2);
-
-        if (name)
-        {
-            size = strlenW(package->files[index].FileName) * sizeof(WCHAR);
-            RegSetValueExW(hkey1,name,0,REG_SZ,
-                        (LPBYTE)package->files[index].FileName,size);
-            RegSetValueExW(hkey2,name,0,REG_SZ,
-                        (LPBYTE)package->files[index].FileName,size);
-        }
-        
-        HeapFree(GetProcessHeap(),0,file);
-        HeapFree(GetProcessHeap(),0,name);
-        msiobj_release(&row->hdr);
-    }
-    MSI_ViewClose(view);
-    msiobj_release(&view->hdr);
-
-    RegCloseKey(hkey1);
-    RegCloseKey(hkey2);
-
-    TRACE("returning %d\n", rc);
-    return rc;
-}
-
-static UINT ITERATE_PublishComponent(MSIRECORD *rec, LPVOID param)
-{
-    MSIPACKAGE *package = (MSIPACKAGE*)param;
-    LPWSTR productid=NULL, compgroupid=NULL;
-    LPWSTR feature=NULL;
-    LPWSTR text = NULL;
-    LPWSTR qualifier = NULL;
-    LPWSTR component = NULL;
-    GUID clsid;
-    WCHAR productid_85[21];
-    WCHAR component_85[21];
-    HKEY hkey;
-    UINT rc = ERROR_SUCCESS;
-    UINT index;
-    /*
-     * I have a fair bit of confusion as to when a < is used and when a > is
-     * used. I do not think i have it right...
-     *
-     * Ok it appears that the > is used if there is a guid for the compoenent
-     * and the < is used if not.
-     */
-    static WCHAR fmt1[] = {'%','s','%','s','<',0,0};
-    static WCHAR fmt2[] = {'%','s','%','s','>','%','s',0,0};
-    LPWSTR output = NULL;
-    DWORD sz = 0;
-    INT component_index;
-
-    component = load_dynamic_stringW(rec,3);
-    component_index = get_loaded_component(package,component);
-
-    if (!ACTION_VerifyComponentForAction(package, component_index,
-                            INSTALLSTATE_LOCAL) && 
-       !ACTION_VerifyComponentForAction(package, component_index,
-                            INSTALLSTATE_SOURCE) &&
-       !ACTION_VerifyComponentForAction(package, component_index,
-                            INSTALLSTATE_ADVERTISED))
-    {
-        TRACE("Skipping: Component %s not scheduled for install\n",
-                        debugstr_w(component));
-        HeapFree(GetProcessHeap(),0,component);
-        return ERROR_SUCCESS;
+        HeapFree(GetProcessHeap(),0,upgrade_code);
     }
-
-    memset(productid_85,0,sizeof(productid_85));
-    memset(component_85,0,sizeof(component_85));
-    compgroupid = load_dynamic_stringW(rec,1);
-
-    rc = MSIREG_OpenUserComponentsKey(compgroupid, &hkey, TRUE);
-    if (rc != ERROR_SUCCESS)
-        goto end;
-    
-    productid = load_dynamic_property(package,szProductCode,NULL);
-    CLSIDFromString(productid, &clsid);
-    
-    encode_base85_guid(&clsid,productid_85);
-
-    text = load_dynamic_stringW(rec,4);
-    qualifier = load_dynamic_stringW(rec,2);
-
-    feature = load_dynamic_stringW(rec,5);
-  
-    index = get_loaded_component(package, component);
-    CLSIDFromString(package->components[index].ComponentId, &clsid);
-    encode_base85_guid(&clsid,component_85);
-
-    TRACE("Doing something with this... %s = %s %s %s %s\n", 
-            debugstr_w(qualifier), debugstr_w(productid_85),
-            debugstr_w(feature), debugstr_w(text), debugstr_w(component_85));
-    sz = lstrlenW(productid_85) + lstrlenW(feature);
-    if (text)
-        sz += lstrlenW(text);
-    if (component && index >= 0)
-        sz += lstrlenW(component_85);
-
-    sz+=3;
-    sz *= sizeof(WCHAR);
-           
-    output = HeapAlloc(GetProcessHeap(),0,sz);
-    memset(output,0,sz);
-
-    if (component && index >= 0)
-        sprintfW(output,fmt2,productid_85,feature,component_85);
-    else
-        sprintfW(output,fmt1,productid_85,feature);
-
-    if (text)
-        strcatW(output,text);
-
-    sz = (lstrlenW(output)+2) * sizeof(WCHAR);
-   RegSetValueExW(hkey, qualifier,0,REG_MULTI_SZ, (LPBYTE)output, sz);
     
 end:
+    HeapFree(GetProcessHeap(),0,productcode);
     RegCloseKey(hkey);
-    HeapFree(GetProcessHeap(),0,output);
-    HeapFree(GetProcessHeap(),0,compgroupid);
-    HeapFree(GetProcessHeap(),0,component);
-    HeapFree(GetProcessHeap(),0,productid);
-    HeapFree(GetProcessHeap(),0,feature);
-    HeapFree(GetProcessHeap(),0,text);
-    HeapFree(GetProcessHeap(),0,qualifier);
-    
-    return rc;
-}
-
-/*
- * At present I am ignorning the advertised components part of this and only
- * focusing on the qualified component sets
- */
-static UINT ACTION_PublishComponents(MSIPACKAGE *package)
-{
-    UINT rc;
-    MSIQUERY * view;
-    static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','P','u','b','l','i','s','h',
-         'C','o','m','p','o','n','e','n','t','`',0};
-    
-    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
-    if (rc != ERROR_SUCCESS)
-        return ERROR_SUCCESS;
-
-    rc = MSI_IterateRecords(view, NULL, ITERATE_PublishComponent, package);
-    msiobj_release(&view->hdr);
-
-    return rc;
-}
-
-/* Msi functions that seem appropriate here */
-
-/***********************************************************************
- * MsiDoActionA       (MSI.@)
- */
-UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
-{
-    LPWSTR szwAction;
-    UINT rc;
-
-    TRACE(" exteral attempt at action %s\n",szAction);
-
-    if (!szAction)
-        return ERROR_FUNCTION_FAILED;
-    if (hInstall == 0)
-        return ERROR_FUNCTION_FAILED;
-
-    szwAction = strdupAtoW(szAction);
-
-    if (!szwAction)
-        return ERROR_FUNCTION_FAILED; 
-
-
-    rc = MsiDoActionW(hInstall, szwAction);
-    HeapFree(GetProcessHeap(),0,szwAction);
-    return rc;
-}
-
-/***********************************************************************
- * MsiDoActionW       (MSI.@)
- */
-UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
-{
-    MSIPACKAGE *package;
-    UINT ret = ERROR_INVALID_HANDLE;
-
-    TRACE(" external attempt at action %s \n",debugstr_w(szAction));
 
-    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
-    if( package )
-    {
-        ret = ACTION_PerformUIAction(package,szAction);
-        msiobj_release( &package->hdr );
-    }
-    return ret;
+    return ERROR_SUCCESS;
 }
 
-UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder, 
-                               LPSTR szPathBuf, DWORD* pcchPathBuf) 
+static UINT ACTION_InstallExecute(MSIPACKAGE *package)
 {
-    LPWSTR szwFolder;
-    LPWSTR szwPathBuf;
     UINT rc;
 
-    TRACE("getting folder %s %p %li\n",szFolder,szPathBuf, *pcchPathBuf);
+    if (!package)
+        return ERROR_INVALID_HANDLE;
 
-    if (!szFolder)
-        return ERROR_FUNCTION_FAILED;
-    if (hInstall == 0)
-        return ERROR_FUNCTION_FAILED;
+    rc = execute_script(package,INSTALL_SCRIPT);
 
-    szwFolder = strdupAtoW(szFolder);
+    return rc;
+}
 
-    if (!szwFolder)
-        return ERROR_FUNCTION_FAILED; 
+static UINT ACTION_InstallFinalize(MSIPACKAGE *package)
+{
+    UINT rc;
 
-    szwPathBuf = HeapAlloc( GetProcessHeap(), 0 , *pcchPathBuf * sizeof(WCHAR));
+    if (!package)
+        return ERROR_INVALID_HANDLE;
 
-    rc = MsiGetTargetPathW(hInstall, szwFolder, szwPathBuf,pcchPathBuf);
+    /* turn off scheduleing */
+    package->script->CurrentlyScripting= FALSE;
 
-    WideCharToMultiByte( CP_ACP, 0, szwPathBuf, *pcchPathBuf, szPathBuf,
-                         *pcchPathBuf, NULL, NULL );
+    /* first do the same as an InstallExecute */
+    rc = ACTION_InstallExecute(package);
+    if (rc != ERROR_SUCCESS)
+        return rc;
 
-    HeapFree(GetProcessHeap(),0,szwFolder);
-    HeapFree(GetProcessHeap(),0,szwPathBuf);
+    /* then handle Commit Actions */
+    rc = execute_script(package,COMMIT_SCRIPT);
 
     return rc;
 }
 
-UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR
-                                szPathBuf, DWORD* pcchPathBuf) 
+static UINT ACTION_ForceReboot(MSIPACKAGE *package)
 {
-    LPWSTR path;
-    UINT rc = ERROR_FUNCTION_FAILED;
-    MSIPACKAGE *package;
+    static const WCHAR RunOnce[] = {
+    'S','o','f','t','w','a','r','e','\\',
+    'M','i','c','r','o','s','o','f','t','\\',
+    'W','i','n','d','o','w','s','\\',
+    'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+    'R','u','n','O','n','c','e',0};
+    static const WCHAR InstallRunOnce[] = {
+    'S','o','f','t','w','a','r','e','\\',
+    'M','i','c','r','o','s','o','f','t','\\',
+    'W','i','n','d','o','w','s','\\',
+    'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+    'I','n','s','t','a','l','l','e','r','\\',
+    'R','u','n','O','n','c','e','E','n','t','r','i','e','s',0};
 
-    TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf);
+    static const WCHAR msiexec_fmt[] = {
+    '%','s',
+    '\\','M','s','i','E','x','e','c','.','e','x','e',' ','/','@',' ',
+    '\"','%','s','\"',0};
+    static const WCHAR install_fmt[] = {
+    '/','I',' ','\"','%','s','\"',' ',
+    'A','F','T','E','R','R','E','B','O','O','T','=','1',' ',
+    'R','U','N','O','N','C','E','E','N','T','R','Y','=','\"','%','s','\"',0};
+    WCHAR buffer[256], sysdir[MAX_PATH];
+    HKEY hkey,hukey;
+    LPWSTR productcode;
+    WCHAR  squished_pc[100];
+    INT rc;
+    DWORD size;
+    static const WCHAR szLUS[] = {
+         'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0};
+    static const WCHAR szSourceList[] = {
+         'S','o','u','r','c','e','L','i','s','t',0};
+    static const WCHAR szPackageName[] = { 
+        'P','a','c','k','a','g','e','N','a','m','e',0};
 
-    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
     if (!package)
         return ERROR_INVALID_HANDLE;
-    path = resolve_folder(package, szFolder, FALSE, FALSE, NULL);
-    msiobj_release( &package->hdr );
 
-    if (path && (strlenW(path) > *pcchPathBuf))
-    {
-        *pcchPathBuf = strlenW(path)+1;
-        rc = ERROR_MORE_DATA;
-    }
-    else if (path)
-    {
-        *pcchPathBuf = strlenW(path)+1;
-        strcpyW(szPathBuf,path);
-        TRACE("Returning Path %s\n",debugstr_w(path));
-        rc = ERROR_SUCCESS;
-    }
-    HeapFree(GetProcessHeap(),0,path);
-    
-    return rc;
-}
+    productcode = load_dynamic_property(package,szProductCode,&rc);
+    if (!productcode)
+        return rc;
 
+    squash_guid(productcode,squished_pc);
 
-UINT WINAPI MsiGetSourcePathA( MSIHANDLE hInstall, LPCSTR szFolder, 
-                               LPSTR szPathBuf, DWORD* pcchPathBuf) 
-{
-    LPWSTR szwFolder;
-    LPWSTR szwPathBuf;
-    UINT rc;
+    GetSystemDirectoryW(sysdir, sizeof(sysdir)/sizeof(sysdir[0]));
+    RegCreateKeyW(HKEY_LOCAL_MACHINE,RunOnce,&hkey);
+    snprintfW(buffer,sizeof(buffer)/sizeof(buffer[0]),msiexec_fmt,sysdir,
+     squished_pc);
 
-    TRACE("getting source %s %p %li\n",szFolder,szPathBuf, *pcchPathBuf);
+    size = strlenW(buffer)*sizeof(WCHAR);
+    RegSetValueExW(hkey,squished_pc,0,REG_SZ,(LPSTR)buffer,size);
+    RegCloseKey(hkey);
 
-    if (!szFolder)
-        return ERROR_FUNCTION_FAILED;
-    if (hInstall == 0)
-        return ERROR_FUNCTION_FAILED;
+    TRACE("Reboot command %s\n",debugstr_w(buffer));
 
-    szwFolder = strdupAtoW(szFolder);
-    if (!szwFolder)
-        return ERROR_FUNCTION_FAILED; 
+    RegCreateKeyW(HKEY_LOCAL_MACHINE,InstallRunOnce,&hkey);
+    sprintfW(buffer,install_fmt,productcode,squished_pc);
 
-    szwPathBuf = HeapAlloc( GetProcessHeap(), 0 , *pcchPathBuf * sizeof(WCHAR));
+    size = strlenW(buffer)*sizeof(WCHAR);
+    RegSetValueExW(hkey,squished_pc,0,REG_SZ,(LPSTR)buffer,size);
+    RegCloseKey(hkey);
 
-    rc = MsiGetSourcePathW(hInstall, szwFolder, szwPathBuf,pcchPathBuf);
+    rc = MSIREG_OpenUserProductsKey(productcode,&hukey,TRUE);
+    if (rc == ERROR_SUCCESS)
+    {
+        HKEY hukey2;
+        LPWSTR buf;
+        RegCreateKeyW(hukey, szSourceList, &hukey2);
+        buf = load_dynamic_property(package,cszSourceDir,NULL);
+        size = strlenW(buf)*sizeof(WCHAR);
+        RegSetValueExW(hukey2,szLUS,0,REG_SZ,(LPSTR)buf,size);
+        HeapFree(GetProcessHeap(),0,buf); 
 
-    WideCharToMultiByte( CP_ACP, 0, szwPathBuf, *pcchPathBuf, szPathBuf,
-                         *pcchPathBuf, NULL, NULL );
+        buf = strrchrW(package->PackagePath,'\\');
+        if (buf)
+        {
+            buf++;
+            size = strlenW(buf)*sizeof(WCHAR);
+            RegSetValueExW(hukey2,szPackageName,0,REG_SZ,(LPSTR)buf,size);
+        }
 
-    HeapFree(GetProcessHeap(),0,szwFolder);
-    HeapFree(GetProcessHeap(),0,szwPathBuf);
+        RegCloseKey(hukey2);
+    }
+    HeapFree(GetProcessHeap(),0,productcode);
 
-    return rc;
+    return ERROR_INSTALL_SUSPEND;
 }
 
-UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR
-                                szPathBuf, DWORD* pcchPathBuf) 
+UINT ACTION_ResolveSource(MSIPACKAGE* package)
 {
-    LPWSTR path;
-    UINT rc = ERROR_FUNCTION_FAILED;
-    MSIPACKAGE *package;
-
-    TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf);
+    /*
+     * we are currently doing what should be done here in the top level Install
+     * however for Adminastrative and uninstalls this step will be needed
+     */
+    return ERROR_SUCCESS;
+}
 
-    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
-    if( !package )
-        return ERROR_INVALID_HANDLE;
-    path = resolve_folder(package, szFolder, TRUE, FALSE, NULL);
-    msiobj_release( &package->hdr );
+static UINT ACTION_RegisterUser(MSIPACKAGE *package)
+{
+    static const WCHAR szProductID[]=
+         {'P','r','o','d','u','c','t','I','D',0};
+    HKEY hkey=0;
+    LPWSTR buffer;
+    LPWSTR productcode;
+    LPWSTR productid;
+    UINT rc,i;
+    DWORD size;
 
-    if (path && strlenW(path) > *pcchPathBuf)
+    static const WCHAR szPropKeys[][80] = 
     {
-        *pcchPathBuf = strlenW(path)+1;
-        rc = ERROR_MORE_DATA;
-    }
-    else if (path)
+        {'P','r','o','d','u','c','t','I','D',0},
+        {'U','S','E','R','N','A','M','E',0},
+        {'C','O','M','P','A','N','Y','N','A','M','E',0},
+        {0},
+    };
+
+    static const WCHAR szRegKeys[][80] = 
     {
-        *pcchPathBuf = strlenW(path)+1;
-        strcpyW(szPathBuf,path);
-        TRACE("Returning Path %s\n",debugstr_w(path));
-        rc = ERROR_SUCCESS;
-    }
-    HeapFree(GetProcessHeap(),0,path);
-    
-    return rc;
-}
+        {'P','r','o','d','u','c','t','I','D',0},
+        {'R','e','g','O','w','n','e','r',0},
+        {'R','e','g','C','o','m','p','a','n','y',0},
+        {0},
+    };
 
+    if (!package)
+        return ERROR_INVALID_HANDLE;
 
-/***********************************************************************
- * MsiSetTargetPathA  (MSI.@)
- */
-UINT WINAPI MsiSetTargetPathA(MSIHANDLE hInstall, LPCSTR szFolder, 
-                             LPCSTR szFolderPath)
-{
-    LPWSTR szwFolder;
-    LPWSTR szwFolderPath;
-    UINT rc;
+    productid = load_dynamic_property(package,szProductID,&rc);
+    if (!productid)
+        return ERROR_SUCCESS;
 
-    if (!szFolder)
-        return ERROR_FUNCTION_FAILED;
-    if (hInstall == 0)
-        return ERROR_FUNCTION_FAILED;
+    productcode = load_dynamic_property(package,szProductCode,&rc);
+    if (!productcode)
+        return rc;
 
-    szwFolder = strdupAtoW(szFolder);
-    if (!szwFolder)
-        return ERROR_FUNCTION_FAILED; 
+    rc = MSIREG_OpenUninstallKey(productcode,&hkey,TRUE);
+    if (rc != ERROR_SUCCESS)
+        goto end;
 
-    szwFolderPath = strdupAtoW(szFolderPath);
-    if (!szwFolderPath)
+    i = 0;
+    while (szPropKeys[i][0]!=0)
     {
-        HeapFree(GetProcessHeap(),0,szwFolder);
-        return ERROR_FUNCTION_FAILED; 
+        buffer = load_dynamic_property(package,szPropKeys[i],&rc);
+        if (rc == ERROR_SUCCESS)
+        {
+            size = strlenW(buffer)*sizeof(WCHAR);
+            RegSetValueExW(hkey,szRegKeys[i],0,REG_SZ,(LPSTR)buffer,size);
+        }
+        else
+            RegSetValueExW(hkey,szRegKeys[i],0,REG_SZ,NULL,0);
+        i++;
     }
 
-    rc = MsiSetTargetPathW(hInstall, szwFolder, szwFolderPath);
-
-    HeapFree(GetProcessHeap(),0,szwFolder);
-    HeapFree(GetProcessHeap(),0,szwFolderPath);
+end:
+    HeapFree(GetProcessHeap(),0,productcode);
+    HeapFree(GetProcessHeap(),0,productid);
+    RegCloseKey(hkey);
 
-    return rc;
+    return ERROR_SUCCESS;
 }
 
-UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder, 
-                             LPCWSTR szFolderPath)
+
+static UINT ACTION_ExecuteAction(MSIPACKAGE *package)
 {
-    DWORD i;
-    LPWSTR path = NULL;
-    LPWSTR path2 = NULL;
-    MSIFOLDER *folder;
+    static const WCHAR szUILevel[] = {'U','I','L','e','v','e','l',0};
+    static const WCHAR szTwo[] = {'2',0};
+    UINT rc;
+    LPWSTR level;
+    level = load_dynamic_property(package,szUILevel,NULL);
 
-    TRACE("(%p %s %s)\n",package, debugstr_w(szFolder),debugstr_w(szFolderPath));
+    MSI_SetPropertyW(package,szUILevel,szTwo);
+    rc = ACTION_ProcessExecSequence(package,FALSE);
+    MSI_SetPropertyW(package,szUILevel,level);
+    HeapFree(GetProcessHeap(),0,level);
+    return rc;
+}
 
-    if (package==NULL)
-        return ERROR_INVALID_HANDLE;
 
-    if (szFolderPath[0]==0)
-        return ERROR_FUNCTION_FAILED;
+/*
+ * Code based off of code located here
+ * http://www.codeproject.com/gdi/fontnamefromfile.asp
+ *
+ * Using string index 4 (full font name) instead of 1 (family name)
+ */
+static LPWSTR load_ttfname_from(LPCWSTR filename)
+{
+    HANDLE handle;
+    LPWSTR ret = NULL;
+    int i;
 
-    if (GetFileAttributesW(szFolderPath) == INVALID_FILE_ATTRIBUTES)
-        return ERROR_FUNCTION_FAILED;
+    typedef struct _tagTT_OFFSET_TABLE{
+        USHORT uMajorVersion;
+        USHORT uMinorVersion;
+        USHORT uNumOfTables;
+        USHORT uSearchRange;
+        USHORT uEntrySelector;
+        USHORT uRangeShift;
+    }TT_OFFSET_TABLE;
 
-    path = resolve_folder(package,szFolder,FALSE,FALSE,&folder);
+    typedef struct _tagTT_TABLE_DIRECTORY{
+        char szTag[4]; /* table name */
+        ULONG uCheckSum; /* Check sum */
+        ULONG uOffset; /* Offset from beginning of file */
+        ULONG uLength; /* length of the table in bytes */
+    }TT_TABLE_DIRECTORY;
 
-    if (!path)
-        return ERROR_INVALID_PARAMETER;
+    typedef struct _tagTT_NAME_TABLE_HEADER{
+    USHORT uFSelector; /* format selector. Always 0 */
+    USHORT uNRCount; /* Name Records count */
+    USHORT uStorageOffset; /* Offset for strings storage, 
+                            * from start of the table */
+    }TT_NAME_TABLE_HEADER;
+   
+    typedef struct _tagTT_NAME_RECORD{
+        USHORT uPlatformID;
+        USHORT uEncodingID;
+        USHORT uLanguageID;
+        USHORT uNameID;
+        USHORT uStringLength;
+        USHORT uStringOffset; /* from start of storage area */
+    }TT_NAME_RECORD;
 
-    HeapFree(GetProcessHeap(),0,folder->Property);
-    folder->Property = build_directory_name(2, szFolderPath, NULL);
+#define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
+#define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
 
-    if (lstrcmpiW(path, folder->Property) == 0)
-    {
-        /*
-         *  Resolved Target has not really changed, so just 
-         *  set this folder and do not recalculate everything.
-         */
-        HeapFree(GetProcessHeap(),0,folder->ResolvedTarget);
-        folder->ResolvedTarget = NULL;
-        path2 = resolve_folder(package,szFolder,FALSE,TRUE,NULL);
-        HeapFree(GetProcessHeap(),0,path2);
-    }
-    else
+    handle = CreateFileW(filename ,GENERIC_READ, 0, NULL, OPEN_EXISTING,
+                    FILE_ATTRIBUTE_NORMAL, 0 );
+    if (handle != INVALID_HANDLE_VALUE)
     {
-        for (i = 0; i < package->loaded_folders; i++)
-        {
-            HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedTarget);
-            package->folders[i].ResolvedTarget=NULL;
-        }
+        TT_TABLE_DIRECTORY tblDir;
+        BOOL bFound = FALSE;
+        TT_OFFSET_TABLE ttOffsetTable;
+
+        ReadFile(handle,&ttOffsetTable, sizeof(TT_OFFSET_TABLE),NULL,NULL);
+        ttOffsetTable.uNumOfTables = SWAPWORD(ttOffsetTable.uNumOfTables);
+        ttOffsetTable.uMajorVersion = SWAPWORD(ttOffsetTable.uMajorVersion);
+        ttOffsetTable.uMinorVersion = SWAPWORD(ttOffsetTable.uMinorVersion);
+        
+        if (ttOffsetTable.uMajorVersion != 1 || 
+                        ttOffsetTable.uMinorVersion != 0)
+            return NULL;
 
-        for (i = 0; i < package->loaded_folders; i++)
+        for (i=0; i< ttOffsetTable.uNumOfTables; i++)
         {
-            path2=resolve_folder(package, package->folders[i].Directory, FALSE,
-                       TRUE, NULL);
-            HeapFree(GetProcessHeap(),0,path2);
+            ReadFile(handle,&tblDir, sizeof(TT_TABLE_DIRECTORY),NULL,NULL);
+            if (strncmp(tblDir.szTag,"name",4)==0)
+            {
+                bFound = TRUE;
+                tblDir.uLength = SWAPLONG(tblDir.uLength);
+                tblDir.uOffset = SWAPLONG(tblDir.uOffset);
+                break;
+            }
         }
-    }
-    HeapFree(GetProcessHeap(),0,path);
-
-    return ERROR_SUCCESS;
-}
-
-/***********************************************************************
- * MsiSetTargetPathW  (MSI.@)
- */
-UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder, 
-                             LPCWSTR szFolderPath)
-{
-    MSIPACKAGE *package;
-    UINT ret;
-
-    TRACE("(%s %s)\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
-
-    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
-    ret = MSI_SetTargetPathW( package, szFolder, szFolderPath );
-    msiobj_release( &package->hdr );
-    return ret;
-}
-
-/***********************************************************************
- *           MsiGetMode    (MSI.@)
- *
- * Returns an internal installer state (if it is running in a mode iRunMode)
- *
- * PARAMS
- *   hInstall    [I]  Handle to the installation
- *   hRunMode    [I]  Checking run mode
- *        MSIRUNMODE_ADMIN             Administrative mode
- *        MSIRUNMODE_ADVERTISE         Advertisement mode
- *        MSIRUNMODE_MAINTENANCE       Maintenance mode
- *        MSIRUNMODE_ROLLBACKENABLED   Rollback is enabled
- *        MSIRUNMODE_LOGENABLED        Log file is writing
- *        MSIRUNMODE_OPERATIONS        Operations in progress??
- *        MSIRUNMODE_REBOOTATEND       We need to reboot after installation completed
- *        MSIRUNMODE_REBOOTNOW         We need to reboot to continue the installation
- *        MSIRUNMODE_CABINET           Files from cabinet are installed
- *        MSIRUNMODE_SOURCESHORTNAMES  Long names in source files is suppressed
- *        MSIRUNMODE_TARGETSHORTNAMES  Long names in destination files is suppressed
- *        MSIRUNMODE_RESERVED11        Reserved
- *        MSIRUNMODE_WINDOWS9X         Running under Windows95/98
- *        MSIRUNMODE_ZAWENABLED        Demand installation is supported
- *        MSIRUNMODE_RESERVED14        Reserved
- *        MSIRUNMODE_RESERVED15        Reserved
- *        MSIRUNMODE_SCHEDULED         called from install script
- *        MSIRUNMODE_ROLLBACK          called from rollback script
- *        MSIRUNMODE_COMMIT            called from commit script
- *
- * RETURNS
- *    In the state: TRUE
- *    Not in the state: FALSE
- *
- */
 
-BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
-{
-    FIXME("STUB (iRunMode=%i)\n",iRunMode);
-    return TRUE;
-}
+        if (bFound)
+        {
+            TT_NAME_TABLE_HEADER ttNTHeader;
+            TT_NAME_RECORD ttRecord;
 
-/***********************************************************************
- * MsiSetFeatureStateA (MSI.@)
- *
- * According to the docs, when this is called it immediately recalculates
- * all the component states as well
- */
-UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
-                                INSTALLSTATE iState)
-{
-    LPWSTR szwFeature = NULL;
-    UINT rc;
+            SetFilePointer(handle, tblDir.uOffset, NULL, FILE_BEGIN);
+            ReadFile(handle,&ttNTHeader, sizeof(TT_NAME_TABLE_HEADER),
+                            NULL,NULL);
 
-    szwFeature = strdupAtoW(szFeature);
+            ttNTHeader.uNRCount = SWAPWORD(ttNTHeader.uNRCount);
+            ttNTHeader.uStorageOffset = SWAPWORD(ttNTHeader.uStorageOffset);
+            bFound = FALSE;
+            for(i=0; i<ttNTHeader.uNRCount; i++)
+            {
+                ReadFile(handle,&ttRecord, sizeof(TT_NAME_RECORD),NULL,NULL);
+                ttRecord.uNameID = SWAPWORD(ttRecord.uNameID);
+                /* 4 is the Full Font Name */
+                if(ttRecord.uNameID == 4)
+                {
+                    int nPos;
+                    LPSTR buf;
+                    static LPCSTR tt = " (TrueType)";
 
-    if (!szwFeature)
-        return ERROR_FUNCTION_FAILED;
-   
-    rc = MsiSetFeatureStateW(hInstall,szwFeature, iState); 
+                    ttRecord.uStringLength = SWAPWORD(ttRecord.uStringLength);
+                    ttRecord.uStringOffset = SWAPWORD(ttRecord.uStringOffset);
+                    nPos = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
+                    SetFilePointer(handle, tblDir.uOffset + 
+                                    ttRecord.uStringOffset + 
+                                    ttNTHeader.uStorageOffset,
+                                    NULL, FILE_BEGIN);
+                    buf = HeapAlloc(GetProcessHeap(), 0, 
+                                    ttRecord.uStringLength + 1 + strlen(tt));
+                    memset(buf, 0, ttRecord.uStringLength + 1 + strlen(tt));
+                    ReadFile(handle, buf, ttRecord.uStringLength, NULL, NULL);
+                    if (strlen(buf) > 0)
+                    {
+                        strcat(buf,tt);
+                        ret = strdupAtoW(buf);
+                        HeapFree(GetProcessHeap(),0,buf);
+                        break;
+                    }
 
-    HeapFree(GetProcessHeap(),0,szwFeature);
+                    HeapFree(GetProcessHeap(),0,buf);
+                    SetFilePointer(handle,nPos, NULL, FILE_BEGIN);
+                }
+            }
+        }
+        CloseHandle(handle);
+    }
+    else
+        ERR("Unable to open font file %s\n", debugstr_w(filename));
 
-    return rc;
+    TRACE("Returning fontname %s\n",debugstr_w(ret));
+    return ret;
 }
 
-
-
-UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature,
-                                INSTALLSTATE iState)
+static UINT ITERATE_RegisterFonts(MSIRECORD *row, LPVOID param)
 {
-    INT index, i;
-    UINT rc = ERROR_SUCCESS;
-
-    TRACE(" %s to %i\n",debugstr_w(szFeature), iState);
+    MSIPACKAGE *package = (MSIPACKAGE*)param;
+    LPWSTR name;
+    LPCWSTR file;
+    UINT index;
+    DWORD size;
+    static const WCHAR regfont1[] =
+        {'S','o','f','t','w','a','r','e','\\',
+         'M','i','c','r','o','s','o','f','t','\\',
+         'W','i','n','d','o','w','s',' ','N','T','\\',
+         'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+         'F','o','n','t','s',0};
+    static const WCHAR regfont2[] =
+        {'S','o','f','t','w','a','r','e','\\',
+         'M','i','c','r','o','s','o','f','t','\\',
+         'W','i','n','d','o','w','s','\\',
+         'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+         'F','o','n','t','s',0};
+    HKEY hkey1;
+    HKEY hkey2;
 
-    index = get_loaded_feature(package,szFeature);
+    file = MSI_RecordGetString(row,1);
+    index = get_loaded_file(package,file);
     if (index < 0)
-        return ERROR_UNKNOWN_FEATURE;
-
-    package->features[index].ActionRequest= iState;
-    package->features[index].Action= iState;
-
-    ACTION_UpdateComponentStates(package,szFeature);
-
-    /* update all the features that are children of this feature */
-    for (i = 0; i < package->loaded_features; i++)
     {
-        if (strcmpW(szFeature, package->features[i].Feature_Parent) == 0)
-            MSI_SetFeatureStateW(package, package->features[i].Feature, iState);
+        ERR("Unable to load file\n");
+        return ERROR_SUCCESS;
     }
-    
-    return rc;
-}
 
-/***********************************************************************
- * MsiSetFeatureStateW (MSI.@)
- */
-UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
-                                INSTALLSTATE iState)
-{
-    MSIPACKAGE* package;
-    UINT rc = ERROR_SUCCESS;
+    /* check to make sure that component is installed */
+    if (!ACTION_VerifyComponentForAction(package, 
+                package->files[index].ComponentIndex, INSTALLSTATE_LOCAL))
+    {
+        TRACE("Skipping: Component not scheduled for install\n");
+        return ERROR_SUCCESS;
+    }
 
-    TRACE(" %s to %i\n",debugstr_w(szFeature), iState);
+    RegCreateKeyW(HKEY_LOCAL_MACHINE,regfont1,&hkey1);
+    RegCreateKeyW(HKEY_LOCAL_MACHINE,regfont2,&hkey2);
 
-    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
-    if (!package)
-        return ERROR_INVALID_HANDLE;
+    if (MSI_RecordIsNull(row,2))
+        name = load_ttfname_from(package->files[index].TargetPath);
+    else
+        name = load_dynamic_stringW(row,2);
 
-    rc = MSI_SetFeatureStateW(package,szFeature,iState);
+    if (name)
+    {
+        size = strlenW(package->files[index].FileName) * sizeof(WCHAR);
+        RegSetValueExW(hkey1,name,0,REG_SZ,
+                    (LPBYTE)package->files[index].FileName,size);
+        RegSetValueExW(hkey2,name,0,REG_SZ,
+                    (LPBYTE)package->files[index].FileName,size);
+    }
 
-    msiobj_release( &package->hdr );
-    return rc;
+    HeapFree(GetProcessHeap(),0,name);
+    RegCloseKey(hkey1);
+    RegCloseKey(hkey2);
+    return ERROR_SUCCESS;
 }
 
-UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPSTR szFeature,
-                  INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
+static UINT ACTION_RegisterFonts(MSIPACKAGE *package)
 {
-    LPWSTR szwFeature = NULL;
     UINT rc;
-    
-    szwFeature = strdupAtoW(szFeature);
-
-    rc = MsiGetFeatureStateW(hInstall,szwFeature,piInstalled, piAction);
-
-    HeapFree( GetProcessHeap(), 0 , szwFeature);
-
-    return rc;
-}
-
-UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPWSTR szFeature,
-                  INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
-{
-    INT index;
-
-    index = get_loaded_feature(package,szFeature);
-    if (index < 0)
-        return ERROR_UNKNOWN_FEATURE;
-
-    if (piInstalled)
-        *piInstalled = package->features[index].Installed;
+    MSIQUERY * view;
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','F','o','n','t','`',0};
 
-    if (piAction)
-        *piAction = package->features[index].Action;
+    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
+    if (rc != ERROR_SUCCESS)
+    {
+        TRACE("MSI_DatabaseOpenViewW failed: %d\n", rc);
+        return ERROR_SUCCESS;
+    }
 
-    TRACE("returning %i %i\n",*piInstalled,*piAction);
+    MSI_IterateRecords(view, NULL, ITERATE_RegisterFonts, package);
+    msiobj_release(&view->hdr);
 
     return ERROR_SUCCESS;
 }
 
-UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPWSTR szFeature,
-                  INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
-{
-    MSIPACKAGE* package;
-    UINT ret;
-
-    TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled,
-piAction);
-
-    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-    ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
-    msiobj_release( &package->hdr );
-    return ret;
-}
-
-/***********************************************************************
- * MsiGetComponentStateA (MSI.@)
- */
-UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPSTR szComponent,
-                  INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
+static UINT ITERATE_PublishComponent(MSIRECORD *rec, LPVOID param)
 {
-    LPWSTR szwComponent= NULL;
-    UINT rc;
-    
-    szwComponent= strdupAtoW(szComponent);
+    MSIPACKAGE *package = (MSIPACKAGE*)param;
+    LPCWSTR compgroupid=NULL;
+    LPCWSTR feature=NULL;
+    LPCWSTR text = NULL;
+    LPCWSTR qualifier = NULL;
+    LPCWSTR component = NULL;
+    LPWSTR advertise = NULL;
+    LPWSTR output = NULL;
+    HKEY hkey;
+    UINT rc = ERROR_SUCCESS;
+    UINT index;
+    DWORD sz = 0;
 
-    rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
+    component = MSI_RecordGetString(rec,3);
+    index = get_loaded_component(package,component);
 
-    HeapFree( GetProcessHeap(), 0 , szwComponent);
+    if (!ACTION_VerifyComponentForAction(package, index,
+                            INSTALLSTATE_LOCAL) && 
+       !ACTION_VerifyComponentForAction(package, index,
+                            INSTALLSTATE_SOURCE) &&
+       !ACTION_VerifyComponentForAction(package, index,
+                            INSTALLSTATE_ADVERTISED))
+    {
+        TRACE("Skipping: Component %s not scheduled for install\n",
+                        debugstr_w(component));
 
-    return rc;
-}
+        return ERROR_SUCCESS;
+    }
 
-UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPWSTR szComponent,
-                  INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
-{
-    INT index;
+    compgroupid = MSI_RecordGetString(rec,1);
 
-    TRACE("%p %s %p %p\n", package, debugstr_w(szComponent), piInstalled,
-piAction);
+    rc = MSIREG_OpenUserComponentsKey(compgroupid, &hkey, TRUE);
+    if (rc != ERROR_SUCCESS)
+        goto end;
+    
+    text = MSI_RecordGetString(rec,4);
+    qualifier = MSI_RecordGetString(rec,2);
+    feature = MSI_RecordGetString(rec,5);
+  
+    advertise = create_component_advertise_string(package, 
+                    &package->components[index], feature);
 
-    index = get_loaded_component(package,szComponent);
-    if (index < 0)
-        return ERROR_UNKNOWN_COMPONENT;
+    sz = strlenW(advertise);
 
-    if (piInstalled)
-        *piInstalled = package->components[index].Installed;
+    if (text)
+        sz += lstrlenW(text);
 
-    if (piAction)
-        *piAction = package->components[index].Action;
+    sz+=3;
+    sz *= sizeof(WCHAR);
+           
+    output = HeapAlloc(GetProcessHeap(),0,sz);
+    memset(output,0,sz);
+    strcpyW(output,advertise);
 
-    TRACE("states (%i, %i)\n",
-(piInstalled)?*piInstalled:-1,(piAction)?*piAction:-1);
+    if (text)
+        strcatW(output,text);
 
-    return ERROR_SUCCESS;
+    sz = (lstrlenW(output)+2) * sizeof(WCHAR);
+    RegSetValueExW(hkey, qualifier,0,REG_MULTI_SZ, (LPBYTE)output, sz);
+    
+end:
+    RegCloseKey(hkey);
+    HeapFree(GetProcessHeap(),0,output);
+    
+    return rc;
 }
 
-/***********************************************************************
- * MsiGetComponentStateW (MSI.@)
+/*
+ * At present I am ignorning the advertised components part of this and only
+ * focusing on the qualified component sets
  */
-UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPWSTR szComponent,
-                  INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
-{
-    MSIPACKAGE* package;
-    UINT ret;
-
-    TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szComponent),
-           piInstalled, piAction);
-
-    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-    ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
-    msiobj_release( &package->hdr );
-    return ret;
-}
-
-#if 0
-static UINT ACTION_Template(MSIPACKAGE *package)
+static UINT ACTION_PublishComponents(MSIPACKAGE *package)
 {
     UINT rc;
     MSIQUERY * view;
-    MSIRECORD * row = 0;
-    static const WCHAR ExecSeqQuery[] = {0};
-
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','P','u','b','l','i','s','h',
+         'C','o','m','p','o','n','e','n','t','`',0};
+    
     rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
     if (rc != ERROR_SUCCESS)
-        return rc;
-
-    rc = MSI_ViewExecute(view, 0);
-    if (rc != ERROR_SUCCESS)
-    {
-        MSI_ViewClose(view);
-        msiobj_release(&view->hdr);
-        return rc;
-    }
-
-    while (1)
-    {
-        rc = MSI_ViewFetch(view,&row);
-        if (rc != ERROR_SUCCESS)
-        {
-            rc = ERROR_SUCCESS;
-            break;
-        }
+        return ERROR_SUCCESS;
 
-        msiobj_release(&row->hdr);
-    }
-    MSI_ViewClose(view);
+    rc = MSI_IterateRecords(view, NULL, ITERATE_PublishComponent, package);
     msiobj_release(&view->hdr);
+
     return rc;
 }
-#endif
index a88a07f..9c472a5 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#define IDENTIFIER_SIZE 96
+
 typedef struct tagMSIFEATURE
 {
-    WCHAR Feature[96];
-    WCHAR Feature_Parent[96];
+    WCHAR Feature[IDENTIFIER_SIZE];
+    WCHAR Feature_Parent[IDENTIFIER_SIZE];
     WCHAR Title[0x100];
     WCHAR Description[0x100];
     INT Display;
     INT Level;
-    WCHAR Directory[96];
+    WCHAR Directory[IDENTIFIER_SIZE];
     INT Attributes;
     
     INSTALLSTATE Installed;
@@ -40,12 +42,12 @@ typedef struct tagMSIFEATURE
 
 typedef struct tagMSICOMPONENT
 {
-    WCHAR Component[96];
-    WCHAR ComponentId[96];
-    WCHAR Directory[96];
+    WCHAR Component[IDENTIFIER_SIZE];
+    WCHAR ComponentId[IDENTIFIER_SIZE];
+    WCHAR Directory[IDENTIFIER_SIZE];
     INT Attributes;
     WCHAR Condition[0x100];
-    WCHAR KeyPath[96];
+    WCHAR KeyPath[IDENTIFIER_SIZE];
 
     INSTALLSTATE Installed;
     INSTALLSTATE ActionRequest;
@@ -56,6 +58,7 @@ typedef struct tagMSICOMPONENT
     INT  RefCount;
 
     LPWSTR FullKeypath;
+    LPWSTR AdvertiseString;
 } MSICOMPONENT;
 
 typedef struct tagMSIFOLDER
@@ -100,14 +103,117 @@ typedef struct tagMSIFILE
     BOOL    Temporary; 
 }MSIFILE;
 
+typedef struct tagMSICLASS
+{
+    WCHAR CLSID[IDENTIFIER_SIZE];     /* Primary Key */
+    WCHAR Context[IDENTIFIER_SIZE];   /* Primary Key */
+    INT ComponentIndex;               /* Primary Key */
+    INT ProgIDIndex;
+    LPWSTR ProgIDText;
+    LPWSTR Description;
+    INT AppIDIndex;
+    LPWSTR FileTypeMask;
+    LPWSTR IconPath;
+    LPWSTR DefInprocHandler;
+    LPWSTR DefInprocHandler32;
+    LPWSTR Argument;
+    INT FeatureIndex;
+    INT Attributes;
+    /* not in the table, set during installation */
+    BOOL Installed;
+} MSICLASS;
+
+typedef struct tagMSIEXTENSION
+{
+    WCHAR Extension[256];  /* Primary Key */
+    INT ComponentIndex;    /* Primary Key */
+    INT ProgIDIndex;
+    LPWSTR ProgIDText;
+    INT MIMEIndex;
+    INT FeatureIndex;
+    /* not in the table, set during installation */
+    BOOL Installed;
+    INT VerbCount;
+    INT Verbs[100]; /* yes hard coded limit, but realistically 100 verbs??? */
+} MSIEXTENSION;
+
+typedef struct tagMSIPROGID
+{
+    LPWSTR ProgID;  /* Primary Key */
+    INT ParentIndex;
+    INT ClassIndex;
+    LPWSTR Description;
+    LPWSTR IconPath;
+    /* not in the table, set during installation */
+    BOOL InstallMe;
+    INT CurVerIndex;
+    INT VersionIndIndex;
+} MSIPROGID;
+
+typedef struct tagMSIVERB
+{
+    INT ExtensionIndex;
+    LPWSTR Verb;
+    INT Sequence;
+    LPWSTR Command;
+    LPWSTR Argument;
+} MSIVERB;
+
+typedef struct tagMSIMIME
+{
+    LPWSTR ContentType;  /* Primary Key */
+    INT ExtensionIndex;
+    WCHAR CLSID[IDENTIFIER_SIZE];
+    INT ClassIndex;
+    /* not in the table, set during installation */
+    BOOL InstallMe;
+} MSIMIME;
+
+typedef struct tagMSIAPPID
+{
+    WCHAR AppID[IDENTIFIER_SIZE]; /* Primary key */
+    LPWSTR RemoteServerName;
+    LPWSTR LocalServer;
+    LPWSTR ServiceParameters;
+    LPWSTR DllSurrogate;
+    BOOL ActivateAtStorage;
+    BOOL RunAsInteractiveUser;
+} MSIAPPID;
+
+enum SCRIPTS {
+        INSTALL_SCRIPT = 0,
+        COMMIT_SCRIPT = 1,
+        ROLLBACK_SCRIPT = 2,
+        TOTAL_SCRIPTS = 3
+};
+
+typedef struct tagMSISCRIPT
+{
+    LPWSTR  *Actions[TOTAL_SCRIPTS];
+    UINT    ActionCount[TOTAL_SCRIPTS];
+    BOOL    ExecuteSequenceRun;
+    BOOL    FindRelatedProductsRun;
+    BOOL    CurrentlyScripting;
+}MSISCRIPT;
+
 
-UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action);
+UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action, BOOL force);
 UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action);
 void ACTION_FinishCustomActions( MSIPACKAGE* package);
 UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action, BOOL execute);
-void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature);
+
+/* actions in other modules */
 UINT ACTION_AppSearch(MSIPACKAGE *package);
+UINT ACTION_FindRelatedProducts(MSIPACKAGE *package);
+UINT ACTION_InstallFiles(MSIPACKAGE *package);
+UINT ACTION_DuplicateFiles(MSIPACKAGE *package);
+UINT ACTION_RegisterClassInfo(MSIPACKAGE *package);
+UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package);
+UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package);
+UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package);
+
 
+/* Helpers */
 DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data );
 WCHAR *load_dynamic_stringW(MSIRECORD *row, INT index);
 LPWSTR load_dynamic_property(MSIPACKAGE *package, LPCWSTR prop, UINT* rc);
@@ -117,3 +223,35 @@ int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component );
 int get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature );
 int get_loaded_file(MSIPACKAGE* package, LPCWSTR file);
 int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path);
+UINT schedule_action(MSIPACKAGE *package, UINT script, LPCWSTR action);
+UINT build_icon_path(MSIPACKAGE *, LPCWSTR, LPWSTR *);
+DWORD build_version_dword(LPCWSTR);
+LPWSTR build_directory_name(DWORD , ...);
+BOOL create_full_pathW(const WCHAR *path);
+BOOL ACTION_VerifyComponentForAction(MSIPACKAGE*, INT, INSTALLSTATE);
+BOOL ACTION_VerifyFeatureForAction(MSIPACKAGE*, INT, INSTALLSTATE);
+void reduce_to_longfilename(WCHAR*);
+void reduce_to_shortfilename(WCHAR*);
+LPWSTR create_component_advertise_string(MSIPACKAGE*, MSICOMPONENT*, LPCWSTR);
+void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature);
+
+
+/* control event stuff */
+VOID ControlEvent_FireSubscribedEvent(MSIPACKAGE *package, LPCWSTR event,
+                                      MSIRECORD *data);
+VOID ControlEvent_CleanupSubscriptions(MSIPACKAGE *package);
+VOID ControlEvent_SubscribeToEvent(MSIPACKAGE *package, LPCWSTR event,
+                                   LPCWSTR control, LPCWSTR attribute);
+VOID ControlEvent_UnSubscribeToEvent( MSIPACKAGE *package, LPCWSTR event,
+                                      LPCWSTR control, LPCWSTR attribute );
+
+/* User Interface messages from the actions */
+void ui_progress(MSIPACKAGE *, int, int, int, int);
+void ui_actiondata(MSIPACKAGE *, LPCWSTR, MSIRECORD *);
+
+
+/* string consts use a number of places  and defined in helpers.c*/
+extern const WCHAR cszSourceDir[];
+extern const WCHAR szProductCode[];
+extern const WCHAR cszRootDrive[];
+extern const WCHAR cszbs[];
diff --git a/reactos/lib/msi/classes.c b/reactos/lib/msi/classes.c
new file mode 100644 (file)
index 0000000..ed0f550
--- /dev/null
@@ -0,0 +1,1602 @@
+/*
+ * Implementation of the Microsoft Installer (msi.dll)
+ *
+ * Copyright 2005 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
+ */
+
+/* actions handled in this module
+ * RegisterClassInfo
+ * RegisterProgIdInfo
+ * RegisterExtensionInfo
+ * RegisterMIMEInfo
+ * UnRegisterClassInfo (TODO)
+ * UnRegisterProgIdInfo (TODO)
+ * UnRegisterExtensionInfo (TODO)
+ * UnRegisterMIMEInfo (TODO)
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winreg.h"
+#include "wine/debug.h"
+#include "msipriv.h"
+#include "winuser.h"
+#include "wine/unicode.h"
+#include "action.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msi);
+
+
+extern const WCHAR szRegisterClassInfo[];
+extern const WCHAR szRegisterProgIdInfo[];
+extern const WCHAR szRegisterExtensionInfo[];
+extern const WCHAR szRegisterMIMEInfo[];
+
+extern const WCHAR szUnregisterClassInfo[];
+extern const WCHAR szUnregisterExtensionInfo[];
+extern const WCHAR szUnregisterMIMEInfo[];
+extern const WCHAR szUnregisterProgIdInfo[];
+
+static INT load_appid(MSIPACKAGE* package, MSIRECORD *row)
+{
+    DWORD index = package->loaded_appids;
+    DWORD sz;
+    LPCWSTR buffer;
+
+    /* fill in the data */
+
+    package->loaded_appids++;
+    if (package->loaded_appids == 1)
+        package->appids = HeapAlloc(GetProcessHeap(),0,sizeof(MSIAPPID));
+    else
+        package->appids = HeapReAlloc(GetProcessHeap(),0,
+            package->appids, package->loaded_appids * sizeof(MSIAPPID));
+
+    memset(&package->appids[index],0,sizeof(MSIAPPID));
+    
+    sz = IDENTIFIER_SIZE;
+    MSI_RecordGetStringW(row, 1, package->appids[index].AppID, &sz);
+    TRACE("loading appid %s\n",debugstr_w(package->appids[index].AppID));
+
+    buffer = MSI_RecordGetString(row,2);
+    deformat_string(package,buffer,&package->appids[index].RemoteServerName);
+
+    package->appids[index].LocalServer = load_dynamic_stringW(row,3);
+    package->appids[index].ServiceParameters = load_dynamic_stringW(row,4);
+    package->appids[index].DllSurrogate = load_dynamic_stringW(row,5);
+
+    package->appids[index].ActivateAtStorage = !MSI_RecordIsNull(row,6);
+    package->appids[index].RunAsInteractiveUser = !MSI_RecordIsNull(row,7);
+    
+    return index;
+}
+
+static INT load_given_appid(MSIPACKAGE *package, LPCWSTR appid)
+{
+    INT rc;
+    MSIRECORD *row;
+    INT i;
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','A','p','p','I','d','`',' ','W','H','E','R','E',' ',
+         '`','A','p','p','I','d','`',' ','=',' ','\'','%','s','\'',0};
+
+    if (!appid)
+        return -1;
+
+    /* check for appids already loaded */
+    for (i = 0; i < package->loaded_appids; i++)
+        if (strcmpiW(package->appids[i].AppID,appid)==0)
+        {
+            TRACE("found appid %s at index %i\n",debugstr_w(appid),i);
+            return i;
+        }
+    
+    row = MSI_QueryGetRecord(package->db, ExecSeqQuery, appid);
+    if (!row)
+        return -1;
+
+    rc = load_appid(package, row);
+    msiobj_release(&row->hdr);
+
+    return rc;
+}
+
+static INT load_given_progid(MSIPACKAGE *package, LPCWSTR progid);
+static INT load_given_class(MSIPACKAGE *package, LPCWSTR classid);
+
+static INT load_progid(MSIPACKAGE* package, MSIRECORD *row)
+{
+    DWORD index = package->loaded_progids;
+    LPCWSTR buffer;
+
+    /* fill in the data */
+
+    package->loaded_progids++;
+    if (package->loaded_progids == 1)
+        package->progids = HeapAlloc(GetProcessHeap(),0,sizeof(MSIPROGID));
+    else
+        package->progids = HeapReAlloc(GetProcessHeap(),0,
+            package->progids , package->loaded_progids * sizeof(MSIPROGID));
+
+    memset(&package->progids[index],0,sizeof(MSIPROGID));
+
+    package->progids[index].ProgID = load_dynamic_stringW(row,1);
+    TRACE("loading progid %s\n",debugstr_w(package->progids[index].ProgID));
+
+    buffer = MSI_RecordGetString(row,2);
+    package->progids[index].ParentIndex = load_given_progid(package,buffer);
+    if (package->progids[index].ParentIndex < 0 && buffer)
+        FIXME("Unknown parent ProgID %s\n",debugstr_w(buffer));
+
+    buffer = MSI_RecordGetString(row,3);
+    package->progids[index].ClassIndex = load_given_class(package,buffer);
+    if (package->progids[index].ClassIndex< 0 && buffer)
+        FIXME("Unknown class %s\n",debugstr_w(buffer));
+
+    package->progids[index].Description = load_dynamic_stringW(row,4);
+
+    if (!MSI_RecordIsNull(row,6))
+    {
+        INT icon_index = MSI_RecordGetInteger(row,6); 
+        LPWSTR FileName = load_dynamic_stringW(row,5);
+        LPWSTR FilePath;
+        static const WCHAR fmt[] = {'%','s',',','%','i',0};
+
+        build_icon_path(package,FileName,&FilePath);
+       
+        package->progids[index].IconPath = 
+                HeapAlloc(GetProcessHeap(),0,(strlenW(FilePath)+10)*
+                                sizeof(WCHAR));
+
+        sprintfW(package->progids[index].IconPath,fmt,FilePath,icon_index);
+
+        HeapFree(GetProcessHeap(),0,FilePath);
+        HeapFree(GetProcessHeap(),0,FileName);
+    }
+    else
+    {
+        buffer = MSI_RecordGetString(row,5);
+        if (buffer)
+            build_icon_path(package,buffer,&(package->progids[index].IconPath));
+    }
+
+    package->progids[index].CurVerIndex = -1;
+    package->progids[index].VersionIndIndex = -1;
+
+    /* if we have a parent then we may be that parents CurVer */
+    if (package->progids[index].ParentIndex >= 0 && 
+        package->progids[index].ParentIndex != index)
+    {
+        int pindex = package->progids[index].ParentIndex;
+        while (package->progids[pindex].ParentIndex>= 0 && 
+               package->progids[pindex].ParentIndex != pindex)
+            pindex = package->progids[pindex].ParentIndex;
+
+        FIXME("BAD BAD need to determing if we are really the CurVer\n");
+
+        package->progids[index].CurVerIndex = pindex;
+        package->progids[pindex].VersionIndIndex = index;
+    }
+    
+    return index;
+}
+
+static INT load_given_progid(MSIPACKAGE *package, LPCWSTR progid)
+{
+    INT rc;
+    MSIRECORD *row;
+    INT i;
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','P','r','o','g','I','d','`',' ','W','H','E','R','E',' ',
+         '`','P','r','o','g','I','d','`',' ','=',' ','\'','%','s','\'',0};
+
+    if (!progid)
+        return -1;
+
+    /* check for progids already loaded */
+    for (i = 0; i < package->loaded_progids; i++)
+        if (strcmpiW(package->progids[i].ProgID,progid)==0)
+        {
+            TRACE("found progid %s at index %i\n",debugstr_w(progid), i);
+            return i;
+        }
+    
+    row = MSI_QueryGetRecord(package->db, ExecSeqQuery, progid);
+    if(!row)
+        return -1;
+
+    rc = load_progid(package, row);
+    msiobj_release(&row->hdr);
+
+    return rc;
+}
+
+static INT load_class(MSIPACKAGE* package, MSIRECORD *row)
+{
+    DWORD index = package->loaded_classes;
+    DWORD sz,i;
+    LPCWSTR buffer;
+
+    /* fill in the data */
+
+    package->loaded_classes++;
+    if (package->loaded_classes== 1)
+        package->classes = HeapAlloc(GetProcessHeap(),0,sizeof(MSICLASS));
+    else
+        package->classes = HeapReAlloc(GetProcessHeap(),0,
+            package->classes, package->loaded_classes * sizeof(MSICLASS));
+
+    memset(&package->classes[index],0,sizeof(MSICLASS));
+
+    sz = IDENTIFIER_SIZE;
+    MSI_RecordGetStringW(row, 1, package->classes[index].CLSID, &sz);
+    TRACE("loading class %s\n",debugstr_w(package->classes[index].CLSID));
+    sz = IDENTIFIER_SIZE;
+    MSI_RecordGetStringW(row, 2, package->classes[index].Context, &sz);
+    buffer = MSI_RecordGetString(row,3);
+    package->classes[index].ComponentIndex = get_loaded_component(package, 
+                    buffer);
+
+    package->classes[index].ProgIDText = load_dynamic_stringW(row,4);
+    package->classes[index].ProgIDIndex = 
+                load_given_progid(package, package->classes[index].ProgIDText);
+
+    package->classes[index].Description = load_dynamic_stringW(row,5);
+
+    buffer = MSI_RecordGetString(row,6);
+    if (buffer)
+        package->classes[index].AppIDIndex = 
+                load_given_appid(package, buffer);
+    else
+        package->classes[index].AppIDIndex = -1;
+
+    package->classes[index].FileTypeMask = load_dynamic_stringW(row,7);
+
+    if (!MSI_RecordIsNull(row,9))
+    {
+
+        INT icon_index = MSI_RecordGetInteger(row,9); 
+        LPWSTR FileName = load_dynamic_stringW(row,8);
+        LPWSTR FilePath;
+        static const WCHAR fmt[] = {'%','s',',','%','i',0};
+
+        build_icon_path(package,FileName,&FilePath);
+       
+        package->classes[index].IconPath = 
+                HeapAlloc(GetProcessHeap(),0,(strlenW(FilePath)+5)*
+                                sizeof(WCHAR));
+
+        sprintfW(package->classes[index].IconPath,fmt,FilePath,icon_index);
+
+        HeapFree(GetProcessHeap(),0,FilePath);
+        HeapFree(GetProcessHeap(),0,FileName);
+    }
+    else
+    {
+        buffer = MSI_RecordGetString(row,8);
+        if (buffer)
+            build_icon_path(package,buffer,&(package->classes[index].IconPath));
+    }
+
+    if (!MSI_RecordIsNull(row,10))
+    {
+        i = MSI_RecordGetInteger(row,10);
+        if (i != MSI_NULL_INTEGER && i > 0 &&  i < 4)
+        {
+            static const WCHAR ole2[] = {'o','l','e','2','.','d','l','l',0};
+            static const WCHAR ole32[] = {'o','l','e','3','2','.','d','l','l',0};
+
+            switch(i)
+            {
+                case 1:
+                    package->classes[index].DefInprocHandler = strdupW(ole2);
+                    break;
+                case 2:
+                    package->classes[index].DefInprocHandler32 = strdupW(ole32);
+                    break;
+                case 3:
+                    package->classes[index].DefInprocHandler = strdupW(ole2);
+                    package->classes[index].DefInprocHandler32 = strdupW(ole32);
+                    break;
+            }
+        }
+        else
+        {
+            package->classes[index].DefInprocHandler32 = load_dynamic_stringW(
+                            row, 10);
+            reduce_to_longfilename(package->classes[index].DefInprocHandler32);
+        }
+    }
+    buffer = MSI_RecordGetString(row,11);
+    deformat_string(package,buffer,&package->classes[index].Argument);
+
+    buffer = MSI_RecordGetString(row,12);
+    package->classes[index].FeatureIndex = get_loaded_feature(package,buffer);
+
+    package->classes[index].Attributes = MSI_RecordGetInteger(row,13);
+    
+    return index;
+}
+
+/*
+ * the Class table has 3 primary keys. Generally it is only 
+ * referenced through the first CLSID key. However when loading
+ * all of the classes we need to make sure we do not ignore rows
+ * with other Context and ComponentIndexs 
+ */
+static INT load_given_class(MSIPACKAGE *package, LPCWSTR classid)
+{
+    INT rc;
+    MSIRECORD *row;
+    INT i;
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','C','l','a','s','s','`',' ','W','H','E','R','E',' ',
+         '`','C','L','S','I','D','`',' ','=',' ','\'','%','s','\'',0};
+
+
+    if (!classid)
+        return -1;
+    
+    /* check for classes already loaded */
+    for (i = 0; i < package->loaded_classes; i++)
+        if (strcmpiW(package->classes[i].CLSID,classid)==0)
+        {
+            TRACE("found class %s at index %i\n",debugstr_w(classid), i);
+            return i;
+        }
+    
+    row = MSI_QueryGetRecord(package->db, ExecSeqQuery, classid);
+    if (!row)
+        return -1;
+
+    rc = load_class(package, row);
+    msiobj_release(&row->hdr);
+
+    return rc;
+}
+
+static INT load_given_extension(MSIPACKAGE *package, LPCWSTR extension);
+
+static INT load_mime(MSIPACKAGE* package, MSIRECORD *row)
+{
+    DWORD index = package->loaded_mimes;
+    DWORD sz;
+    LPCWSTR buffer;
+
+    /* fill in the data */
+
+    package->loaded_mimes++;
+    if (package->loaded_mimes== 1)
+        package->mimes= HeapAlloc(GetProcessHeap(),0,sizeof(MSIMIME));
+    else
+        package->mimes= HeapReAlloc(GetProcessHeap(),0,
+            package->mimes, package->loaded_mimes* 
+            sizeof(MSIMIME));
+
+    memset(&package->mimes[index],0,sizeof(MSIMIME));
+
+    package->mimes[index].ContentType = load_dynamic_stringW(row,1); 
+    TRACE("loading mime %s\n",debugstr_w(package->mimes[index].ContentType));
+
+    buffer = MSI_RecordGetString(row,2);
+    package->mimes[index].ExtensionIndex = load_given_extension(package,
+                    buffer);
+
+    sz = IDENTIFIER_SIZE;
+    MSI_RecordGetStringW(row,3,package->mimes[index].CLSID,&sz);
+    package->mimes[index].ClassIndex= load_given_class(package,
+                    package->mimes[index].CLSID);
+    
+    return index;
+}
+
+static INT load_given_mime(MSIPACKAGE *package, LPCWSTR mime)
+{
+    INT rc;
+    MSIRECORD *row;
+    INT i;
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','M','I','M','E','`',' ','W','H','E','R','E',' ',
+         '`','C','o','n','t','e','n','t','T','y','p','e','`',' ','=',' ',
+         '\'','%','s','\'',0};
+
+    if (!mime)
+        return -1;
+    
+    /* check for mime already loaded */
+    for (i = 0; i < package->loaded_mimes; i++)
+        if (strcmpiW(package->mimes[i].ContentType,mime)==0)
+        {
+            TRACE("found mime %s at index %i\n",debugstr_w(mime), i);
+            return i;
+        }
+    
+    row = MSI_QueryGetRecord(package->db, ExecSeqQuery, mime);
+    if (!row)
+        return -1;
+
+    rc = load_mime(package, row);
+    msiobj_release(&row->hdr);
+
+    return rc;
+}
+
+static INT load_extension(MSIPACKAGE* package, MSIRECORD *row)
+{
+    DWORD index = package->loaded_extensions;
+    DWORD sz;
+    LPCWSTR buffer;
+
+    /* fill in the data */
+
+    package->loaded_extensions++;
+    if (package->loaded_extensions == 1)
+        package->extensions = HeapAlloc(GetProcessHeap(),0,sizeof(MSIEXTENSION));
+    else
+        package->extensions = HeapReAlloc(GetProcessHeap(),0,
+            package->extensions, package->loaded_extensions* 
+            sizeof(MSIEXTENSION));
+
+    memset(&package->extensions[index],0,sizeof(MSIEXTENSION));
+
+    sz = 256;
+    MSI_RecordGetStringW(row,1,package->extensions[index].Extension,&sz);
+    TRACE("loading extension %s\n",
+                    debugstr_w(package->extensions[index].Extension));
+
+    buffer = MSI_RecordGetString(row,2);
+    package->extensions[index].ComponentIndex = 
+            get_loaded_component(package,buffer);
+
+    package->extensions[index].ProgIDText = load_dynamic_stringW(row,3);
+    package->extensions[index].ProgIDIndex = load_given_progid(package,
+                    package->extensions[index].ProgIDText);
+
+    buffer = MSI_RecordGetString(row,4);
+    package->extensions[index].MIMEIndex = load_given_mime(package,buffer);
+
+    buffer = MSI_RecordGetString(row,5);
+    package->extensions[index].FeatureIndex = 
+            get_loaded_feature(package,buffer);
+
+    return index;
+}
+
+/*
+ * While the extension table has 2 primary keys, this function is only looking
+ * at the Extension key which is what is referenced as a forign key 
+ */
+static INT load_given_extension(MSIPACKAGE *package, LPCWSTR extension)
+{
+    INT rc;
+    MSIRECORD *row;
+    INT i;
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','E','x','t','e','n','s','i','o','n','`',' ',
+         'W','H','E','R','E',' ',
+         '`','E','x','t','e','n','s','i','o','n','`',' ','=',' ',
+         '\'','%','s','\'',0};
+
+    if (!extension)
+        return -1;
+
+    /* check for extensions already loaded */
+    for (i = 0; i < package->loaded_extensions; i++)
+        if (strcmpiW(package->extensions[i].Extension,extension)==0)
+        {
+            TRACE("extension %s already loaded at %i\n",debugstr_w(extension),
+                            i);
+            return i;
+        }
+    
+    row = MSI_QueryGetRecord(package->db, ExecSeqQuery, extension);
+    if (!row)
+        return -1;
+
+    rc = load_extension(package, row);
+    msiobj_release(&row->hdr);
+
+    return rc;
+}
+
+static UINT iterate_load_verb(MSIRECORD *row, LPVOID param)
+{
+    MSIPACKAGE* package = (MSIPACKAGE*)param;
+    DWORD index = package->loaded_verbs;
+    LPCWSTR buffer;
+
+    /* fill in the data */
+
+    package->loaded_verbs++;
+    if (package->loaded_verbs == 1)
+        package->verbs = HeapAlloc(GetProcessHeap(),0,sizeof(MSIVERB));
+    else
+        package->verbs = HeapReAlloc(GetProcessHeap(),0,
+            package->verbs , package->loaded_verbs * sizeof(MSIVERB));
+
+    memset(&package->verbs[index],0,sizeof(MSIVERB));
+
+    buffer = MSI_RecordGetString(row,1);
+    package->verbs[index].ExtensionIndex = load_given_extension(package,buffer);
+    if (package->verbs[index].ExtensionIndex < 0 && buffer)
+        ERR("Verb unable to find loaded extension %s\n", debugstr_w(buffer));
+
+    package->verbs[index].Verb = load_dynamic_stringW(row,2);
+    TRACE("loading verb %s\n",debugstr_w(package->verbs[index].Verb));
+    package->verbs[index].Sequence = MSI_RecordGetInteger(row,3);
+
+    buffer = MSI_RecordGetString(row,4);
+    deformat_string(package,buffer,&package->verbs[index].Command);
+
+    buffer = MSI_RecordGetString(row,5);
+    deformat_string(package,buffer,&package->verbs[index].Argument);
+
+    /* assosiate the verb with the correct extension */
+    if (package->verbs[index].ExtensionIndex >= 0)
+    {
+        MSIEXTENSION* extension = &package->extensions[package->verbs[index].
+                ExtensionIndex];
+        int count = extension->VerbCount;
+
+        if (count >= 99)
+            FIXME("Exceeding max verb count! Increase that limit!!!\n");
+        else
+        {
+            extension->VerbCount++;
+            extension->Verbs[count] = index;
+        }
+    }
+    
+    return ERROR_SUCCESS;
+}
+
+static UINT iterate_all_classes(MSIRECORD *rec, LPVOID param)
+{
+    LPCWSTR clsid;
+    LPCWSTR context;
+    LPCWSTR buffer;
+    INT    component_index;
+    MSIPACKAGE* package =(MSIPACKAGE*)param;
+    INT i;
+    BOOL match = FALSE;
+
+    clsid = MSI_RecordGetString(rec,1);
+    context = MSI_RecordGetString(rec,2);
+    buffer = MSI_RecordGetString(rec,3);
+    component_index = get_loaded_component(package,buffer);
+
+    for (i = 0; i < package->loaded_classes; i++)
+    {
+        if (strcmpiW(clsid,package->classes[i].CLSID))
+            continue;
+        if (strcmpW(context,package->classes[i].Context))
+            continue;
+        if (component_index == package->classes[i].ComponentIndex)
+        {
+            match = TRUE;
+            break;
+        }
+    }
+    
+    if (!match)
+        load_class(package, rec);
+
+    return ERROR_SUCCESS;
+}
+
+static VOID load_all_classes(MSIPACKAGE *package)
+{
+    UINT rc = ERROR_SUCCESS;
+    MSIQUERY *view;
+
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
+         '`','C','l','a','s','s','`',0};
+
+    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
+    if (rc != ERROR_SUCCESS)
+        return;
+
+    rc = MSI_IterateRecords(view, NULL, iterate_all_classes, package);
+    msiobj_release(&view->hdr);
+}
+
+static UINT iterate_all_extensions(MSIRECORD *rec, LPVOID param)
+{
+    LPCWSTR buffer;
+    LPCWSTR extension;
+    INT    component_index;
+    MSIPACKAGE* package =(MSIPACKAGE*)param;
+    BOOL match = FALSE;
+    INT i;
+
+    extension = MSI_RecordGetString(rec,1);
+    buffer = MSI_RecordGetString(rec,2);
+    component_index = get_loaded_component(package,buffer);
+
+    for (i = 0; i < package->loaded_extensions; i++)
+    {
+        if (strcmpiW(extension,package->extensions[i].Extension))
+            continue;
+        if (component_index == package->extensions[i].ComponentIndex)
+        {
+            match = TRUE;
+            break;
+        }
+    }
+
+    if (!match)
+        load_extension(package, rec);
+
+    return ERROR_SUCCESS;
+}
+
+static VOID load_all_extensions(MSIPACKAGE *package)
+{
+    UINT rc = ERROR_SUCCESS;
+    MSIQUERY *view;
+
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','E','x','t','e','n','s','i','o','n','`',0};
+
+    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
+    if (rc != ERROR_SUCCESS)
+        return;
+
+    rc = MSI_IterateRecords(view, NULL, iterate_all_extensions, package);
+    msiobj_release(&view->hdr);
+}
+
+static UINT iterate_all_progids(MSIRECORD *rec, LPVOID param)
+{
+    LPCWSTR buffer;
+    MSIPACKAGE* package =(MSIPACKAGE*)param;
+
+    buffer = MSI_RecordGetString(rec,1);
+    load_given_progid(package,buffer);
+    return ERROR_SUCCESS;
+}
+
+static VOID load_all_progids(MSIPACKAGE *package)
+{
+    UINT rc = ERROR_SUCCESS;
+    MSIQUERY *view;
+
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','`','P','r','o','g','I','d','`',' ',
+         'F','R','O','M',' ', '`','P','r','o','g','I','d','`',0};
+
+    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
+    if (rc != ERROR_SUCCESS)
+        return;
+
+    rc = MSI_IterateRecords(view, NULL, iterate_all_progids, package);
+    msiobj_release(&view->hdr);
+}
+
+static VOID load_all_verbs(MSIPACKAGE *package)
+{
+    UINT rc = ERROR_SUCCESS;
+    MSIQUERY *view;
+
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','V','e','r','b','`',0};
+
+    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
+    if (rc != ERROR_SUCCESS)
+        return;
+
+    rc = MSI_IterateRecords(view, NULL, iterate_load_verb, package);
+    msiobj_release(&view->hdr);
+}
+
+static UINT iterate_all_mimes(MSIRECORD *rec, LPVOID param)
+{
+    LPCWSTR buffer;
+    MSIPACKAGE* package =(MSIPACKAGE*)param;
+
+    buffer = MSI_RecordGetString(rec,1);
+    load_given_mime(package,buffer);
+    return ERROR_SUCCESS;
+}
+
+static VOID load_all_mimes(MSIPACKAGE *package)
+{
+    UINT rc = ERROR_SUCCESS;
+    MSIQUERY *view;
+
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ',
+         '`','C','o','n','t','e','n','t','T','y','p','e','`',
+         ' ','F','R','O','M',' ',
+         '`','M','I','M','E','`',0};
+
+    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
+    if (rc != ERROR_SUCCESS)
+        return;
+
+    rc = MSI_IterateRecords(view, NULL, iterate_all_mimes, package);
+    msiobj_release(&view->hdr);
+}
+
+static void load_classes_and_such(MSIPACKAGE *package)
+{
+    TRACE("Loading all the class info and related tables\n");
+
+    /* check if already loaded */
+    if (package->classes || package->extensions || package->progids || 
+        package->verbs || package->mimes)
+        return;
+
+    load_all_classes(package);
+    load_all_extensions(package);
+    load_all_progids(package);
+    /* these loads must come after the other loads */
+    load_all_verbs(package);
+    load_all_mimes(package);
+}
+
+static void mark_progid_for_install(MSIPACKAGE* package, INT index)
+{
+    MSIPROGID* progid;
+    int i;
+
+    if (index < 0 || index >= package->loaded_progids)
+        return;
+
+    progid = &package->progids[index];
+
+    if (progid->InstallMe == TRUE)
+        return;
+
+    progid->InstallMe = TRUE;
+
+    /* all children if this is a parent also install */
+   for (i = 0; i < package->loaded_progids; i++)
+        if (package->progids[i].ParentIndex == index)
+            mark_progid_for_install(package,i);
+}
+
+static void mark_mime_for_install(MSIPACKAGE* package, INT index)
+{
+    MSIMIME* mime;
+
+    if (index < 0 || index >= package->loaded_mimes)
+        return;
+
+    mime = &package->mimes[index];
+
+    if (mime->InstallMe == TRUE)
+        return;
+
+    mime->InstallMe = TRUE;
+}
+
+static UINT register_appid(MSIPACKAGE *package, int appidIndex, LPCWSTR app )
+{
+    static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
+    HKEY hkey2,hkey3;
+
+    if (!package)
+        return ERROR_INVALID_HANDLE;
+
+    RegCreateKeyW(HKEY_CLASSES_ROOT,szAppID,&hkey2);
+    RegCreateKeyW(hkey2,package->appids[appidIndex].AppID,&hkey3);
+    RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)app,
+                   (strlenW(app)+1)*sizeof(WCHAR));
+
+    if (package->appids[appidIndex].RemoteServerName)
+    {
+        UINT size; 
+        static const WCHAR szRemoteServerName[] =
+             {'R','e','m','o','t','e','S','e','r','v','e','r','N','a','m','e',
+              0};
+
+        size = (strlenW(package->appids[appidIndex].RemoteServerName)+1) * 
+                sizeof(WCHAR);
+
+        RegSetValueExW(hkey3,szRemoteServerName,0,REG_SZ,
+                        (LPVOID)package->appids[appidIndex].RemoteServerName,
+                        size);
+    }
+
+    if (package->appids[appidIndex].LocalServer)
+    {
+        static const WCHAR szLocalService[] =
+             {'L','o','c','a','l','S','e','r','v','i','c','e',0};
+        UINT size;
+        size = (strlenW(package->appids[appidIndex].LocalServer)+1) * 
+                sizeof(WCHAR);
+
+        RegSetValueExW(hkey3,szLocalService,0,REG_SZ,
+                        (LPVOID)package->appids[appidIndex].LocalServer,size);
+    }
+
+    if (package->appids[appidIndex].ServiceParameters)
+    {
+        static const WCHAR szService[] =
+             {'S','e','r','v','i','c','e',
+              'P','a','r','a','m','e','t','e','r','s',0};
+        UINT size;
+        size = (strlenW(package->appids[appidIndex].ServiceParameters)+1) * 
+                sizeof(WCHAR);
+        RegSetValueExW(hkey3,szService,0,REG_SZ,
+                        (LPVOID)package->appids[appidIndex].ServiceParameters,
+                        size);
+    }
+
+    if (package->appids[appidIndex].DllSurrogate)
+    {
+        static const WCHAR szDLL[] =
+             {'D','l','l','S','u','r','r','o','g','a','t','e',0};
+        UINT size;
+        size = (strlenW(package->appids[appidIndex].DllSurrogate)+1) * 
+                sizeof(WCHAR);
+        RegSetValueExW(hkey3,szDLL,0,REG_SZ,
+                        (LPVOID)package->appids[appidIndex].DllSurrogate,size);
+    }
+
+    if (package->appids[appidIndex].ActivateAtStorage)
+    {
+        static const WCHAR szActivate[] =
+             {'A','c','t','i','v','a','t','e','A','s',
+              'S','t','o','r','a','g','e',0};
+        static const WCHAR szY[] = {'Y',0};
+
+        RegSetValueExW(hkey3,szActivate,0,REG_SZ,(LPVOID)szY,4);
+    }
+
+    if (package->appids[appidIndex].RunAsInteractiveUser)
+    {
+        static const WCHAR szRunAs[] = {'R','u','n','A','s',0};
+        static const WCHAR szUser[] = 
+             {'I','n','t','e','r','a','c','t','i','v','e',' ',
+              'U','s','e','r',0};
+
+        RegSetValueExW(hkey3,szRunAs,0,REG_SZ,(LPVOID)szUser,sizeof(szUser));
+    }
+
+    RegCloseKey(hkey3);
+    RegCloseKey(hkey2);
+    return ERROR_SUCCESS;
+}
+
+UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
+{
+    /* 
+     * Again I am assuming the words, "Whose key file represents" when referring
+     * to a Component as to meaning that Components KeyPath file
+     */
+    
+    UINT rc;
+    MSIRECORD *uirow;
+    static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
+    static const WCHAR szProgID[] = { 'P','r','o','g','I','D',0 };
+    static const WCHAR szVIProgID[] = { 'V','e','r','s','i','o','n','I','n','d','e','p','e','n','d','e','n','t','P','r','o','g','I','D',0 };
+    static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
+    static const WCHAR szSpace[] = {' ',0};
+    static const WCHAR szInprocServer32[] = {'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
+    static const WCHAR szFileType_fmt[] = {'F','i','l','e','T','y','p','e','\\','%','s','\\','%','i',0};
+    HKEY hkey,hkey2,hkey3;
+    BOOL install_on_demand = FALSE;
+    int i;
+
+    if (!package)
+        return ERROR_INVALID_HANDLE;
+
+    load_classes_and_such(package);
+    rc = RegCreateKeyW(HKEY_CLASSES_ROOT,szCLSID,&hkey);
+    if (rc != ERROR_SUCCESS)
+        return ERROR_FUNCTION_FAILED;
+
+    /* install_on_demand should be set if OLE supports install on demand OLE
+     * servers. For now i am defaulting to FALSE because i do not know how to
+     * check, and i am told our builtin OLE does not support it
+     */
+    
+    for (i = 0; i < package->loaded_classes; i++)
+    {
+        INT index,f_index;
+        DWORD size, sz;
+        LPWSTR argument;
+
+        if (package->classes[i].ComponentIndex < 0)
+        {
+            continue;
+        }
+
+        index = package->classes[i].ComponentIndex;
+        f_index = package->classes[i].FeatureIndex;
+
+        /* 
+         * yes. MSDN says that these are based on _Feature_ not on
+         * Component.  So verify the feature is to be installed
+         */
+        if ((!ACTION_VerifyFeatureForAction(package, f_index,
+                                INSTALLSTATE_LOCAL)) &&
+             !(install_on_demand && ACTION_VerifyFeatureForAction(package,
+                             f_index, INSTALLSTATE_ADVERTISED)))
+        {
+            TRACE("Skipping class %s reg due to disabled feature %s\n", 
+                            debugstr_w(package->classes[i].CLSID), 
+                            debugstr_w(package->features[f_index].Feature));
+
+            continue;
+        }
+
+        TRACE("Registering index %i  class %s\n",i,
+                        debugstr_w(package->classes[i].CLSID));
+
+        package->classes[i].Installed = TRUE;
+        if (package->classes[i].ProgIDIndex >= 0)
+            mark_progid_for_install(package, package->classes[i].ProgIDIndex);
+
+        RegCreateKeyW(hkey,package->classes[i].CLSID,&hkey2);
+
+        if (package->classes[i].Description)
+            RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)package->classes[i].
+                            Description, (strlenW(package->classes[i].
+                                     Description)+1)*sizeof(WCHAR));
+
+        RegCreateKeyW(hkey2,package->classes[i].Context,&hkey3);
+        index = get_loaded_file(package,package->components[index].KeyPath);
+
+
+        /* the context server is a short path name 
+         * except for if it is InprocServer32... 
+         */
+        if (strcmpiW(package->classes[i].Context,szInprocServer32)!=0)
+        {
+            sz = 0;
+            sz = GetShortPathNameW(package->files[index].TargetPath, NULL, 0);
+            if (sz == 0)
+            {
+                ERR("Unable to find short path for CLSID COM Server\n");
+                argument = NULL;
+            }
+            else
+            {
+                size = sz * sizeof(WCHAR);
+
+                if (package->classes[i].Argument)
+                {
+                    size += strlenW(package->classes[i].Argument) * 
+                            sizeof(WCHAR);
+                    size += sizeof(WCHAR);
+                }
+
+                argument = HeapAlloc(GetProcessHeap(), 0, size + sizeof(WCHAR));
+                GetShortPathNameW(package->files[index].TargetPath, argument, 
+                                sz);
+
+                if (package->classes[i].Argument)
+                {
+                    strcatW(argument,szSpace);
+                    strcatW(argument,package->classes[i].Argument);
+                }
+            }
+        }
+        else
+        {
+            size = lstrlenW(package->files[index].TargetPath) * sizeof(WCHAR);
+
+            if (package->classes[i].Argument)
+            {
+                size += strlenW(package->classes[i].Argument) * sizeof(WCHAR);
+                size += sizeof(WCHAR);
+            }
+
+            argument = HeapAlloc(GetProcessHeap(), 0, size + sizeof(WCHAR));
+            strcpyW(argument, package->files[index].TargetPath);
+
+            if (package->classes[i].Argument)
+            {
+                strcatW(argument,szSpace);
+                strcatW(argument,package->classes[i].Argument);
+            }
+        }
+
+        if (argument)
+        {
+            RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)argument, size);
+            HeapFree(GetProcessHeap(),0,argument);
+        }
+
+        RegCloseKey(hkey3);
+
+        if (package->classes[i].ProgIDIndex >= 0 || 
+            package->classes[i].ProgIDText)
+        {
+            LPCWSTR progid;
+
+            if (package->classes[i].ProgIDIndex >= 0)
+                progid = package->progids[
+                        package->classes[i].ProgIDIndex].ProgID;
+            else
+                progid = package->classes[i].ProgIDText;
+
+            RegCreateKeyW(hkey2,szProgID,&hkey3);
+            RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)progid,
+                            (strlenW(progid)+1) *sizeof(WCHAR));
+            RegCloseKey(hkey3);
+
+            if (package->classes[i].ProgIDIndex >= 0 &&
+                package->progids[package->classes[i].ProgIDIndex].
+                                VersionIndIndex >= 0)
+            {
+                LPWSTR viprogid = strdupW(package->progids[package->progids[
+                        package->classes[i].ProgIDIndex].VersionIndIndex].
+                        ProgID);
+                RegCreateKeyW(hkey2,szVIProgID,&hkey3);
+                RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)viprogid,
+                            (strlenW(viprogid)+1) *sizeof(WCHAR));
+                RegCloseKey(hkey3);
+                HeapFree(GetProcessHeap(), 0, viprogid);
+            }
+        }
+
+        if (package->classes[i].AppIDIndex >= 0)
+        { 
+            RegSetValueExW(hkey2,szAppID,0,REG_SZ,
+             (LPVOID)package->appids[package->classes[i].AppIDIndex].AppID,
+             (strlenW(package->appids[package->classes[i].AppIDIndex].AppID)+1)
+             *sizeof(WCHAR));
+
+            register_appid(package,package->classes[i].AppIDIndex,
+                            package->classes[i].Description);
+        }
+
+        if (package->classes[i].IconPath)
+        {
+            static const WCHAR szDefaultIcon[] = 
+                {'D','e','f','a','u','l','t','I','c','o','n',0};
+
+            RegCreateKeyW(hkey2,szDefaultIcon,&hkey3);
+
+            RegSetValueExW(hkey3,NULL,0,REG_SZ,
+                           (LPVOID)package->classes[i].IconPath,
+                           (strlenW(package->classes[i].IconPath)+1) * 
+                           sizeof(WCHAR));
+
+            RegCloseKey(hkey3);
+        }
+
+        if (package->classes[i].DefInprocHandler)
+        {
+            static const WCHAR szInproc[] =
+                {'I','n','p','r','o','c','H','a','n','d','l','e','r',0};
+
+            size = (strlenW(package->classes[i].DefInprocHandler) + 1) * 
+                    sizeof(WCHAR);
+            RegCreateKeyW(hkey2,szInproc,&hkey3);
+            RegSetValueExW(hkey3,NULL,0,REG_SZ, 
+                            (LPVOID)package->classes[i].DefInprocHandler, size);
+            RegCloseKey(hkey3);
+        }
+
+        if (package->classes[i].DefInprocHandler32)
+        {
+            static const WCHAR szInproc32[] =
+                {'I','n','p','r','o','c','H','a','n','d','l','e','r','3','2',
+                 0};
+            size = (strlenW(package->classes[i].DefInprocHandler32) + 1) * 
+                    sizeof(WCHAR);
+
+            RegCreateKeyW(hkey2,szInproc32,&hkey3);
+            RegSetValueExW(hkey3,NULL,0,REG_SZ, 
+                           (LPVOID)package->classes[i].DefInprocHandler32,size);
+            RegCloseKey(hkey3);
+        }
+        
+        RegCloseKey(hkey2);
+
+        /* if there is a FileTypeMask, register the FileType */
+        if (package->classes[i].FileTypeMask)
+        {
+            LPWSTR ptr, ptr2;
+            LPWSTR keyname;
+            INT index = 0;
+            ptr = package->classes[i].FileTypeMask;
+            while (ptr && *ptr)
+            {
+                ptr2 = strchrW(ptr,';');
+                if (ptr2)
+                    *ptr2 = 0;
+                keyname = HeapAlloc(GetProcessHeap(),0,(strlenW(szFileType_fmt)+
+