MSI: fix the UPDATE query

Mike McCormack mike at codeweavers.com
Tue Jun 29 07:10:29 CDT 2004


ChangeLog:
* fix the UPDATE query
-------------- next part --------------
diff -ur dlls/msi.old/msipriv.h dlls/msi/msipriv.h
--- dlls/msi.old/msipriv.h	2004-06-29 07:07:24.000000000 -0500
+++ dlls/msi/msipriv.h	2004-06-29 07:08:09.000000000 -0500
@@ -182,8 +182,8 @@
 
 
 /* string table functions */
-extern BOOL msi_addstring( string_table *st, UINT string_no, const CHAR *data, int len, UINT refcount );
-extern BOOL msi_addstringW( string_table *st, UINT string_no, const WCHAR *data, int len, UINT refcount );
+extern BOOL msi_addstring( string_table *st, int string_no, const CHAR *data, int len, UINT refcount );
+extern BOOL msi_addstringW( string_table *st, int string_no, const WCHAR *data, int len, UINT refcount );
 extern UINT msi_id2stringW( string_table *st, UINT string_no, LPWSTR buffer, UINT *sz );
 extern UINT msi_id2stringA( string_table *st, UINT string_no, LPSTR buffer, UINT *sz );
 
@@ -194,9 +194,10 @@
 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 );
+extern UINT msi_string_totalsize( string_table *st, UINT *last );
 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 );
 
 
 UINT VIEW_find_column( MSIVIEW *view, LPWSTR name, UINT *n );
diff -ur dlls/msi.old/sql.y dlls/msi/sql.y
--- dlls/msi.old/sql.y	2004-06-29 07:07:24.000000000 -0500
+++ dlls/msi/sql.y	2004-06-29 07:08:09.000000000 -0500
@@ -155,20 +155,20 @@
     ;
 
 oneinsert:
-    TK_INSERT TK_INTO table selcollist TK_VALUES constlist
+    TK_INSERT TK_INTO table TK_LP selcollist TK_RP TK_VALUES TK_LP constlist TK_RP
     {
         SQL_input *sql = (SQL_input*) info;
         MSIVIEW *insert = NULL; 
 
-        INSERT_CreateView( sql->db, &insert, $3, $4, $6, FALSE ); 
+        INSERT_CreateView( sql->db, &insert, $3, $5, $9, FALSE ); 
         $$ = insert;
     }
-  | TK_INSERT TK_INTO table selcollist TK_VALUES constlist TK_TEMP
+  | TK_INSERT TK_INTO table TK_LP selcollist TK_RP TK_VALUES TK_LP constlist TK_RP TK_TEMP
     {
         SQL_input *sql = (SQL_input*) info;
         MSIVIEW *insert = NULL; 
 
-        INSERT_CreateView( sql->db, &insert, $3, $4, $6, TRUE ); 
+        INSERT_CreateView( sql->db, &insert, $3, $5, $9, TRUE ); 
         $$ = insert;
     }
     ;
@@ -461,10 +461,6 @@
 val:
     column_val
   | const_val
-  | TK_WILDCARD
-        {
-            $$ = EXPR_wildcard();
-        }
     ;
 
 constlist:
@@ -504,6 +500,10 @@
         {
             $$ = EXPR_sval( &$1 );
         }
+  | TK_WILDCARD
+        {
+            $$ = EXPR_wildcard();
+        }
     ;
 
 column_val:
diff -ur dlls/msi.old/string.c dlls/msi/string.c
--- dlls/msi.old/string.c	2004-06-29 07:07:24.000000000 -0500
+++ dlls/msi/string.c	2004-06-29 07:08:09.000000000 -0500
@@ -46,7 +46,7 @@
 
 struct string_table
 {
-    UINT count;         /* the number of strings */
+    UINT maxcount;         /* the number of strings */
     UINT freeslot;
     UINT codepage;
     msistring *strings; /* an array of strings (in the tree) */
@@ -79,7 +79,9 @@
         HeapFree( GetProcessHeap(), 0, st );
         return NULL;    
     }
-    st->count = entries;
+    if( entries < 1 )
+        entries = 1;
+    st->maxcount = entries;
     st->freeslot = 1;
     st->codepage = codepage;
 
@@ -90,7 +92,7 @@
 {
     UINT i;
 
-    for( i=0; i<st->count; i++ )
+    for( i=0; i<st->maxcount; i++ )
     {
         if( st->strings[i].refcount )
             HeapFree( GetProcessHeap(), 0, st->strings[i].str );
@@ -106,22 +108,25 @@
 
     TRACE("%p\n", st);
 
-    for( i = st->freeslot; i < st->count; i++ )
-        if( !st->strings[i].refcount )
-            return i;
-    for( i = 1; i < st->freeslot; i++ )
+    if( st->freeslot )
+    {
+        for( i = st->freeslot; i < st->maxcount; i++ )
+            if( !st->strings[i].refcount )
+                return i;
+    }
+    for( i = 1; i < st->maxcount; i++ )
         if( !st->strings[i].refcount )
             return i;
 
     /* dynamically resize */
-    sz = st->count + 1 + st->count/2;
+    sz = st->maxcount + 1 + st->maxcount/2;
     p = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
                      st->strings, sz*sizeof(msistring) );
     if( !p )
         return -1;
     st->strings = p;
-    st->freeslot = st->count;
-    st->count = sz;
+    st->freeslot = st->maxcount;
+    st->maxcount = sz;
     if( st->strings[st->freeslot].refcount )
         ERR("oops. expected freeslot to be free...\n");
     return st->freeslot;
@@ -129,12 +134,12 @@
 
 static void st_mark_entry_used( string_table *st, int n )
 {
-    if( n >= st->count )
+    if( n >= st->maxcount )
         return;
     st->freeslot = n + 1;
 }
 
-int msi_addstring( string_table *st, UINT n, const CHAR *data, int len, UINT refcount )
+int msi_addstring( string_table *st, int n, const CHAR *data, int len, UINT refcount )
 {
     int sz;
 
@@ -157,6 +162,12 @@
             return -1;
     }
 
+    if( n < 1 )
+    {
+        ERR("invalid index adding %s (%d)\n", debugstr_a( data ), n );
+        return -1;
+    }
+
     /* allocate a new string */
     if( len < 0 )
         len = strlen(data);
@@ -174,7 +185,7 @@
     return n;
 }
 
-int msi_addstringW( string_table *st, UINT n, const WCHAR *data, int len, UINT refcount )
+int msi_addstringW( string_table *st, int n, const WCHAR *data, int len, UINT refcount )
 {
     /* TRACE("[%2d] = %s\n", string_no, debugstr_an(data,len) ); */
 
@@ -197,6 +208,12 @@
             return -1;
     }
 
+    if( n < 1 )
+    {
+        ERR("invalid index adding %s (%d)\n", debugstr_w( data ), n );
+        return -1;
+    }
+
     /* allocate a new string */
     if(len<0)
         len = strlenW(data);
@@ -223,7 +240,7 @@
     if( id == 0 )
         return zero;
 
-    if( id >= st->count )
+    if( id >= st->maxcount )
         return NULL;
 
     if( id && !st->strings[id].refcount )
@@ -249,7 +266,7 @@
     UINT len;
     const WCHAR *str;
 
-    TRACE("Finding string %d of %d\n", id, st->count);
+    TRACE("Finding string %d of %d\n", id, st->maxcount);
 
     str = msi_string_lookup_id( st, id );
     if( !str )
@@ -287,8 +304,9 @@
 {
     UINT len;
     const WCHAR *str;
+    int n;
 
-    TRACE("Finding string %d of %d\n", id, st->count);
+    TRACE("Finding string %d of %d\n", id, st->maxcount);
 
     str = msi_string_lookup_id( st, id );
     if( !str )
@@ -302,7 +320,17 @@
         return ERROR_SUCCESS;
     }
 
-    *sz = WideCharToMultiByte( st->codepage, 0, str, -1, buffer, *sz, NULL, NULL );
+    if( len > *sz )
+    {
+        n = strlenW( str ) + 1;
+        while( n && (len > *sz) )
+            len = WideCharToMultiByte( st->codepage, 0, 
+                           str, --n, NULL, 0, NULL, NULL );
+    }
+    else
+        n = -1;
+
+    *sz = WideCharToMultiByte( st->codepage, 0, str, n, buffer, len, NULL, NULL );
 
     return ERROR_SUCCESS;
 }
@@ -320,7 +348,7 @@
     UINT i, r = ERROR_INVALID_PARAMETER;
 
     hash = msistring_makehash( str );
-    for( i=0; i<st->count; i++ )
+    for( i=0; i<st->maxcount; i++ )
     {
         if( ( st->strings[i].hash == hash ) &&
             !strcmpW( st->strings[i].str, str ) )
@@ -383,30 +411,41 @@
 
 UINT msi_string_count( string_table *st )
 {
-    return st->count;
+    return st->maxcount;
 }
 
 UINT msi_id_refcount( string_table *st, UINT i )
 {
-    if( i >= st->count )
+    if( i >= st->maxcount )
         return 0;
     return st->strings[i].refcount;
 }
 
-UINT msi_string_totalsize( string_table *st )
+UINT msi_string_totalsize( string_table *st, UINT *total )
 {
     UINT size = 0, i, len;
 
-    for( i=0; i<st->count; i++)
+    if( st->strings[0].str || st->strings[0].refcount )
+        ERR("oops. element 0 has a string\n");
+    *total = 0;
+    for( i=1; i<st->maxcount; i++ )
     {
         if( st->strings[i].str )
         {
+            TRACE("[%u] = %s\n", i, debugstr_w(st->strings[i].str));
             len = WideCharToMultiByte( st->codepage, 0,
                      st->strings[i].str, -1, NULL, 0, NULL, NULL);
             if( len )
                 len--;
             size += len;
+            *total = (i+1);
         }
     }
+    TRACE("%u/%u strings %u bytes codepage %x\n", *total, st->maxcount, size, st->codepage );
     return size;
 }
+
+UINT msi_string_get_codepage( string_table *st )
+{
+    return st->codepage;
+}
diff -ur dlls/msi.old/table.c dlls/msi/table.c
--- dlls/msi.old/table.c	2004-06-29 07:07:24.000000000 -0500
+++ dlls/msi/table.c	2004-06-29 07:08:09.000000000 -0500
@@ -702,7 +702,7 @@
 {
     CHAR *data;
     USHORT *pool;
-    UINT r, ret = ERROR_FUNCTION_FAILED, datasize = 0, poolsize = 0;
+    UINT r, ret = ERROR_FUNCTION_FAILED, datasize = 0, poolsize = 0, codepage;
     DWORD i, count, offset, len, n;
     static const WCHAR szStringData[] = {
         '_','S','t','r','i','n','g','D','a','t','a',0 };
@@ -723,10 +723,12 @@
         goto end;
 
     count = poolsize/4;
-    db->strings = msi_init_stringtable( count, pool[0] );
+    if( poolsize > 4 )
+        codepage = pool[0] | ( pool[1] << 16 );
+    else
+        codepage = CP_ACP;
+    db->strings = msi_init_stringtable( count, codepage );
 
-    if( pool[1] )
-        ERR("The first string should have zero refcount, but doesn't %04x\n", pool[1]);
     offset = 0;
     for( i=1; i<count; i++ )
     {
@@ -752,7 +754,7 @@
 
 UINT save_string_table( MSIDATABASE *db )
 {
-    UINT i, count, datasize, poolsize, sz, used, r;
+    UINT i, count, datasize, poolsize, sz, used, r, codepage;
     UINT ret = ERROR_FUNCTION_FAILED;
     static const WCHAR szStringData[] = {
         '_','S','t','r','i','n','g','D','a','t','a',0 };
@@ -764,9 +766,8 @@
     TRACE("\n");
 
     /* construct the new table in memory first */
-    count = msi_string_count( db->strings );
+    datasize = msi_string_totalsize( db->strings, &count );
     poolsize = count*2*sizeof(USHORT);
-    datasize = msi_string_totalsize( db->strings );
 
     pool = HeapAlloc( GetProcessHeap(), 0, poolsize );
     if( ! pool )
@@ -782,8 +783,9 @@
     }
 
     used = 0;
-    pool[0]=0;   /* the first element is always zero */
-    pool[1]=0;
+    codepage = msi_string_get_codepage( db->strings );
+    pool[0]=codepage&0xffff;
+    pool[1]=(codepage>>16);
     for( i=1; i<count; i++ )
     {
         sz = datasize - used;
@@ -793,8 +795,9 @@
             ERR("failed to fetch string\n");
             sz = 0;
         }
-        else
+        if( sz && (sz < (datasize - used ) ) )
             sz--;
+        TRACE("adding %u bytes %s\n", sz, data+used );
         pool[ i*2 ] = sz;
         pool[ i*2 + 1 ] = msi_id_refcount( db->strings, i );
         used += sz;


More information about the wine-patches mailing list