Mike McCormack : msi: Fix writing of long strings to the database.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Aug 28 05:09:28 CDT 2006


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

Author: Mike McCormack <mike at codeweavers.com>
Date:   Mon Aug 28 16:51:41 2006 +0900

msi: Fix writing of long strings to the database.

---

 dlls/msi/msipriv.h  |    2 +-
 dlls/msi/string.c   |   24 +++++++++++++++++-------
 dlls/msi/table.c    |   25 +++++++++++++++++++------
 dlls/msi/tests/db.c |    2 --
 4 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 1c5a894..abaa347 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -328,7 +328,7 @@ extern string_table *msi_init_stringtabl
 extern VOID msi_destroy_stringtable( string_table *st );
 extern UINT msi_string_count( string_table *st );
 extern UINT msi_id_refcount( string_table *st, UINT i );
-extern UINT msi_string_totalsize( string_table *st, UINT *last );
+extern UINT msi_string_totalsize( string_table *st, UINT *datasize, UINT *poolsize );
 extern UINT msi_strcmp( string_table *st, UINT lval, UINT rval, UINT *res );
 extern const WCHAR *msi_string_lookup_id( string_table *st, UINT id );
 extern UINT msi_string_get_codepage( string_table *st );
diff --git a/dlls/msi/string.c b/dlls/msi/string.c
index 3155c12..db10ae5 100644
--- a/dlls/msi/string.c
+++ b/dlls/msi/string.c
@@ -435,13 +435,17 @@ UINT msi_id_refcount( string_table *st, 
     return st->strings[i].refcount;
 }
 
-UINT msi_string_totalsize( string_table *st, UINT *total )
+UINT msi_string_totalsize( string_table *st, UINT *datasize, UINT *poolsize )
 {
-    UINT size = 0, i, len;
+    UINT i, len, max, holesize;
 
     if( st->strings[0].str || st->strings[0].refcount )
         ERR("oops. element 0 has a string\n");
-    *total = 0;
+
+    *poolsize = 4;
+    *datasize = 0;
+    max = 1;
+    holesize = 0;
     for( i=1; i<st->maxcount; i++ )
     {
         if( st->strings[i].str )
@@ -451,12 +455,18 @@ UINT msi_string_totalsize( string_table 
                      st->strings[i].str, -1, NULL, 0, NULL, NULL);
             if( len )
                 len--;
-            size += len;
-            *total = (i+1);
+            (*datasize) += len;
+            if (len>0xffff)
+                (*poolsize) += 4;
+            max = i + 1;
+            (*poolsize) += holesize + 4;
+            holesize = 0;
         }
+        else
+            holesize += 4;
     }
-    TRACE("%u/%u strings %u bytes codepage %x\n", *total, st->maxcount, size, st->codepage );
-    return size;
+    TRACE("data %u pool %u codepage %x\n", *datasize, *poolsize, st->codepage );
+    return max;
 }
 
 UINT msi_string_get_codepage( string_table *st )
diff --git a/dlls/msi/table.c b/dlls/msi/table.c
index 57cd4df..fb468bc 100644
--- a/dlls/msi/table.c
+++ b/dlls/msi/table.c
@@ -765,7 +765,7 @@ end:
 
 static UINT save_string_table( MSIDATABASE *db )
 {
-    UINT i, count, datasize, poolsize, sz, used, r, codepage;
+    UINT i, count, datasize = 0, poolsize = 0, sz, used, r, codepage, n;
     UINT ret = ERROR_FUNCTION_FAILED;
     static const WCHAR szStringData[] = {
         '_','S','t','r','i','n','g','D','a','t','a',0 };
@@ -777,8 +777,9 @@ static UINT save_string_table( MSIDATABA
     TRACE("\n");
 
     /* construct the new table in memory first */
-    datasize = msi_string_totalsize( db->strings, &count );
-    poolsize = (count + 1)*2*sizeof(USHORT);
+    count = msi_string_totalsize( db->strings, &datasize, &poolsize );
+
+    TRACE("%u %u %u\n", count, datasize, poolsize );
 
     pool = msi_alloc( poolsize );
     if( ! pool )
@@ -797,6 +798,7 @@ static UINT save_string_table( MSIDATABA
     codepage = msi_string_get_codepage( db->strings );
     pool[0]=codepage&0xffff;
     pool[1]=(codepage>>16);
+    n = 1;
     for( i=1; i<count; i++ )
     {
         sz = datasize - used;
@@ -808,9 +810,20 @@ static UINT save_string_table( MSIDATABA
         }
         if( sz && (sz < (datasize - used ) ) )
             sz--;
-        TRACE("adding %u bytes %s\n", sz, debugstr_a(data+used) );
-        pool[ i*2 ] = sz;
-        pool[ i*2 + 1 ] = msi_id_refcount( db->strings, i );
+
+        pool[ n*2 + 1 ] = msi_id_refcount( db->strings, i );
+        if (sz < 0x10000)
+        {
+            pool[ n*2 ] = sz;
+            n++;
+        }
+        else
+        {
+            pool[ n*2 ] = 0;
+            pool[ n*2 + 2 ] = sz&0xffff;
+            pool[ n*2 + 3 ] = (sz>>16);
+            n += 2;
+        }
         used += sz;
         if( used > datasize  )
         {
diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c
index 6da7666..781c6a5 100644
--- a/dlls/msi/tests/db.c
+++ b/dlls/msi/tests/db.c
@@ -940,9 +940,7 @@ static void test_longstrings(void)
 
     r = MsiRecordGetString(hrec, 2, NULL, &len);
     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
-    todo_wine {
     ok(len == STRING_LENGTH, "string length wrong\n");
-    }
 
     MsiCloseHandle(hrec);
     MsiCloseHandle(hdb);




More information about the wine-cvs mailing list