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