Sync to Wine-20050830:
Francois Gouget <fgouget@free.fr>
- Change some Dll* functions so they are exported by name like on
  Windows.
  Update the documentation accordingly.
Johan Dahlin <jdahlin@async.com.br>
- Implemented MsiSetComponentState*.
- Added stubs for MsiSetComponentStateA and MsiSetComponentStateW.
- Added a null check for component.
Alexandre Julliard <julliard@winehq.org>
- Don't prefix the functions DllCanUnloadNow, DllGetClassObject and
  Dll(Un)RegisterServer with the dll name so that the compiler can check
  the prototypes.
Vincent Beron <vberon@mecano.gme.usherb.ca>
- Correct mismatches between spec files and comments about export
  number.
Aric Stewart <aric@codeweavers.com>
- Display the correct text string in the action text field for the
  dialog boxes. Also the string should be deformatted.
- Make index INT not UINT because it can be -1.
- Fixed a memory overflow and leak identified by Mike McCormack.
- Add some body to ResolveSource because it is possible to need it when
  an install is begun but the media is not in the drive, such as in
  install-on-demand cases.
- The file name used in the ui messages is the target name not the
  source name.
Yuri Kozlov <kozlov.y@gmail.com>
- Remove duplicate declaration of MSI_SetPropertyW.
Mike McCormack <mike@codeweavers.com>
- Handle loading strings over 64k from the string table.
- build a standard Wine list of folders instead of using an array
- use folder pointers instead of array indexes
- build a standard Wine list of files instead of using an array
- use file pointers instead of array indexes
- build a standard Wine list of features instead of using an array
- use feature pointers instead of array indexes
- build a standard Wine list of components instead of using an array
- use component pointers instead of array indexes
- Store the component information in a standard Wine list.
- Add include guard to header and make functions extern.
- build a standard Wine list of extensions instead of using an array
- use extension pointers instead of array indexes
- build a standard Wine list of appids instead of using an array
- use appid pointers instead of array indexes
- build a standard Wine list of mime types instead of using an array
- use mime type pointers instead of array indexes
- Add the allocated mime type to the mime type list.
- build a standard Wine list of classes instead of using an array
- use class pointers instead of array indexes
- Fix a small bug introduced when converting appids to a list.
- Implement MsiModifyView (MSIMODIFY_INSERT_TEMPORARY).
- Better stub for MsiViewGetError.
- Don't dereference variables in a trace.
- the combination of all table keys must be unique, not each key
- MsiViewExecute may not be called before MsiModifyView
- Make sure to save the result calculated in ACTION_UpdateInstallStates.
Steven Edwards <steven_ed4153@yahoo.com>
- Add real stub for MsiConfigureFeatureW.
Modified: trunk/reactos/lib/msi/action.c
Modified: trunk/reactos/lib/msi/action.h
Modified: trunk/reactos/lib/msi/classes.c
Modified: trunk/reactos/lib/msi/create.c
Modified: trunk/reactos/lib/msi/custom.c
Modified: trunk/reactos/lib/msi/delete.c
Modified: trunk/reactos/lib/msi/events.c
Modified: trunk/reactos/lib/msi/files.c
Modified: trunk/reactos/lib/msi/format.c
Modified: trunk/reactos/lib/msi/helpers.c
Modified: trunk/reactos/lib/msi/insert.c
Modified: trunk/reactos/lib/msi/install.c
Modified: trunk/reactos/lib/msi/msi.c
Modified: trunk/reactos/lib/msi/msi.spec
Modified: trunk/reactos/lib/msi/msipriv.h
Modified: trunk/reactos/lib/msi/msiquery.c
Modified: trunk/reactos/lib/msi/package.c
Modified: trunk/reactos/lib/msi/regsvr.c
Modified: trunk/reactos/lib/msi/select.c
Modified: trunk/reactos/lib/msi/table.c
Modified: trunk/reactos/w32api/include/msi.h
Modified: trunk/reactos/w32api/include/msiquery.h

Modified: trunk/reactos/lib/msi/action.c
--- trunk/reactos/lib/msi/action.c	2005-09-05 21:19:23 UTC (rev 17671)
+++ trunk/reactos/lib/msi/action.c	2005-09-05 21:34:19 UTC (rev 17672)
@@ -379,6 +379,7 @@
     WCHAR timet[0x100];
     MSIRECORD * row = 0;
     LPCWSTR ActionText;
+    LPWSTR deformated;
 
     GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);
 
@@ -387,8 +388,10 @@
         return;
 
     ActionText = MSI_RecordGetString(row,2);
+    deformat_string(package, ActionText, &deformated);
 
-    sprintfW(message,template_s,timet,action,ActionText);
+    sprintfW(message,template_s,timet,action,deformated);
+    ce_actiontext(package, deformated);
     msiobj_release(&row->hdr);
 
     row = MSI_CreateRecord(1);
@@ -396,6 +399,7 @@
  
     MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONSTART, row);
     msiobj_release(&row->hdr);
+    HeapFree(GetProcessHeap(),0,deformated);
 }
 
 static void ui_actioninfo(MSIPACKAGE *package, LPCWSTR action, BOOL start, 
@@ -799,7 +803,6 @@
     {
         if (strcmpW(StandardActions[i].action, action)==0)
         {
-            ce_actiontext(package, action);
             if (!run)
             {
                 ui_actioninfo(package, action, TRUE, 0);
@@ -965,71 +968,80 @@
     return rc;
 }
 
-static int load_component(MSIPACKAGE* package, MSIRECORD * row)
+static MSICOMPONENT* load_component( MSIRECORD * row )
 {
-    int index = package->loaded_components;
+    MSICOMPONENT *comp;
     DWORD sz;
 
+    comp = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MSICOMPONENT) );
+    if (!comp)
+        return comp;
+
     /* fill in the data */
-
-    package->loaded_components++;
-    if (package->loaded_components == 1)
-        package->components = HeapAlloc(GetProcessHeap(),0,
-                                        sizeof(MSICOMPONENT));
-    else
-        package->components = HeapReAlloc(GetProcessHeap(),0,
-            package->components, package->loaded_components * 
-            sizeof(MSICOMPONENT));
-
-    memset(&package->components[index],0,sizeof(MSICOMPONENT));
-
     sz = IDENTIFIER_SIZE;       
-    MSI_RecordGetStringW(row,1,package->components[index].Component,&sz);
+    MSI_RecordGetStringW(row,1,comp->Component,&sz);
 
     TRACE("Loading Component %s\n",
-           debugstr_w(package->components[index].Component));
+           debugstr_w(comp->Component));
 
     sz = 0x100;
     if (!MSI_RecordIsNull(row,2))
-        MSI_RecordGetStringW(row,2,package->components[index].ComponentId,&sz);
+        MSI_RecordGetStringW(row,2,comp->ComponentId,&sz);
             
     sz = IDENTIFIER_SIZE;       
-    MSI_RecordGetStringW(row,3,package->components[index].Directory,&sz);
+    MSI_RecordGetStringW(row,3,comp->Directory,&sz);
 
-    package->components[index].Attributes = MSI_RecordGetInteger(row,4);
+    comp->Attributes = MSI_RecordGetInteger(row,4);
 
     sz = 0x100;       
-    MSI_RecordGetStringW(row,5,package->components[index].Condition,&sz);
+    MSI_RecordGetStringW(row,5,comp->Condition,&sz);
 
     sz = IDENTIFIER_SIZE;       
-    MSI_RecordGetStringW(row,6,package->components[index].KeyPath,&sz);
+    MSI_RecordGetStringW(row,6,comp->KeyPath,&sz);
 
-    package->components[index].Installed = INSTALLSTATE_ABSENT;
-    package->components[index].Action = INSTALLSTATE_UNKNOWN;
-    package->components[index].ActionRequest = INSTALLSTATE_UNKNOWN;
+    comp->Installed = INSTALLSTATE_ABSENT;
+    comp->Action = INSTALLSTATE_UNKNOWN;
+    comp->ActionRequest = INSTALLSTATE_UNKNOWN;
 
-    package->components[index].Enabled = TRUE;
+    comp->Enabled = TRUE;
 
-    return index;
+    return comp;
 }
 
 typedef struct {
     MSIPACKAGE *package;
-    INT index;
-    INT cnt;
+    MSIFEATURE *feature;
 } _ilfs;
 
-static UINT iterate_component_check(MSIRECORD *row, LPVOID param)
+static UINT add_feature_component( MSIFEATURE *feature, MSICOMPONENT *comp )
 {
+    ComponentList *cl;
+
+    cl = HeapAlloc( GetProcessHeap(), 0, sizeof (*cl) );
+    if ( !cl )
+        return ERROR_NOT_ENOUGH_MEMORY;
+    cl->component = comp;
+    list_add_tail( &feature->Components, &cl->entry );
+
+    return ERROR_SUCCESS;
+}
+
+static UINT iterate_component_check( MSIRECORD *row, LPVOID param )
+{
     _ilfs* ilfs= (_ilfs*)param;
-    INT c_indx;
+    MSIPACKAGE *package = ilfs->package;
+    MSIFEATURE *feature = ilfs->feature;
+    MSICOMPONENT *comp;
 
-    c_indx = load_component(ilfs->package,row);
+    comp = load_component( row );
+    if (!comp)
+        return ERROR_FUNCTION_FAILED;
 
-    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);
+    list_add_tail( &package->components, &comp->entry );
+    add_feature_component( feature, comp );
 
+    TRACE("Loaded new component %p\n", comp);
+
     return ERROR_SUCCESS;
 }
 
@@ -1038,8 +1050,7 @@
     _ilfs* ilfs= (_ilfs*)param;
     LPCWSTR component;
     DWORD rc;
-    INT c_indx;
-    INT cnt = ilfs->package->features[ilfs->index].ComponentCount;
+    MSICOMPONENT *comp;
     MSIQUERY * view;
     static const WCHAR Query[] = 
         {'S','E','L','E','C','T',' ','*',' ','F','R', 'O','M',' ', 
@@ -1051,13 +1062,11 @@
     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)
+    comp = get_loaded_component( ilfs->package, component );
+    if (comp)
     {
-        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 ++;
+        TRACE("Component %s already loaded\n", debugstr_w(component) );
+        add_feature_component( ilfs->feature, comp );
         return ERROR_SUCCESS;
     }
 
@@ -1065,7 +1074,6 @@
     if (rc != ERROR_SUCCESS)
         return ERROR_SUCCESS;
 
-    ilfs->cnt = cnt;
     rc = MSI_IterateRecords(view, NULL, iterate_component_check, ilfs);
     msiobj_release( &view->hdr );
 
@@ -1075,7 +1083,7 @@
 static UINT load_feature(MSIRECORD * row, LPVOID param)
 {
     MSIPACKAGE* package = (MSIPACKAGE*)param;
-    int index = package->loaded_features;
+    MSIFEATURE* feature;
     DWORD sz;
     static const WCHAR Query1[] = 
         {'S','E','L','E','C','T',' ',
@@ -1088,59 +1096,57 @@
     UINT    rc;
     _ilfs ilfs;
 
-    ilfs.package = package;
-    ilfs.index = index;
-
     /* fill in the data */
 
-    package->loaded_features ++;
-    if (package->loaded_features == 1)
-        package->features = HeapAlloc(GetProcessHeap(),0,sizeof(MSIFEATURE));
-    else
-        package->features = HeapReAlloc(GetProcessHeap(),0,package->features,
-                                package->loaded_features * sizeof(MSIFEATURE));
+    feature = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (MSIFEATURE) );
+    if (!feature)
+        return ERROR_NOT_ENOUGH_MEMORY;
 
-    memset(&package->features[index],0,sizeof(MSIFEATURE));
+    list_init( &feature->Components );
     
     sz = IDENTIFIER_SIZE;       
-    MSI_RecordGetStringW(row,1,package->features[index].Feature,&sz);
+    MSI_RecordGetStringW(row,1,feature->Feature,&sz);
 
-    TRACE("Loading feature %s\n",debugstr_w(package->features[index].Feature));
+    TRACE("Loading feature %s\n",debugstr_w(feature->Feature));
 
     sz = IDENTIFIER_SIZE;
     if (!MSI_RecordIsNull(row,2))
-        MSI_RecordGetStringW(row,2,package->features[index].Feature_Parent,&sz);
+        MSI_RecordGetStringW(row,2,feature->Feature_Parent,&sz);
 
     sz = 0x100;
-     if (!MSI_RecordIsNull(row,3))
-        MSI_RecordGetStringW(row,3,package->features[index].Title,&sz);
+    if (!MSI_RecordIsNull(row,3))
+        MSI_RecordGetStringW(row,3,feature->Title,&sz);
 
-     sz = 0x100;
-     if (!MSI_RecordIsNull(row,4))
-        MSI_RecordGetStringW(row,4,package->features[index].Description,&sz);
+    sz = 0x100;
+    if (!MSI_RecordIsNull(row,4))
+        MSI_RecordGetStringW(row,4,feature->Description,&sz);
 
     if (!MSI_RecordIsNull(row,5))
-        package->features[index].Display = MSI_RecordGetInteger(row,5);
+        feature->Display = MSI_RecordGetInteger(row,5);
   
-    package->features[index].Level= MSI_RecordGetInteger(row,6);
+    feature->Level= MSI_RecordGetInteger(row,6);
 
-     sz = IDENTIFIER_SIZE;
-     if (!MSI_RecordIsNull(row,7))
-        MSI_RecordGetStringW(row,7,package->features[index].Directory,&sz);
+    sz = IDENTIFIER_SIZE;
+    if (!MSI_RecordIsNull(row,7))
+        MSI_RecordGetStringW(row,7,feature->Directory,&sz);
 
-    package->features[index].Attributes= MSI_RecordGetInteger(row,8);
+    feature->Attributes = MSI_RecordGetInteger(row,8);
 
-    package->features[index].Installed = INSTALLSTATE_ABSENT;
-    package->features[index].Action = INSTALLSTATE_UNKNOWN;
-    package->features[index].ActionRequest = INSTALLSTATE_UNKNOWN;
+    feature->Installed = INSTALLSTATE_ABSENT;
+    feature->Action = INSTALLSTATE_UNKNOWN;
+    feature->ActionRequest = INSTALLSTATE_UNKNOWN;
 
+    list_add_tail( &package->features, &feature->entry );
+
     /* load feature components */
 
-    rc = MSI_OpenQuery(package->db, &view, Query1, 
-                    package->features[index].Feature);
+    rc = MSI_OpenQuery( package->db, &view, Query1, feature->Feature );
     if (rc != ERROR_SUCCESS)
         return ERROR_SUCCESS;
 
+    ilfs.package = package;
+    ilfs.feature = feature;
+
     MSI_IterateRecords(view, NULL, iterate_load_featurecomponents , &ilfs);
     msiobj_release(&view->hdr);
 
@@ -1150,45 +1156,41 @@
 static UINT load_file(MSIRECORD *row, LPVOID param)
 {
     MSIPACKAGE* package = (MSIPACKAGE*)param;
-    DWORD index = package->loaded_files;
     LPCWSTR component;
+    MSIFILE *file;
 
     /* fill in the data */
 
-    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));
+    file = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (MSIFILE) );
+    if (!file)
+        return ERROR_NOT_ENOUGH_MEMORY;
  
-    package->files[index].File = load_dynamic_stringW(row, 1);
+    file->File = load_dynamic_stringW( row, 1 );
 
-    component = MSI_RecordGetString(row, 2);
-    package->files[index].ComponentIndex = get_loaded_component(package,
-                    component);
+    component = MSI_RecordGetString( row, 2 );
+    file->Component = get_loaded_component( package, component );
 
-    if (package->files[index].ComponentIndex == -1)
+    if (!file->Component)
         ERR("Unfound Component %s\n",debugstr_w(component));
 
-    package->files[index].FileName = load_dynamic_stringW(row,3);
-    reduce_to_longfilename(package->files[index].FileName);
+    file->FileName = load_dynamic_stringW( row, 3 );
+    reduce_to_longfilename( file->FileName );
 
-    package->files[index].ShortName = load_dynamic_stringW(row,3);
-    reduce_to_shortfilename(package->files[index].ShortName);
+    file->ShortName = load_dynamic_stringW( row, 3 );
+    reduce_to_shortfilename( file->ShortName );
     
-    package->files[index].FileSize = MSI_RecordGetInteger(row,4);
-    package->files[index].Version = load_dynamic_stringW(row, 5);
-    package->files[index].Language = load_dynamic_stringW(row, 6);
-    package->files[index].Attributes= MSI_RecordGetInteger(row,7);
-    package->files[index].Sequence= MSI_RecordGetInteger(row,8);
+    file->FileSize = MSI_RecordGetInteger( row, 4 );
+    file->Version = load_dynamic_stringW( row, 5 );
+    file->Language = load_dynamic_stringW( row, 6 );
+    file->Attributes = MSI_RecordGetInteger( row, 7 );
+    file->Sequence = MSI_RecordGetInteger( row, 8 );
 
-    package->files[index].Temporary = FALSE;
-    package->files[index].State = 0;
+    file->Temporary = FALSE;
+    file->State = 0;
 
-    TRACE("File Loaded (%s)\n",debugstr_w(package->files[index].File));  
+    TRACE("File Loaded (%s)\n",debugstr_w(file->File));  
+
+    list_add_tail( &package->files, &file->entry );
  
     return ERROR_SUCCESS;
 }
@@ -1292,7 +1294,7 @@
 }
 
 
-static INT load_folder(MSIPACKAGE *package, const WCHAR* dir)
+static MSIFOLDER *load_folder( MSIPACKAGE *package, LPCWSTR dir )
 {
     static const WCHAR Query[] =
         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
@@ -1304,38 +1306,25 @@
     LPCWSTR parent;
     LPWSTR shortname = NULL;
     MSIRECORD * row = 0;
-    INT index = -1;
-    DWORD i;
+    MSIFOLDER *folder;
 
     TRACE("Looking for dir %s\n",debugstr_w(dir));
 
-    for (i = 0; i < package->loaded_folders; i++)
-    {
-        if (strcmpW(package->folders[i].Directory,dir)==0)
-        {
-            TRACE(" %s retuning on index %lu\n",debugstr_w(dir),i);
-            return i;
-        }
-    }
+    folder = get_loaded_folder( package, dir );
+    if (folder)
+        return folder;
 
     TRACE("Working to load %s\n",debugstr_w(dir));
 
-    index = package->loaded_folders++;
-    if (package->loaded_folders==1)
-        package->folders = HeapAlloc(GetProcessHeap(),0,
-                                        sizeof(MSIFOLDER));
-    else
-        package->folders= HeapReAlloc(GetProcessHeap(),0,
-            package->folders, package->loaded_folders* 
-            sizeof(MSIFOLDER));
+    folder = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (MSIFOLDER) );
+    if (!folder)
+        return NULL;
 
-    memset(&package->folders[index],0,sizeof(MSIFOLDER));
+    folder->Directory = strdupW(dir);
 
-    package->folders[index].Directory = strdupW(dir);
-
     row = MSI_QueryGetRecord(package->db, Query, dir);
     if (!row)
-        return -1;
+        return NULL;
 
     ptargetdir = targetdir = load_dynamic_stringW(row,3);
 
@@ -1371,73 +1360,78 @@
     if (targetdir)
     {
         TRACE("   TargetDefault = %s\n",debugstr_w(targetdir));
-        HeapFree(GetProcessHeap(),0, package->folders[index].TargetDefault);
-        package->folders[index].TargetDefault = strdupW(targetdir);
+        HeapFree(GetProcessHeap(),0, folder->TargetDefault);
+        folder->TargetDefault = strdupW(targetdir);
     }
 
     if (srcdir)
-        package->folders[index].SourceDefault = strdupW(srcdir);
+        folder->SourceDefault = strdupW(srcdir);
     else if (shortname)
-        package->folders[index].SourceDefault = strdupW(shortname);
+        folder->SourceDefault = strdupW(shortname);
     else if (targetdir)
-        package->folders[index].SourceDefault = strdupW(targetdir);
+        folder->SourceDefault = strdupW(targetdir);
     HeapFree(GetProcessHeap(), 0, ptargetdir);
-        TRACE("   SourceDefault = %s\n",debugstr_w(package->folders[index].SourceDefault));
+        TRACE("   SourceDefault = %s\n", debugstr_w( folder->SourceDefault ));
 
     parent = MSI_RecordGetString(row,2);
     if (parent) 
     {
-        i = load_folder(package,parent);
-        package->folders[index].ParentIndex = i;
-        TRACE("Parent is index %i... %s %s\n",
-                    package->folders[index].ParentIndex,
-        debugstr_w(package->folders[package->folders[index].ParentIndex].Directory),
-                    debugstr_w(parent));
+        folder->Parent = load_folder( package, parent );
+        if ( folder->Parent )
+            TRACE("loaded parent %p %s\n", folder->Parent,
+                  debugstr_w(folder->Parent->Directory));
+        else
+            ERR("failed to load parent folder %s\n", debugstr_w(parent));
     }
-    else
-        package->folders[index].ParentIndex = -2;
 
-    package->folders[index].Property = load_dynamic_property(package, dir,NULL);
+    folder->Property = load_dynamic_property( package, dir, NULL );
 
     msiobj_release(&row->hdr);
-    TRACE(" %s retuning on index %i\n",debugstr_w(dir),index);
-    return index;
+
+    list_add_tail( &package->folders, &folder->entry );
+
+    TRACE("%s returning %p\n",debugstr_w(dir),folder);
+
+    return folder;
 }
 
 /* scan for and update current install states */
 static void ACTION_UpdateInstallStates(MSIPACKAGE *package)
 {
-    int i;
+    MSICOMPONENT *comp;
+    MSIFEATURE *feature;
 
-    for (i = 0; i < package->loaded_components; i++)
+    LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
     {
         INSTALLSTATE res;
-        res = MsiGetComponentPathW(package->ProductCode, 
-                        package->components[i].ComponentId , NULL, NULL);
+        res = MsiGetComponentPathW( package->ProductCode, 
+                                    comp->ComponentId, NULL, NULL);
         if (res < 0)
             res = INSTALLSTATE_ABSENT;
-        package->components[i].Installed = res;
+        comp->Installed = res;
     }
 
-    for (i = 0; i < package->loaded_features; i++)
+    LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
     {
+        ComponentList *cl;
         INSTALLSTATE res = -10;
-        int j;
-        for (j = 0; j < package->features[i].ComponentCount; j++)
+
+        LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
         {
-            MSICOMPONENT* component = &package->components[package->features[i].
-                                                           Components[j]];
+            comp= cl->component;
+
             if (res == -10)
-                res = component->Installed;
+                res = comp->Installed;
             else
             {
-                if (res == component->Installed)
+                if (res == comp->Installed)
                     continue;
 
-                if (res != component->Installed)
+                if (res != comp->Installed)
                         res = INSTALLSTATE_INCOMPLETE;
             }
         }
+        feature->Installed = res;
     }
 }
 
@@ -1446,19 +1440,19 @@
 {
     static const WCHAR all[]={'A','L','L',0};
     LPWSTR override = NULL;
-    INT i;
     BOOL rc = FALSE;
+    MSIFEATURE *feature;
 
     override = load_dynamic_property(package, property, NULL);
     if (override)
     {
         rc = TRUE;
-        for(i = 0; i < package->loaded_features; i++)
+        LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
         {
             if (strcmpiW(override,all)==0)
             {
-                package->features[i].ActionRequest= state;
-                package->features[i].Action = state;
+                feature->ActionRequest= state;
+                feature->Action = state;
             }
             else
             {
@@ -1468,12 +1462,11 @@
                 while (ptr)
                 {
                     if ((ptr2 && 
-                        strncmpW(ptr,package->features[i].Feature, ptr2-ptr)==0)
-                        || (!ptr2 &&
-                        strcmpW(ptr,package->features[i].Feature)==0))
+                        strncmpW(ptr,feature->Feature, ptr2-ptr)==0)
+                        || (!ptr2 && strcmpW(ptr,feature->Feature)==0))
                     {
-                        package->features[i].ActionRequest= state;
-                        package->features[i].Action = state;
+                        feature->ActionRequest= state;
+                        feature->Action = state;
                         break;
                     }
                     if (ptr2)
@@ -1496,8 +1489,6 @@
 {
     LPWSTR level;
     INT install_level;
-    DWORD i;
-    INT j;
     static const WCHAR szlevel[] =
         {'I','N','S','T','A','L','L','L','E','V','E','L',0};
     static const WCHAR szAddLocal[] =
@@ -1505,7 +1496,10 @@
     static const WCHAR szRemove[] =
         {'R','E','M','O','V','E',0};
     BOOL override = FALSE;
+    MSICOMPONENT* component;
+    MSIFEATURE *feature;
 
+
     /* I do not know if this is where it should happen.. but */
 
     TRACE("Checking Install Level\n");
@@ -1546,30 +1540,27 @@
 
     if (!override)
     {
-        for(i = 0; i < package->loaded_features; i++)
+        LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
         {
-            BOOL feature_state = ((package->features[i].Level > 0) &&
-                             (package->features[i].Level <= install_level));
+            BOOL feature_state = ((feature->Level > 0) &&
+                             (feature->Level <= install_level));
 
-            if ((feature_state) && 
-               (package->features[i].Action == INSTALLSTATE_UNKNOWN))
+            if ((feature_state) && (feature->Action == INSTALLSTATE_UNKNOWN))
             {
-                if (package->features[i].Attributes & 
-                                msidbFeatureAttributesFavorSource)
+                if (feature->Attributes & msidbFeatureAttributesFavorSource)
                 {
-                    package->features[i].ActionRequest = INSTALLSTATE_SOURCE;
-                    package->features[i].Action = INSTALLSTATE_SOURCE;
+                    feature->ActionRequest = INSTALLSTATE_SOURCE;
+                    feature->Action = INSTALLSTATE_SOURCE;
                 }
-                else if (package->features[i].Attributes &
-                                msidbFeatureAttributesFavorAdvertise)
+                else if (feature->Attributes & msidbFeatureAttributesFavorAdvertise)
                 {
-                    package->features[i].ActionRequest =INSTALLSTATE_ADVERTISED;
-                    package->features[i].Action =INSTALLSTATE_ADVERTISED;
+                    feature->ActionRequest = INSTALLSTATE_ADVERTISED;
+                    feature->Action = INSTALLSTATE_ADVERTISED;
                 }
                 else
                 {
-                    package->features[i].ActionRequest = INSTALLSTATE_LOCAL;
-                    package->features[i].Action = INSTALLSTATE_LOCAL;
+                    feature->ActionRequest = INSTALLSTATE_LOCAL;
+                    feature->Action = INSTALLSTATE_LOCAL;
                 }
             }
         }
@@ -1587,17 +1578,17 @@
      * now we want to enable or disable components base on feature 
     */
 
-    for(i = 0; i < package->loaded_features; i++)
+    LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
     {
-        MSIFEATURE* feature = &package->features[i];
+        ComponentList *cl;
+
         TRACE("Examining Feature %s (Installed %i, Action %i, Request %i)\n",
             debugstr_w(feature->Feature), feature->Installed, feature->Action,
             feature->ActionRequest);
 
-        for( j = 0; j < feature->ComponentCount; j++)
+        LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
         {
-            MSICOMPONENT* component = &package->components[
-                                                    feature->Components[j]];
+            component = cl->component;
 
             if (!component->Enabled)
             {
@@ -1644,10 +1635,8 @@
         }
     } 
 
-    for(i = 0; i < package->loaded_components; i++)
+    LIST_FOR_EACH_ENTRY( component, &package->components, MSICOMPONENT, entry )
     {
-        MSICOMPONENT* component= &package->components[i];
-
         TRACE("Result: Component %s (Installed %i, Action %i, Request %i)\n",
             debugstr_w(component->Component), component->Installed, 
             component->Action, component->ActionRequest);
@@ -1678,14 +1667,14 @@
 static UINT ITERATE_CostFinalizeConditions(MSIRECORD *row, LPVOID param)
 {
     MSIPACKAGE *package = (MSIPACKAGE*)param;
-    LPCWSTR Feature;
-    int feature_index;
+    LPCWSTR name;
+    MSIFEATURE *feature;
 
-    Feature = MSI_RecordGetString(row,1);
+    name = 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));
+    feature = get_loaded_feature( package, name );
+    if (!feature)
+        ERR("FAILED to find loaded feature %s\n",debugstr_w(name));
     else
     {
         LPCWSTR Condition;
@@ -1694,9 +1683,8 @@
         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;
+            TRACE("Reseting feature %s to level %i\n", debugstr_w(name), level);
+            feature->Level = level;
         }
     }
     return ERROR_SUCCESS;
@@ -1722,9 +1710,10 @@
     static const WCHAR szlevel[] =
         {'I','N','S','T','A','L','L','L','E','V','E','L',0};
     static const WCHAR szOne[] = { '1', 0 };
+    MSICOMPONENT *comp;
+    MSIFILE *file;
     UINT rc;
     MSIQUERY * view;
-    DWORD i;
     LPWSTR level;
     DWORD sz = 3;
     WCHAR buffer[3];
@@ -1743,16 +1732,13 @@
         msiobj_release(&view->hdr);
     }
 
-    TRACE("File calculations %i files\n",package->loaded_files);
+    TRACE("File calculations\n");
 
-    for (i = 0; i < package->loaded_files; i++)
+    LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
     {
         MSICOMPONENT* comp = NULL;
-        MSIFILE* file= NULL;
 
-        file = &package->files[i];
-        if (file->ComponentIndex >= 0)
-            comp = &package->components[file->ComponentIndex];
+        comp = file->Component;
 
         if (file->Temporary == TRUE)
             continue;
@@ -1838,16 +1824,15 @@
     }
 
     TRACE("Enabling or Disabling Components\n");
-    for (i = 0; i < package->loaded_components; i++)
+    LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
     {
-        if (package->components[i].Condition[0])
+        if (comp->Condition[0])
         {
             if (MSI_EvaluateConditionW(package,
-                package->components[i].Condition) == MSICONDITION_FALSE)
+                comp->Condition) == MSICONDITION_FALSE)
             {
-                TRACE("Disabling component %s\n",
-                      debugstr_w(package->components[i].Component));
-                package->components[i].Enabled = FALSE;
+                TRACE("Disabling component %s\n", debugstr_w(comp->Component));
+                comp->Enabled = FALSE;
             }
         }
     }
@@ -1995,7 +1980,7 @@
     DWORD type,size;
     LPWSTR  deformated;
     LPCWSTR szRoot, component, name, key, value;
-    INT component_index;
+    MSICOMPONENT *comp;
     MSIRECORD * uirow;
     LPWSTR uikey;
     INT   root;
@@ -2010,21 +1995,21 @@
     name = NULL;
 
     component = MSI_RecordGetString(row, 6);
-    component_index = get_loaded_component(package,component);
+    comp = get_loaded_component(package,component);
+    if (!comp)
+        return ERROR_SUCCESS;
 
-    if (!ACTION_VerifyComponentForAction(package, component_index,
-                            INSTALLSTATE_LOCAL))
+    if (!ACTION_VerifyComponentForAction(package, comp, INSTALLSTATE_LOCAL))
     {
         TRACE("Skipping write due to disabled component %s\n",
                         debugstr_w(component));
 
-        package->components[component_index].Action =
-                package->components[component_index].Installed;
+        comp->Action = comp->Installed;
 
         return ERROR_SUCCESS;
     }
 
-    package->components[component_index].Action = INSTALLSTATE_LOCAL;
+    comp->Action = INSTALLSTATE_LOCAL;
 
     name = MSI_RecordGetString(row, 4);
     if( MSI_RecordIsNull(row,5) && name )
@@ -2192,6 +2177,7 @@
 
 static UINT ACTION_InstallValidate(MSIPACKAGE *package)
 {
+    MSICOMPONENT *comp;
     DWORD progress = 0;
     DWORD total = 0;
     static const WCHAR q1[]=
@@ -2200,7 +2186,8 @@
     UINT rc;
     MSIQUERY * view;
     MSIRECORD * row = 0;
-    int i;
+    MSIFEATURE *feature;
+    MSIFILE *file;
 
     TRACE(" InstallValidate \n");
 
@@ -2231,14 +2218,18 @@
     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;
+    LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
+    {
+        total += COMPONENT_PROGRESS_VALUE;
+    }
+    LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
+    {
+        total += file->FileSize;
+    }
     ui_progress(package,0,total,0,0);
 
-    for(i = 0; i < package->loaded_features; i++)
+    LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
     {
-        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);
@@ -2290,10 +2281,8 @@
     return rc;
 }
 
-static LPWSTR resolve_keypath( MSIPACKAGE* package, INT
-                            component_index)
+static LPWSTR resolve_keypath( MSIPACKAGE* package, MSICOMPONENT *cmp )
 {
-    MSICOMPONENT* cmp = &package->components[component_index];
 
     if (cmp->KeyPath[0]==0)
     {
@@ -2349,14 +2338,10 @@
     }
     else
     {
-        int j;
-        j = get_loaded_file(package,cmp->KeyPath);
+        MSIFILE *file = get_loaded_file( package, cmp->KeyPath );
 
-        if (j>=0)
-        {
-            LPWSTR p = strdupW(package->files[j].TargetPath);
-            return p;
-        }
+        if (file)
+            return strdupW( file->TargetPath );
     }
     return NULL;
 }
@@ -2408,78 +2393,78 @@
 /*
  * Return TRUE if the count should be written out and FALSE if not
  */
-static void ACTION_RefCountComponent( MSIPACKAGE* package, UINT index)
+static void ACTION_RefCountComponent( MSIPACKAGE* package, MSICOMPONENT *comp )
 {
+    MSIFEATURE *feature;
     INT count = 0;
     BOOL write = FALSE;
-    INT j;
 
     /* only refcount DLLs */
-    if (package->components[index].KeyPath[0]==0 || 
-        package->components[index].Attributes & 
-            msidbComponentAttributesRegistryKeyPath || 
-        package->components[index].Attributes & 
-            msidbComponentAttributesODBCDataSource)
+    if (comp->KeyPath[0]==0 || 
+        comp->Attributes & msidbComponentAttributesRegistryKeyPath || 
+        comp->Attributes & msidbComponentAttributesODBCDataSource)
         write = FALSE;
     else
     {
-        count = ACTION_GetSharedDLLsCount(package->components[index].
-                        FullKeypath);
+        count = ACTION_GetSharedDLLsCount( comp->FullKeypath);
         write = (count > 0);
 
-        if (package->components[index].Attributes & 
-                    msidbComponentAttributesSharedDllRefCount)
+        if (comp->Attributes & msidbComponentAttributesSharedDllRefCount)
             write = TRUE;
     }
 
     /* increment counts */
-    for (j = 0; j < package->loaded_features; j++)
+    LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
     {
-        int i;
+        ComponentList *cl;
 
-        if (!ACTION_VerifyFeatureForAction(package,j,INSTALLSTATE_LOCAL))
+        if (!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_LOCAL ))
             continue;
 
-        for (i = 0; i < package->features[j].ComponentCount; i++)
+        LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
         {
-            if (package->features[j].Components[i] == index)
+            if ( cl->component == comp )
                 count++;
         }
     }
+
     /* decrement counts */
-    for (j = 0; j < package->loaded_features; j++)
+    LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
     {
-        int i;
-        if (!ACTION_VerifyFeatureForAction(package,j,INSTALLSTATE_ABSENT))
+        ComponentList *cl;
+
+        if (!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_ABSENT ))
             continue;
 
-        for (i = 0; i < package->features[j].ComponentCount; i++)
+        LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
         {
-            if (package->features[j].Components[i] == index)
+            if ( cl->component == comp )
                 count--;
         }
     }
 
     /* ref count all the files in the component */
     if (write)
-        for (j = 0; j < package->loaded_files; j++)
+    {
+        MSIFILE *file;
+
+        LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
         {
-            if (package->files[j].Temporary)
+            if (file->Temporary)
                 continue;
-            if (package->files[j].ComponentIndex == index)
-                ACTION_WriteSharedDLLsCount(package->files[j].TargetPath,count);
+            if (file->Component == comp)
+                ACTION_WriteSharedDLLsCount( file->TargetPath, count );
         }
+    }
     
     /* add a count for permenent */
-    if (package->components[index].Attributes &
-                                msidbComponentAttributesPermanent)
+    if (comp->Attributes & msidbComponentAttributesPermanent)
         count ++;
     
-    package->components[index].RefCount = count;
+    comp->RefCount = count;
 
     if (write)
-        ACTION_WriteSharedDLLsCount(package->components[index].FullKeypath,
-            package->components[index].RefCount);
+        ACTION_WriteSharedDLLsCount( comp->FullKeypath, comp->RefCount );
 }
 
 /*
@@ -2494,7 +2479,7 @@
     WCHAR squished_pc[GUID_SIZE];
     WCHAR squished_cc[GUID_SIZE];
     UINT rc;
-    DWORD i;
+    MSICOMPONENT *comp;
     HKEY hkey=0,hkey2=0;
 
     if (!package)
@@ -2508,32 +2493,33 @@
       
     squash_guid(package->ProductCode,squished_pc);
     ui_progress(package,1,COMPONENT_PROGRESS_VALUE,1,0);
-    for (i = 0; i < package->loaded_components; i++)
+
+    LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
     {
         ui_progress(package,2,0,0,0);
-        if (package->components[i].ComponentId[0]!=0)
+        if (comp->ComponentId[0]!=0)
         {
             WCHAR *keypath = NULL;
             MSIRECORD * uirow;
 
-            squash_guid(package->components[i].ComponentId,squished_cc);
+            squash_guid(comp->ComponentId,squished_cc);
            
-            keypath = resolve_keypath(package,i);
-            package->components[i].FullKeypath = keypath;
+            keypath = resolve_keypath( package, comp );
+            comp->FullKeypath = keypath;
 
             /* do the refcounting */
-            ACTION_RefCountComponent( package, i);
+            ACTION_RefCountComponent( package, comp );
[truncated at 1000 lines; 4574 more skipped]