ReactOS  0.4.14-dev-606-g14ebc0b
parser.c
Go to the documentation of this file.
1 /*
2  * INF file parsing
3  *
4  * Copyright 2002 Alexandre Julliard for CodeWeavers
5  * 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 /* Partially synced with Wine Staging 2.2 */
23 
24 #include "setupapi_private.h"
25 
26 #include <ndk/obfuncs.h>
27 
28 /* Unicode constants */
29 static const WCHAR BackSlash[] = {'\\',0};
30 static const WCHAR Class[] = {'C','l','a','s','s',0};
31 static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0};
32 static const WCHAR InfDirectory[] = {'i','n','f','\\',0};
33 static const WCHAR InfFileSpecification[] = {'*','.','i','n','f',0};
34 
35 #define CONTROL_Z '\x1a'
36 #define MAX_SECTION_NAME_LEN 255
37 #define MAX_FIELD_LEN 511 /* larger fields get silently truncated */
38 /* actual string limit is MAX_INF_STRING_LENGTH+1 (plus terminating null) under Windows */
39 #define MAX_STRING_LEN (MAX_INF_STRING_LENGTH+1)
40 
41 /* inf file structure definitions */
42 
43 struct field
44 {
45  const WCHAR *text; /* field text */
46 };
47 
48 struct line
49 {
50  int first_field; /* index of first field in field array */
51  int nb_fields; /* number of fields in line */
52  int key_field; /* index of field for key or -1 if no key */
53 };
54 
55 struct section
56 {
57  const WCHAR *name; /* section name */
58  unsigned int nb_lines; /* number of used lines */
59  unsigned int alloc_lines; /* total number of allocated lines in array below */
60  struct line lines[16]; /* lines information (grown dynamically, 16 is initial size) */
61 };
62 
63 struct inf_file
64 {
65  struct inf_file *next; /* next appended file */
66  WCHAR *strings; /* buffer for string data (section names and field values) */
67  WCHAR *string_pos; /* position of next available string in buffer */
68  unsigned int nb_sections; /* number of used sections */
69  unsigned int alloc_sections; /* total number of allocated section pointers */
70  struct section **sections; /* section pointers array */
71  unsigned int nb_fields;
72  unsigned int alloc_fields;
73  struct field *fields;
74  int strings_section; /* index of [Strings] section or -1 if none */
75  WCHAR *filename; /* filename of the INF */
76 };
77 
78 /* parser definitions */
79 
81 {
82  LINE_START, /* at beginning of a line */
83  SECTION_NAME, /* parsing a section name */
84  KEY_NAME, /* parsing a key name */
85  VALUE_NAME, /* parsing a value name */
86  EOL_BACKSLASH, /* backslash at end of line */
87  QUOTES, /* inside quotes */
88  LEADING_SPACES, /* leading spaces */
89  TRAILING_SPACES, /* trailing spaces */
90  COMMENT, /* inside a comment */
92 };
93 
94 struct parser
95 {
96  const WCHAR *start; /* start position of item being parsed */
97  const WCHAR *end; /* end of buffer */
98  struct inf_file *file; /* file being built */
99  enum parser_state state; /* current parser state */
100  enum parser_state stack[4]; /* state stack */
101  int stack_pos; /* current pos in stack */
102 
103  int cur_section; /* index of section being parsed*/
104  struct line *line; /* current line */
105  unsigned int line_pos; /* current line position in file */
106  unsigned int broken_line; /* first line containing invalid data (if any) */
107  unsigned int error; /* error code */
108  unsigned int token_len; /* current token len */
109  WCHAR token[MAX_FIELD_LEN+1]; /* current token */
110 };
111 
112 typedef const WCHAR * (*parser_state_func)( struct parser *parser, const WCHAR *pos );
113 
114 /* parser state machine functions */
115 static const WCHAR *line_start_state( struct parser *parser, const WCHAR *pos );
116 static const WCHAR *section_name_state( struct parser *parser, const WCHAR *pos );
117 static const WCHAR *key_name_state( struct parser *parser, const WCHAR *pos );
118 static const WCHAR *value_name_state( struct parser *parser, const WCHAR *pos );
119 static const WCHAR *eol_backslash_state( struct parser *parser, const WCHAR *pos );
120 static const WCHAR *quotes_state( struct parser *parser, const WCHAR *pos );
121 static const WCHAR *leading_spaces_state( struct parser *parser, const WCHAR *pos );
122 static const WCHAR *trailing_spaces_state( struct parser *parser, const WCHAR *pos );
123 static const WCHAR *comment_state( struct parser *parser, const WCHAR *pos );
124 
126 {
127  line_start_state, /* LINE_START */
128  section_name_state, /* SECTION_NAME */
129  key_name_state, /* KEY_NAME */
130  value_name_state, /* VALUE_NAME */
131  eol_backslash_state, /* EOL_BACKSLASH */
132  quotes_state, /* QUOTES */
133  leading_spaces_state, /* LEADING_SPACES */
134  trailing_spaces_state, /* TRAILING_SPACES */
135  comment_state /* COMMENT */
136 };
137 
138 
139 /* Unicode string constants */
140 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
141 static const WCHAR Signature[] = {'S','i','g','n','a','t','u','r','e',0};
142 static const WCHAR Chicago[] = {'$','C','h','i','c','a','g','o','$',0};
143 static const WCHAR WindowsNT[] = {'$','W','i','n','d','o','w','s',' ','N','T','$',0};
144 static const WCHAR Windows95[] = {'$','W','i','n','d','o','w','s',' ','9','5','$',0};
145 static const WCHAR LayoutFile[] = {'L','a','y','o','u','t','F','i','l','e',0};
146 
147 /* extend an array, allocating more memory if necessary */
148 static void *grow_array( void *array, unsigned int *count, size_t elem )
149 {
150  void *new_array;
151  unsigned int new_count = *count + *count / 2;
152  if (new_count < 32) new_count = 32;
153 
154  if (array)
155  new_array = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, array, new_count * elem );
156  else
157  new_array = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * elem );
158 
159  if (new_array)
160  *count = new_count;
161  else
162  HeapFree( GetProcessHeap(), 0, array );
163  return new_array;
164 }
165 
166 
167 /* get the directory of the inf file (as counted string, not null-terminated) */
168 static const WCHAR *get_inf_dir( const struct inf_file *file, unsigned int *len )
169 {
170  const WCHAR *p = strrchrW( file->filename, '\\' );
171  *len = p ? (p + 1 - file->filename) : 0;
172  return file->filename;
173 }
174 
175 
176 /* find a section by name */
177 static int find_section( const struct inf_file *file, const WCHAR *name )
178 {
179  unsigned int i;
180 
181  for (i = 0; i < file->nb_sections; i++)
182  if (!strcmpiW( name, file->sections[i]->name )) return i;
183  return -1;
184 }
185 
186 
187 /* find a line by name */
188 static struct line *find_line( struct inf_file *file, int section_index, const WCHAR *name )
189 {
190  struct section *section;
191  struct line *line;
192  unsigned int i;
193 
194  if (section_index < 0 || section_index >= file->nb_sections) return NULL;
195  section = file->sections[section_index];
196  for (i = 0, line = section->lines; i < section->nb_lines; i++, line++)
197  {
198  if (line->key_field == -1) continue;
199  if (!strcmpiW( name, file->fields[line->key_field].text )) return line;
200  }
201  return NULL;
202 }
203 
204 
205 /* add a section to the file and return the section index */
206 static int add_section( struct inf_file *file, const WCHAR *name )
207 {
208  struct section *section;
209 
210  if (file->nb_sections >= file->alloc_sections)
211  {
212  if (!(file->sections = grow_array( file->sections, &file->alloc_sections,
213  sizeof(file->sections[0]) ))) return -1;
214  }
215  if (!(section = HeapAlloc( GetProcessHeap(), 0, sizeof(*section) ))) return -1;
216  section->name = name;
217  section->nb_lines = 0;
218  section->alloc_lines = sizeof(section->lines)/sizeof(section->lines[0]);
219  file->sections[file->nb_sections] = section;
220  return file->nb_sections++;
221 }
222 
223 
224 /* add a line to a given section */
225 static struct line *add_line( struct inf_file *file, int section_index )
226 {
227  struct section *section;
228  struct line *line;
229 
230  ASSERT( section_index >= 0 && section_index < file->nb_sections );
231 
232  section = file->sections[section_index];
233  if (section->nb_lines == section->alloc_lines) /* need to grow the section */
234  {
235  int size = sizeof(*section) - sizeof(section->lines) + 2*section->alloc_lines*sizeof(*line);
236  if (!(section = HeapReAlloc( GetProcessHeap(), 0, section, size ))) return NULL;
237  section->alloc_lines *= 2;
238  file->sections[section_index] = section;
239  }
241  line->first_field = file->nb_fields;
242  line->nb_fields = 0;
243  line->key_field = -1;
244  return line;
245 }
246 
247 
248 /* retrieve a given line from section/line index */
249 static inline struct line *get_line( struct inf_file *file, unsigned int section_index,
250  unsigned int line_index )
251 {
252  struct section *section;
253 
254  if (section_index >= file->nb_sections) return NULL;
255  section = file->sections[section_index];
256  if (line_index >= section->nb_lines) return NULL;
257  return &section->lines[line_index];
258 }
259 
260 
261 /* retrieve a given field from section/line/field index */
262 static struct field *get_field( struct inf_file *file, int section_index, int line_index,
263  int field_index )
264 {
265  struct line *line = get_line( file, section_index, line_index );
266 
267  if (!line) return NULL;
268  if (!field_index) /* get the key */
269  {
270  if (line->key_field == -1) return NULL;
271  return &file->fields[line->key_field];
272  }
273  field_index--;
274  if (field_index >= line->nb_fields) return NULL;
275  return &file->fields[line->first_field + field_index];
276 }
277 
278 
279 /* allocate a new field, growing the array if necessary */
280 static struct field *add_field( struct inf_file *file, const WCHAR *text )
281 {
282  struct field *field;
283 
284  if (file->nb_fields >= file->alloc_fields)
285  {
286  if (!(file->fields = grow_array( file->fields, &file->alloc_fields,
287  sizeof(file->fields[0]) ))) return NULL;
288  }
289  field = &file->fields[file->nb_fields++];
290  field->text = text;
291  return field;
292 }
293 
294 
295 /* retrieve the string substitution for a directory id */
296 static const WCHAR *get_dirid_subst( const struct inf_file *file, int dirid, unsigned int *len )
297 {
298  const WCHAR *ret;
299 
300  if (dirid == DIRID_SRCPATH) return get_inf_dir( file, len );
301  ret = DIRID_get_string( dirid );
302  if (ret) *len = strlenW(ret);
303  return ret;
304 }
305 
306 
307 /* retrieve the string substitution for a given string, or NULL if not found */
308 /* if found, len is set to the substitution length */
309 static const WCHAR *get_string_subst( const struct inf_file *file, const WCHAR *str, unsigned int *len,
310  BOOL no_trailing_slash )
311 {
312  static const WCHAR percent = '%';
313 
314  struct section *strings_section;
315  struct line *line;
316  struct field *field;
317  unsigned int i, j;
318  int dirid;
319  WCHAR *dirid_str, *end;
320  const WCHAR *ret = NULL;
321  WCHAR StringLangId[13] = {'S','t','r','i','n','g','s','.',0};
322  TCHAR Lang[5];
323 
324  if (!*len) /* empty string (%%) is replaced by single percent */
325  {
326  *len = 1;
327  return &percent;
328  }
329  if (file->strings_section == -1) goto not_found;
330  strings_section = file->sections[file->strings_section];
331  for (j = 0, line = strings_section->lines; j < strings_section->nb_lines; j++, line++)
332  {
333  if (line->key_field == -1) continue;
334  if (strncmpiW( str, file->fields[line->key_field].text, *len )) continue;
335  if (!file->fields[line->key_field].text[*len]) break;
336  }
337  if (j == strings_section->nb_lines || !line->nb_fields) goto not_found;
338  field = &file->fields[line->first_field];
339  GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_ILANGUAGE, Lang, sizeof(Lang)/sizeof(TCHAR)); // get the current system locale for translated strings
340 
341  strcpyW(StringLangId + 8, Lang + 2);
342  // now you have e.g. Strings.07 for german neutral translations
343  for (i = 0; i < file->nb_sections; i++) // search in all sections
344  {
345  if (!strcmpiW(file->sections[i]->name,StringLangId)) // if the section is a Strings.* section
346  {
347  strings_section = file->sections[i]; // select this section for further use
348  for (j = 0, line = strings_section->lines; j < strings_section->nb_lines; j++, line++) // process all lines in this section
349  {
350  if (line->key_field == -1) continue; // if no key then skip
351  if (strncmpiW( str, file->fields[line->key_field].text, *len )) continue; // if wrong key name, then skip
352  if (!file->fields[line->key_field].text[*len]) // if value exist
353  {
354  field = &file->fields[line->first_field]; // then extract value and
355  break; // no more search necessary
356  }
357  }
358  }
359  }
360 
361  strcpyW(StringLangId + 8, Lang); // append the Language identifier from GetLocaleInfo
362  // now you have e.g. Strings.0407 for german translations
363  for (i = 0; i < file->nb_sections; i++) // search in all sections
364  {
365  if (!strcmpiW(file->sections[i]->name,StringLangId)) // if the section is a Strings.* section
366  {
367  strings_section = file->sections[i]; // select this section for further use
368  for (j = 0, line = strings_section->lines; j < strings_section->nb_lines; j++, line++) // process all lines in this section
369  {
370  if (line->key_field == -1) continue; // if no key then skip
371  if (strncmpiW( str, file->fields[line->key_field].text, *len )) continue; // if wrong key name, then skip
372  if (!file->fields[line->key_field].text[*len]) // if value exist
373  {
374  field = &file->fields[line->first_field]; // then extract value and
375  break; // no more search necessary
376  }
377  }
378  }
379  }
380  *len = strlenW( field->text ); // set length
381  ret = field->text; // return the english or translated string
382  return ret;
383 
384 
385  not_found: /* check for integer id */
386  if ((dirid_str = HeapAlloc( GetProcessHeap(), 0, (*len+1) * sizeof(WCHAR) )))
387  {
388  memcpy( dirid_str, str, *len * sizeof(WCHAR) );
389  dirid_str[*len] = 0;
390  dirid = strtolW( dirid_str, &end, 10 );
391  if (!*end) ret = get_dirid_subst( file, dirid, len );
392  if (no_trailing_slash && ret && *len && ret[*len - 1] == '\\') *len -= 1;
393  HeapFree( GetProcessHeap(), 0, dirid_str );
394  return ret;
395  }
396  return NULL;
397 }
398 
399 
400 /* do string substitutions on the specified text */
401 /* the buffer is assumed to be large enough */
402 /* returns necessary length not including terminating null */
403 static unsigned int PARSER_string_substW( const struct inf_file *file, const WCHAR *text,
404  WCHAR *buffer, unsigned int size )
405 {
406  const WCHAR *start, *subst, *p;
407  unsigned int len, total = 0;
408  BOOL inside = FALSE;
409 
410  if (!buffer) size = MAX_STRING_LEN + 1;
411  for (p = start = text; *p; p++)
412  {
413  if (*p != '%') continue;
414  inside = !inside;
415  if (inside) /* start of a %xx% string */
416  {
417  len = p - start;
418  if (len > size - 1) len = size - 1;
419  if (buffer) memcpy( buffer + total, start, len * sizeof(WCHAR) );
420  total += len;
421  size -= len;
422  start = p;
423  }
424  else /* end of the %xx% string, find substitution */
425  {
426  len = p - start - 1;
427  subst = get_string_subst( file, start + 1, &len, p[1] == '\\' );
428  if (!subst)
429  {
430  subst = start;
431  len = p - start + 1;
432  }
433  if (len > size - 1) len = size - 1;
434  if (buffer) memcpy( buffer + total, subst, len * sizeof(WCHAR) );
435  total += len;
436  size -= len;
437  start = p + 1;
438  }
439  }
440 
441  if (start != p) /* unfinished string, copy it */
442  {
443  len = p - start;
444  if (len > size - 1) len = size - 1;
445  if (buffer) memcpy( buffer + total, start, len * sizeof(WCHAR) );
446  total += len;
447  }
448  if (buffer && size) buffer[total] = 0;
449  return total;
450 }
451 
452 
453 /* do string substitutions on the specified text */
454 /* the buffer is assumed to be large enough */
455 /* returns necessary length not including terminating null */
456 static unsigned int PARSER_string_substA( const struct inf_file *file, const WCHAR *text,
457  char *buffer, unsigned int size )
458 {
459  WCHAR buffW[MAX_STRING_LEN+1];
460  DWORD ret;
461 
462  unsigned int len = PARSER_string_substW( file, text, buffW, sizeof(buffW)/sizeof(WCHAR) );
463  if (!buffer) RtlUnicodeToMultiByteSize( &ret, buffW, len * sizeof(WCHAR) );
464  else
465  {
466  RtlUnicodeToMultiByteN( buffer, size-1, &ret, buffW, len * sizeof(WCHAR) );
467  buffer[ret] = 0;
468  }
469  return ret;
470 }
471 
472 
473 /* push some string data into the strings buffer */
474 static WCHAR *push_string( struct inf_file *file, const WCHAR *string )
475 {
476  WCHAR *ret = file->string_pos;
477  strcpyW( ret, string );
478  file->string_pos += strlenW( ret ) + 1;
479  return ret;
480 }
481 
482 
483 /* push the current state on the parser stack */
484 static inline void push_state( struct parser *parser, enum parser_state state )
485 {
486  ASSERT( parser->stack_pos < sizeof(parser->stack)/sizeof(parser->stack[0]) );
488 }
489 
490 
491 /* pop the current state */
492 static inline void pop_state( struct parser *parser )
493 {
494  ASSERT( parser->stack_pos );
496 }
497 
498 
499 /* set the parser state and return the previous one */
500 static inline enum parser_state set_state( struct parser *parser, enum parser_state state )
501 {
502  enum parser_state ret = parser->state;
503  parser->state = state;
504  return ret;
505 }
506 
507 
508 /* check if the pointer points to an end of file */
509 static inline BOOL is_eof( const struct parser *parser, const WCHAR *ptr )
510 {
511  return (ptr >= parser->end || *ptr == CONTROL_Z);
512 }
513 
514 
515 /* check if the pointer points to an end of line */
516 static inline BOOL is_eol( const struct parser *parser, const WCHAR *ptr )
517 {
518  return (ptr >= parser->end || *ptr == CONTROL_Z || *ptr == '\n');
519 }
520 
521 
522 /* push data from current token start up to pos into the current token */
523 static int push_token( struct parser *parser, const WCHAR *pos )
524 {
525  int len = pos - parser->start;
526  const WCHAR *src = parser->start;
528 
530 
531  parser->token_len += len;
532  for ( ; len > 0; len--, dst++, src++) *dst = *src ? *src : ' ';
533  *dst = 0;
534  parser->start = pos;
535  return 0;
536 }
537 
538 
539 /* add a section with the current token as name */
540 static int add_section_from_token( struct parser *parser )
541 {
542  int section_index;
543 
545  {
547  return -1;
548  }
549  if ((section_index = find_section( parser->file, parser->token )) == -1)
550  {
551  /* need to create a new one */
552  const WCHAR *name = push_string( parser->file, parser->token );
553  if ((section_index = add_section( parser->file, name )) == -1)
554  {
556  return -1;
557  }
558  }
559  parser->token_len = 0;
560  parser->cur_section = section_index;
561  return section_index;
562 }
563 
564 
565 /* add a field containing the current token to the current line */
566 static struct field *add_field_from_token( struct parser *parser, BOOL is_key )
567 {
568  struct field *field;
569  WCHAR *text;
570 
571  if (!parser->line) /* need to start a new line */
572  {
573  if (parser->cur_section == -1) /* got a line before the first section */
574  {
576  return NULL;
577  }
578  if (!(parser->line = add_line( parser->file, parser->cur_section ))) goto error;
579  }
580  else ASSERT(!is_key);
581 
583  if ((field = add_field( parser->file, text )))
584  {
585  if (!is_key) parser->line->nb_fields++;
586  else
587  {
588  /* replace first field by key field */
589  parser->line->key_field = parser->line->first_field;
590  parser->line->first_field++;
591  }
592  parser->token_len = 0;
593  return field;
594  }
595  error:
597  return NULL;
598 }
599 
600 
601 /* close the current line and prepare for parsing a new one */
602 static void close_current_line( struct parser *parser )
603 {
604  struct line *cur_line = parser->line;
605 
606  if (cur_line)
607  {
608  /* if line has a single field and no key, the field is the key too */
609  if (cur_line->nb_fields == 1 && cur_line->key_field == -1)
610  cur_line->key_field = cur_line->first_field;
611  }
612  parser->line = NULL;
613 }
614 
615 
616 /* handler for parser LINE_START state */
617 static const WCHAR *line_start_state( struct parser *parser, const WCHAR *pos )
618 {
619  const WCHAR *p;
620 
621  for (p = pos; !is_eof( parser, p ); p++)
622  {
623  switch(*p)
624  {
625  case '\n':
626  parser->line_pos++;
628  break;
629  case ';':
632  return p + 1;
633  case '[':
634  parser->start = p + 1;
636  return p + 1;
637  default:
638  if (isspaceW(*p)) break;
639  if (parser->cur_section != -1)
640  {
641  parser->start = p;
643  return p;
644  }
645  if (!parser->broken_line)
647  break;
648  }
649  }
651  return NULL;
652 }
653 
654 
655 /* handler for parser SECTION_NAME state */
656 static const WCHAR *section_name_state( struct parser *parser, const WCHAR *pos )
657 {
658  const WCHAR *p;
659 
660  for (p = pos; !is_eol( parser, p ); p++)
661  {
662  if (*p == ']')
663  {
664  push_token( parser, p );
665  if (add_section_from_token( parser ) == -1) return NULL;
667  set_state( parser, COMMENT ); /* ignore everything else on the line */
668  return p + 1;
669  }
670  }
671  parser->error = ERROR_BAD_SECTION_NAME_LINE; /* unfinished section name */
672  return NULL;
673 }
674 
675 
676 /* handler for parser KEY_NAME state */
677 static const WCHAR *key_name_state( struct parser *parser, const WCHAR *pos )
678 {
679  const WCHAR *p, *token_end = parser->start;
680 
681  for (p = pos; !is_eol( parser, p ); p++)
682  {
683  if (*p == ',') break;
684  switch(*p)
685  {
686 
687  case '=':
688  push_token( parser, token_end );
689  if (!add_field_from_token( parser, TRUE )) return NULL;
690  parser->start = p + 1;
693  return p + 1;
694  case ';':
695  push_token( parser, token_end );
696  if (!add_field_from_token( parser, FALSE )) return NULL;
699  return p + 1;
700  case '"':
701  push_token( parser, p );
702  parser->start = p + 1;
704  set_state( parser, QUOTES );
705  return p + 1;
706  case '\\':
707  push_token( parser, token_end );
708  parser->start = p;
711  return p;
712  default:
713  if (!isspaceW(*p)) token_end = p + 1;
714  else
715  {
716  push_token( parser, p );
719  return p;
720  }
721  break;
722  }
723  }
724  push_token( parser, token_end );
726  return p;
727 }
728 
729 
730 /* handler for parser VALUE_NAME state */
731 static const WCHAR *value_name_state( struct parser *parser, const WCHAR *pos )
732 {
733  const WCHAR *p, *token_end = parser->start;
734 
735  for (p = pos; !is_eol( parser, p ); p++)
736  {
737  switch(*p)
738  {
739  case ';':
740  push_token( parser, token_end );
741  if (!add_field_from_token( parser, FALSE )) return NULL;
744  return p + 1;
745  case ',':
746  push_token( parser, token_end );
747  if (!add_field_from_token( parser, FALSE )) return NULL;
748  parser->start = p + 1;
751  return p + 1;
752  case '"':
753  push_token( parser, p );
754  parser->start = p + 1;
756  set_state( parser, QUOTES );
757  return p + 1;
758  case '\\':
759  push_token( parser, token_end );
760  parser->start = p;
763  return p;
764  default:
765  if (!isspaceW(*p)) token_end = p + 1;
766  else
767  {
768  push_token( parser, p );
771  return p;
772  }
773  break;
774  }
775  }
776  push_token( parser, token_end );
777  if (!add_field_from_token( parser, FALSE )) return NULL;
779  return p;
780 }
781 
782 
783 /* handler for parser EOL_BACKSLASH state */
784 static const WCHAR *eol_backslash_state( struct parser *parser, const WCHAR *pos )
785 {
786  const WCHAR *p;
787 
788  for (p = pos; !is_eof( parser, p ); p++)
789  {
790  switch(*p)
791  {
792  case '\n':
793  parser->line_pos++;
794  parser->start = p + 1;
796  return p + 1;
797  case '\\':
798  continue;
799  case ';':
802  return p + 1;
803  default:
804  if (isspaceW(*p)) continue;
805  push_token( parser, p );
806  pop_state( parser );
807  return p;
808  }
809  }
810  parser->start = p;
811  pop_state( parser );
812  return p;
813 }
814 
815 
816 /* handler for parser QUOTES state */
817 static const WCHAR *quotes_state( struct parser *parser, const WCHAR *pos )
818 {
819  const WCHAR *p;
820 
821  for (p = pos; !is_eol( parser, p ); p++)
822  {
823  if (*p == '"')
824  {
825  if (p+1 < parser->end && p[1] == '"') /* double quotes */
826  {
827  push_token( parser, p + 1 );
828  parser->start = p + 2;
829  p++;
830  }
831  else /* end of quotes */
832  {
833  push_token( parser, p );
834  parser->start = p + 1;
835  pop_state( parser );
836  return p + 1;
837  }
838  }
839  }
840  push_token( parser, p );
841  pop_state( parser );
842  return p;
843 }
844 
845 
846 /* handler for parser LEADING_SPACES state */
847 static const WCHAR *leading_spaces_state( struct parser *parser, const WCHAR *pos )
848 {
849  const WCHAR *p;
850 
851  for (p = pos; !is_eol( parser, p ); p++)
852  {
853  if (*p == '\\')
854  {
855  parser->start = p;
857  return p;
858  }
859  if (!isspaceW(*p)) break;
860  }
861  parser->start = p;
862  pop_state( parser );
863  return p;
864 }
865 
866 
867 /* handler for parser TRAILING_SPACES state */
868 static const WCHAR *trailing_spaces_state( struct parser *parser, const WCHAR *pos )
869 {
870  const WCHAR *p;
871 
872  for (p = pos; !is_eol( parser, p ); p++)
873  {
874  if (*p == '\\')
875  {
877  return p;
878  }
879  if (!isspaceW(*p)) break;
880  }
881  pop_state( parser );
882  return p;
883 }
884 
885 
886 /* handler for parser COMMENT state */
887 static const WCHAR *comment_state( struct parser *parser, const WCHAR *pos )
888 {
889  const WCHAR *p = pos;
890 
891  while (!is_eol( parser, p )) p++;
892  pop_state( parser );
893  return p;
894 }
895 
896 
897 static void free_inf_file( struct inf_file *file )
898 {
899  unsigned int i;
900 
901  for (i = 0; i < file->nb_sections; i++) HeapFree( GetProcessHeap(), 0, file->sections[i] );
902  HeapFree( GetProcessHeap(), 0, file->filename );
903  HeapFree( GetProcessHeap(), 0, file->sections );
904  HeapFree( GetProcessHeap(), 0, file->fields );
905  HeapFree( GetProcessHeap(), 0, file->strings );
906  HeapFree( GetProcessHeap(), 0, file );
907 }
908 
909 
910 /* parse a complete buffer */
911 static DWORD parse_buffer( struct inf_file *file, const WCHAR *buffer, const WCHAR *end,
912  UINT *error_line )
913 {
914  static const WCHAR Strings[] = {'S','t','r','i','n','g','s',0};
915 
916  struct parser parser;
917  const WCHAR *pos = buffer;
918 
919  parser.start = buffer;
920  parser.end = end;
921  parser.file = file;
922  parser.line = NULL;
924  parser.stack_pos = 0;
925  parser.cur_section = -1;
926  parser.line_pos = 1;
927  parser.broken_line = 0;
928  parser.error = 0;
929  parser.token_len = 0;
930 
931  /* parser main loop */
932  while (pos) pos = (parser_funcs[parser.state])( &parser, pos );
933 
934  /* trim excess buffer space */
935  if (file->alloc_sections > file->nb_sections)
936  {
937  file->sections = HeapReAlloc( GetProcessHeap(), 0, file->sections,
938  file->nb_sections * sizeof(file->sections[0]) );
939  file->alloc_sections = file->nb_sections;
940  }
941  if (file->alloc_fields > file->nb_fields)
942  {
943  file->fields = HeapReAlloc( GetProcessHeap(), 0, file->fields,
944  file->nb_fields * sizeof(file->fields[0]) );
945  file->alloc_fields = file->nb_fields;
946  }
948  (file->string_pos - file->strings) * sizeof(WCHAR) );
949 
950  if (parser.error)
951  {
952  if (error_line) *error_line = parser.line_pos;
953  return parser.error;
954  }
955 
956  /* find the [strings] section */
957  file->strings_section = find_section( file, Strings );
958 
959  if (file->strings_section == -1 && parser.broken_line)
960  {
961  if (error_line) *error_line = parser.broken_line;
963  }
964 
965  return 0;
966 }
967 
968 
969 /* append a child INF file to its parent list, in a thread-safe manner */
970 static void append_inf_file( struct inf_file *parent, struct inf_file *child )
971 {
972  struct inf_file **ppnext = &parent->next;
973  child->next = NULL;
974 
975  for (;;)
976  {
977  struct inf_file *next = InterlockedCompareExchangePointer( (void **)ppnext, child, NULL );
978  if (!next) return;
979  ppnext = &next->next;
980  }
981 }
982 
983 
984 /***********************************************************************
985  * parse_file
986  *
987  * parse an INF file.
988  */
989 static struct inf_file *parse_file( HANDLE handle, UINT *error_line, DWORD style )
990 {
991  void *buffer;
992  DWORD err = 0;
993  struct inf_file *file;
994 
997  if (!mapping) return NULL;
999  NtClose( mapping );
1000  if (!buffer) return NULL;
1001 
1002  if (!(file = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*file) )))
1003  {
1005  goto done;
1006  }
1007 
1008  /* we won't need more strings space than the size of the file,
1009  * so we can preallocate it here
1010  */
1011  if (!(file->strings = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) )))
1012  {
1014  goto done;
1015  }
1016  file->string_pos = file->strings;
1017  file->strings_section = -1;
1018 
1019  if (!RtlIsTextUnicode( buffer, size, NULL ))
1020  {
1021  static const BYTE utf8_bom[3] = { 0xef, 0xbb, 0xbf };
1022  WCHAR *new_buff;
1023  UINT codepage = CP_ACP;
1024  UINT offset = 0;
1025 
1026  if (size > sizeof(utf8_bom) && !memcmp( buffer, utf8_bom, sizeof(utf8_bom) ))
1027  {
1028  codepage = CP_UTF8;
1029  offset = sizeof(utf8_bom);
1030  }
1031 
1032  if ((new_buff = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) )))
1033  {
1035  size - offset, new_buff, size );
1036  err = parse_buffer( file, new_buff, new_buff + len, error_line );
1037  HeapFree( GetProcessHeap(), 0, new_buff );
1038  }
1039  }
1040  else
1041  {
1042  WCHAR *new_buff = buffer;
1043  /* UCS-16 files should start with the Unicode BOM; we should skip it */
1044  if (*new_buff == 0xfeff)
1045  new_buff++;
1046  err = parse_buffer( file, new_buff, (WCHAR *)((char *)buffer + size), error_line );
1047  }
1048 
1049  if (!err) /* now check signature */
1050  {
1051  int version_index = find_section( file, Version );
1052  if (version_index != -1)
1053  {
1054  struct line *line = find_line( file, version_index, Signature );
1055  if (line && line->nb_fields > 0)
1056  {
1057  struct field *field = file->fields + line->first_field;
1058  if (!strcmpiW( field->text, Chicago )) goto done;
1059  if (!strcmpiW( field->text, WindowsNT )) goto done;
1060  if (!strcmpiW( field->text, Windows95 )) goto done;
1061  }
1062  }
1063  if (error_line) *error_line = 0;
1065  }
1066 
1067  done:
1069  if (err)
1070  {
1071  if (file) free_inf_file( file );
1072  SetLastError( err );
1073  file = NULL;
1074  }
1075  return file;
1076 }
1077 
1078 
1079 /***********************************************************************
1080  * PARSER_get_inf_filename
1081  *
1082  * Retrieve the filename of an inf file.
1083  */
1085 {
1086  struct inf_file *file = hinf;
1087  return file->filename;
1088 }
1089 
1090 
1091 /***********************************************************************
1092  * PARSER_get_src_root
1093  *
1094  * Retrieve the source directory of an inf file.
1095  */
1097 {
1098  unsigned int len;
1099  const WCHAR *dir = get_inf_dir( hinf, &len );
1100  WCHAR *ret = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) );
1101  if (ret)
1102  {
1103  memcpy( ret, dir, len * sizeof(WCHAR) );
1104  ret[len] = 0;
1105  }
1106  return ret;
1107 }
1108 
1109 
1110 /***********************************************************************
1111  * PARSER_get_dest_dir
1112  *
1113  * retrieve a destination dir of the form "dirid,relative_path" in the given entry.
1114  * returned buffer must be freed by caller.
1115  */
1117 {
1118  const WCHAR *dir;
1119  WCHAR *ptr, *ret;
1120  INT dirid;
1121  unsigned int len1;
1122  DWORD len2;
1123 
1124  if (!SetupGetIntField( context, 1, &dirid )) return NULL;
1125  if (!(dir = get_dirid_subst( context->Inf, dirid, &len1 ))) return NULL;
1126  if (!SetupGetStringFieldW( context, 2, NULL, 0, &len2 )) len2 = 0;
1127  if (!(ret = HeapAlloc( GetProcessHeap(), 0, (len1+len2+1) * sizeof(WCHAR) ))) return NULL;
1128  memcpy( ret, dir, len1 * sizeof(WCHAR) );
1129  ptr = ret + len1;
1130  if (len2 && ptr > ret && ptr[-1] != '\\') *ptr++ = '\\';
1131  if (!SetupGetStringFieldW( context, 2, ptr, len2, NULL )) *ptr = 0;
1132  return ret;
1133 }
1134 
1135 
1136 /***********************************************************************
1137  * SetupOpenInfFileA (SETUPAPI.@)
1138  */
1140 {
1143 
1144  classW.Buffer = NULL;
1145  if (class && !RtlCreateUnicodeStringFromAsciiz( &classW, class ))
1146  {
1148  return ret;
1149  }
1151  {
1152  ret = SetupOpenInfFileW( nameW.Buffer, classW.Buffer, style, error );
1154  }
1156  return ret;
1157 }
1158 
1159 
1160 static BOOL
1162  IN HINF hInf,
1163  OUT LPGUID ClassGuid,
1164  OUT PWSTR ClassName,
1165  IN DWORD ClassNameSize,
1167 {
1168  DWORD requiredSize;
1169  WCHAR guidW[MAX_GUID_STRING_LEN + 1];
1170  BOOL ret = FALSE;
1171 
1172  /* Read class Guid */
1173  if (!SetupGetLineTextW(NULL, hInf, Version, ClassGUID, guidW, sizeof(guidW), NULL))
1174  goto cleanup;
1175  guidW[37] = '\0'; /* Replace the } by a NULL character */
1176  if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK)
1177  goto cleanup;
1178 
1179  /* Read class name */
1180  ret = SetupGetLineTextW(NULL, hInf, Version, Class, ClassName, ClassNameSize, &requiredSize);
1181  if (ret && ClassName == NULL && ClassNameSize == 0)
1182  {
1183  if (RequiredSize)
1184  *RequiredSize = requiredSize;
1186  ret = FALSE;
1187  goto cleanup;
1188  }
1189  if (!ret)
1190  {
1192  {
1193  if (RequiredSize)
1194  *RequiredSize = requiredSize;
1195  goto cleanup;
1196  }
1197  else if (!SetupDiClassNameFromGuidW(ClassGuid, ClassName, ClassNameSize, &requiredSize))
1198  {
1200  {
1201  if (RequiredSize)
1202  *RequiredSize = requiredSize;
1203  goto cleanup;
1204  }
1205  /* Return a NULL class name */
1206  if (RequiredSize)
1207  *RequiredSize = 1;
1208  if (ClassNameSize < 1)
1209  {
1211  goto cleanup;
1212  }
1213  memcpy(ClassGuid, &GUID_NULL, sizeof(GUID));
1214  *ClassName = UNICODE_NULL;
1215  }
1216  }
1217 
1218  ret = TRUE;
1219 
1220 cleanup:
1221  TRACE("Returning %d\n", ret);
1222  return ret;
1223 }
1224 
1225 
1226 /***********************************************************************
1227  * SetupOpenInfFileW (SETUPAPI.@)
1228  */
1230 {
1231  struct inf_file *file = NULL;
1232  HANDLE handle;
1233  WCHAR *path, *p;
1234  UINT len;
1235 
1236  TRACE("%s %s %lx %p\n", debugstr_w(name), debugstr_w(class), style, error);
1237 
1239  {
1241  return (HINF)INVALID_HANDLE_VALUE;
1242  }
1243 
1244  if (strchrW( name, '\\' ) || strchrW( name, '/' ))
1245  {
1246  if (!(len = GetFullPathNameW( name, 0, NULL, NULL ))) return INVALID_HANDLE_VALUE;
1247  if (!(path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1248  {
1250  return INVALID_HANDLE_VALUE;
1251  }
1254  }
1255  else /* try Windows directory */
1256  {
1257  static const WCHAR Inf[] = {'\\','i','n','f','\\',0};
1258  static const WCHAR System32[] = {'\\','s','y','s','t','e','m','3','2','\\',0};
1259 
1260  len = GetWindowsDirectoryW( NULL, 0 ) + strlenW(name) + 12;
1261  if (!(path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1262  {
1264  return INVALID_HANDLE_VALUE;
1265  }
1267  p = path + strlenW(path);
1268  strcpyW( p, Inf );
1269  strcatW( p, name );
1272  {
1273  strcpyW( p, System32 );
1274  strcatW( p, name );
1276  }
1277  }
1278 
1280  {
1282  CloseHandle( handle );
1283  }
1284  if (!file)
1285  {
1286  HeapFree( GetProcessHeap(), 0, path );
1287  return INVALID_HANDLE_VALUE;
1288  }
1289  TRACE( "%s -> %p\n", debugstr_w(path), file );
1290  file->filename = path;
1291 
1292  if (class)
1293  {
1294  GUID ClassGuid;
1295  LPWSTR ClassName = HeapAlloc(GetProcessHeap(), 0, (strlenW(class) + 1) * sizeof(WCHAR));
1296  if (!ClassName)
1297  {
1298  /* Not enough memory */
1301  return INVALID_HANDLE_VALUE;
1302  }
1303  else if (!PARSER_GetInfClassW((HINF)file, &ClassGuid, ClassName, strlenW(class) + 1, NULL))
1304  {
1305  /* Unable to get class name in .inf file */
1306  HeapFree(GetProcessHeap(), 0, ClassName);
1309  return INVALID_HANDLE_VALUE;
1310  }
1311  else if (strcmpW(class, ClassName) != 0)
1312  {
1313  /* Provided name name is not the expected one */
1314  HeapFree(GetProcessHeap(), 0, ClassName);
1317  return INVALID_HANDLE_VALUE;
1318  }
1319  HeapFree(GetProcessHeap(), 0, ClassName);
1320  }
1321 
1322  SetLastError( 0 );
1323  return file;
1324 }
1325 
1326 
1327 /***********************************************************************
1328  * SetupOpenAppendInfFileA (SETUPAPI.@)
1329  */
1331 {
1332  HINF child_hinf;
1333 
1334  if (!name) return SetupOpenAppendInfFileW( NULL, parent_hinf, error );
1335  child_hinf = SetupOpenInfFileA( name, NULL, INF_STYLE_WIN4, error );
1336  if (child_hinf == INVALID_HANDLE_VALUE) return FALSE;
1337  append_inf_file( parent_hinf, child_hinf );
1338  TRACE( "%p: appended %s (%p)\n", parent_hinf, debugstr_a(name), child_hinf );
1339  return TRUE;
1340 }
1341 
1342 
1343 /***********************************************************************
1344  * SetupOpenAppendInfFileW (SETUPAPI.@)
1345  */
1347 {
1348  HINF child_hinf;
1349 
1350  if (!name)
1351  {
1354  int idx = 1;
1355 
1356  if (!SetupFindFirstLineW( parent_hinf, Version, LayoutFile, &context )) return FALSE;
1358  sizeof(filename)/sizeof(WCHAR), NULL ))
1359  {
1360  child_hinf = SetupOpenInfFileW( filename, NULL, INF_STYLE_WIN4, error );
1361  if (child_hinf == INVALID_HANDLE_VALUE) return FALSE;
1362  append_inf_file( parent_hinf, child_hinf );
1363  TRACE( "%p: appended %s (%p)\n", parent_hinf, debugstr_w(filename), child_hinf );
1364  }
1365  return TRUE;
1366  }
1367  child_hinf = SetupOpenInfFileW( name, NULL, INF_STYLE_WIN4, error );
1368  if (child_hinf == INVALID_HANDLE_VALUE) return FALSE;
1369  append_inf_file( parent_hinf, child_hinf );
1370  TRACE( "%p: appended %s (%p)\n", parent_hinf, debugstr_w(name), child_hinf );
1371  return TRUE;
1372 }
1373 
1374 
1375 /***********************************************************************
1376  * SetupOpenMasterInf (SETUPAPI.@)
1377  */
1379 {
1380  static const WCHAR Layout[] = {'\\','i','n','f','\\', 'l', 'a', 'y', 'o', 'u', 't', '.', 'i', 'n', 'f', 0};
1382 
1384  strcatW( Buffer, Layout );
1386 }
1387 
1388 
1389 
1390 /***********************************************************************
1391  * SetupCloseInfFile (SETUPAPI.@)
1392  */
1394 {
1395  struct inf_file *file = hinf;
1396 
1397  if (!hinf || (hinf == INVALID_HANDLE_VALUE)) return;
1398 
1399  free_inf_file( file );
1400 }
1401 
1402 
1403 /***********************************************************************
1404  * SetupEnumInfSectionsA (SETUPAPI.@)
1405  */
1407 {
1408  struct inf_file *file = hinf;
1409 
1410  for (file = hinf; file; file = file->next)
1411  {
1413  {
1414  DWORD len = WideCharToMultiByte( CP_ACP, 0, file->sections[index]->name, -1,
1415  NULL, 0, NULL, NULL );
1416  if (need) *need = len;
1417  if (!buffer)
1418  {
1419  if (!size) return TRUE;
1421  return FALSE;
1422  }
1423  if (len > size)
1424  {
1426  return FALSE;
1427  }
1428  WideCharToMultiByte( CP_ACP, 0, file->sections[index]->name, -1, buffer, size, NULL, NULL );
1429  return TRUE;
1430  }
1431  index -= file->nb_sections;
1432  }
1434  return FALSE;
1435 }
1436 
1437 
1438 /***********************************************************************
1439  * SetupEnumInfSectionsW (SETUPAPI.@)
1440  */
1442 {
1443  struct inf_file *file = hinf;
1444 
1445  for (file = hinf; file; file = file->next)
1446  {
1448  {
1449  DWORD len = strlenW( file->sections[index]->name ) + 1;
1450  if (need) *need = len;
1451  if (!buffer)
1452  {
1453  if (!size) return TRUE;
1455  return FALSE;
1456  }
1457  if (len > size)
1458  {
1460  return FALSE;
1461  }
1462  memcpy( buffer, file->sections[index]->name, len * sizeof(WCHAR) );
1463  return TRUE;
1464  }
1465  index -= file->nb_sections;
1466  }
1468  return FALSE;
1469 }
1470 
1471 
1472 /***********************************************************************
1473  * SetupGetLineCountA (SETUPAPI.@)
1474  */
1476 {
1477  UNICODE_STRING sectionW;
1478  LONG ret = -1;
1479 
1480  if (!RtlCreateUnicodeStringFromAsciiz( &sectionW, name ))
1482  else
1483  {
1484  ret = SetupGetLineCountW( hinf, sectionW.Buffer );
1485  RtlFreeUnicodeString( &sectionW );
1486  }
1487  return ret;
1488 }
1489 
1490 
1491 /***********************************************************************
1492  * SetupGetLineCountW (SETUPAPI.@)
1493  */
1495 {
1496  struct inf_file *file = hinf;
1497  int section_index;
1498  LONG ret = -1;
1499 
1500  for (file = hinf; file; file = file->next)
1501  {
1502  if ((section_index = find_section( file, section )) == -1) continue;
1503  if (ret == -1) ret = 0;
1504  ret += file->sections[section_index]->nb_lines;
1505  }
1506  TRACE( "(%p,%s) returning %d\n", hinf, debugstr_w(section), ret );
1507  SetLastError( (ret == -1) ? ERROR_SECTION_NOT_FOUND : 0 );
1508  return ret;
1509 }
1510 
1511 
1512 /***********************************************************************
1513  * SetupGetLineByIndexA (SETUPAPI.@)
1514  */
1516 {
1517  UNICODE_STRING sectionW;
1518  BOOL ret = FALSE;
1519 
1520  if (!RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
1522  else
1523  {
1524  ret = SetupGetLineByIndexW( hinf, sectionW.Buffer, index, context );
1525  RtlFreeUnicodeString( &sectionW );
1526  }
1527  return ret;
1528 }
1529 
1530 
1531 /***********************************************************************
1532  * SetupGetLineByIndexW (SETUPAPI.@)
1533  */
1535 {
1536  struct inf_file *file = hinf;
1537  int section_index;
1538 
1539  for (file = hinf; file; file = file->next)
1540  {
1541  if ((section_index = find_section( file, section )) == -1) continue;
1542  if (index < file->sections[section_index]->nb_lines)
1543  {
1544  context->Inf = hinf;
1545  context->CurrentInf = file;
1546  context->Section = section_index;
1547  context->Line = index;
1548  SetLastError( 0 );
1549  TRACE( "(%p,%s): returning %d/%d\n",
1550  hinf, debugstr_w(section), section_index, index );
1551  return TRUE;
1552  }
1553  index -= file->sections[section_index]->nb_lines;
1554  }
1555  TRACE( "(%p,%s) not found\n", hinf, debugstr_w(section) );
1557  return FALSE;
1558 }
1559 
1560 
1561 /***********************************************************************
1562  * SetupFindFirstLineA (SETUPAPI.@)
1563  */
1565 {
1566  UNICODE_STRING sectionW, keyW;
1567  BOOL ret = FALSE;
1568 
1569  if (!RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
1570  {
1572  return FALSE;
1573  }
1574 
1575  if (!key) ret = SetupFindFirstLineW( hinf, sectionW.Buffer, NULL, context );
1576  else
1577  {
1579  {
1580  ret = SetupFindFirstLineW( hinf, sectionW.Buffer, keyW.Buffer, context );
1582  }
1584  }
1585  RtlFreeUnicodeString( &sectionW );
1586  return ret;
1587 }
1588 
1589 
1590 /***********************************************************************
1591  * SetupFindFirstLineW (SETUPAPI.@)
1592  */
1594 {
1595  struct inf_file *file;
1596  int section_index;
1597 
1598  for (file = hinf; file; file = file->next)
1599  {
1600  if ((section_index = find_section( file, section )) == -1) continue;
1601  if (key)
1602  {
1603  INFCONTEXT ctx;
1604  ctx.Inf = hinf;
1605  ctx.CurrentInf = file;
1606  ctx.Section = section_index;
1607  ctx.Line = -1;
1608  return SetupFindNextMatchLineW( &ctx, key, context );
1609  }
1610  if (file->sections[section_index]->nb_lines)
1611  {
1612  context->Inf = hinf;
1613  context->CurrentInf = file;
1614  context->Section = section_index;
1615  context->Line = 0;
1616  SetLastError( 0 );
1617  TRACE( "(%p,%s,%s): returning %d/0\n",
1618  hinf, debugstr_w(section), debugstr_w(key), section_index );
1619  return TRUE;
1620  }
1621  }
1622  TRACE( "(%p,%s,%s): not found\n", hinf, debugstr_w(section), debugstr_w(key) );
1624  return FALSE;
1625 }
1626 
1627 
1628 /***********************************************************************
1629  * SetupFindNextLine (SETUPAPI.@)
1630  */
1632 {
1633  struct inf_file *file = context_in->CurrentInf;
1634  struct section *section;
1635 
1636  if (context_in->Section >= file->nb_sections) goto error;
1637 
1638  section = file->sections[context_in->Section];
1639  if (context_in->Line+1 < section->nb_lines)
1640  {
1641  if (context_out != context_in) *context_out = *context_in;
1642  context_out->Line++;
1643  SetLastError( 0 );
1644  return TRUE;
1645  }
1646 
1647  /* now search the appended files */
1648 
1649  for (file = file->next; file; file = file->next)
1650  {
1651  int section_index = find_section( file, section->name );
1652  if (section_index == -1) continue;
1653  if (file->sections[section_index]->nb_lines)
1654  {
1655  context_out->Inf = context_in->Inf;
1656  context_out->CurrentInf = file;
1657  context_out->Section = section_index;
1658  context_out->Line = 0;
1659  SetLastError( 0 );
1660  return TRUE;
1661  }
1662  }
1663  error:
1665  return FALSE;
1666 }
1667 
1668 
1669 /***********************************************************************
1670  * SetupFindNextMatchLineA (SETUPAPI.@)
1671  */
1673  PINFCONTEXT context_out )
1674 {
1676  BOOL ret = FALSE;
1677 
1678  if (!key) return SetupFindNextLine( context_in, context_out );
1679 
1682  else
1683  {
1684  ret = SetupFindNextMatchLineW( context_in, keyW.Buffer, context_out );
1686  }
1687  return ret;
1688 }
1689 
1690 
1691 /***********************************************************************
1692  * SetupFindNextMatchLineW (SETUPAPI.@)
1693  */
1695  PINFCONTEXT context_out )
1696 {
1697  struct inf_file *file = context_in->CurrentInf;
1698  struct section *section;
1699  struct line *line;
1700  unsigned int i;
1701 
1702  if (!key) return SetupFindNextLine( context_in, context_out );
1703 
1704  if (context_in->Section >= file->nb_sections) goto error;
1705 
1706  section = file->sections[context_in->Section];
1707 
1708  for (i = context_in->Line+1, line = &section->lines[i]; i < section->nb_lines; i++, line++)
1709  {
1710  if (line->key_field == -1) continue;
1711  if (!strcmpiW( key, file->fields[line->key_field].text ))
1712  {
1713  if (context_out != context_in) *context_out = *context_in;
1714  context_out->Line = i;
1715  SetLastError( 0 );
1716  TRACE( "(%p,%s,%s): returning %d\n",
1718  return TRUE;
1719  }
1720  }
1721 
1722  /* now search the appended files */
1723 
1724  for (file = file->next; file; file = file->next)
1725  {
1726  int section_index = find_section( file, section->name );
1727  if (section_index == -1) continue;
1728  section = file->sections[section_index];
1729  for (i = 0, line = section->lines; i < section->nb_lines; i++, line++)
1730  {
1731  if (line->key_field == -1) continue;
1732  if (!strcmpiW( key, file->fields[line->key_field].text ))
1733  {
1734  context_out->Inf = context_in->Inf;
1735  context_out->CurrentInf = file;
1736  context_out->Section = section_index;
1737  context_out->Line = i;
1738  SetLastError( 0 );
1739  TRACE( "(%p,%s,%s): returning %d/%d\n",
1740  file, debugstr_w(section->name), debugstr_w(key), section_index, i );
1741  return TRUE;
1742  }
1743  }
1744  }
1745  TRACE( "(%p,%s,%s): not found\n",
1746  context_in->CurrentInf, debugstr_w(section->name), debugstr_w(key) );
1747  error:
1749  return FALSE;
1750 }
1751 
1752 
1753 /***********************************************************************
1754  * SetupGetLineTextW (SETUPAPI.@)
1755  */
1757  PCWSTR key_name, PWSTR buffer, DWORD size, PDWORD required )
1758 {
1759  struct inf_file *file;
1760  struct line *line;
1761  struct field *field;
1762  int i;
1763  DWORD total = 0;
1764 
1765  if (!context)
1766  {
1767  INFCONTEXT new_context;
1768  if (!SetupFindFirstLineW( hinf, section_name, key_name, &new_context )) return FALSE;
1769  file = new_context.CurrentInf;
1770  line = get_line( file, new_context.Section, new_context.Line );
1771  }
1772  else
1773  {
1774  file = context->CurrentInf;
1775  if (!(line = get_line( file, context->Section, context->Line )))
1776  {
1778  return FALSE;
1779  }
1780  }
1781 
1782  for (i = 0, field = &file->fields[line->first_field]; i < line->nb_fields; i++, field++)
1783  total += PARSER_string_substW( file, field->text, NULL, 0 ) + 1;
1784 
1785  if (required) *required = total;
1786  if (buffer)
1787  {
1788  if (total > size)
1789  {
1791  return FALSE;
1792  }
1793  for (i = 0, field = &file->fields[line->first_field]; i < line->nb_fields; i++, field++)
1794  {
1795  unsigned int len = PARSER_string_substW( file, field->text, buffer, size );
1796  if (i+1 < line->nb_fields) buffer[len] = ',';
1797  buffer += len + 1;
1798  }
1799  }
1800  return TRUE;
1801 }
1802 
1803 
1804 /***********************************************************************
1805  * SetupGetLineTextA (SETUPAPI.@)
1806  */
1808  PCSTR key_name, PSTR buffer, DWORD size, PDWORD required )
1809 {
1810  struct inf_file *file;
1811  struct line *line;
1812  struct field *field;
1813  int i;
1814  DWORD total = 0;
1815 
1816  if (!context)
1817  {
1818  INFCONTEXT new_context;
1819  if (!SetupFindFirstLineA( hinf, section_name, key_name, &new_context )) return FALSE;
1820  file = new_context.CurrentInf;
1821  line = get_line( file, new_context.Section, new_context.Line );
1822  }
1823  else
1824  {
1825  file = context->CurrentInf;
1826  if (!(line = get_line( file, context->Section, context->Line )))
1827  {
1829  return FALSE;
1830  }
1831  }
1832 
1833  for (i = 0, field = &file->fields[line->first_field]; i < line->nb_fields; i++, field++)
1834  total += PARSER_string_substA( file, field->text, NULL, 0 ) + 1;
1835 
1836  if (required) *required = total;
1837  if (buffer)
1838  {
1839  if (total > size)
1840  {
1842  return FALSE;
1843  }
1844  for (i = 0, field = &file->fields[line->first_field]; i < line->nb_fields; i++, field++)
1845  {
1846  unsigned int len = PARSER_string_substA( file, field->text, buffer, size );
1847  if (i+1 < line->nb_fields) buffer[len] = ',';
1848  buffer += len + 1;
1849  }
1850  }
1851  return TRUE;
1852 }
1853 
1854 
1855 /***********************************************************************
1856  * SetupGetFieldCount (SETUPAPI.@)
1857  */
1859 {
1860  struct inf_file *file = context->CurrentInf;
1861  struct line *line = get_line( file, context->Section, context->Line );
1862 
1863  if (!line) return 0;
1864  return line->nb_fields;
1865 }
1866 
1867 
1868 /***********************************************************************
1869  * SetupGetStringFieldA (SETUPAPI.@)
1870  */
1872  DWORD size, PDWORD required )
1873 {
1874  struct inf_file *file = context->CurrentInf;
1875  struct field *field = get_field( file, context->Section, context->Line, index );
1876  unsigned int len;
1877 
1878  SetLastError(0);
1879  if (!field) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; }
1881  if (required) *required = len + 1;
1882  if (buffer)
1883  {
1884  if (size <= len)
1885  {
1887  return FALSE;
1888  }
1890 
1891  TRACE( "context %p/%p/%d/%d index %d returning %s\n",
1892  context->Inf, context->CurrentInf, context->Section, context->Line,
1893  index, debugstr_a(buffer) );
1894  }
1895  return TRUE;
1896 }
1897 
1898 
1899 /***********************************************************************
1900  * SetupGetStringFieldW (SETUPAPI.@)
1901  */
1903  DWORD size, PDWORD required )
1904 {
1905  struct inf_file *file = context->CurrentInf;
1906  struct field *field = get_field( file, context->Section, context->Line, index );
1907  unsigned int len;
1908 
1909  SetLastError(0);
1910  if (!field) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; }
1912  if (required) *required = len + 1;
1913  if (buffer)
1914  {
1915  if (size <= len)
1916  {
1918  return FALSE;
1919  }
1921 
1922  TRACE( "context %p/%p/%d/%d index %d returning %s\n",
1923  context->Inf, context->CurrentInf, context->Section, context->Line,
1924  index, debugstr_w(buffer) );
1925  }
1926  return TRUE;
1927 }
1928 
1929 
1930 /***********************************************************************
1931  * SetupGetIntField (SETUPAPI.@)
1932  */
1934 {
1935  char localbuff[20];
1936  char *end, *buffer = localbuff;
1937  DWORD required;
1938  INT res;
1939  BOOL ret;
1940 
1941  if (!(ret = SetupGetStringFieldA( context, index, localbuff, sizeof(localbuff), &required )))
1942  {
1943  if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE;
1944  if (!(buffer = HeapAlloc( GetProcessHeap(), 0, required ))) return FALSE;
1945  if (!(ret = SetupGetStringFieldA( context, index, buffer, required, NULL ))) goto done;
1946  }
1947  /* The call to SetupGetStringFieldA succeeded. If buffer is empty we have an optional field */
1948  if (!*buffer) *result = 0;
1949  else
1950  {
1951  res = strtol( buffer, &end, 0 );
1952  if (end != buffer && !*end) *result = res;
1953  else
1954  {
1956  ret = FALSE;
1957  }
1958  }
1959 
1960  done:
1961  if (buffer != localbuff) HeapFree( GetProcessHeap(), 0, buffer );
1962  return ret;
1963 }
1964 
1965 
1966 /***********************************************************************
1967  * SetupGetBinaryField (SETUPAPI.@)
1968  */
1970  DWORD size, LPDWORD required )
1971 {
1972  struct inf_file *file = context->CurrentInf;
1973  struct line *line = get_line( file, context->Section, context->Line );
1974  struct field *field;
1975  int i;
1976 
1977  if (!line)
1978  {
1980  return FALSE;
1981  }
1982  if (!index || index > line->nb_fields)
1983  {
1985  return FALSE;
1986  }
1987  index--; /* fields start at 0 */
1988  if (required) *required = line->nb_fields - index;
1989  if (!buffer) return TRUE;
1990  if (size < line->nb_fields - index)
1991  {
1993  return FALSE;
1994  }
1995  field = &file->fields[line->first_field + index];
1996  for (i = index; i < line->nb_fields; i++, field++)
1997  {
1998  const WCHAR *p;
1999  DWORD value = 0;
2000  for (p = field->text; *p && isxdigitW(*p); p++)
2001  {
2002  if ((value <<= 4) > 255)
2003  {
2005  return FALSE;
2006  }
2007  if (*p <= '9') value |= (*p - '0');
2008  else value |= (tolowerW(*p) - 'a' + 10);
2009  }
2010  buffer[i - index] = value;
2011  }
2012  if (TRACE_ON(setupapi))
2013  {
2014  TRACE( "%p/%p/%d/%d index %d returning:\n",
2015  context->Inf, context->CurrentInf, context->Section, context->Line, index );
2016  for (i = index; i < line->nb_fields; i++) TRACE( " %02x\n", buffer[i - index] );
2017  }
2018  return TRUE;
2019 }
2020 
2021 
2022 /***********************************************************************
2023  * SetupGetMultiSzFieldA (SETUPAPI.@)
2024  */
2026  DWORD size, LPDWORD required )
2027 {
2028  struct inf_file *file = context->CurrentInf;
2029  struct line *line = get_line( file, context->Section, context->Line );
2030  struct field *field;
2031  unsigned int len;
2032  int i;
2033  DWORD total = 1;
2034 
2035  if (!line)
2036  {
2038  return FALSE;
2039  }
2040  if (!index || index > line->nb_fields)
2041  {
2043  return FALSE;
2044  }
2045  index--; /* fields start at 0 */
2046  field = &file->fields[line->first_field + index];
2047  for (i = index; i < line->nb_fields; i++, field++)
2048  {
2049  if (!(len = PARSER_string_substA( file, field->text, NULL, 0 ))) break;
2050  total += len + 1;
2051  }
2052 
2053  if (required) *required = total;
2054  if (!buffer) return TRUE;
2055  if (total > size)
2056  {
2058  return FALSE;
2059  }
2060  field = &file->fields[line->first_field + index];
2061  for (i = index; i < line->nb_fields; i++, field++)
2062  {
2063  if (!(len = PARSER_string_substA( file, field->text, buffer, size ))) break;
2064  buffer += len + 1;
2065  }
2066  *buffer = 0; /* add final null */
2067  return TRUE;
2068 }
2069 
2070 
2071 /***********************************************************************
2072  * SetupGetMultiSzFieldW (SETUPAPI.@)
2073  */
2075  DWORD size, LPDWORD required )
2076 {
2077  struct inf_file *file = context->CurrentInf;
2078  struct line *line = get_line( file, context->Section, context->Line );
2079  struct field *field;
2080  unsigned int len;
2081  int i;
2082  DWORD total = 1;
2083 
2084  if (!line)
2085  {
2087  return FALSE;
2088  }
2089  if (!index || index > line->nb_fields)
2090  {
2092  return FALSE;
2093  }
2094  index--; /* fields start at 0 */
2095  field = &file->fields[line->first_field + index];
2096  for (i = index; i < line->nb_fields; i++, field++)
2097  {
2098  if (!(len = PARSER_string_substW( file, field->text, NULL, 0 ))) break;
2099  total += len + 1;
2100  }
2101 
2102  if (required) *required = total;
2103  if (!buffer) return TRUE;
2104  if (total > size)
2105  {
2107  return FALSE;
2108  }
2109  field = &file->fields[line->first_field + index];
2110  for (i = index; i < line->nb_fields; i++, field++)
2111  {
2112  if (!(len = PARSER_string_substW( file, field->text, buffer, size ))) break;
2113  buffer += len + 1;
2114  }
2115  *buffer = 0; /* add final null */
2116  return TRUE;
2117 }
2118 
2119 /***********************************************************************
2120  * pSetupGetField (SETUPAPI.@)
2121  */
2123 {
2124  struct inf_file *file = context->CurrentInf;
2125  struct field *field = get_field( file, context->Section, context->Line, index );
2126 
2127  if (!field)
2128  {
2130  return NULL;
2131  }
2132  return field->text;
2133 }
2134 
2135 /***********************************************************************
2136  * SetupGetInfFileListW (SETUPAPI.@)
2137  */
2138 BOOL WINAPI
2140  IN PCWSTR DirectoryPath OPTIONAL,
2141  IN DWORD InfStyle,
2142  IN OUT PWSTR ReturnBuffer OPTIONAL,
2145 {
2146  HANDLE hSearch;
2147  LPWSTR pFullFileName = NULL;
2148  LPWSTR pFileName; /* Pointer into pFullFileName buffer */
2149  LPWSTR pBuffer = ReturnBuffer;
2150  WIN32_FIND_DATAW wfdFileInfo;
2151  size_t len;
2152  DWORD requiredSize = 0;
2153  BOOL ret = FALSE;
2154 
2155  TRACE("%s %lx %p %ld %p\n", debugstr_w(DirectoryPath), InfStyle,
2156  ReturnBuffer, ReturnBufferSize, RequiredSize);
2157 
2158  if (InfStyle & ~(INF_STYLE_OLDNT | INF_STYLE_WIN4))
2159  {
2160  TRACE("Unknown flags: 0x%08lx\n", InfStyle & ~(INF_STYLE_OLDNT | INF_STYLE_WIN4));
2162  goto cleanup;
2163  }
2164  else if (ReturnBufferSize == 0 && ReturnBuffer != NULL)
2165  {
2167  goto cleanup;
2168  }
2169  else if (ReturnBufferSize > 0 && ReturnBuffer == NULL)
2170  {
2172  goto cleanup;
2173  }
2174 
2175  /* Allocate memory for file filter */
2176  if (DirectoryPath != NULL)
2177  /* "DirectoryPath\" form */
2178  len = strlenW(DirectoryPath) + 1 + 1;
2179  else
2180  /* "%SYSTEMROOT%\Inf\" form */
2181  len = MAX_PATH + 1 + strlenW(InfDirectory) + 1;
2182  len += MAX_PATH; /* To contain file name or "*.inf" string */
2183  pFullFileName = MyMalloc(len * sizeof(WCHAR));
2184  if (pFullFileName == NULL)
2185  {
2187  goto cleanup;
2188  }
2189 
2190  /* Fill file filter buffer */
2191  if (DirectoryPath)
2192  {
2193  strcpyW(pFullFileName, DirectoryPath);
2194  if (*pFullFileName && pFullFileName[strlenW(pFullFileName) - 1] != '\\')
2195  strcatW(pFullFileName, BackSlash);
2196  }
2197  else
2198  {
2199  len = GetSystemWindowsDirectoryW(pFullFileName, MAX_PATH);
2200  if (len == 0 || len > MAX_PATH)
2201  goto cleanup;
2202  if (pFullFileName[strlenW(pFullFileName) - 1] != '\\')
2203  strcatW(pFullFileName, BackSlash);
2204  strcatW(pFullFileName, InfDirectory);
2205  }
2206  pFileName = &pFullFileName[strlenW(pFullFileName)];
2207 
2208  /* Search for the first file */
2209  strcpyW(pFileName, InfFileSpecification);
2210  hSearch = FindFirstFileW(pFullFileName, &wfdFileInfo);
2211  if (hSearch == INVALID_HANDLE_VALUE)
2212  {
2213  TRACE("No file returned by %s\n", debugstr_w(pFullFileName));
2214  goto cleanup;
2215  }
2216 
2217  do
2218  {
2219  HINF hInf;
2220 
2221  strcpyW(pFileName, wfdFileInfo.cFileName);
2222  hInf = SetupOpenInfFileW(
2223  pFullFileName,
2224  NULL, /* Inf class */
2225  InfStyle,
2226  NULL /* Error line */);
2227  if (hInf == INVALID_HANDLE_VALUE)
2228  {
2230  {
2231  /* InfStyle was not correct. Skip this file */
2232  continue;
2233  }
2234  TRACE("Invalid .inf file %s\n", debugstr_w(pFullFileName));
2235  continue;
2236  }
2237 
2238  len = strlenW(wfdFileInfo.cFileName) + 1;
2239  requiredSize += (DWORD)len;
2240  if (requiredSize <= ReturnBufferSize)
2241  {
2242  strcpyW(pBuffer, wfdFileInfo.cFileName);
2243  pBuffer = &pBuffer[len];
2244  }
2245  SetupCloseInfFile(hInf);
2246  } while (FindNextFileW(hSearch, &wfdFileInfo));
2247  FindClose(hSearch);
2248 
2249  requiredSize += 1; /* Final NULL char */
2250  if (requiredSize <= ReturnBufferSize)
2251  {
2252  *pBuffer = '\0';
2253  ret = TRUE;
2254  }
2255  else
2256  {
2258  ret = FALSE;
2259  }
2260  if (RequiredSize)
2261  *RequiredSize = requiredSize;
2262 
2263 cleanup:
2264  MyFree(pFullFileName);
2265  return ret;
2266 }
2267 
2268 /***********************************************************************
2269  * SetupGetInfFileListA (SETUPAPI.@)
2270  */
2271 BOOL WINAPI
2273  IN PCSTR DirectoryPath OPTIONAL,
2274  IN DWORD InfStyle,
2275  IN OUT PSTR ReturnBuffer OPTIONAL,
2278 {
2279  PWSTR DirectoryPathW = NULL;
2280  PWSTR ReturnBufferW = NULL;
2281  BOOL ret = FALSE;
2282 
2283  TRACE("%s %lx %p %ld %p\n", debugstr_a(DirectoryPath), InfStyle,
2284  ReturnBuffer, ReturnBufferSize, RequiredSize);
2285 
2286  if (DirectoryPath != NULL)
2287  {
2288  DirectoryPathW = pSetupMultiByteToUnicode(DirectoryPath, CP_ACP);
2289  if (DirectoryPathW == NULL) goto Cleanup;
2290  }
2291 
2292  if (ReturnBuffer != NULL && ReturnBufferSize != 0)
2293  {
2294  ReturnBufferW = MyMalloc(ReturnBufferSize * sizeof(WCHAR));
2295  if (ReturnBufferW == NULL) goto Cleanup;
2296  }
2297 
2298  ret = SetupGetInfFileListW(DirectoryPathW, InfStyle, ReturnBufferW, ReturnBufferSize, RequiredSize);
2299 
2300  if (ret && ReturnBufferW != NULL)
2301  {
2302  ret = WideCharToMultiByte(CP_ACP, 0, ReturnBufferW, -1, ReturnBuffer, ReturnBufferSize, NULL, NULL) != 0;
2303  }
2304 
2305 Cleanup:
2306  MyFree(DirectoryPathW);
2307  MyFree(ReturnBufferW);
2308 
2309  return ret;
2310 }
2311 
2312 /***********************************************************************
2313  * SetupDiGetINFClassW (SETUPAPI.@)
2314  */
2315 BOOL WINAPI
2317  IN PCWSTR InfName,
2318  OUT LPGUID ClassGuid,
2319  OUT PWSTR ClassName,
2320  IN DWORD ClassNameSize,
2322 {
2323  HINF hInf = INVALID_HANDLE_VALUE;
2324  BOOL ret = FALSE;
2325 
2326  TRACE("%s %p %p %ld %p\n", debugstr_w(InfName), ClassGuid,
2327  ClassName, ClassNameSize, RequiredSize);
2328 
2329  /* Open .inf file */
2330  hInf = SetupOpenInfFileW(InfName, NULL, INF_STYLE_WIN4, NULL);
2331  if (hInf == INVALID_HANDLE_VALUE)
2332  goto cleanup;
2333 
2334  ret = PARSER_GetInfClassW(hInf, ClassGuid, ClassName, ClassNameSize, RequiredSize);
2335 
2336 cleanup:
2337  if (hInf != INVALID_HANDLE_VALUE)
2338  SetupCloseInfFile(hInf);
2339 
2340  TRACE("Returning %d\n", ret);
2341  return ret;
2342 }
2343 
2344 /***********************************************************************
2345  * SetupDiGetINFClassA (SETUPAPI.@)
2346  */
2348  IN PCSTR InfName,
2349  OUT LPGUID ClassGuid,
2350  OUT PSTR ClassName,
2351  IN DWORD ClassNameSize,
2353 {
2354  PWSTR InfNameW = NULL;
2355  PWSTR ClassNameW = NULL;
2356  BOOL ret = FALSE;
2357 
2358  TRACE("%s %p %p %ld %p\n", debugstr_a(InfName), ClassGuid,
2359  ClassName, ClassNameSize, RequiredSize);
2360 
2361  if (InfName != NULL)
2362  {
2363  InfNameW = pSetupMultiByteToUnicode(InfName, CP_ACP);
2364  if (InfNameW == NULL) goto Cleanup;
2365  }
2366 
2367  if (ClassName != NULL && ClassNameSize != 0)
2368  {
2369  ClassNameW = MyMalloc(ClassNameSize * sizeof(WCHAR));
2370  if (ClassNameW == NULL) goto Cleanup;
2371  }
2372 
2373  ret = SetupDiGetINFClassW(InfNameW, ClassGuid, ClassNameW, ClassNameSize, RequiredSize);
2374 
2375  if (ret && ClassNameW != NULL)
2376  {
2377  ret = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName, ClassNameSize, NULL, NULL) != 0;
2378  }
2379 
2380 Cleanup:
2381  MyFree(InfNameW);
2382  MyFree(ClassNameW);
2383 
2384  return ret;
2385 }
2386 
2388  IN HINF hInf,
2389  IN LPCWSTR pStr,
2391  IN PVOID Context)
2392 {
2393  struct inf_file *file = (struct inf_file *)hInf;
2394  size_t len = strlenW(pStr);
2395  unsigned int i;
2396 
2397  for (i = 0; i < file->nb_sections; i++)
2398  {
2399  if (strncmpiW(pStr, file->sections[i]->name, len) == 0)
2400  {
2401  if (!Callback(file->sections[i]->name, Context))
2402  return FALSE;
2403  }
2404  }
2405  return TRUE;
2406 }
const WCHAR * text
Definition: parser.c:45
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
int stack_pos
Definition: inffile.c:92
static const WCHAR classW[]
Definition: lex.c:40
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
BOOL WINAPI SetupFindNextMatchLineA(PINFCONTEXT context_in, PCSTR key, PINFCONTEXT context_out)
Definition: parser.c:1672
static struct line * find_line(struct inf_file *file, int section_index, const WCHAR *name)
Definition: parser.c:188
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define IN
Definition: typedefs.h:38
static void free_inf_file(struct inf_file *file)
Definition: parser.c:897
const CHAR * start
Definition: inffile.c:87
UINT WINAPI GetSystemWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2396
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define ERROR_SECTION_NOT_FOUND
Definition: setupapi.h:288
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:406
IN PVOID IN PVOID IN USHORT Version
Definition: pci.h:359
const WCHAR * PARSER_get_inf_filename(HINF hinf)
Definition: parser.c:1084
struct line * line
Definition: parser.c:104
static const WCHAR * quotes_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:817
static const WCHAR * get_string_subst(const struct inf_file *file, const WCHAR *str, unsigned int *len, BOOL no_trailing_slash)
Definition: parser.c:309
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
#define INF_STYLE_WIN4
Definition: infsupp.h:41
#define MapViewOfFile
Definition: compat.h:410
#define WideCharToMultiByte
Definition: compat.h:101
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:95
BOOL WINAPI SetupGetLineByIndexA(HINF hinf, PCSTR section, DWORD index, INFCONTEXT *context)
Definition: parser.c:1515
Definition: http.c:7098
GLsizei const GLchar ** path
Definition: glext.h:7234
static UINT index
Definition: parser.c:36
uint16_t * PWSTR
Definition: typedefs.h:54
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
const WCHAR * text
Definition: package.c:1827
#define CP_ACP
Definition: compat.h:99
WINE_UNICODE_INLINE int isspaceW(WCHAR wc)
Definition: unicode.h:165
BOOL(* FIND_CALLBACK)(LPCWSTR SectionName, PVOID Context)
struct section ** sections
Definition: parser.c:70
GLuint GLuint GLsizei count
Definition: gl.h:1545
BOOL WINAPI SetupGetStringFieldW(PINFCONTEXT context, DWORD index, PWSTR buffer, DWORD size, PDWORD required)
Definition: parser.c:1902
BOOL EnumerateSectionsStartingWith(IN HINF hInf, IN LPCWSTR pStr, IN FIND_CALLBACK Callback, IN PVOID Context)
Definition: parser.c:2387
static char utf8_bom[3]
Definition: file.c:108
enum parser_state state
Definition: import.c:100
#define strtolW(s, e, b)
Definition: unicode.h:33
NTSYSAPI NTSTATUS NTAPI RtlUnicodeToMultiByteSize(PULONG MbSize, PCWCH UnicodeString, ULONG UnicodeSize)
struct inf_file * file
Definition: parser.c:98
int first_field
Definition: parser.c:50
#define INF_STYLE_OLDNT
Definition: infsupp.h:37
#define ERROR_SECTION_NAME_TOO_LONG
Definition: setupapi.h:284
GLintptr offset
Definition: glext.h:5920
static void pop_state(struct parser *parser)
Definition: parser.c:492
static struct field * add_field(struct inf_file *file, const WCHAR *text)
Definition: parser.c:280
static BOOL PARSER_GetInfClassW(IN HINF hInf, OUT LPGUID ClassGuid, OUT PWSTR ClassName, IN DWORD ClassNameSize, OUT PDWORD RequiredSize OPTIONAL)
Definition: parser.c:1161
static const WCHAR BackSlash[]
Definition: parser.c:29
#define GetLocaleInfo
Definition: winnls.h:1183
BOOL WINAPI SetupDiGetINFClassW(IN PCWSTR InfName, OUT LPGUID ClassGuid, OUT PWSTR ClassName, IN DWORD ClassNameSize, OUT PDWORD RequiredSize OPTIONAL)
Definition: parser.c:2316
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define INVALID_HANDLE_VALUE
Definition: compat.h:399
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
_In_ DWORD _In_ DWORD ReturnBufferSize
Definition: setupapi.h:1892
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1105
GLuint buffer
Definition: glext.h:5915
BOOL WINAPI SetupDiClassNameFromGuidW(const GUID *ClassGuid, PWSTR ClassName, DWORD ClassNameSize, PDWORD RequiredSize)
Definition: devinst.c:1076
BOOL WINAPI SetupGetBinaryField(PINFCONTEXT context, DWORD index, BYTE *buffer, DWORD size, LPDWORD required)
Definition: parser.c:1969
BOOL WINAPI SetupGetLineByIndexW(HINF hinf, PCWSTR section, DWORD index, INFCONTEXT *context)
Definition: parser.c:1534
GLuint GLuint end
Definition: gl.h:1545
WCHAR * PARSER_get_dest_dir(INFCONTEXT *context)
Definition: parser.c:1116
#define LOCALE_ILANGUAGE
Definition: winnls.h:25
unsigned int nb_fields
Definition: parser.c:71
Definition: parser.c:55
#define strncmpiW(s1, s2, n)
Definition: unicode.h:40
#define DIRID_SRCPATH
Definition: setupapi.h:186
HINF WINAPI SetupOpenInfFileW(PCWSTR name, PCWSTR class, DWORD style, UINT *error)
Definition: parser.c:1229
HINF CurrentInf
Definition: infsupp.h:25
static void append_inf_file(struct inf_file *parent, struct inf_file *child)
Definition: parser.c:970
const char * filename
Definition: ioapi.h:135
int32_t INT
Definition: typedefs.h:56
static const WCHAR * comment_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:887
static HWND child
Definition: cursoricon.c:298
#define FILE_SHARE_READ
Definition: compat.h:125
const WCHAR * name
Definition: parser.c:57
Definition: parser.c:87
UINT WINAPI GetWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2351
struct field * fields
Definition: parser.c:73
static void * grow_array(void *array, unsigned int *count, size_t elem)
Definition: parser.c:148
unsigned int broken_line
Definition: parser.c:106
#define ERROR_INVALID_USER_BUFFER
Definition: winerror.h:1091
BOOL WINAPI SetupEnumInfSectionsW(HINF hinf, UINT index, PWSTR buffer, DWORD size, DWORD *need)
Definition: parser.c:1441
static const parser_state_func parser_funcs[NB_PARSER_STATES]
Definition: parser.c:125
static enum parser_state set_state(struct parser *parser, enum parser_state state)
Definition: parser.c:500
BOOL WINAPI SetupGetInfFileListW(IN PCWSTR DirectoryPath OPTIONAL, IN DWORD InfStyle, IN OUT PWSTR ReturnBuffer OPTIONAL, IN DWORD ReturnBufferSize OPTIONAL, OUT PDWORD RequiredSize OPTIONAL)
Definition: parser.c:2139
#define ERROR_EXPECTED_SECTION_NAME
Definition: setupapi.h:282
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
NTSYSAPI BOOLEAN NTAPI RtlIsTextUnicode(_In_ CONST VOID *Buffer, _In_ INT Size, _Inout_opt_ INT *Flags)
static const WCHAR ClassGUID[]
Definition: parser.c:31
static int add_section_from_token(struct parser *parser)
Definition: parser.c:540
char name[1]
Definition: fci.c:135
#define CP_UTF8
Definition: nls.h:20
#define UNICODE_NULL
RPC_STATUS WINAPI UuidFromStringW(RPC_WSTR s, UUID *uuid)
Definition: rpcrt4_main.c:612
static const WCHAR * get_dirid_subst(const struct inf_file *file, int dirid, unsigned int *len)
Definition: parser.c:296
BOOL WINAPI SetupFindFirstLineA(HINF hinf, PCSTR section, PCSTR key, INFCONTEXT *context)
Definition: parser.c:1564
LPWSTR WINAPI pSetupMultiByteToUnicode(LPCSTR lpMultiByteStr, UINT uCodePage)
Definition: misc.c:281
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
int strings_section
Definition: parser.c:74
struct section sections[2]
Definition: diskspace.c:792
BOOL WINAPI SetupEnumInfSectionsA(HINF hinf, UINT index, PSTR buffer, DWORD size, DWORD *need)
Definition: parser.c:1406
#define debugstr_w
Definition: kernel32.h:32
static size_t elem
Definition: string.c:68
PINFCACHELINE line
Definition: inffile.c:95
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
static const WCHAR Chicago[]
Definition: parser.c:142
#define ERROR_CLASS_MISMATCH
Definition: setupapi.h:292
static PVOID ptr
Definition: dispmode.c:27
unsigned int idx
Definition: utils.c:41
int codepage
Definition: win_iconv.c:156
DWORD WINAPI SetupGetFieldCount(PINFCONTEXT context)
Definition: parser.c:1858
static const WCHAR * key_name_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:677
const WCHAR * str
static void push_state(struct parser *parser, enum parser_state state)
Definition: parser.c:484
static const WCHAR Windows95[]
Definition: parser.c:144
smooth NULL
Definition: ftsmooth.c:416
PVOID pBuffer
static struct field * get_field(struct inf_file *file, int section_index, int line_index, int field_index)
Definition: parser.c:262
static void close_current_line(struct parser *parser)
Definition: parser.c:602
const WCHAR *(* parser_state_func)(struct parser *parser, const WCHAR *pos)
Definition: parser.c:112
Definition: parser.c:48
#define ERROR_LINE_NOT_FOUND
Definition: setupapi.h:289
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeStringFromAsciiz(_Out_ PUNICODE_STRING Destination, _In_ PCSZ Source)
Definition: bufpool.h:45
#define FILE_MAP_READ
Definition: compat.h:435
GLuint index
Definition: glext.h:6031
unsigned int dir
Definition: maze.c:112
#define MAX_FIELD_LEN
Definition: parser.c:37
#define OPEN_EXISTING
Definition: compat.h:434
_Inout_ PRTL_BUFFER _In_ SIZE_T RequiredSize
static UINT PSTR buffer
Definition: parser.c:36
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 GLint GLint j
Definition: glfuncs.h:250
BOOL WINAPI SetupGetLineTextA(PINFCONTEXT context, HINF hinf, PCSTR section_name, PCSTR key_name, PSTR buffer, DWORD size, PDWORD required)
Definition: parser.c:1807
struct line lines[16]
Definition: parser.c:60
static const WCHAR nameW[]
Definition: main.c:46
Definition: _stack.h:47
const WCHAR * end
Definition: parser.c:97
#define CONTROL_Z
Definition: parser.c:35
char TCHAR
Definition: xmlstorage.h:189
const char * section
Definition: parser.c:191
static int add_section(struct inf_file *file, const WCHAR *name)
Definition: parser.c:206
BOOL WINAPI SetupFindFirstLineW(HINF hinf, PCWSTR section, PCWSTR key, INFCONTEXT *context)
Definition: parser.c:1593
int * PINT
Definition: windef.h:177
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
#define GetProcessHeap()
Definition: compat.h:403
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
WCHAR * filename
Definition: parser.c:75
BOOL WINAPI SetupDiGetINFClassA(IN PCSTR InfName, OUT LPGUID ClassGuid, OUT PSTR ClassName, IN DWORD ClassNameSize, OUT PDWORD RequiredSize OPTIONAL)
Definition: parser.c:2347
r parent
Definition: btrfs.c:2869
BOOL WINAPI SetupOpenAppendInfFileA(PCSTR name, HINF parent_hinf, UINT *error)
Definition: parser.c:1330
__wchar_t WCHAR
Definition: xmlstorage.h:180
Definition: parser.c:43
#define debugstr_a
Definition: kernel32.h:31
WCHAR * strings
Definition: parser.c:66
#define MAX_GUID_STRING_LEN
Definition: apphelp.c:29
static const WCHAR keyW[]
Definition: tokenize.c:60
#define CreateFileMappingW(a, b, c, d, e, f)
Definition: compat.h:409
BOOL WINAPI SetupGetMultiSzFieldA(PINFCONTEXT context, DWORD index, PSTR buffer, DWORD size, LPDWORD required)
Definition: parser.c:2025
static struct inf_file * parse_file(HANDLE handle, UINT *error_line, DWORD style)
Definition: parser.c:989
int key_field
Definition: parser.c:52
#define MAX_PATH
Definition: compat.h:26
#define WINAPI
Definition: msvc.h:6
const char file[]
Definition: icontest.c:11
#define LOCALE_SYSTEM_DEFAULT
WINE_UNICODE_INLINE WCHAR tolowerW(WCHAR ch)
Definition: unicode.h:135
static DWORD parse_buffer(struct inf_file *file, const WCHAR *buffer, const WCHAR *end, UINT *error_line)
Definition: parser.c:911
unsigned long DWORD
Definition: ntddk_ex.h:95
GLenum GLenum GLenum GLenum mapping
Definition: glext.h:9031
DWORD error
Definition: parser.c:105
WCHAR * PARSER_get_src_root(HINF hinf)
Definition: parser.c:1096
static WCHAR * push_string(struct inf_file *file, const WCHAR *string)
Definition: parser.c:474
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
static DWORD
Definition: parser.c:34
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:481
unsigned int token_len
Definition: inffile.c:98
#define SetLastError(x)
Definition: compat.h:417
static unsigned int PARSER_string_substA(const struct inf_file *file, const WCHAR *text, char *buffer, unsigned int size)
Definition: parser.c:456
static const WCHAR Strings[]
Definition: reg.c:35
unsigned int error
Definition: inffile.c:97
static const WCHAR WindowsNT[]
Definition: parser.c:143
FILE * file
Definition: import.c:88
#define ERROR_BAD_SECTION_NAME_LINE
Definition: setupapi.h:283
static const WCHAR * get_inf_dir(const struct inf_file *file, unsigned int *len)
Definition: parser.c:168
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
enum parser_state stack[4]
Definition: inffile.c:91
const WCHAR * start
Definition: parser.c:96
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
static const WCHAR * section_name_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:656
WINE_UNICODE_INLINE int isxdigitW(WCHAR wc)
Definition: unicode.h:175
static struct line * get_line(struct inf_file *file, unsigned int section_index, unsigned int line_index)
Definition: parser.c:249
int cur_section
Definition: parser.c:103
int ret
NTSYSAPI NTSTATUS NTAPI RtlUnicodeToMultiByteN(PCHAR MbString, ULONG MbSize, PULONG ResultSize, PCWCH UnicodeString, ULONG UnicodeSize)
static BOOL is_eol(const struct parser *parser, const WCHAR *ptr)
Definition: parser.c:516
char line[200]
Definition: main.c:97
static int state
Definition: maze.c:121
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
#define GUID_NULL
Definition: ks.h:106
#define GENERIC_READ
Definition: compat.h:124
GLenum src
Definition: glext.h:6340
#define err(...)
PINFCACHESECTION cur_section
Definition: inffile.c:94
static const WCHAR Cleanup[]
Definition: register.c:80
GLsizei const GLfloat * value
Definition: glext.h:6069
Definition: parser.c:90
const WCHAR * DIRID_get_string(int dirid)
Definition: dirid.c:159
BOOL WINAPI SetupOpenAppendInfFileW(PCWSTR name, HINF parent_hinf, UINT *error)
Definition: parser.c:1346
HINF WINAPI SetupOpenInfFileA(PCSTR name, PCSTR class, DWORD style, UINT *error)
Definition: parser.c:1139
#define strcmpiW(s1, s2)
Definition: unicode.h:39
WINE_UNICODE_INLINE WCHAR * strrchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:254
const CHAR * end
Definition: inffile.c:88
#define ERROR_INVALID_DATA
Definition: winerror.h:116
static struct line * add_line(struct inf_file *file, int section_index)
Definition: parser.c:225
#define MAX_SECTION_NAME_LEN
Definition: parser.c:36
unsigned int nb_lines
Definition: parser.c:58
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219
static unsigned __int64 next
Definition: rand_nt.c:6
parser_state
Definition: import.c:64
static BOOL is_eof(const struct parser *parser, const WCHAR *ptr)
Definition: parser.c:509
BOOL WINAPI SetupGetStringFieldA(PINFCONTEXT context, DWORD index, PSTR buffer, DWORD size, PDWORD required)
Definition: parser.c:1871
GLuint start
Definition: gl.h:1545
static const WCHAR InfDirectory[]
Definition: parser.c:32
CHAR token[MAX_FIELD_LEN+1]
Definition: inffile.c:99
#define HeapReAlloc
Definition: compat.h:401
unsigned int alloc_lines
Definition: parser.c:59
signed char * PSTR
Definition: retypes.h:7
GLenum GLenum dst
Definition: glext.h:6340
UINT Section
Definition: infsupp.h:26
WINE_UNICODE_INLINE WCHAR * strcatW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:242
struct inf_file * next
Definition: parser.c:65
unsigned int UINT
Definition: ndis.h:50
unsigned int alloc_sections
Definition: parser.c:69
#define PAGE_READONLY
Definition: compat.h:127
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
DWORD * PDWORD
Definition: pedump.c:68
#define MultiByteToWideChar
Definition: compat.h:100
static int find_section(const struct inf_file *file, const WCHAR *name)
Definition: parser.c:177
#define CreateFileW
Definition: compat.h:408
BOOL WINAPI SetupGetInfFileListA(IN PCSTR DirectoryPath OPTIONAL, IN DWORD InfStyle, IN OUT PSTR ReturnBuffer OPTIONAL, IN DWORD ReturnBufferSize OPTIONAL, OUT PDWORD RequiredSize OPTIONAL)
Definition: parser.c:2272
static const WCHAR * line_start_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:617
Definition: import.c:86
LPCWSTR WINAPI pSetupGetField(PINFCONTEXT context, DWORD index)
Definition: parser.c:2122
Definition: name.c:38
#define MAX_STRING_LEN
Definition: parser.c:39
_Check_return_ long __cdecl strtol(_In_z_ const char *_Str, _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix)
WINE_UNICODE_INLINE int strcmpW(const WCHAR *str1, const WCHAR *str2)
Definition: unicode.h:229
#define OUT
Definition: typedefs.h:39
GLuint res
Definition: glext.h:9613
static const WCHAR * eol_backslash_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:784
uint32_t * LPDWORD
Definition: typedefs.h:57
#define ERROR_WRONG_INF_STYLE
Definition: setupapi.h:286
static unsigned int PARSER_string_substW(const struct inf_file *file, const WCHAR *text, WCHAR *buffer, unsigned int size)
Definition: parser.c:403
char * cleanup(char *str)
Definition: wpickclick.c:99
BOOL WINAPI SetupFindNextLine(PINFCONTEXT context_in, PINFCONTEXT context_out)
Definition: parser.c:1631
LPVOID WINAPI MyMalloc(DWORD dwSize)
Definition: misc.c:147
static struct field * add_field_from_token(struct parser *parser, BOOL is_key)
Definition: parser.c:566
HINF Inf
Definition: infsupp.h:24
unsigned int alloc_fields
Definition: parser.c:72
HINF WINAPI SetupOpenMasterInf(VOID)
Definition: parser.c:1378
const char * PCSTR
Definition: typedefs.h:51
WCHAR * string_pos
Definition: parser.c:67
static const WCHAR * value_name_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:731
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
unsigned int nb_sections
Definition: parser.c:68
static const WCHAR * trailing_spaces_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:868
int nb_fields
Definition: parser.c:51
static const WCHAR LayoutFile[]
Definition: parser.c:145
unsigned int line_pos
Definition: inffile.c:96
#define UnmapViewOfFile
Definition: compat.h:411
Arabic default style
Definition: afstyles.h:93
static const WCHAR Signature[]
Definition: parser.c:141
GLuint64EXT * result
Definition: glext.h:11304
LPFNPSPCALLBACK Callback
Definition: desk.c:111
VOID WINAPI MyFree(LPVOID lpMem)
Definition: misc.c:128
#define TRACE_ON(x)
Definition: compat.h:65
static int push_token(struct parser *parser, const WCHAR *pos)
Definition: parser.c:523
static const WCHAR InfFileSpecification[]
Definition: parser.c:33
LONG WINAPI SetupGetLineCountA(HINF hinf, PCSTR name)
Definition: parser.c:1475
#define HEAP_REALLOC_IN_PLACE_ONLY
Definition: nt_native.h:1696
static const WCHAR * leading_spaces_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:847
#define HeapFree(x, y, z)
Definition: compat.h:402
static UINT PSTR DWORD UINT * need
Definition: parser.c:36
BOOL WINAPI SetupFindNextMatchLineW(PINFCONTEXT context_in, PCWSTR key, PINFCONTEXT context_out)
Definition: parser.c:1694
Definition: inf.c:48
UINT Line
Definition: infsupp.h:27
BOOL WINAPI SetupGetIntField(PINFCONTEXT context, DWORD index, PINT result)
Definition: parser.c:1933
BOOL WINAPI SetupGetMultiSzFieldW(PINFCONTEXT context, DWORD index, PWSTR buffer, DWORD size, LPDWORD required)
Definition: parser.c:2074
void WINAPI SetupCloseInfFile(HINF hinf)
Definition: parser.c:1393
#define RPC_S_OK
Definition: rpcnterr.h:22
Definition: path.c:41
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
LONG WINAPI SetupGetLineCountW(HINF hinf, PCWSTR section)
Definition: parser.c:1494
Definition: fci.c:126
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
BOOL WINAPI SetupGetLineTextW(PINFCONTEXT context, HINF hinf, PCWSTR section_name, PCWSTR key_name, PWSTR buffer, DWORD size, PDWORD required)
Definition: parser.c:1756
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
GLuint const GLchar * name
Definition: glext.h:6031