Sync to Wine-20050524:
Alexander Julliard <julliard@winehq.org>
- Added rules for building import libraries in the individual dll
  makefiles, and added support for building a .def.a static import
  library too.
Aric Stewart <aric@codeweavers.com>
- Fix a few leaking object handles.
- Correct user component publication.
- Implement MsiEnumComponentQualifiers.
- Implement Publish Components in order for MsiGetQualifiedComponent
  apis to work. Also implement MsiGetQualifiedComponent, or at least some
  of the functionality as it is supposed to install stuff if it is
  absent, which it does not do yet.
- Correct query quoting based on Mike's patch.
  Also more error messages about return codes from custom actions and
  ignore an error that we should be ignoring.
- Double terminate SZ_MULTI properly.
- ClassInfo and ExtensionInfo are also written for ADVERTISED
  components.
- Write the RegOwner and RegCompany keys as blank if they do not exist
  when doing the RegisterUser action.
- Fix quoting on queries.
- Respect '+' and '*' in WriteRegistryValues to only create the key if
  it does not already exist. Prevents overwriting values with NULL.
- We cannot internally load the files in FileCost because that action
  may be skipped or not called. So do it in CostInitialize.
- Quote the file path in SelfRegModules.
- Do not write squished null guids to the feature registration.
- Correctly use short filenames from uncompressed file sources. Also
  default feature and component install states to ABSENT instead of
  UNKNOWN.
- Correct a problem with parse_data if binary data was not in full bytes.
- More properly handle uncompressed file sources, fix the creating and
  parsing of Source Directories.
- ExecuteAction runs the whole Execute table and not just from
  InstallValidate onward.  To do this make sure we do not do the
  costing initialization work again if it is already done (by checking
  the CostingComplete Property).
- A lot of work to refine feature states, setting the state affects
  the state of all child features and also respect features that want
  to default to something other than LOCAL.
- Fix a few leaking object handles.
- Correct user component publication.
- Implement MsiEnumComponentQualifiers.
- We have a stub for MsiGetUserInfoA we should use it.
- A few small fixes.
- Add a missing msiobj_release that was resulting in a leaked object
  with each MsiCreateRecord call.
- Fix a leaking handle.
- Make MsiCollectUserInfo more internally consistent.
  Thanks to Mike McCormack.
- Fix a leaking handle in MsiConfigureProductExW.
- Implement MsiGetProductCodeW.
- Implement MsiGetUserInfoW.
- Implement MsiCollectUserInfoA/W.
- Implement MsiQueryFeatureStateW.
- Correct a leaking hkey handle.
- Expand some handling of special properties in MsiGetProductInfo.
- Fix for the return codes for the Qualified component calls. They are
  not INSTALLSTATEs but rather success values.
- Quoting fixes.
Mike McCormack <mike@codeweavers.com>
- Make sure that dialogs are only created and destroyed in a single
  thread.
- Track memory allocations in the SQL parser.
- Create the ORDER BY view in a single call.
- Simplify parsing of the FROM keyword.
- Improve parser error checking.
- Simplify parsing of select query.
- remove the unused utf8 field of an expression
- make the parse result a single assignment at top level of parsing
- abort parsing on a memory allocation failure
- Only tables can be backquoted, strings must be single quoted.
- Declare MsiExportDatabase* in the spec file, and fix a typo.
- make sure to free the string table when closing the database
- don't free szPersist in MsiOpenDatabase if it's not a string
- Avoid some non-standard str functions.
Francois Gouget <fgouget@free.fr>
- Tweak the documentation to make winapi_check happy.
Juan Lang <juan_lang@yahoo.com>
- Don't fail in RegisterFonts if the Fonts table is missing.
- Partially implement AppSearch for RegLocator-type searches.
- Turn handled errors from ERRs to WARNs or TRACEs.
Vincent Beron <vberon@mecano.gme.usherb.ca>
- Use SUBLANG_NEUTRAL for French resources.
Stefan Leichter <Stefan.Leichter@camLine.com>
- Update version resource of msi.dll to current version shipped from
  windows update.
- Added minimal implementation of MsiCreateAndVerifyInstallerDirectory.
Marcus Meissner <marcus@jet.franken.de>
- Set PhysicalMemory property from system data.
Modified: trunk/reactos/include/wine/msidefs.h
Modified: trunk/reactos/lib/msi/Makefile.in
Modified: trunk/reactos/lib/msi/action.c
Modified: trunk/reactos/lib/msi/action.h
Modified: trunk/reactos/lib/msi/appsearch.c
Modified: trunk/reactos/lib/msi/cond.tab.c
Modified: trunk/reactos/lib/msi/cond.y
Modified: trunk/reactos/lib/msi/create.c
Modified: trunk/reactos/lib/msi/custom.c
Modified: trunk/reactos/lib/msi/database.c
Modified: trunk/reactos/lib/msi/dialog.c
Modified: trunk/reactos/lib/msi/insert.c
Modified: trunk/reactos/lib/msi/msi.c
Modified: trunk/reactos/lib/msi/msi.spec
Modified: trunk/reactos/lib/msi/msi_Fr.rc
Modified: trunk/reactos/lib/msi/msipriv.h
Modified: trunk/reactos/lib/msi/msiquery.c
Modified: trunk/reactos/lib/msi/order.c
Modified: trunk/reactos/lib/msi/package.c
Modified: trunk/reactos/lib/msi/query.h
Modified: trunk/reactos/lib/msi/record.c
Modified: trunk/reactos/lib/msi/registry.c
Modified: trunk/reactos/lib/msi/sql.tab.c
Modified: trunk/reactos/lib/msi/sql.y
Modified: trunk/reactos/lib/msi/suminfo.c
Modified: trunk/reactos/lib/msi/table.c
Modified: trunk/reactos/lib/msi/tokenize.c
Modified: trunk/reactos/lib/msi/update.c
Modified: trunk/reactos/lib/msi/version.rc
Modified: trunk/reactos/lib/msi/where.c

Modified: trunk/reactos/include/wine/msidefs.h
--- trunk/reactos/include/wine/msidefs.h	2005-05-26 21:15:58 UTC (rev 15536)
+++ trunk/reactos/include/wine/msidefs.h	2005-05-26 21:55:34 UTC (rev 15537)
@@ -23,6 +23,17 @@
 extern "C" {
 #endif
 
+enum msidbFileAttributes {
+    msidbFileAttributesReadOnly = 0x00000001,
+    msidbFileAttributesHidden = 0x00000002,
+    msidbFileAttributesSystem = 0x00000004,
+    msidbFileAttributesVital = 0x00000200,
+    msidbFileAttributesChecksum = 0x00000400,
+    msidbFileAttributesPatchAdded = 0x00001000,
+    msidbFileAttributesNoncompressed = 0x00002000,
+    msidbFileAttributesCompressed = 0x00004000
+};
+        
 enum msidbDialogAttributes {
     msidbDialogAttributesVisible = 0x00000001,
     msidbDialogAttributesModal = 0x00000002,
@@ -103,6 +114,22 @@
     msidbComponentAttributes64bit = 0x00000100
 };
 
+enum msidbRegistryRoot
+{
+    msidbRegistryRootClassesRoot = 0,
+    msidbRegistryRootCurrentUser = 1,
+    msidbRegistryRootLocalMachine = 2,
+    msidbRegistryRootUsers = 3,
+};
+
+enum msidbLocatorType
+{
+    msidbLocatorTypeDirectory = 0x000,
+    msidbLocatorTypeFileName = 0x001,
+    msidbLocatorTypeRawValue = 0x002,
+    msidbLocatorType64bit = 0x010,
+};
+
 /*
  * Windows SDK braindamage alert
  *

Modified: trunk/reactos/lib/msi/Makefile.in
--- trunk/reactos/lib/msi/Makefile.in	2005-05-26 21:15:58 UTC (rev 15536)
+++ trunk/reactos/lib/msi/Makefile.in	2005-05-26 21:55:34 UTC (rev 15537)
@@ -3,6 +3,7 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = msi.dll
+IMPORTLIB = libmsi.$(IMPLIBEXT)
 IMPORTS   = shell32 cabinet oleaut32 ole32 version user32 gdi32 advapi32 kernel32
 EXTRALIBS = -luuid $(LIBUNICODE)
 

Modified: trunk/reactos/lib/msi/action.c
--- trunk/reactos/lib/msi/action.c	2005-05-26 21:15:58 UTC (rev 15536)
+++ trunk/reactos/lib/msi/action.c	2005-05-26 21:55:34 UTC (rev 15537)
@@ -99,6 +99,7 @@
 static UINT ACTION_ResolveSource(MSIPACKAGE *package);
 static UINT ACTION_ExecuteAction(MSIPACKAGE *package);
 static UINT ACTION_RegisterFonts(MSIPACKAGE *package);
+static UINT ACTION_PublishComponents(MSIPACKAGE *package);
 
  
 /*
@@ -324,7 +325,7 @@
     { szInstallServices, NULL},
     { szPatchFiles, NULL},
     { szProcessComponents, ACTION_ProcessComponents },
-    { szPublishComponents, NULL},
+    { szPublishComponents, ACTION_PublishComponents },
     { szPublishFeatures, ACTION_PublishFeatures },
     { szPublishProduct, ACTION_PublishProduct },
     { szRegisterClassInfo, ACTION_RegisterClassInfo },
@@ -380,6 +381,13 @@
         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;
@@ -598,6 +606,7 @@
     {
         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);
@@ -630,15 +639,16 @@
     MSI_ProcessMessage(package, INSTALLMESSAGE_PROGRESS, row);
     msiobj_release(&row->hdr);
 
-    msi_dialog_check_messages(package->dialog, NULL);
+    msi_dialog_check_messages(NULL);
 }
 
 static void ui_actiondata(MSIPACKAGE *package, LPCWSTR action, MSIRECORD * record)
 {
     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};
+         '`','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;
@@ -655,12 +665,14 @@
         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;
         }
 
@@ -705,8 +717,9 @@
         {'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0};
     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};
+         '`','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];
     WCHAR timet[0x100];
     UINT rc;
@@ -1005,14 +1018,14 @@
     MSIRECORD * row = 0;
     static const WCHAR ExecSeqQuery[] =
         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         'I','n','s','t','a','l','l','E','x','e','c','u','t','e',
-         'S','e','q','u','e','n','c','e',' ', 'W','H','E','R','E',' ',
-         'S','e','q','u','e','n','c','e',' ', '=',' ','%','i',0};
+         '`','I','n','s','t','a','l','l','E','x','e','c','u','t','e',
+         'S','e','q','u','e','n','c','e','`',' ', 'W','H','E','R','E',' ',
+         '`','S','e','q','u','e','n','c','e','`',' ', '=',' ','%','i',0};
 
     static const WCHAR UISeqQuery[] =
         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-	 'I','n','s','t','a','l','l','U','I','S','e','q','u','e','n','c','e',
-	 ' ', 'W','H','E','R','E',' ', 'S','e','q','u','e','n','c','e',
+     '`','I','n','s','t','a','l','l','U','I','S','e','q','u','e','n','c','e',
+     '`', ' ', 'W','H','E','R','E',' ','`','S','e','q','u','e','n','c','e','`',
 	 ' ', '=',' ','%','i',0};
 
     if (UI)
@@ -1090,18 +1103,19 @@
     UINT rc;
     static const WCHAR ExecSeqQuery[] =
         {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
-         'I','n','s','t','a','l','l','E','x','e','c','u','t','e',
-         'S','e','q','u','e','n','c','e',' ', 'W','H','E','R','E',' ',
-         'S','e','q','u','e','n','c','e',' ', '>',' ','%','i',' ',
+         '`','I','n','s','t','a','l','l','E','x','e','c','u','t','e',
+         'S','e','q','u','e','n','c','e','`',' ', 'W','H','E','R','E',' ',
+         '`','S','e','q','u','e','n','c','e','`',' ', '>',' ','%','i',' ',
          'O','R','D','E','R',' ', 'B','Y',' ',
-         'S','e','q','u','e','n','c','e',0 };
+         '`','S','e','q','u','e','n','c','e','`',0 };
     MSIRECORD * row = 0;
     static const WCHAR IVQuery[] =
-        {'S','E','L','E','C','T',' ','S','e','q','u','e','n','c','e',' ',
-         'F','R','O','M',' ','I','n','s','t','a','l','l',
-         'E','x','e','c','u','t','e','S','e','q','u','e','n','c','e',' ',
-         'W','H','E','R','E',' ','A','c','t','i','o','n',' ','=',' ','`',
-         'I','n','s','t','a','l','l','V','a','l','i','d','a','t','e','`', 0};
+        {'S','E','L','E','C','T',' ','`','S','e','q','u','e','n','c','e','`',
+         ' ', 'F','R','O','M',' ','`','I','n','s','t','a','l','l',
+         'E','x','e','c','u','t','e','S','e','q','u','e','n','c','e','`',' ',
+         'W','H','E','R','E',' ','`','A','c','t','i','o','n','`',' ','=',
+         ' ','\'', 'I','n','s','t','a','l','l',
+         'V','a','l','i','d','a','t','e','\'', 0};
     INT seq = 0;
 
 
@@ -1225,10 +1239,12 @@
     UINT rc;
     static const WCHAR ExecSeqQuery [] =
         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         'I','n','s','t','a','l','l','U','I','S','e','q','u','e','n','c','e',
-         ' ','W','H','E','R','E',' ', 'S','e','q','u','e','n','c','e',' ',
+         '`','I','n','s','t','a','l','l',
+         'U','I','S','e','q','u','e','n','c','e','`',
+         ' ','W','H','E','R','E',' ', 
+         '`','S','e','q','u','e','n','c','e','`',' ',
          '>',' ','0',' ','O','R','D','E','R',' ','B','Y',' ',
-         'S','e','q','u','e','n','c','e',0};
+         '`','S','e','q','u','e','n','c','e','`',0};
     
     rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
     
@@ -1420,7 +1436,7 @@
     if (!handled)
         handled = ACTION_HandleDialogBox(package, action, &rc);
 
-    msi_dialog_check_messages( package->dialog, NULL );
+    msi_dialog_check_messages( NULL );
 
     if (!handled)
     {
@@ -1493,9 +1509,10 @@
 static UINT ACTION_CreateFolders(MSIPACKAGE *package)
 {
     static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ','D','i','r','e','c','t','o','r','y','_',
+        {'S','E','L','E','C','T',' ',
+         '`','D','i','r','e','c','t','o','r','y','_','`',
          ' ','F','R','O','M',' ',
-         'C','r','e','a','t','e','F','o','l','d','e','r',0 };
+         '`','C','r','e','a','t','e','F','o','l','d','e','r','`',0 };
     UINT rc;
     MSIQUERY *view;
     MSIFOLDER *folder;
@@ -1606,7 +1623,7 @@
     sz = 96;       
     MSI_RecordGetStringW(row,6,package->components[index].KeyPath,&sz);
 
-    package->components[index].Installed = INSTALLSTATE_UNKNOWN;
+    package->components[index].Installed = INSTALLSTATE_ABSENT;
     package->components[index].Action = INSTALLSTATE_UNKNOWN;
     package->components[index].ActionRequest = INSTALLSTATE_UNKNOWN;
 
@@ -1620,14 +1637,18 @@
     int index = package->loaded_features;
     DWORD sz;
     static const WCHAR Query1[] = 
-        {'S','E','L','E','C','T',' ','C','o','m','p','o','n','e','n','t','_',
-         ' ','F','R','O','M',' ','F','e','a','t','u','r','e',
-         'C','o','m','p','o','n','e','n','t','s',' ','W','H','E','R','E',' ',
-         'F','e', 'a','t','u','r','e','_','=','\'','%','s','\'',0};
+        {'S','E','L','E','C','T',' ',
+         '`','C','o','m','p','o','n','e','n','t','_','`',
+         ' ','F','R','O','M',' ','`','F','e','a','t','u','r','e',
+         '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};
+         '`','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;
@@ -1673,7 +1694,7 @@
 
     package->features[index].Attributes= MSI_RecordGetInteger(row,8);
 
-    package->features[index].Installed = INSTALLSTATE_UNKNOWN;
+    package->features[index].Installed = INSTALLSTATE_ABSENT;
     package->features[index].Action = INSTALLSTATE_UNKNOWN;
     package->features[index].ActionRequest = INSTALLSTATE_UNKNOWN;
 
@@ -1712,6 +1733,7 @@
                   c_indx);
             package->features[index].Components[cnt] = c_indx;
             package->features[index].ComponentCount ++;
+            msiobj_release( &row2->hdr );
             continue;
         }
 
@@ -1751,61 +1773,6 @@
     msiobj_release(&view->hdr);
 }
 
-/*
- * I am not doing any of the costing functionality yet. 
- * Mostly looking at doing the Component and Feature loading
- *
- * The native MSI does A LOT of modification to tables here. Mostly adding
- * a lot of temporary columns to the Feature and Component tables. 
- *
- *    note: Native msi also tracks the short filename. But I am only going to
- *          track the long ones.  Also looking at this directory table
- *          it appears that the directory table does not get the parents
- *          resolved base on property only based on their entries in the 
- *          directory table.
- */
-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',' ',
-         'F','e','a','t','u','r','e',0};
-    static const WCHAR szCosting[] =
-        {'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 };
-    static const WCHAR szZero[] = { '0', 0 };
-
-    MSI_SetPropertyW(package, szCosting, szZero);
-    MSI_SetPropertyW(package, cszRootDrive , c_colon);
-
-    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);
-    msiobj_release(&view->hdr);
-
-    return ERROR_SUCCESS;
-}
-
 static UINT load_file(MSIPACKAGE* package, MSIRECORD * row)
 {
     DWORD index = package->loaded_files;
@@ -1838,8 +1805,10 @@
     HeapFree(GetProcessHeap(), 0, buffer);
 
     package->files[index].FileName = load_dynamic_stringW(row,3);
+    reduce_to_longfilename(package->files[index].FileName);
 
-    reduce_to_longfilename(package->files[index].FileName);
+    package->files[index].ShortName = load_dynamic_stringW(row,3);
+    reduce_to_shortfilename(package->files[index].ShortName);
     
     package->files[index].FileSize = MSI_RecordGetInteger(row,4);
     package->files[index].Version = load_dynamic_stringW(row, 5);
@@ -1855,15 +1824,15 @@
     return ERROR_SUCCESS;
 }
 
-static UINT ACTION_FileCost(MSIPACKAGE *package)
+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',' ',
-         'F','i','l','e',' ', 'O','R','D','E','R',' ','B','Y',' ',
-         'S','e','q','u','e','n','c','e', 0};
+         '`','F','i','l','e','`',' ', 'O','R','D','E','R',' ','B','Y',' ',
+         '`','S','e','q','u','e','n','c','e','`', 0};
 
     if (!package)
         return ERROR_INVALID_HANDLE;
@@ -1897,16 +1866,88 @@
     return ERROR_SUCCESS;
 }
 
+
+/*
+ * I am not doing any of the costing functionality yet. 
+ * Mostly looking at doing the Component and Feature loading
+ *
+ * The native MSI does A LOT of modification to tables here. Mostly adding
+ * a lot of temporary columns to the Feature and Component tables. 
+ *
+ *    note: Native msi also tracks the short filename. But I am only going to
+ *          track the long ones.  Also looking at this directory table
+ *          it appears that the directory table does not get the parents
+ *          resolved base on property only based on their entries in the 
+ *          directory table.
+ */
+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',' ',
+         '`','F','e','a','t','u','r','e','`',0};
+    static const WCHAR szCosting[] =
+        {'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 };
+    static const WCHAR szZero[] = { '0', 0 };
+    WCHAR buffer[3];
+    DWORD sz = 3;
+
+    MSI_GetPropertyW(package, szCosting, buffer, &sz);
+    if (buffer[0]=='1')
+        return ERROR_SUCCESS;
+    
+    MSI_SetPropertyW(package, szCosting, szZero);
+    MSI_SetPropertyW(package, cszRootDrive , c_colon);
+
+    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);
+    msiobj_release(&view->hdr);
+
+    load_all_files(package);
+
+    return ERROR_SUCCESS;
+}
+
+static UINT ACTION_FileCost(MSIPACKAGE *package)
+{
+    return ERROR_SUCCESS;
+}
+
+
 static INT load_folder(MSIPACKAGE *package, const WCHAR* dir)
 {
     static const WCHAR Query[] =
         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         'D','i','r','e','c', 't','o','r','y',' ','W','H','E','R','E',' ','`',
-         'D','i','r','e','c','t', 'o','r','y','`',' ','=',' ','`','%','s','`',
+         '`','D','i','r','e','c', 't','o','r','y','`',' ',
+         '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 shortname = NULL;
     MSIRECORD * row = 0;
     INT index = -1;
     DWORD i;
@@ -1972,15 +2013,16 @@
     /* for now only pick long filename versions */
     if (strchrW(targetdir,'|'))
     {
+        shortname = targetdir;
         targetdir = strchrW(targetdir,'|'); 
         *targetdir = 0;
         targetdir ++;
     }
+    /* for the sourcedir pick the short filename */
     if (srcdir && strchrW(srcdir,'|'))
     {
-        srcdir= strchrW(srcdir,'|'); 
-        *srcdir= 0;
-        srcdir ++;
+        LPWSTR p = strchrW(srcdir,'|'); 
+        *p = 0;
     }
 
     /* now check for root dirs */
@@ -1999,9 +2041,12 @@
 
     if (srcdir)
         package->folders[index].SourceDefault = strdupW(srcdir);
+    else if (shortname)
+        package->folders[index].SourceDefault = strdupW(shortname);
     else if (targetdir)
         package->folders[index].SourceDefault = strdupW(targetdir);
     HeapFree(GetProcessHeap(), 0, ptargetdir);
+        TRACE("   SourceDefault = %s\n",debugstr_w(package->folders[index].SourceDefault));
 
     parent = load_dynamic_stringW(row,2);
     if (parent) 
@@ -2105,6 +2150,7 @@
     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)
@@ -2136,6 +2182,7 @@
         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);
@@ -2201,17 +2248,25 @@
     {
         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; 
@@ -2225,12 +2280,19 @@
                         {
                             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);
     } 
 }
 
@@ -2344,10 +2406,26 @@
             BOOL feature_state = ((package->features[i].Level > 0) &&
                              (package->features[i].Level <= install_level));
 
-            if (feature_state)
+            if ((feature_state) && 
+               (package->features[i].Action == INSTALLSTATE_UNKNOWN))
             {
-                package->features[i].ActionRequest = INSTALLSTATE_LOCAL;
-                package->features[i].Action = INSTALLSTATE_LOCAL;
+                if (package->features[i].Attributes & 
+                                msidbFeatureAttributesFavorSource)
+                {
+                    package->features[i].ActionRequest = INSTALLSTATE_SOURCE;
+                    package->features[i].Action = INSTALLSTATE_SOURCE;
+                }
+                else if (package->features[i].Attributes &
+                                msidbFeatureAttributesFavorAdvertise)
+                {
+                    package->features[i].ActionRequest =INSTALLSTATE_ADVERTISED;
+                    package->features[i].Action =INSTALLSTATE_ADVERTISED;
+                }
+                else
+                {
+                    package->features[i].ActionRequest = INSTALLSTATE_LOCAL;
+                    package->features[i].Action = INSTALLSTATE_LOCAL;
+                }
             }
         }
     }
@@ -2380,6 +2458,27 @@
                     component->Action = INSTALLSTATE_LOCAL;
                     component->ActionRequest = INSTALLSTATE_LOCAL;
                 }
+                else if (feature->ActionRequest == INSTALLSTATE_SOURCE)
+                {
+                    if ((component->Action == INSTALLSTATE_UNKNOWN) ||
+                        (component->Action == INSTALLSTATE_ABSENT) ||
+                        (component->Action == INSTALLSTATE_ADVERTISED))
+                           
+                    {
+                        component->Action = INSTALLSTATE_SOURCE;
+                        component->ActionRequest = INSTALLSTATE_SOURCE;
+                    }
+                }
+                else if (feature->ActionRequest == INSTALLSTATE_ADVERTISED)
+                {
+                    if ((component->Action == INSTALLSTATE_UNKNOWN) ||
+                        (component->Action == INSTALLSTATE_ABSENT))
+                           
+                    {
+                        component->Action = INSTALLSTATE_ADVERTISED;
+                        component->ActionRequest = INSTALLSTATE_ADVERTISED;
+                    }
+                }
                 else if (feature->ActionRequest == INSTALLSTATE_ABSENT)
                 {
                     if (component->Action == INSTALLSTATE_UNKNOWN)
@@ -2415,10 +2514,10 @@
 {
     static const WCHAR ExecSeqQuery[] =
         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         'D','i','r','e','c','t','o','r','y',0};
+         '`','D','i','r','e','c','t','o','r','y','`',0};
     static const WCHAR ConditionQuery[] =
         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         'C','o','n','d','i','t','i','o','n',0};
+         '`','C','o','n','d','i','t','i','o','n','`',0};
     static const WCHAR szCosting[] =
         {'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 };
     static const WCHAR szlevel[] =
@@ -2428,7 +2527,13 @@
     MSIQUERY * view;
     DWORD i;
     LPWSTR level;
+    DWORD sz = 3;
+    WCHAR buffer[3];
 
+    MSI_GetPropertyW(package, szCosting, buffer, &sz);
+    if (buffer[0]=='1')
+        return ERROR_SUCCESS;
+
     TRACE("Building Directory properties\n");
 
     rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
@@ -2669,6 +2774,7 @@
 
     if (the_file == INVALID_HANDLE_VALUE)
     {
+        ERR("Unable to create file %s\n",debugstr_w(source));
         rc = ERROR_FUNCTION_FAILED;
         goto end;
     }
@@ -2771,7 +2877,7 @@
         LPWSTR tracknametmp;
         static const WCHAR tmpprefix[] = {'C','A','B','T','M','P','_',0};
        
-        if (data->file_name && strcmp(data->file_name,pfdin->psz1))
+        if (data->file_name && lstrcmpiA(data->file_name,pfdin->psz1))
                 return 0;
         
         file = cabinet_alloc((len+1)*sizeof(char));
@@ -2884,8 +2990,8 @@
     return ret;
 }
 
-static UINT ready_media_for_file(MSIPACKAGE *package, UINT sequence, 
-                                 WCHAR* path, WCHAR* file)
+static UINT ready_media_for_file(MSIPACKAGE *package, WCHAR* path, 
+                                 MSIFILE* file)
 {
     UINT rc;
     MSIQUERY * view;
@@ -2893,25 +2999,31 @@
     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};
+         '`','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 (sequence <= last_sequence)
+    if (file->Attributes & msidbFileAttributesNoncompressed)
     {
-        TRACE("Media already ready (%u, %u)\n",sequence,last_sequence);
-        /*extract_a_cabinet_file(package, source,path,file); */
+        TRACE("Uncompressed File, no media to ready.\n");
         return ERROR_SUCCESS;
     }
 
-    sprintfW(Query,ExecSeqQuery,sequence);
+    if (file->Sequence <= last_sequence)
+    {
+        TRACE("Media already ready (%u, %u)\n",file->Sequence,last_sequence);
+        /*extract_a_cabinet_file(package, source,path,file->File); */
+        return ERROR_SUCCESS;
+    }
 
+    sprintfW(Query,ExecSeqQuery,file->Sequence);
+
     rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
     if (rc != ERROR_SUCCESS)
         return rc;
@@ -3038,12 +3150,10 @@
         if ((file->State == 1) || (file->State == 2))
         {
             LPWSTR p;
-            INT len;
             MSICOMPONENT* comp = NULL;
 
             TRACE("Installing %s\n",debugstr_w(file->File));
-            rc = ready_media_for_file(package,file->Sequence,path_to_source,
-                            file->File);
+            rc = ready_media_for_file(package, path_to_source, file);
             /* 
              * WARNING!
              * our file table could change here because a new temp file
@@ -3068,12 +3178,19 @@
             HeapFree(GetProcessHeap(),0,file->TargetPath);
 
             file->TargetPath = build_directory_name(2, p, file->FileName);
+            HeapFree(GetProcessHeap(),0,p);
 
-            len = strlenW(path_to_source) + strlenW(file->File) + 2;
-            file->SourcePath = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
-            strcpyW(file->SourcePath, path_to_source);
-            strcatW(file->SourcePath, file->File);
+            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));
 
@@ -3088,16 +3205,26 @@
             msiobj_release( &uirow->hdr );
             ui_progress(package,2,file->FileSize,0,0);
 
-            if (!MoveFileW(file->SourcePath,file->TargetPath))
+            
+            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 file (%s -> %s) (error %d)\n",
+                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)
                 {
-                    CopyFileW(file->SourcePath,file->TargetPath,FALSE);
-                    DeleteFileW(file->SourcePath);
+                    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)
@@ -3105,14 +3232,17 @@
                     ERR("Source File Not Found!  Continuing\n");
                     rc = 0;
                 }
-                else
+                else if (file->Attributes & msidbFileAttributesVital)
                 {
-                    ERR("Ignoring Error and continuing...\n");
+                    ERR("Ignoring Error and continuing (nonvital file)...\n");
                     rc = 0;
                 }
             }
             else
+            {
                 file->State = 4;
+                rc = ERROR_SUCCESS;
+            }
         }
     }
 
@@ -3151,7 +3281,7 @@
     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};
+         '`','D','u','p','l','i','c','a','t','e','F','i','l','e','`',0};
 
     if (!package)
         return ERROR_INVALID_HANDLE;
@@ -3304,21 +3434,35 @@
         {
             LPWSTR ptr;
             CHAR byte[5];
-            LPWSTR deformated;
+            LPWSTR deformated = NULL;
             int count;
 
             deformat_string(package, &value[2], &deformated);
 
             /* binary value type */
-            ptr = deformated; 
-            *type=REG_BINARY;
-            *size = strlenW(ptr)/2;
+            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;
@@ -3395,7 +3539,7 @@
     MSIRECORD * row = 0;
     static const WCHAR ExecSeqQuery[] =
         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         'R','e','g','i','s','t','r','y',0 };
+         '`','R','e','g','i','s','t','r','y','`',0 };
 
     if (!package)
         return ERROR_INVALID_HANDLE;
@@ -3438,6 +3582,7 @@
         MSIRECORD * uirow;
         LPWSTR uikey;
         INT   root;
+        BOOL check_first = FALSE;
 
         rc = MSI_ViewFetch(view,&row);
         if (rc != ERROR_SUCCESS)
@@ -3483,6 +3628,7 @@
             {
                 HeapFree(GetProcessHeap(),0,name);
                 name = NULL;
+                check_first = TRUE;
             }
         }
 
@@ -3545,9 +3691,33 @@
 
         deformat_string(package, name, &deformated);
 
-        TRACE("Setting value %s\n",debugstr_w(deformated));
-        RegSetValueExW(hkey, deformated, 0, type, value_data, size);
+        /* 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);
@@ -3589,7 +3759,7 @@
     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};
+         '`','R','e','g','i','s','t','r','y','`',0};
     UINT rc;
     MSIQUERY * view;
     MSIRECORD * row = 0;
@@ -3629,6 +3799,14 @@
         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;
 }
 
@@ -3639,7 +3817,7 @@
     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};
+         '`','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};
 
@@ -3708,8 +3886,9 @@
         LPWSTR key,deformated,buffer,name,deformated_name;
         static const WCHAR ExecSeqQuery[] =
             {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-             'R','e','g','i','s','t','r','y',' ','W','H','E','R','E',' ',
-             'R','e','g','i','s','t','r','y',' ','=',' ' ,'`','%','s','`',0 };
+             '`','R','e','g','i','s','t','r','y','`',' ',
+             'W','H','E','R','E',' ', '`','R','e','g','i','s','t','r','y','`',
+             ' ','=',' ' ,'\'','%','s','\'',0 };
         static const WCHAR fmt[]={'%','0','2','i',':','\\','%','s','\\',0};
         static const WCHAR fmt2[]=
             {'%','0','2','i',':','\\','%','s','\\','%','s',0};
@@ -3941,9 +4120,6 @@
             MSIRECORD * uirow;
 
             squash_guid(package->components[i].ComponentId,squished_cc);
-            rc = RegCreateKeyW(hkey,squished_cc,&hkey2);
-            if (rc != ERROR_SUCCESS)
-                continue;
            
             keypath = resolve_keypath(package,i);
             package->components[i].FullKeypath = keypath;
@@ -3951,8 +4127,9 @@
             /* do the refcounting */
             ACTION_RefCountComponent( package, i);
 
-            TRACE("Component %s, Keypath=%s, RefCount=%i\n", 
-                            debugstr_w(package->components[i].Component), 
+            TRACE("Component %s (%s), Keypath=%s, RefCount=%i\n", 
+                            debugstr_w(package->components[i].Component),
+                            debugstr_w(squished_cc),
                             debugstr_w(package->components[i].FullKeypath), 
                             package->components[i].RefCount);
             /*
@@ -3962,6 +4139,10 @@
             if (ACTION_VerifyComponentForAction(package, i,
                                     INSTALLSTATE_LOCAL))
             {
+                rc = RegCreateKeyW(hkey,squished_cc,&hkey2);
+                if (rc != ERROR_SUCCESS)
+                    continue;
+
                 if (keypath)
                 {
                     RegSetValueExW(hkey2,squished_pc,0,REG_SZ,(LPVOID)keypath,
@@ -3996,6 +4177,11 @@
                                     INSTALLSTATE_ABSENT))
             {
                 DWORD res;
+
[truncated at 1000 lines; 12545 more skipped]