diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 73bccecd94f..4757da4d319 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -754,9 +754,9 @@ enum StringPersistence }; extern BOOL msi_addstringW( string_table *st, const WCHAR *data, int len, USHORT refcount, enum StringPersistence persistence ) DECLSPEC_HIDDEN; -extern UINT msi_string2idW( const string_table *st, LPCWSTR buffer, UINT *id ) DECLSPEC_HIDDEN; +extern UINT msi_string2id( const string_table *st, const WCHAR *data, int len, UINT *id ) DECLSPEC_HIDDEN; extern VOID msi_destroy_stringtable( string_table *st ) DECLSPEC_HIDDEN; -extern const WCHAR *msi_string_lookup_id( const string_table *st, UINT id ) DECLSPEC_HIDDEN; +extern const WCHAR *msi_string_lookup( const string_table *st, UINT id, int *len ) DECLSPEC_HIDDEN; extern HRESULT msi_init_string_table( IStorage *stg ) DECLSPEC_HIDDEN; extern string_table *msi_load_string_table( IStorage *stg, UINT *bytes_per_strref ) DECLSPEC_HIDDEN; extern UINT msi_save_string_table( const string_table *st, IStorage *storage, UINT *bytes_per_strref ) DECLSPEC_HIDDEN; diff --git a/dlls/msi/msiquery.c b/dlls/msi/msiquery.c index 433b3c772f6..4b826f85811 100644 --- a/dlls/msi/msiquery.c +++ b/dlls/msi/msiquery.c @@ -347,7 +347,7 @@ UINT msi_view_get_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD **rec) { LPCWSTR sval; - sval = msi_string_lookup_id(db->strings, ival); + sval = msi_string_lookup(db->strings, ival, NULL); MSI_RecordSetStringW(*rec, i, sval); } else diff --git a/dlls/msi/storages.c b/dlls/msi/storages.c index c980df8aa32..35c1de5903d 100644 --- a/dlls/msi/storages.c +++ b/dlls/msi/storages.c @@ -312,7 +312,7 @@ static UINT storages_find_row(MSISTORAGESVIEW *sv, MSIRECORD *rec, UINT *row) UINT r, i, id, data; str = MSI_RecordGetString(rec, 1); - r = msi_string2idW(sv->db->strings, str, &id); + r = msi_string2id(sv->db->strings, str, -1, &id); if (r != ERROR_SUCCESS) return r; diff --git a/dlls/msi/streams.c b/dlls/msi/streams.c index 71616e93eb0..d9d632fafbc 100644 --- a/dlls/msi/streams.c +++ b/dlls/msi/streams.c @@ -299,7 +299,7 @@ static UINT streams_find_row(MSISTREAMSVIEW *sv, MSIRECORD *rec, UINT *row) UINT r, i, id, data; str = MSI_RecordGetString(rec, 1); - r = msi_string2idW(sv->db->strings, str, &id); + r = msi_string2id(sv->db->strings, str, -1, &id); if (r != ERROR_SUCCESS) return r; diff --git a/dlls/msi/string.c b/dlls/msi/string.c index 065c04a3720..5e2c574d10b 100644 --- a/dlls/msi/string.c +++ b/dlls/msi/string.c @@ -45,7 +45,8 @@ struct msistring { USHORT persistent_refcount; USHORT nonpersistent_refcount; - LPWSTR str; + WCHAR *data; + int len; }; struct string_table @@ -112,7 +113,7 @@ VOID msi_destroy_stringtable( string_table *st ) { if( st->strings[i].persistent_refcount || st->strings[i].nonpersistent_refcount ) - msi_free( st->strings[i].str ); + msi_free( st->strings[i].data ); } msi_free( st->strings ); msi_free( st->sorted ); @@ -162,6 +163,19 @@ static int st_find_free_entry( string_table *st ) return st->freeslot; } +static inline int cmp_string( const WCHAR *str1, int len1, const WCHAR *str2, int len2 ) +{ + if (len1 < len2) return -1; + else if (len1 > len2) return 1; + while (len1) + { + if (*str1 == *str2) { str1++; str2++; } + else return *str1 - *str2; + len1--; + } + return 0; +} + static int find_insert_index( const string_table *st, UINT string_id ) { int i, c, low = 0, high = st->sortcount - 1; @@ -169,8 +183,8 @@ static int find_insert_index( const string_table *st, UINT string_id ) while (low <= high) { i = (low + high) / 2; - c = strcmpW( st->strings[string_id].str, st->strings[st->sorted[i]].str ); - + c = cmp_string( st->strings[string_id].data, st->strings[string_id].len, + st->strings[st->sorted[i]].data, st->strings[st->sorted[i]].len ); if (c < 0) high = i - 1; else if (c > 0) @@ -194,7 +208,8 @@ static void insert_string_sorted( string_table *st, UINT string_id ) st->sortcount++; } -static void set_st_entry( string_table *st, UINT n, LPWSTR str, USHORT refcount, enum StringPersistence persistence ) +static void set_st_entry( string_table *st, UINT n, WCHAR *str, int len, USHORT refcount, + enum StringPersistence persistence ) { if (persistence == StringPersistent) { @@ -207,7 +222,8 @@ static void set_st_entry( string_table *st, UINT n, LPWSTR str, USHORT refcount, st->strings[n].nonpersistent_refcount = refcount; } - st->strings[n].str = str; + st->strings[n].data = str; + st->strings[n].len = len; insert_string_sorted( st, n ); @@ -237,9 +253,8 @@ static UINT msi_string2idA( const string_table *st, LPCSTR buffer, UINT *id ) return ERROR_NOT_ENOUGH_MEMORY; MultiByteToWideChar( st->codepage, 0, buffer, -1, str, sz ); - r = msi_string2idW( st, str, id ); + r = msi_string2id( st, str, sz - 1, id ); msi_free( str ); - return r; } @@ -289,7 +304,7 @@ static int msi_addstring( string_table *st, UINT n, const CHAR *data, int len, U MultiByteToWideChar( st->codepage, 0, data, len, str, sz ); str[sz] = 0; - set_st_entry( st, n, str, refcount, persistence ); + set_st_entry( st, n, str, sz, refcount, persistence ); return n; } @@ -301,10 +316,10 @@ int msi_addstringW( string_table *st, const WCHAR *data, int len, USHORT refcoun if( !data ) return 0; - if( !data[0] ) + if( !data[0] && !len ) return 0; - if( msi_string2idW( st, data, &n ) == ERROR_SUCCESS ) + if (msi_string2id( st, data, len, &n) == ERROR_SUCCESS ) { if (persistence == StringPersistent) st->strings[n].persistent_refcount += refcount; @@ -320,7 +335,7 @@ int msi_addstringW( string_table *st, const WCHAR *data, int len, USHORT refcoun /* allocate a new string */ if(len<0) len = strlenW(data); - TRACE("%s, n = %d len = %d\n", debugstr_w(data), n, len ); + TRACE( "%s, n = %d len = %d\n", debugstr_wn(data, len), n, len ); str = msi_alloc( (len+1)*sizeof(WCHAR) ); if( !str ) @@ -328,13 +343,13 @@ int msi_addstringW( string_table *st, const WCHAR *data, int len, USHORT refcoun memcpy( str, data, len*sizeof(WCHAR) ); str[len] = 0; - set_st_entry( st, n, str, refcount, persistence ); + set_st_entry( st, n, str, len, refcount, persistence ); return n; } /* find the string identified by an id - return null if there's none */ -const WCHAR *msi_string_lookup_id( const string_table *st, UINT id ) +const WCHAR *msi_string_lookup( const string_table *st, UINT id, int *len ) { if( id == 0 ) return szEmpty; @@ -345,7 +360,9 @@ const WCHAR *msi_string_lookup_id( const string_table *st, UINT id ) if( id && !st->strings[id].persistent_refcount && !st->strings[id].nonpersistent_refcount) return NULL; - return st->strings[id].str; + if (len) *len = st->strings[id].len; + + return st->strings[id].data; } /* @@ -361,16 +378,15 @@ const WCHAR *msi_string_lookup_id( const string_table *st, UINT id ) */ static UINT msi_id2stringA( const string_table *st, UINT id, LPSTR buffer, UINT *sz ) { - UINT len, lenW; + int len, lenW; const WCHAR *str; TRACE("Finding string %d of %d\n", id, st->maxcount); - str = msi_string_lookup_id( st, id ); + str = msi_string_lookup( st, id, &lenW ); if( !str ) return ERROR_FUNCTION_FAILED; - lenW = strlenW( str ); len = WideCharToMultiByte( st->codepage, 0, str, lenW, NULL, 0, NULL, NULL ); if( *sz < len ) { @@ -382,20 +398,22 @@ static UINT msi_id2stringA( const string_table *st, UINT id, LPSTR buffer, UINT } /* - * msi_string2idW + * msi_string2id * * [in] st - pointer to the string table * [in] str - string to find in the string table * [out] id - id of the string, if found */ -UINT msi_string2idW( const string_table *st, LPCWSTR str, UINT *id ) +UINT msi_string2id( const string_table *st, const WCHAR *str, int len, UINT *id ) { int i, c, low = 0, high = st->sortcount - 1; + if (len < 0) len = strlenW( str ); + while (low <= high) { i = (low + high) / 2; - c = strcmpW( str, st->strings[st->sorted[i]].str ); + c = cmp_string( str, len, st->strings[st->sorted[i]].data, st->strings[st->sorted[i]].len ); if (c < 0) high = i - 1; @@ -407,7 +425,6 @@ UINT msi_string2idW( const string_table *st, LPCWSTR str, UINT *id ) return ERROR_SUCCESS; } } - return ERROR_INVALID_PARAMETER; } @@ -415,7 +432,7 @@ static void string_totalsize( const string_table *st, UINT *datasize, UINT *pool { UINT i, len, holesize; - if( st->strings[0].str || st->strings[0].persistent_refcount || st->strings[0].nonpersistent_refcount) + if( st->strings[0].data || st->strings[0].persistent_refcount || st->strings[0].nonpersistent_refcount) ERR("oops. element 0 has a string\n"); *poolsize = 4; @@ -425,14 +442,14 @@ static void string_totalsize( const string_table *st, UINT *datasize, UINT *pool { if( !st->strings[i].persistent_refcount ) { - TRACE("[%u] nonpersistent = %s\n", i, debugstr_w(st->strings[i].str)); + TRACE("[%u] nonpersistent = %s\n", i, debugstr_wn(st->strings[i].data, st->strings[i].len)); (*poolsize) += 4; } - else if( st->strings[i].str ) + else if( st->strings[i].data ) { - 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); + TRACE("[%u] = %s\n", i, debugstr_wn(st->strings[i].data, st->strings[i].len)); + len = WideCharToMultiByte( st->codepage, 0, st->strings[i].data, st->strings[i].len + 1, + NULL, 0, NULL, NULL); if( len ) len--; (*datasize) += len; diff --git a/dlls/msi/table.c b/dlls/msi/table.c index 93b0268c494..3276259b2bf 100644 --- a/dlls/msi/table.c +++ b/dlls/msi/table.c @@ -660,7 +660,7 @@ static UINT get_tablecolumns( MSIDATABASE *db, LPCWSTR szTableName, MSICOLUMNINF } /* convert table and column names to IDs from the string table */ - r = msi_string2idW( db->strings, szTableName, &table_id ); + r = msi_string2id( db->strings, szTableName, -1, &table_id ); if (r != ERROR_SUCCESS) { WARN("Couldn't find id for %s\n", debugstr_w(szTableName)); @@ -693,9 +693,9 @@ static UINT get_tablecolumns( MSIDATABASE *db, LPCWSTR szTableName, MSICOLUMNINF ERR("duplicate column %d\n", col); continue; } - colinfo[col - 1].tablename = msi_string_lookup_id( db->strings, table_id ); + colinfo[col - 1].tablename = msi_string_lookup( db->strings, table_id, NULL ); colinfo[col - 1].number = col; - colinfo[col - 1].colname = msi_string_lookup_id( db->strings, id ); + colinfo[col - 1].colname = msi_string_lookup( db->strings, id, NULL ); colinfo[col - 1].type = read_table_int( table->data, i, table->colinfo[3].offset, sizeof(USHORT) ) - (1 << 15); colinfo[col - 1].offset = 0; @@ -763,9 +763,9 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info, UINT table_id = msi_addstringW( db->strings, col->table, -1, 1, string_persistence ); UINT col_id = msi_addstringW( db->strings, col->column, -1, 1, string_persistence ); - table->colinfo[ i ].tablename = msi_string_lookup_id( db->strings, table_id ); + table->colinfo[ i ].tablename = msi_string_lookup( db->strings, table_id, NULL ); table->colinfo[ i ].number = i + 1; - table->colinfo[ i ].colname = msi_string_lookup_id( db->strings, col_id ); + table->colinfo[ i ].colname = msi_string_lookup( db->strings, col_id, NULL ); table->colinfo[ i ].type = col->type; table->colinfo[ i ].offset = 0; table->colinfo[ i ].ref_count = 0; @@ -981,7 +981,7 @@ BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name ) !strcmpW( name, szStreams ) || !strcmpW( name, szStorages ) ) return TRUE; - r = msi_string2idW( db->strings, name, &table_id ); + r = msi_string2id( db->strings, name, -1, &table_id ); if( r != ERROR_SUCCESS ) { TRACE("Couldn't find id for %s\n", debugstr_w(name)); @@ -1087,7 +1087,7 @@ static UINT msi_stream_name( const MSITABLEVIEW *tv, UINT row, LPWSTR *pstname ) if ( tv->columns[i].type & MSITYPE_STRING ) { - sval = msi_string_lookup_id( tv->db->strings, ival ); + sval = msi_string_lookup( tv->db->strings, ival, NULL ); if ( !sval ) { r = ERROR_INVALID_PARAMETER; @@ -1276,7 +1276,7 @@ static UINT get_table_value_from_record( MSITABLEVIEW *tv, MSIRECORD *rec, UINT LPCWSTR sval = MSI_RecordGetString( rec, iField ); if (sval) { - r = msi_string2idW(tv->db->strings, sval, pvalue); + r = msi_string2id(tv->db->strings, sval, -1, pvalue); if (r != ERROR_SUCCESS) return ERROR_NOT_FOUND; } @@ -2343,7 +2343,7 @@ static MSIRECORD *msi_get_transform_record( const MSITABLEVIEW *tv, const string LPCWSTR sval; val = read_raw_int(rawdata, ofs, bytes_per_strref); - sval = msi_string_lookup_id( st, val ); + sval = msi_string_lookup( st, val, NULL ); MSI_RecordSetStringW( rec, i+1, sval ); TRACE(" field %d [%s]\n", i+1, debugstr_w(sval)); ofs += bytes_per_strref; @@ -2395,13 +2395,12 @@ static void dump_record( MSIRECORD *rec ) static void dump_table( const string_table *st, const USHORT *rawdata, UINT rawsize ) { - LPCWSTR sval; UINT i; - - for( i=0; i<(rawsize/2); i++ ) + for (i = 0; i < rawsize / 2; i++) { - sval = msi_string_lookup_id( st, rawdata[i] ); - MESSAGE(" %04x %s\n", rawdata[i], debugstr_w(sval) ); + int len; + const WCHAR *sval = msi_string_lookup( st, rawdata[i], &len ); + MESSAGE(" %04x %s\n", rawdata[i], debugstr_wn(sval, len) ); } } @@ -2425,7 +2424,7 @@ static UINT* msi_record_to_row( const MSITABLEVIEW *tv, MSIRECORD *rec ) str = MSI_RecordGetString( rec, i+1 ); if (str) { - r = msi_string2idW( tv->db->strings, str, &data[i] ); + r = msi_string2id( tv->db->strings, str, -1, &data[i] ); /* if there's no matching string in the string table, these keys can't match any record, so fail now. */ diff --git a/dlls/msi/where.c b/dlls/msi/where.c index 36c8ec83e01..45fda442bc8 100644 --- a/dlls/msi/where.c +++ b/dlls/msi/where.c @@ -494,7 +494,7 @@ static UINT STRING_evaluate( MSIWHEREVIEW *wv, const UINT rows[], case EXPR_COL_NUMBER_STRING: r = expr_fetch_value(&expr->u.column, rows, &val); if (r == ERROR_SUCCESS) - *str = msi_string_lookup_id(wv->db->strings, val); + *str = msi_string_lookup(wv->db->strings, val, NULL); else *str = NULL; break; @@ -883,7 +883,7 @@ static UINT join_find_row( MSIWHEREVIEW *wv, MSIRECORD *rec, UINT *row ) UINT r, i, id, data; str = MSI_RecordGetString( rec, 1 ); - r = msi_string2idW( wv->db->strings, str, &id ); + r = msi_string2id( wv->db->strings, str, -1, &id ); if (r != ERROR_SUCCESS) return r;