ReactOS  0.4.14-dev-293-g2b39b42
string.c
Go to the documentation of this file.
1 /*
2  * String Table Functions
3  *
4  * Copyright 2002-2004, Mike McCormack for CodeWeavers
5  * Copyright 2007 Robert Shearman for CodeWeavers
6  * Copyright 2010 Hans Leidekker for CodeWeavers
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 
23 #define COBJMACROS
24 
25 #include <stdarg.h>
26 #include <assert.h>
27 
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winerror.h"
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
33 #include "msi.h"
34 #include "msiquery.h"
35 #include "objbase.h"
36 #include "objidl.h"
37 #include "msipriv.h"
38 #include "winnls.h"
39 
40 #include "query.h"
41 
43 
44 struct msistring
45 {
49  int len;
50 };
51 
53 {
54  UINT maxcount; /* the number of strings */
58  struct msistring *strings; /* an array of strings */
59  UINT *sorted; /* index */
60 };
61 
63 {
65  {
66  WARN("invalid codepage %u\n", codepage);
67  return FALSE;
68  }
69  return TRUE;
70 }
71 
72 static string_table *init_stringtable( int entries, UINT codepage )
73 {
74  string_table *st;
75 
77  return NULL;
78 
79  st = msi_alloc( sizeof (string_table) );
80  if( !st )
81  return NULL;
82  if( entries < 1 )
83  entries = 1;
84 
85  st->strings = msi_alloc_zero( sizeof(struct msistring) * entries );
86  if( !st->strings )
87  {
88  msi_free( st );
89  return NULL;
90  }
91 
92  st->sorted = msi_alloc( sizeof (UINT) * entries );
93  if( !st->sorted )
94  {
95  msi_free( st->strings );
96  msi_free( st );
97  return NULL;
98  }
99 
100  st->maxcount = entries;
101  st->freeslot = 1;
102  st->codepage = codepage;
103  st->sortcount = 0;
104 
105  return st;
106 }
107 
109 {
110  UINT i;
111 
112  for( i=0; i<st->maxcount; i++ )
113  {
114  if( st->strings[i].persistent_refcount ||
115  st->strings[i].nonpersistent_refcount )
116  msi_free( st->strings[i].data );
117  }
118  msi_free( st->strings );
119  msi_free( st->sorted );
120  msi_free( st );
121 }
122 
124 {
125  UINT i, sz, *s;
126  struct msistring *p;
127 
128  TRACE("%p\n", st);
129 
130  if( st->freeslot )
131  {
132  for( i = st->freeslot; i < st->maxcount; i++ )
133  if( !st->strings[i].persistent_refcount &&
134  !st->strings[i].nonpersistent_refcount )
135  return i;
136  }
137  for( i = 1; i < st->maxcount; i++ )
138  if( !st->strings[i].persistent_refcount &&
139  !st->strings[i].nonpersistent_refcount )
140  return i;
141 
142  /* dynamically resize */
143  sz = st->maxcount + 1 + st->maxcount/2;
144  p = msi_realloc_zero( st->strings, sz * sizeof(struct msistring) );
145  if( !p )
146  return -1;
147 
148  s = msi_realloc( st->sorted, sz*sizeof(UINT) );
149  if( !s )
150  {
151  msi_free( p );
152  return -1;
153  }
154 
155  st->strings = p;
156  st->sorted = s;
157 
158  st->freeslot = st->maxcount;
159  st->maxcount = sz;
160  if( st->strings[st->freeslot].persistent_refcount ||
161  st->strings[st->freeslot].nonpersistent_refcount )
162  ERR("oops. expected freeslot to be free...\n");
163  return st->freeslot;
164 }
165 
166 static inline int cmp_string( const WCHAR *str1, int len1, const WCHAR *str2, int len2 )
167 {
168  if (len1 < len2) return -1;
169  else if (len1 > len2) return 1;
170  while (len1)
171  {
172  if (*str1 == *str2) { str1++; str2++; }
173  else return *str1 - *str2;
174  len1--;
175  }
176  return 0;
177 }
178 
179 static int find_insert_index( const string_table *st, UINT string_id )
180 {
181  int i, c, low = 0, high = st->sortcount - 1;
182 
183  while (low <= high)
184  {
185  i = (low + high) / 2;
186  c = cmp_string( st->strings[string_id].data, st->strings[string_id].len,
187  st->strings[st->sorted[i]].data, st->strings[st->sorted[i]].len );
188  if (c < 0)
189  high = i - 1;
190  else if (c > 0)
191  low = i + 1;
192  else
193  return -1; /* already exists */
194  }
195  return high + 1;
196 }
197 
198 static void insert_string_sorted( string_table *st, UINT string_id )
199 {
200  int i;
201 
202  i = find_insert_index( st, string_id );
203  if (i == -1)
204  return;
205 
206  memmove( &st->sorted[i] + 1, &st->sorted[i], (st->sortcount - i) * sizeof(UINT) );
207  st->sorted[i] = string_id;
208  st->sortcount++;
209 }
210 
211 static void set_st_entry( string_table *st, UINT n, WCHAR *str, int len, USHORT refcount,
212  enum StringPersistence persistence )
213 {
214  if (persistence == StringPersistent)
215  {
216  st->strings[n].persistent_refcount = refcount;
217  st->strings[n].nonpersistent_refcount = 0;
218  }
219  else
220  {
221  st->strings[n].persistent_refcount = 0;
222  st->strings[n].nonpersistent_refcount = refcount;
223  }
224 
225  st->strings[n].data = str;
226  st->strings[n].len = len;
227 
228  insert_string_sorted( st, n );
229 
230  if( n < st->maxcount )
231  st->freeslot = n + 1;
232 }
233 
234 static UINT string2id( const string_table *st, const char *buffer, UINT *id )
235 {
236  DWORD sz;
238  LPWSTR str;
239 
240  TRACE("Finding string %s in string table\n", debugstr_a(buffer) );
241 
242  if( buffer[0] == 0 )
243  {
244  *id = 0;
245  return ERROR_SUCCESS;
246  }
247 
248  sz = MultiByteToWideChar( st->codepage, 0, buffer, -1, NULL, 0 );
249  if( sz <= 0 )
250  return r;
251  str = msi_alloc( sz*sizeof(WCHAR) );
252  if( !str )
254  MultiByteToWideChar( st->codepage, 0, buffer, -1, str, sz );
255 
256  r = msi_string2id( st, str, sz - 1, id );
257  msi_free( str );
258  return r;
259 }
260 
261 static int add_string( string_table *st, UINT n, const char *data, UINT len, USHORT refcount, enum StringPersistence persistence )
262 {
263  LPWSTR str;
264  int sz;
265 
266  if( !data || !len )
267  return 0;
268  if( n > 0 )
269  {
270  if( st->strings[n].persistent_refcount ||
271  st->strings[n].nonpersistent_refcount )
272  return -1;
273  }
274  else
275  {
276  if (string2id( st, data, &n ) == ERROR_SUCCESS)
277  {
278  if (persistence == StringPersistent)
279  st->strings[n].persistent_refcount += refcount;
280  else
281  st->strings[n].nonpersistent_refcount += refcount;
282  return n;
283  }
284  n = st_find_free_entry( st );
285  if( n == -1 )
286  return -1;
287  }
288 
289  if( n < 1 )
290  {
291  ERR("invalid index adding %s (%d)\n", debugstr_a( data ), n );
292  return -1;
293  }
294 
295  /* allocate a new string */
296  sz = MultiByteToWideChar( st->codepage, 0, data, len, NULL, 0 );
297  str = msi_alloc( (sz+1)*sizeof(WCHAR) );
298  if( !str )
299  return -1;
300  MultiByteToWideChar( st->codepage, 0, data, len, str, sz );
301  str[sz] = 0;
302 
303  set_st_entry( st, n, str, sz, refcount, persistence );
304  return n;
305 }
306 
307 int msi_add_string( string_table *st, const WCHAR *data, int len, enum StringPersistence persistence )
308 {
309  UINT n;
310  LPWSTR str;
311 
312  if( !data )
313  return 0;
314 
315  if (len < 0) len = strlenW( data );
316 
317  if( !data[0] && !len )
318  return 0;
319 
320  if (msi_string2id( st, data, len, &n) == ERROR_SUCCESS )
321  {
322  if (persistence == StringPersistent)
323  st->strings[n].persistent_refcount++;
324  else
325  st->strings[n].nonpersistent_refcount++;
326  return n;
327  }
328 
329  n = st_find_free_entry( st );
330  if( n == -1 )
331  return -1;
332 
333  /* allocate a new string */
334  TRACE( "%s, n = %d len = %d\n", debugstr_wn(data, len), n, len );
335 
336  str = msi_alloc( (len+1)*sizeof(WCHAR) );
337  if( !str )
338  return -1;
339  memcpy( str, data, len*sizeof(WCHAR) );
340  str[len] = 0;
341 
342  set_st_entry( st, n, str, len, 1, persistence );
343  return n;
344 }
345 
346 /* find the string identified by an id - return null if there's none */
347 const WCHAR *msi_string_lookup( const string_table *st, UINT id, int *len )
348 {
349  if( id == 0 )
350  {
351  if (len) *len = 0;
352  return szEmpty;
353  }
354  if( id >= st->maxcount )
355  return NULL;
356 
357  if( id && !st->strings[id].persistent_refcount && !st->strings[id].nonpersistent_refcount)
358  return NULL;
359 
360  if (len) *len = st->strings[id].len;
361 
362  return st->strings[id].data;
363 }
364 
365 /*
366  * id2string
367  *
368  * [in] st - pointer to the string table
369  * [in] id - id of the string to retrieve
370  * [out] buffer - destination of the UTF8 string
371  * [in/out] sz - number of bytes available in the buffer on input
372  * number of bytes used on output
373  *
374  * Returned string is not nul terminated.
375  */
376 static UINT id2string( const string_table *st, UINT id, char *buffer, UINT *sz )
377 {
378  int len, lenW;
379  const WCHAR *str;
380 
381  TRACE("Finding string %d of %d\n", id, st->maxcount);
382 
383  str = msi_string_lookup( st, id, &lenW );
384  if( !str )
385  return ERROR_FUNCTION_FAILED;
386 
387  len = WideCharToMultiByte( st->codepage, 0, str, lenW, NULL, 0, NULL, NULL );
388  if( *sz < len )
389  {
390  *sz = len;
391  return ERROR_MORE_DATA;
392  }
393  *sz = WideCharToMultiByte( st->codepage, 0, str, lenW, buffer, *sz, NULL, NULL );
394  return ERROR_SUCCESS;
395 }
396 
397 /*
398  * msi_string2id
399  *
400  * [in] st - pointer to the string table
401  * [in] str - string to find in the string table
402  * [out] id - id of the string, if found
403  */
404 UINT msi_string2id( const string_table *st, const WCHAR *str, int len, UINT *id )
405 {
406  int i, c, low = 0, high = st->sortcount - 1;
407 
408  if (len < 0) len = strlenW( str );
409 
410  while (low <= high)
411  {
412  i = (low + high) / 2;
413  c = cmp_string( str, len, st->strings[st->sorted[i]].data, st->strings[st->sorted[i]].len );
414 
415  if (c < 0)
416  high = i - 1;
417  else if (c > 0)
418  low = i + 1;
419  else
420  {
421  *id = st->sorted[i];
422  return ERROR_SUCCESS;
423  }
424  }
426 }
427 
428 static void string_totalsize( const string_table *st, UINT *datasize, UINT *poolsize )
429 {
430  UINT i, len, holesize;
431 
432  if( st->strings[0].data || st->strings[0].persistent_refcount || st->strings[0].nonpersistent_refcount)
433  ERR("oops. element 0 has a string\n");
434 
435  *poolsize = 4;
436  *datasize = 0;
437  holesize = 0;
438  for( i=1; i<st->maxcount; i++ )
439  {
440  if( !st->strings[i].persistent_refcount )
441  {
442  TRACE("[%u] nonpersistent = %s\n", i, debugstr_wn(st->strings[i].data, st->strings[i].len));
443  (*poolsize) += 4;
444  }
445  else if( st->strings[i].data )
446  {
447  TRACE("[%u] = %s\n", i, debugstr_wn(st->strings[i].data, st->strings[i].len));
448  len = WideCharToMultiByte( st->codepage, 0, st->strings[i].data, st->strings[i].len + 1,
449  NULL, 0, NULL, NULL);
450  if( len )
451  len--;
452  (*datasize) += len;
453  if (len>0xffff)
454  (*poolsize) += 4;
455  (*poolsize) += holesize + 4;
456  holesize = 0;
457  }
458  else
459  holesize += 4;
460  }
461  TRACE("data %u pool %u codepage %x\n", *datasize, *poolsize, st->codepage );
462 }
463 
465 {
466  USHORT zero[2] = { 0, 0 };
467  UINT ret;
468 
469  /* create the StringPool stream... add the zero string to it*/
470  ret = write_stream_data(stg, szStringPool, zero, sizeof zero, TRUE);
471  if (ret != ERROR_SUCCESS)
472  return E_FAIL;
473 
474  /* create the StringData stream... make it zero length */
476  if (ret != ERROR_SUCCESS)
477  return E_FAIL;
478 
479  return S_OK;
480 }
481 
482 string_table *msi_load_string_table( IStorage *stg, UINT *bytes_per_strref )
483 {
484  string_table *st = NULL;
485  CHAR *data = NULL;
486  USHORT *pool = NULL;
487  UINT r, datasize = 0, poolsize = 0, codepage;
488  DWORD i, count, offset, len, n, refs;
489 
490  r = read_stream_data( stg, szStringPool, TRUE, (BYTE **)&pool, &poolsize );
491  if( r != ERROR_SUCCESS)
492  goto end;
493  r = read_stream_data( stg, szStringData, TRUE, (BYTE **)&data, &datasize );
494  if( r != ERROR_SUCCESS)
495  goto end;
496 
497  if ( (poolsize > 4) && (pool[1] & 0x8000) )
498  *bytes_per_strref = LONG_STR_BYTES;
499  else
500  *bytes_per_strref = sizeof(USHORT);
501 
502  count = poolsize/4;
503  if( poolsize > 4 )
504  codepage = pool[0] | ( (pool[1] & ~0x8000) << 16 );
505  else
506  codepage = CP_ACP;
508  if (!st)
509  goto end;
510 
511  offset = 0;
512  n = 1;
513  i = 1;
514  while( i<count )
515  {
516  /* the string reference count is always the second word */
517  refs = pool[i*2+1];
518 
519  /* empty entries have two zeros, still have a string id */
520  if (pool[i*2] == 0 && refs == 0)
521  {
522  i++;
523  n++;
524  continue;
525  }
526 
527  /*
528  * If a string is over 64k, the previous string entry is made null
529  * and its the high word of the length is inserted in the null string's
530  * reference count field.
531  */
532  if( pool[i*2] == 0)
533  {
534  len = (pool[i*2+3] << 16) + pool[i*2+2];
535  i += 2;
536  }
537  else
538  {
539  len = pool[i*2];
540  i += 1;
541  }
542 
543  if ( (offset + len) > datasize )
544  {
545  ERR("string table corrupt?\n");
546  break;
547  }
548 
549  r = add_string( st, n, data+offset, len, refs, StringPersistent );
550  if( r != n )
551  ERR("Failed to add string %d\n", n );
552  n++;
553  offset += len;
554  }
555 
556  if ( datasize != offset )
557  ERR("string table load failed! (%08x != %08x), please report\n", datasize, offset );
558 
559  TRACE("Loaded %d strings\n", count);
560 
561 end:
562  msi_free( pool );
563  msi_free( data );
564 
565  return st;
566 }
567 
568 UINT msi_save_string_table( const string_table *st, IStorage *storage, UINT *bytes_per_strref )
569 {
570  UINT i, datasize = 0, poolsize = 0, sz, used, r, codepage, n;
572  CHAR *data = NULL;
573  USHORT *pool = NULL;
574 
575  TRACE("\n");
576 
577  /* construct the new table in memory first */
578  string_totalsize( st, &datasize, &poolsize );
579 
580  TRACE("%u %u %u\n", st->maxcount, datasize, poolsize );
581 
582  pool = msi_alloc( poolsize );
583  if( ! pool )
584  {
585  WARN("Failed to alloc pool %d bytes\n", poolsize );
586  goto err;
587  }
588  data = msi_alloc( datasize );
589  if( ! data )
590  {
591  WARN("Failed to alloc data %d bytes\n", datasize );
592  goto err;
593  }
594 
595  used = 0;
596  codepage = st->codepage;
597  pool[0] = codepage & 0xffff;
598  pool[1] = codepage >> 16;
599  if (st->maxcount > 0xffff)
600  {
601  pool[1] |= 0x8000;
602  *bytes_per_strref = LONG_STR_BYTES;
603  }
604  else
605  *bytes_per_strref = sizeof(USHORT);
606 
607  n = 1;
608  for( i=1; i<st->maxcount; i++ )
609  {
610  if( !st->strings[i].persistent_refcount )
611  {
612  pool[ n*2 ] = 0;
613  pool[ n*2 + 1] = 0;
614  n++;
615  continue;
616  }
617 
618  sz = datasize - used;
619  r = id2string( st, i, data+used, &sz );
620  if( r != ERROR_SUCCESS )
621  {
622  ERR("failed to fetch string\n");
623  sz = 0;
624  }
625 
626  if (sz)
627  pool[ n*2 + 1 ] = st->strings[i].persistent_refcount;
628  else
629  pool[ n*2 + 1 ] = 0;
630  if (sz < 0x10000)
631  {
632  pool[ n*2 ] = sz;
633  n++;
634  }
635  else
636  {
637  pool[ n*2 ] = 0;
638  pool[ n*2 + 2 ] = sz&0xffff;
639  pool[ n*2 + 3 ] = (sz>>16);
640  n += 2;
641  }
642  used += sz;
643  if( used > datasize )
644  {
645  ERR("oops overran %d >= %d\n", used, datasize);
646  goto err;
647  }
648  }
649 
650  if( used != datasize )
651  {
652  ERR("oops used %d != datasize %d\n", used, datasize);
653  goto err;
654  }
655 
656  /* write the streams */
658  TRACE("Wrote StringData r=%08x\n", r);
659  if( r )
660  goto err;
661  r = write_stream_data( storage, szStringPool, pool, poolsize, TRUE );
662  TRACE("Wrote StringPool r=%08x\n", r);
663  if( r )
664  goto err;
665 
666  ret = ERROR_SUCCESS;
667 
668 err:
669  msi_free( data );
670  msi_free( pool );
671 
672  return ret;
673 }
674 
676 {
677  return st->codepage;
678 }
679 
681 {
683  {
684  st->codepage = codepage;
685  return ERROR_SUCCESS;
686  }
687  return ERROR_FUNCTION_FAILED;
688 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
StringPersistence
Definition: msipriv.h:757
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define TRUE
Definition: types.h:120
USHORT persistent_refcount
Definition: string.c:46
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
static SIZE_T datasize
Definition: asm.c:30
#define ERROR_SUCCESS
Definition: deptool.c:10
#define WideCharToMultiByte
Definition: compat.h:101
static void string_totalsize(const string_table *st, UINT *datasize, UINT *poolsize)
Definition: string.c:428
USHORT nonpersistent_refcount
Definition: string.c:47
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define CP_ACP
Definition: compat.h:99
GLuint GLuint GLsizei count
Definition: gl.h:1545
static UINT string2id(const string_table *st, const char *buffer, UINT *id)
Definition: string.c:234
char CHAR
Definition: xmlstorage.h:175
#define WARN(fmt,...)
Definition: debug.h:111
GLintptr offset
Definition: glext.h:5920
GLdouble n
Definition: glext.h:7729
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
UINT write_stream_data(IStorage *stg, LPCWSTR stname, LPCVOID data, UINT sz, BOOL bTable) DECLSPEC_HIDDEN
Definition: table.c:306
#define LONG_STR_BYTES
Definition: msipriv.h:54
GLuint buffer
Definition: glext.h:5915
static void insert_string_sorted(string_table *st, UINT string_id)
Definition: string.c:198
int msi_add_string(string_table *st, const WCHAR *data, int len, enum StringPersistence persistence)
Definition: string.c:307
GLuint GLuint end
Definition: gl.h:1545
UINT freeslot
Definition: string.c:55
#define E_FAIL
Definition: ddrawi.h:102
static void * msi_realloc(void *mem, size_t len) __WINE_ALLOC_SIZE(2)
Definition: msipriv.h:1216
static void * msi_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1210
WCHAR * data
Definition: string.c:48
static string_table * init_stringtable(int entries, UINT codepage)
Definition: string.c:72
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985
unsigned int BOOL
Definition: ntddk_ex.h:94
UINT msi_set_string_table_codepage(string_table *st, UINT codepage)
Definition: string.c:680
struct msistring * strings
Definition: string.c:58
UINT msi_save_string_table(const string_table *st, IStorage *storage, UINT *bytes_per_strref)
Definition: string.c:568
int codepage
Definition: win_iconv.c:156
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
UINT sortcount
Definition: string.c:57
c used
Definition: write.c:2877
static const WCHAR szEmpty[]
Definition: provider.c:50
UINT msi_get_string_table_codepage(const string_table *st)
Definition: string.c:675
#define TRACE(s)
Definition: solgame.cpp:4
string_table * msi_load_string_table(IStorage *stg, UINT *bytes_per_strref)
Definition: string.c:482
VOID msi_destroy_stringtable(string_table *st)
Definition: string.c:108
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define debugstr_a
Definition: kernel32.h:31
LONG HRESULT
Definition: typedefs.h:77
WINE_DEFAULT_DEBUG_CHANNEL(commctrl)
UINT maxcount
Definition: string.c:54
static UINT id2string(const string_table *st, UINT id, char *buffer, UINT *sz)
Definition: string.c:376
const GLubyte * c
Definition: glext.h:8905
static int cmp_string(const WCHAR *str1, int len1, const WCHAR *str2, int len2)
Definition: string.c:166
unsigned long DWORD
Definition: ntddk_ex.h:95
int len
Definition: string.c:49
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
static void set_st_entry(string_table *st, UINT n, WCHAR *str, int len, USHORT refcount, enum StringPersistence persistence)
Definition: string.c:211
static size_t len
Definition: string.c:60
static BOOL validate_codepage(UINT codepage)
Definition: string.c:62
HRESULT msi_init_string_table(IStorage *stg)
Definition: string.c:464
int ret
static double zero
Definition: j0_y0.c:96
static const WCHAR szStringPool[]
Definition: msipriv.h:1189
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
GLdouble s
Definition: gl.h:2039
#define err(...)
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define debugstr_wn
Definition: kernel32.h:33
#define ERR(fmt,...)
Definition: debug.h:109
#define S_OK
Definition: intsafe.h:59
BOOL WINAPI IsValidCodePage(UINT CodePage)
Definition: nls.c:1484
UINT msi_string2id(const string_table *st, const WCHAR *str, int len, UINT *id)
Definition: string.c:404
UINT codepage
Definition: string.c:56
unsigned short USHORT
Definition: pedump.c:61
static int st_find_free_entry(string_table *st)
Definition: string.c:123
const WCHAR * msi_string_lookup(const string_table *st, UINT id, int *len)
Definition: string.c:347
static size_t const unsigned char size_t count
Definition: string.c:63
static int find_insert_index(const string_table *st, UINT string_id)
Definition: string.c:179
unsigned int UINT
Definition: ndis.h:50
#define MultiByteToWideChar
Definition: compat.h:100
static const WCHAR szStringData[]
Definition: msipriv.h:1188
static BOOL msi_free(void *mem)
Definition: msipriv.h:1227
#define c
Definition: ke_i.h:80
static void * msi_alloc(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1204
GLenum GLuint id
Definition: glext.h:5579
UINT * sorted
Definition: string.c:59
static void * msi_realloc_zero(void *mem, size_t len) __WINE_ALLOC_SIZE(2)
Definition: msipriv.h:1222
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
static int add_string(string_table *st, UINT n, const char *data, UINT len, USHORT refcount, enum StringPersistence persistence)
Definition: string.c:261
static HRESULT read_stream_data(nsChannelBSC *This, IStream *stream)
Definition: navigate.c:960