ReactOS 0.4.15-dev-7788-g1ad9096
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 */
29static const WCHAR BackSlash[] = {'\\',0};
30static const WCHAR Class[] = {'C','l','a','s','s',0};
31static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0};
32static const WCHAR InfDirectory[] = {'i','n','f','\\',0};
33static 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
43struct field
44{
45 const WCHAR *text; /* field text */
46};
47
48struct 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
55struct 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
63struct 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
94struct 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
112typedef const WCHAR * (*parser_state_func)( struct parser *parser, const WCHAR *pos );
113
114/* parser state machine functions */
115static const WCHAR *line_start_state( struct parser *parser, const WCHAR *pos );
116static const WCHAR *section_name_state( struct parser *parser, const WCHAR *pos );
117static const WCHAR *key_name_state( struct parser *parser, const WCHAR *pos );
118static const WCHAR *value_name_state( struct parser *parser, const WCHAR *pos );
119static const WCHAR *eol_backslash_state( struct parser *parser, const WCHAR *pos );
120static const WCHAR *quotes_state( struct parser *parser, const WCHAR *pos );
121static const WCHAR *leading_spaces_state( struct parser *parser, const WCHAR *pos );
122static const WCHAR *trailing_spaces_state( struct parser *parser, const WCHAR *pos );
123static 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 */
140static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
141static const WCHAR Signature[] = {'S','i','g','n','a','t','u','r','e',0};
142static const WCHAR Chicago[] = {'$','C','h','i','c','a','g','o','$',0};
143static const WCHAR WindowsNT[] = {'$','W','i','n','d','o','w','s',' ','N','T','$',0};
144static const WCHAR Windows95[] = {'$','W','i','n','d','o','w','s',' ','9','5','$',0};
145static const WCHAR LayoutFile[] = {'L','a','y','o','u','t','F','i','l','e',0};
146
147/* extend an array, allocating more memory if necessary */
148static 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
163 return new_array;
164}
165
166
167/* get the directory of the inf file (as counted string, not null-terminated) */
168static 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 */
177static 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 */
188static 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 */
206static 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 */
225static 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 */
249static 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 */
262static 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 */
280static 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 */
296static 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 */
309static 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 */
403static 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 */
456static 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 */
474static 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 */
484static 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 */
492static inline void pop_state( struct parser *parser )
493{
496}
497
498
499/* set the parser state and return the previous one */
500static inline enum parser_state set_state( struct parser *parser, enum parser_state state )
501{
503 parser->state = state;
504 return ret;
505}
506
507
508/* check if the pointer points to an end of file */
509static 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 */
516static 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 */
523static 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 */
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 */
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 */
566static 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 */
602static 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 */
617static 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 */
656static 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 */
677static 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;
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 */
731static 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;
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 */
784static 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 */
817static 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 */
847static 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 */
868static 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 */
887static 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
897static 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 );
907}
908
909
910/* parse a complete buffer */
911static 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
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;
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 */
970static 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 */
989static 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;
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
1160static 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
1220cleanup:
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 {
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 {
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
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 {
1412 if (index < file->nb_sections)
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 {
1447 if (index < file->nb_sections)
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 );
1581 RtlFreeUnicodeString( &keyW );
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 {
1604 ctx.Inf = hinf;
1605 ctx.CurrentInf = file;
1606 ctx.Section = section_index;
1607 ctx.Line = -1;
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{
1675 UNICODE_STRING keyW;
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 );
1685 RtlFreeUnicodeString( &keyW );
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 */
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);
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,
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);
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,
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 {
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 */
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
2263cleanup:
2264 MyFree(pFullFileName);
2265 return ret;
2266}
2267
2268/***********************************************************************
2269 * SetupGetInfFileListA (SETUPAPI.@)
2270 */
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
2305Cleanup:
2306 MyFree(DirectoryPathW);
2307 MyFree(ReturnBufferW);
2308
2309 return ret;
2310}
2311
2312/***********************************************************************
2313 * SetupDiGetINFClassW (SETUPAPI.@)
2314 */
2317 IN PCWSTR InfName,
2318 OUT LPGUID ClassGuid,
2319 OUT PWSTR ClassName,
2320 IN DWORD ClassNameSize,
2322{
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
2336cleanup:
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
2380Cleanup:
2381 MyFree(InfNameW);
2382 MyFree(ClassNameW);
2383
2384 return ret;
2385}
2386
2388 IN HINF hInf,
2389 IN LPCWSTR pStr,
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}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
Arabic default style
Definition: afstyles.h:94
static int state
Definition: maze.c:121
unsigned int dir
Definition: maze.c:112
parser_state
Definition: import.c:59
static WCHAR *(* get_line)(FILE *)
Definition: import.c:55
static const WCHAR nameW[]
Definition: main.c:46
#define index(s, c)
Definition: various.h:29
Definition: bufpool.h:45
Definition: _stack.h:55
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
const WCHAR * DIRID_get_string(int dirid)
Definition: dirid.c:159
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define MAX_GUID_STRING_LEN
Definition: apphelp.c:29
unsigned int idx
Definition: utils.c:41
static const WCHAR Strings[]
Definition: reg.c:35
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define PAGE_READONLY
Definition: compat.h:138
#define UnmapViewOfFile
Definition: compat.h:746
#define CP_ACP
Definition: compat.h:109
#define OPEN_EXISTING
Definition: compat.h:775
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define CreateFileMappingW(a, b, c, d, e, f)
Definition: compat.h:744
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define GENERIC_READ
Definition: compat.h:135
#define TRACE_ON(x)
Definition: compat.h:75
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CreateFileW
Definition: compat.h:741
#define FILE_MAP_READ
Definition: compat.h:776
#define WideCharToMultiByte
Definition: compat.h:111
#define MapViewOfFile
Definition: compat.h:745
#define MultiByteToWideChar
Definition: compat.h:110
#define FILE_SHARE_READ
Definition: compat.h:136
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
static void cleanup(void)
Definition: main.c:1335
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
UINT WINAPI GetSystemWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2397
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
UINT WINAPI GetWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2352
const WCHAR * text
Definition: package.c:1799
BOOL WINAPI SetupDiClassNameFromGuidW(const GUID *ClassGuid, PWSTR ClassName, DWORD ClassNameSize, PDWORD RequiredSize)
Definition: devinst.c:1067
LPWSTR WINAPI pSetupMultiByteToUnicode(LPCSTR lpMultiByteStr, UINT uCodePage)
Definition: misc.c:281
LPVOID WINAPI MyMalloc(DWORD dwSize)
Definition: misc.c:147
VOID WINAPI MyFree(LPVOID lpMem)
Definition: misc.c:128
BOOL WINAPI SetupFindNextMatchLineA(PINFCONTEXT context_in, PCSTR key, PINFCONTEXT context_out)
Definition: parser.c:1672
static const WCHAR * key_name_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:677
#define MAX_FIELD_LEN
Definition: parser.c:37
static const WCHAR * value_name_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:731
const WCHAR * PARSER_get_inf_filename(HINF hinf)
Definition: parser.c:1084
static int add_section(struct inf_file *file, const WCHAR *name)
Definition: parser.c:206
BOOL WINAPI SetupEnumInfSectionsW(HINF hinf, UINT index, PWSTR buffer, DWORD size, DWORD *need)
Definition: parser.c:1441
WCHAR * PARSER_get_src_root(HINF hinf)
Definition: parser.c:1096
HINF WINAPI SetupOpenInfFileW(PCWSTR name, PCWSTR class, DWORD style, UINT *error)
Definition: parser.c:1229
static const WCHAR ClassGUID[]
Definition: parser.c:31
static struct field * add_field_from_token(struct parser *parser, BOOL is_key)
Definition: parser.c:566
LONG WINAPI SetupGetLineCountW(HINF hinf, PCWSTR section)
Definition: parser.c:1494
static void push_state(struct parser *parser, enum parser_state state)
Definition: parser.c:484
static BOOL is_eol(const struct parser *parser, const WCHAR *ptr)
Definition: parser.c:516
static const WCHAR * section_name_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:656
void WINAPI SetupCloseInfFile(HINF hinf)
Definition: parser.c:1393
DWORD WINAPI SetupGetFieldCount(PINFCONTEXT context)
Definition: parser.c:1858
BOOL WINAPI SetupGetMultiSzFieldW(PINFCONTEXT context, DWORD index, PWSTR buffer, DWORD size, LPDWORD required)
Definition: parser.c:2074
static WCHAR * push_string(struct inf_file *file, const WCHAR *string)
Definition: parser.c:474
BOOL WINAPI SetupGetBinaryField(PINFCONTEXT context, DWORD index, BYTE *buffer, DWORD size, LPDWORD required)
Definition: parser.c:1969
static const WCHAR WindowsNT[]
Definition: parser.c:143
static void append_inf_file(struct inf_file *parent, struct inf_file *child)
Definition: parser.c:970
static const WCHAR * get_dirid_subst(const struct inf_file *file, int dirid, unsigned int *len)
Definition: parser.c:296
static const WCHAR * leading_spaces_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:847
static void * grow_array(void *array, unsigned int *count, size_t elem)
Definition: parser.c:148
#define MAX_STRING_LEN
Definition: parser.c:39
static void close_current_line(struct parser *parser)
Definition: parser.c:602
static BOOL is_eof(const struct parser *parser, const WCHAR *ptr)
Definition: parser.c:509
static void pop_state(struct parser *parser)
Definition: parser.c:492
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 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 Signature[]
Definition: parser.c:141
static struct field * add_field(struct inf_file *file, const WCHAR *text)
Definition: parser.c:280
static const WCHAR * get_inf_dir(const struct inf_file *file, unsigned int *len)
Definition: parser.c:168
static const WCHAR Chicago[]
Definition: parser.c:142
BOOL WINAPI SetupFindFirstLineW(HINF hinf, PCWSTR section, PCWSTR key, INFCONTEXT *context)
Definition: parser.c:1593
static const WCHAR LayoutFile[]
Definition: parser.c:145
BOOL WINAPI SetupFindNextLine(PINFCONTEXT context_in, PINFCONTEXT context_out)
Definition: parser.c:1631
static enum parser_state set_state(struct parser *parser, enum parser_state state)
Definition: parser.c:500
static int add_section_from_token(struct parser *parser)
Definition: parser.c:540
static int find_section(const struct inf_file *file, const WCHAR *name)
Definition: parser.c:177
#define CONTROL_Z
Definition: parser.c:35
static const WCHAR * line_start_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:617
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
const WCHAR *(* parser_state_func)(struct parser *parser, const WCHAR *pos)
Definition: parser.c:112
BOOL WINAPI SetupDiGetINFClassA(IN PCSTR InfName, OUT LPGUID ClassGuid, OUT PSTR ClassName, IN DWORD ClassNameSize, OUT PDWORD RequiredSize OPTIONAL)
Definition: parser.c:2347
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 const WCHAR BackSlash[]
Definition: parser.c:29
WCHAR * PARSER_get_dest_dir(INFCONTEXT *context)
Definition: parser.c:1116
BOOL WINAPI SetupGetIntField(PINFCONTEXT context, DWORD index, PINT result)
Definition: parser.c:1933
BOOL WINAPI SetupOpenAppendInfFileA(PCSTR name, HINF parent_hinf, UINT *error)
Definition: parser.c:1330
static const WCHAR Windows95[]
Definition: parser.c:144
BOOL WINAPI SetupGetLineByIndexW(HINF hinf, PCWSTR section, DWORD index, INFCONTEXT *context)
Definition: parser.c:1534
BOOL WINAPI SetupFindFirstLineA(HINF hinf, PCSTR section, PCSTR key, INFCONTEXT *context)
Definition: parser.c:1564
BOOL WINAPI SetupGetMultiSzFieldA(PINFCONTEXT context, DWORD index, PSTR buffer, DWORD size, LPDWORD required)
Definition: parser.c:2025
HINF WINAPI SetupOpenInfFileA(PCSTR name, PCSTR class, DWORD style, UINT *error)
Definition: parser.c:1139
LPCWSTR WINAPI pSetupGetField(PINFCONTEXT context, DWORD index)
Definition: parser.c:2122
BOOL WINAPI SetupEnumInfSectionsA(HINF hinf, UINT index, PSTR buffer, DWORD size, DWORD *need)
Definition: parser.c:1406
BOOL WINAPI SetupGetLineTextA(PINFCONTEXT context, HINF hinf, PCSTR section_name, PCSTR key_name, PSTR buffer, DWORD size, PDWORD required)
Definition: parser.c:1807
static struct inf_file * parse_file(HANDLE handle, UINT *error_line, DWORD style)
Definition: parser.c:989
static struct line * add_line(struct inf_file *file, int section_index)
Definition: parser.c:225
static const WCHAR * eol_backslash_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:784
@ NB_PARSER_STATES
Definition: parser.c:91
@ SECTION_NAME
Definition: parser.c:83
@ TRAILING_SPACES
Definition: parser.c:89
@ QUOTES
Definition: parser.c:87
@ LINE_START
Definition: parser.c:82
@ EOL_BACKSLASH
Definition: parser.c:86
@ COMMENT
Definition: parser.c:90
@ LEADING_SPACES
Definition: parser.c:88
@ KEY_NAME
Definition: parser.c:84
@ VALUE_NAME
Definition: parser.c:85
static struct field * get_field(struct inf_file *file, int section_index, int line_index, int field_index)
Definition: parser.c:262
static const WCHAR * quotes_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:817
BOOL WINAPI SetupOpenAppendInfFileW(PCWSTR name, HINF parent_hinf, UINT *error)
Definition: parser.c:1346
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
static unsigned int PARSER_string_substW(const struct inf_file *file, const WCHAR *text, WCHAR *buffer, unsigned int size)
Definition: parser.c:403
LONG WINAPI SetupGetLineCountA(HINF hinf, PCSTR name)
Definition: parser.c:1475
static void free_inf_file(struct inf_file *file)
Definition: parser.c:897
BOOL WINAPI SetupGetStringFieldA(PINFCONTEXT context, DWORD index, PSTR buffer, DWORD size, PDWORD required)
Definition: parser.c:1871
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
BOOL WINAPI SetupGetLineByIndexA(HINF hinf, PCSTR section, DWORD index, INFCONTEXT *context)
Definition: parser.c:1515
static const WCHAR InfFileSpecification[]
Definition: parser.c:33
static const WCHAR * comment_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:887
static const WCHAR InfDirectory[]
Definition: parser.c:32
static int push_token(struct parser *parser, const WCHAR *pos)
Definition: parser.c:523
#define MAX_SECTION_NAME_LEN
Definition: parser.c:36
BOOL WINAPI SetupDiGetINFClassW(IN PCWSTR InfName, OUT LPGUID ClassGuid, OUT PWSTR ClassName, IN DWORD ClassNameSize, OUT PDWORD RequiredSize OPTIONAL)
Definition: parser.c:2316
static struct line * find_line(struct inf_file *file, int section_index, const WCHAR *name)
Definition: parser.c:188
static const WCHAR * trailing_spaces_state(struct parser *parser, const WCHAR *pos)
Definition: parser.c:868
HINF WINAPI SetupOpenMasterInf(VOID)
Definition: parser.c:1378
BOOL WINAPI SetupFindNextMatchLineW(PINFCONTEXT context_in, PCWSTR key, PINFCONTEXT context_out)
Definition: parser.c:1694
BOOL WINAPI SetupGetLineTextW(PINFCONTEXT context, HINF hinf, PCWSTR section_name, PCWSTR key_name, PWSTR buffer, DWORD size, PDWORD required)
Definition: parser.c:1756
static const parser_state_func parser_funcs[NB_PARSER_STATES]
Definition: parser.c:125
static const WCHAR Cleanup[]
Definition: register.c:80
r parent
Definition: btrfs.c:3010
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
size_t total
GLuint start
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
GLuint index
Definition: glext.h:6031
GLenum GLenum dst
Definition: glext.h:6340
GLenum GLenum GLenum GLenum mapping
Definition: glext.h:9031
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
GLintptr offset
Definition: glext.h:5920
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
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
_Check_return_ long __cdecl strtol(_In_z_ const char *_Str, _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix)
#define MAX_FIELD_LEN
Definition: infcore.c:18
parser_state
Definition: infcore.c:26
#define INF_STYLE_OLDNT
Definition: infsupp.h:37
#define INF_STYLE_WIN4
Definition: infsupp.h:41
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
const char * filename
Definition: ioapi.h:137
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
#define GUID_NULL
Definition: ks.h:106
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ASSERT(a)
Definition: mode.c:44
static PVOID ptr
Definition: dispmode.c:27
static size_t elem
Definition: string.c:68
struct section sections[2]
Definition: diskspace.c:792
static UINT PSTR DWORD UINT * need
Definition: parser.c:36
static HWND child
Definition: cursoricon.c:298
unsigned int UINT
Definition: ndis.h:50
NTSYSAPI BOOLEAN NTAPI RtlIsTextUnicode(_In_ CONST VOID *Buffer, _In_ INT Size, _Inout_opt_ INT *Flags)
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeStringFromAsciiz(_Out_ PUNICODE_STRING Destination, _In_ PCSZ Source)
_Use_decl_annotations_ NTSTATUS NTAPI RtlUnicodeToMultiByteN(_Out_ PCHAR MbString, _In_ ULONG MbSize, _Out_opt_ PULONG ResultSize, _In_ PCWCH UnicodeString, _In_ ULONG UnicodeSize)
Definition: nlsboot.c:107
_Use_decl_annotations_ NTSTATUS NTAPI RtlUnicodeToMultiByteSize(_Out_ PULONG MbSize, _In_ PCWCH UnicodeString, _In_ ULONG UnicodeSize)
Definition: nlsboot.c:145
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define DWORD
Definition: nt_native.h:44
#define HEAP_REALLOC_IN_PLACE_ONLY
Definition: nt_native.h:1696
#define LOCALE_SYSTEM_DEFAULT
#define UNICODE_NULL
DWORD * PDWORD
Definition: pedump.c:68
long LONG
Definition: pedump.c:60
static unsigned __int64 next
Definition: rand_nt.c:6
PVOID pBuffer
#define strncmpiW(s1, s2, n)
Definition: unicode.h:40
#define strcmpW(s1, s2)
Definition: unicode.h:38
#define strchrW(s, c)
Definition: unicode.h:34
#define strcmpiW(s1, s2)
Definition: unicode.h:39
#define tolowerW(n)
Definition: unicode.h:44
#define strlenW(s)
Definition: unicode.h:28
#define strrchrW(s, c)
Definition: unicode.h:35
#define strcatW(d, s)
Definition: unicode.h:30
#define isxdigitW(n)
Definition: unicode.h:51
#define isspaceW(n)
Definition: unicode.h:52
#define strtolW(s, e, b)
Definition: unicode.h:33
#define strcpyW(d, s)
Definition: unicode.h:29
#define err(...)
const WCHAR * str
#define RPC_S_OK
Definition: rpcnterr.h:22
RPC_STATUS WINAPI UuidFromStringW(RPC_WSTR s, UUID *uuid)
Definition: rpcrt4_main.c:614
#define CP_UTF8
Definition: nls.h:20
static char utf8_bom[3]
Definition: file.c:108
#define ERROR_WRONG_INF_STYLE
Definition: setupapi.h:291
#define ERROR_BAD_SECTION_NAME_LINE
Definition: setupapi.h:288
#define ERROR_EXPECTED_SECTION_NAME
Definition: setupapi.h:287
#define DIRID_SRCPATH
Definition: setupapi.h:186
#define ERROR_SECTION_NOT_FOUND
Definition: setupapi.h:293
#define ERROR_CLASS_MISMATCH
Definition: setupapi.h:297
#define ERROR_SECTION_NAME_TOO_LONG
Definition: setupapi.h:289
_In_ DWORD _In_ DWORD ReturnBufferSize
Definition: setupapi.h:1897
#define ERROR_LINE_NOT_FOUND
Definition: setupapi.h:294
BOOL(* FIND_CALLBACK)(LPCWSTR SectionName, PVOID Context)
#define TRACE(s)
Definition: solgame.cpp:4
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
HINF Inf
Definition: infsupp.h:24
UINT Line
Definition: infsupp.h:27
HINF CurrentInf
Definition: infsupp.h:25
UINT Section
Definition: infsupp.h:26
Definition: http.c:7252
Definition: parser.c:44
const WCHAR * text
Definition: parser.c:45
Definition: fci.c:127
char name[1]
Definition: fci.c:135
Definition: inf.c:49
struct inf_file * next
Definition: parser.c:65
unsigned int nb_sections
Definition: parser.c:68
unsigned int alloc_sections
Definition: parser.c:69
unsigned int alloc_fields
Definition: parser.c:72
WCHAR * string_pos
Definition: parser.c:67
unsigned int nb_fields
Definition: parser.c:71
struct section ** sections
Definition: parser.c:70
WCHAR * filename
Definition: parser.c:75
struct field * fields
Definition: parser.c:73
int strings_section
Definition: parser.c:74
WCHAR * strings
Definition: parser.c:66
Definition: copy.c:22
Definition: parser.c:49
int first_field
Definition: parser.c:50
int nb_fields
Definition: parser.c:51
int key_field
Definition: parser.c:52
Definition: name.c:39
Definition: import.c:81
unsigned int line_pos
Definition: inffile.c:96
const WCHAR * start
Definition: parser.c:96
PINFCACHESECTION cur_section
Definition: inffile.c:94
int stack_pos
Definition: inffile.c:92
int cur_section
Definition: parser.c:103
struct line * line
Definition: parser.c:104
struct inf_file * file
Definition: parser.c:98
const CHAR * end
Definition: inffile.c:88
const WCHAR * end
Definition: parser.c:97
enum parser_state state
Definition: import.c:95
CHAR token[MAX_FIELD_LEN+1]
Definition: inffile.c:99
unsigned int token_len
Definition: inffile.c:98
const CHAR * start
Definition: inffile.c:87
enum parser_state stack[4]
Definition: inffile.c:91
unsigned int error
Definition: inffile.c:97
FILE * file
Definition: import.c:82
PINFCACHELINE line
Definition: inffile.c:95
unsigned int broken_line
Definition: parser.c:106
Definition: parser.c:56
const WCHAR * name
Definition: parser.c:57
unsigned int alloc_lines
Definition: parser.c:59
unsigned int nb_lines
Definition: parser.c:58
struct line lines[16]
Definition: parser.c:60
uint16_t * PWSTR
Definition: typedefs.h:56
char * PSTR
Definition: typedefs.h:51
const uint16_t * PCWSTR
Definition: typedefs.h:57
uint32_t * LPDWORD
Definition: typedefs.h:59
int32_t INT
Definition: typedefs.h:58
const char * PCSTR
Definition: typedefs.h:52
#define IN
Definition: typedefs.h:39
#define OUT
Definition: typedefs.h:40
Definition: pdh_main.c:94
static const WCHAR classW[]
Definition: lex.c:40
int ret
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ ULONG _Out_ PVOID _Out_ PULONG RequiredSize
Definition: wdfdevice.h:4439
_Must_inspect_result_ _In_ WDFDEVICE _In_ LPCGUID _Out_ PINTERFACE _In_ USHORT _In_ USHORT Version
Definition: wdffdo.h:469
_In_ WDFINTERRUPT _In_ PFN_WDF_INTERRUPT_SYNCHRONIZE Callback
Definition: wdfinterrupt.h:458
int codepage
Definition: win_iconv.c:156
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
int * PINT
Definition: windef.h:177
#define WINAPI
Definition: msvc.h:6
#define ERROR_INVALID_USER_BUFFER
Definition: winerror.h:1091
#define ERROR_INVALID_DATA
Definition: winerror.h:116
#define GetLocaleInfo
Definition: winnls.h:1186
#define LOCALE_ILANGUAGE
Definition: winnls.h:25
char TCHAR
Definition: xmlstorage.h:189
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
unsigned char BYTE
Definition: xxhash.c:193