Mike McCormack : msi: Allow rows in the _Columns table to be unordered.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Oct 19 07:19:18 CDT 2006


Module: wine
Branch: master
Commit: 8ecd34b97132bde3638c56f7e71dd0213af0159d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=8ecd34b97132bde3638c56f7e71dd0213af0159d

Author: Mike McCormack <mike at codeweavers.com>
Date:   Fri Oct 20 01:53:51 2006 +0900

msi: Allow rows in the _Columns table to be unordered.

---

 dlls/msi/table.c |   74 ++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 50 insertions(+), 24 deletions(-)

diff --git a/dlls/msi/table.c b/dlls/msi/table.c
index 15f4da2..8d416f2 100644
--- a/dlls/msi/table.c
+++ b/dlls/msi/table.c
@@ -34,6 +34,7 @@ #include "objidl.h"
 #include "winnls.h"
 #include "msipriv.h"
 #include "query.h"
+#include "assert.h"
 
 #include "wine/debug.h"
 #include "wine/unicode.h"
@@ -81,7 +82,7 @@ #define MAX_STREAM_NAME 0x1f
 
 static UINT table_get_column_info( MSIDATABASE *db, LPCWSTR name,
        MSICOLUMNINFO **pcols, UINT *pcount );
-static UINT get_tablecolumns( MSIDATABASE *db, 
+static UINT get_tablecolumns( MSIDATABASE *db,
        LPCWSTR szTableName, MSICOLUMNINFO *colinfo, UINT *sz);
 static void msi_free_colinfo( MSICOLUMNINFO *colinfo, UINT count );
 
@@ -926,12 +927,14 @@ static LPWSTR msi_makestring( MSIDATABAS
     return strdupW(msi_string_lookup_id( db->strings, stringid ));
 }
 
-static UINT get_tablecolumns( MSIDATABASE *db, 
+static UINT get_tablecolumns( MSIDATABASE *db,
        LPCWSTR szTableName, MSICOLUMNINFO *colinfo, UINT *sz)
 {
     UINT r, i, n=0, table_id, count, maxcount = *sz;
     MSITABLE *table = NULL;
 
+    TRACE("%s\n", debugstr_w(szTableName));
+
     /* first check if there is a default table with that name */
     r = get_defaulttablecolumns( szTableName, colinfo, sz );
     if( ( r == ERROR_SUCCESS ) && *sz )
@@ -954,6 +957,8 @@ static UINT get_tablecolumns( MSIDATABAS
 
     TRACE("Table id is %d, row count is %d\n", table_id, table->row_count);
 
+    /* if maxcount is non-zero, assume it's exactly right for this table */
+    memset( colinfo, 0, maxcount*sizeof(*colinfo) );
     count = table->row_count;
     for( i=0; i<count; i++ )
     {
@@ -962,32 +967,53 @@ static UINT get_tablecolumns( MSIDATABAS
         if( colinfo )
         {
             UINT id = table->data[ i ] [ 2 ];
-            colinfo[n].tablename = msi_makestring( db, table_id );
-            colinfo[n].number = table->data[ i ][ 1 ] - (1<<15);
-            colinfo[n].colname = msi_makestring( db, id );
-            colinfo[n].type = table->data[ i ] [ 3 ] ^ 0x8000;
-            colinfo[n].hash_table = NULL;
-            /* this assumes that columns are in order in the table */
-            if( n )
-                colinfo[n].offset = colinfo[n-1].offset
-                                  + bytes_per_column( &colinfo[n-1] );
-            else
-                colinfo[n].offset = 0;
-            TRACE("table %s column %d is [%s] (%d) with type %08x "
-                  "offset %d at row %d\n", debugstr_w(szTableName),
-                   colinfo[n].number, debugstr_w(colinfo[n].colname),
-                   id, colinfo[n].type, colinfo[n].offset, i);
-            if( n != (colinfo[n].number-1) )
+            UINT col = table->data[ i ][ 1 ] - (1<<15);
+
+            /* check the column number is in range */
+            if (col<1 || col>maxcount)
             {
-                ERR("oops. data in the _Columns table isn't in the right "
-                    "order for table %s\n", debugstr_w(szTableName));
-                msi_free_colinfo(colinfo, n+1 );
-                return ERROR_FUNCTION_FAILED;
+                ERR("column %d out of range\n", col);
+                continue;
             }
+
+            /* check if this column was already set */
+            if (colinfo[ col - 1 ].number)
+            {
+                ERR("duplicate column %d\n", col);
+                continue;
+            }
+
+            colinfo[ col - 1 ].tablename = msi_makestring( db, table_id );
+            colinfo[ col - 1 ].number = col;
+            colinfo[ col - 1 ].colname = msi_makestring( db, id );
+            colinfo[ col - 1 ].type = table->data[ i ] [ 3 ] - (1<<15);
+            colinfo[ col - 1 ].offset = 0;
+            colinfo[ col - 1 ].hash_table = NULL;
         }
         n++;
-        if( colinfo && ( n >= maxcount ) )
-            break;
+    }
+
+    TRACE("%s has %d columns\n", debugstr_w(szTableName), n);
+
+    if (maxcount && n != maxcount)
+    {
+        ERR("missing column in table %s\n", debugstr_w(szTableName));
+        msi_free_colinfo(colinfo, maxcount );
+        return ERROR_FUNCTION_FAILED;
+    }
+
+    /* calculate the offsets */
+    for( i=0; maxcount && (i<maxcount); i++ )
+    {
+         assert( (i+1) == colinfo[ i ].number );
+         if (i)
+             colinfo[i].offset = colinfo[ i - 1 ].offset
+                               + bytes_per_column( &colinfo[ i - 1 ] );
+         else
+             colinfo[i].offset = 0;
+         TRACE("column %d is [%s] with type %08x ofs %d\n",
+               colinfo[i].number, debugstr_w(colinfo[i].colname),
+               colinfo[i].type, colinfo[i].offset);
     }
     *sz = n;
 




More information about the wine-cvs mailing list