When loading table data, split it up into rows.
[wine.git] / dlls / msi / string.c
bloba1345f25e20cb0fa00ad76460effcc422feeed98
1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2002 Mike McCormack for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <stdarg.h>
22 #include <assert.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "wine/debug.h"
28 #include "msi.h"
29 #include "msiquery.h"
30 #include "objbase.h"
31 #include "objidl.h"
32 #include "msipriv.h"
33 #include "winnls.h"
35 #include "query.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msi);
39 typedef struct _msistring
41 UINT hash;
42 UINT refcount;
43 LPSTR str;
44 } msistring;
46 struct string_table
48 UINT count; /* the number of strings */
49 UINT freeslot;
50 msistring *strings; /* an array of strings (in the tree) */
53 static int msistring_makehash( char *str )
55 int hash = 0;
57 while( *str )
59 hash ^= *str++;
60 hash *= 53;
61 hash = (hash<<5) || (hash>>27);
63 return hash;
66 string_table *msi_init_stringtable( int entries )
68 string_table *st;
70 st = HeapAlloc( GetProcessHeap(), 0, sizeof (string_table) );
71 if( !st )
72 return NULL;
73 st->strings = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
74 sizeof (msistring) * entries );
75 if( !st )
77 HeapFree( GetProcessHeap(), 0, st );
78 return NULL;
80 st->count = entries;
81 st->freeslot = 0;
83 return st;
86 VOID msi_destroy_stringtable( string_table *st )
88 UINT i;
90 for( i=0; i<st->count; i++ )
92 if( st->strings[i].refcount )
93 HeapFree( GetProcessHeap(), 0, st->strings[i].str );
95 HeapFree( GetProcessHeap(), 0, st->strings );
96 HeapFree( GetProcessHeap(), 0, st );
99 static int st_find_free_entry( string_table *st )
101 int i;
103 for( i = st->freeslot; i < st->count; i++ )
104 if( !st->strings[i].refcount )
105 return i;
106 for( i = 0; i < st->freeslot; i++ )
107 if( !st->strings[i].refcount )
108 return i;
110 FIXME("dynamically resize\n");
112 return -1;
115 static void st_mark_entry_used( string_table *st, int n )
117 if( n >= st->count )
118 return;
119 st->freeslot = n + 1;
122 int msi_addstring( string_table *st, UINT string_no, CHAR *data, UINT len, UINT refcount )
124 int n;
126 /* TRACE("[%2d] = %s\n", string_no, debugstr_an(data,len) ); */
128 n = st_find_free_entry( st );
129 if( n < 0 )
130 return -1;
132 /* allocate a new string */
133 if( len < 0 )
134 len = strlen( data );
135 st->strings[n].str = HeapAlloc( GetProcessHeap(), 0, len + 1 );
136 if( !st->strings[n].str )
137 return -1;
138 memcpy( st->strings[n].str, data, len );
139 st->strings[n].str[len] = 0;
140 st->strings[n].refcount = 1;
141 st->strings[n].hash = msistring_makehash( st->strings[n].str );
143 st_mark_entry_used( st, n );
145 return n;
148 UINT msi_id2stringW( string_table *st, UINT string_no, LPWSTR buffer, UINT *sz )
150 UINT len;
151 LPSTR str;
153 TRACE("Finding string %d of %d\n", string_no, st->count);
154 if( string_no >= st->count )
155 return ERROR_FUNCTION_FAILED;
157 if( !st->strings[string_no].refcount )
158 return ERROR_FUNCTION_FAILED;
160 str = st->strings[string_no].str;
161 len = strlen( str );
163 if( !buffer )
165 *sz = MultiByteToWideChar(CP_ACP,0,str,len,NULL,0);
166 return ERROR_SUCCESS;
169 len = MultiByteToWideChar(CP_ACP,0,str,len+1,buffer,*sz);
170 if (!len) buffer[*sz-1] = 0;
171 else *sz = len;
173 return ERROR_SUCCESS;
176 UINT msi_id2stringA( string_table *st, UINT string_no, LPSTR buffer, UINT *sz )
178 UINT len;
179 LPSTR str;
181 TRACE("Finding string %d of %d\n", string_no, st->count);
182 if( string_no >= st->count )
183 return ERROR_FUNCTION_FAILED;
185 if( !st->strings[string_no].refcount )
186 return ERROR_FUNCTION_FAILED;
188 str = st->strings[string_no].str;
189 len = strlen( str );
191 if( !buffer )
193 *sz = len;
194 return ERROR_SUCCESS;
197 if (len >= *sz) len = *sz - 1;
198 memcpy( buffer, str, len );
199 buffer[len] = 0;
200 *sz = len+1;
202 return ERROR_SUCCESS;
205 UINT msi_string2id( string_table *st, LPCWSTR buffer, UINT *id )
207 DWORD sz;
208 UINT i, r = ERROR_INVALID_PARAMETER;
209 LPSTR str;
210 int hash;
212 TRACE("Finding string %s in string table\n", debugstr_w(buffer) );
214 sz = WideCharToMultiByte( CP_ACP, 0, buffer, -1, NULL, 0, NULL, NULL );
215 if( sz <= 0 )
216 return r;
217 str = HeapAlloc( GetProcessHeap(), 0, sz );
218 if( !str )
219 return ERROR_NOT_ENOUGH_MEMORY;
220 WideCharToMultiByte( CP_ACP, 0, buffer, -1, str, sz, NULL, NULL );
222 hash = msistring_makehash( str );
223 for( i=0; i<st->count; i++)
225 if( ( st->strings[i].hash == hash ) &&
226 !strcmp( st->strings[i].str, str ) )
228 r = ERROR_SUCCESS;
229 *id = i;
230 break;
234 if( str )
235 HeapFree( GetProcessHeap(), 0, str );
237 return r;
240 UINT msi_string_count( string_table *st )
242 return st->count;
245 UINT msi_id_refcount( string_table *st, UINT i )
247 if( i >= st->count )
248 return 0;
249 return st->strings[i].refcount;
252 UINT msi_string_totalsize( string_table *st )
254 UINT size = 0, i;
256 for( i=0; i<st->count; i++)
258 if( st->strings[i].str )
259 size += strlen( st->strings[i].str );
261 return size;