3 * Copyright (C) 2002,2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: boot/freeldr/freeldr/lib/inffile/inffile.c
23 * PURPOSE: INF file parser that caches contents of INF file in memory
24 * PROGRAMMER: Royce Mitchell III
28 /* INCLUDES *****************************************************************/
32 #define CONTROL_Z '\x1a'
33 #define MAX_SECTION_NAME_LEN 255
34 #define MAX_FIELD_LEN 511 /* larger fields get silently truncated */
35 /* actual string limit is MAX_INF_STRING_LENGTH+1 (plus terminating null) under Windows */
36 #define MAX_STRING_LEN (MAX_INF_STRING_LENGTH+1)
38 #define TAG_INF_KEY 'KfnI'
39 #define TAG_INF_FIELD 'ffnI'
40 #define TAG_INF_LINE 'LfnI'
41 #define TAG_INF_SECTION 'SfnI'
42 #define TAG_INF_CACHE 'CfnI'
43 #define TAG_INF_FILE 'FfnI'
45 typedef struct _INFCACHEFIELD
47 struct _INFCACHEFIELD
*Next
;
48 struct _INFCACHEFIELD
*Prev
;
51 } INFCACHEFIELD
, *PINFCACHEFIELD
;
53 typedef struct _INFCACHELINE
55 struct _INFCACHELINE
*Next
;
56 struct _INFCACHELINE
*Prev
;
62 PINFCACHEFIELD FirstField
;
63 PINFCACHEFIELD LastField
;
65 } INFCACHELINE
, *PINFCACHELINE
;
67 typedef struct _INFCACHESECTION
69 struct _INFCACHESECTION
*Next
;
70 struct _INFCACHESECTION
*Prev
;
72 PINFCACHELINE FirstLine
;
73 PINFCACHELINE LastLine
;
78 } INFCACHESECTION
, *PINFCACHESECTION
;
80 typedef struct _INFCACHE
82 PINFCACHESECTION FirstSection
;
83 PINFCACHESECTION LastSection
;
85 PINFCACHESECTION StringsSection
;
86 } INFCACHE
, *PINFCACHE
;
88 /* parser definitions */
91 LINE_START
, /* at beginning of a line */
92 SECTION_NAME
, /* parsing a section name */
93 KEY_NAME
, /* parsing a key name */
94 VALUE_NAME
, /* parsing a value name */
95 EOL_BACKSLASH
, /* backslash at end of line */
96 QUOTES
, /* inside quotes */
97 LEADING_SPACES
, /* leading spaces */
98 TRAILING_SPACES
, /* trailing spaces */
99 COMMENT
, /* inside a comment */
105 const CHAR
*start
; /* start position of item being parsed */
106 const CHAR
*end
; /* end of buffer */
107 PINFCACHE file
; /* file being built */
108 enum parser_state state
; /* current parser state */
109 enum parser_state stack
[4]; /* state stack */
110 int stack_pos
; /* current pos in stack */
112 PINFCACHESECTION cur_section
; /* pointer to the section being parsed*/
113 PINFCACHELINE line
; /* current line */
114 unsigned int line_pos
; /* current line position in file */
115 unsigned int error
; /* error code */
116 unsigned int token_len
; /* current token len */
117 CHAR token
[MAX_FIELD_LEN
+ 1]; /* current token */
120 typedef const CHAR
* (*parser_state_func
)(struct parser
*parser
, const CHAR
*pos
);
122 /* parser state machine functions */
123 static const CHAR
*line_start_state(struct parser
*parser
, const CHAR
*pos
);
124 static const CHAR
*section_name_state(struct parser
*parser
, const CHAR
*pos
);
125 static const CHAR
*key_name_state(struct parser
*parser
, const CHAR
*pos
);
126 static const CHAR
*value_name_state(struct parser
*parser
, const CHAR
*pos
);
127 static const CHAR
*eol_backslash_state(struct parser
*parser
, const CHAR
*pos
);
128 static const CHAR
*quotes_state(struct parser
*parser
, const CHAR
*pos
);
129 static const CHAR
*leading_spaces_state(struct parser
*parser
, const CHAR
*pos
);
130 static const CHAR
*trailing_spaces_state(struct parser
*parser
, const CHAR
*pos
);
131 static const CHAR
*comment_state(struct parser
*parser
, const CHAR
*pos
);
134 const parser_state_func
135 parser_funcs
[NB_PARSER_STATES
] =
137 line_start_state
, /* LINE_START */
138 section_name_state
, /* SECTION_NAME */
139 key_name_state
, /* KEY_NAME */
140 value_name_state
, /* VALUE_NAME */
141 eol_backslash_state
, /* EOL_BACKSLASH */
142 quotes_state
, /* QUOTES */
143 leading_spaces_state
, /* LEADING_SPACES */
144 trailing_spaces_state
, /* TRAILING_SPACES */
145 comment_state
/* COMMENT */
149 /* PRIVATE FUNCTIONS ********************************************************/
157 PINFCACHEFIELD Field
;
165 if (Line
->Key
!= NULL
)
167 FrLdrTempFree(Line
->Key
, TAG_INF_KEY
);
171 /* Remove data fields */
172 while (Line
->FirstField
!= NULL
)
174 Field
= Line
->FirstField
->Next
;
175 FrLdrTempFree(Line
->FirstField
, TAG_INF_FIELD
);
176 Line
->FirstField
= Field
;
178 Line
->LastField
= NULL
;
180 FrLdrTempFree(Line
, TAG_INF_LINE
);
188 InfpCacheFreeSection(
189 PINFCACHESECTION Section
)
191 PINFCACHESECTION Next
;
198 /* Release all keys */
199 Next
= Section
->Next
;
200 while (Section
->FirstLine
!= NULL
)
202 Section
->FirstLine
= InfpCacheFreeLine(Section
->FirstLine
);
204 Section
->LastLine
= NULL
;
206 FrLdrTempFree(Section
, TAG_INF_SECTION
);
214 InfpCacheFindSection(
218 PINFCACHESECTION Section
= NULL
;
220 if (Cache
== NULL
|| Name
== NULL
)
225 /* iterate through list of sections */
226 Section
= Cache
->FirstSection
;
227 while (Section
!= NULL
)
229 if (_stricmp(Section
->Name
, Name
) == 0)
234 /* get the next section*/
235 Section
= Section
->Next
;
248 PINFCACHESECTION Section
= NULL
;
251 if ((Cache
== NULL
) || (Name
== NULL
))
253 // DPRINT("Invalid parameter\n");
257 /* Allocate and initialize the new section */
258 Size
= sizeof(INFCACHESECTION
) + strlen(Name
);
259 Section
= (PINFCACHESECTION
)FrLdrTempAlloc(Size
, TAG_INF_SECTION
);
262 // DPRINT("RtlAllocateHeap() failed\n");
265 memset(Section
, 0, Size
);
267 /* Copy section name */
268 strcpy(Section
->Name
, Name
);
271 if (Cache
->FirstSection
== NULL
)
273 Cache
->FirstSection
= Section
;
274 Cache
->LastSection
= Section
;
278 Cache
->LastSection
->Next
= Section
;
279 Section
->Prev
= Cache
->LastSection
;
280 Cache
->LastSection
= Section
;
289 InfpCacheAddLine(PINFCACHESECTION Section
)
295 // DPRINT("Invalid parameter\n");
299 Line
= (PINFCACHELINE
)FrLdrTempAlloc(sizeof(INFCACHELINE
), TAG_INF_LINE
);
302 // DPRINT("RtlAllocateHeap() failed\n");
305 memset(Line
, 0, sizeof(INFCACHELINE
));
308 if (Section
->FirstLine
== NULL
)
310 Section
->FirstLine
= Line
;
311 Section
->LastLine
= Line
;
315 Section
->LastLine
->Next
= Line
;
316 Line
->Prev
= Section
->LastLine
;
317 Section
->LastLine
= Line
;
319 Section
->LineCount
++;
334 if (Line
->Key
!= NULL
)
337 Line
->Key
= FrLdrTempAlloc(strlen(Key
) + 1, TAG_INF_KEY
);
338 if (Line
->Key
== NULL
)
341 strcpy(Line
->Key
, Key
);
343 return (PVOID
)Line
->Key
;
353 PINFCACHEFIELD Field
;
356 Size
= sizeof(INFCACHEFIELD
) + strlen(Data
);
357 Field
= (PINFCACHEFIELD
)FrLdrTempAlloc(Size
, TAG_INF_FIELD
);
362 memset(Field
, 0, Size
);
364 strcpy(Field
->Data
, Data
);
367 if (Line
->FirstField
== NULL
)
369 Line
->FirstField
= Field
;
370 Line
->LastField
= Field
;
374 Line
->LastField
->Next
= Field
;
375 Field
->Prev
= Line
->LastField
;
376 Line
->LastField
= Field
;
386 InfpCacheFindKeyLine(
387 PINFCACHESECTION Section
,
392 Line
= Section
->FirstLine
;
395 if ((Line
->Key
!= NULL
) && (_stricmp(Line
->Key
, Key
) == 0))
407 /* push the current state on the parser stack */
408 __inline
static void push_state(struct parser
*parser
, enum parser_state state
)
410 // assert(parser->stack_pos < sizeof(parser->stack)/sizeof(parser->stack[0]));
411 parser
->stack
[parser
->stack_pos
++] = state
;
415 /* pop the current state */
416 __inline
static void pop_state(struct parser
*parser
)
418 // assert( parser->stack_pos );
419 parser
->state
= parser
->stack
[--parser
->stack_pos
];
423 /* set the parser state and return the previous one */
424 __inline
static enum parser_state
set_state(struct parser
*parser
, enum parser_state state
)
426 enum parser_state ret
= parser
->state
;
427 parser
->state
= state
;
432 /* check if the pointer points to an end of file */
433 __inline
static int is_eof(struct parser
*parser
, const CHAR
*ptr
)
435 return (ptr
>= parser
->end
|| *ptr
== CONTROL_Z
);
439 /* check if the pointer points to an end of line */
440 __inline
static int is_eol(struct parser
*parser
, const CHAR
*ptr
)
442 return ((ptr
>= parser
->end
) ||
443 (*ptr
== CONTROL_Z
) ||
445 ((*ptr
== '\r') && (*(ptr
+ 1) == '\n')));
449 /* push data from current token start up to pos into the current token */
453 struct parser
*parser
,
456 SIZE_T len
= pos
- parser
->start
;
457 const CHAR
*src
= parser
->start
;
458 CHAR
*dst
= parser
->token
+ parser
->token_len
;
460 if (len
> MAX_FIELD_LEN
- parser
->token_len
)
461 len
= MAX_FIELD_LEN
- parser
->token_len
;
463 parser
->token_len
+= (ULONG
)len
;
464 for ( ; len
> 0; len
--, dst
++, src
++)
465 *dst
= *src
? (CHAR
)*src
: L
' ';
473 /* add a section with the current token as name */
476 add_section_from_token(struct parser
*parser
)
478 PINFCACHESECTION Section
;
480 if (parser
->token_len
> MAX_SECTION_NAME_LEN
)
482 parser
->error
= FALSE
;
486 Section
= InfpCacheFindSection(parser
->file
, parser
->token
);
489 /* need to create a new one */
490 Section
= InfpCacheAddSection(parser
->file
, parser
->token
);
493 parser
->error
= FALSE
;
498 parser
->token_len
= 0;
499 parser
->cur_section
= Section
;
501 return (PVOID
)Section
;
505 /* add a field containing the current token to the current line */
508 add_field_from_token(
509 struct parser
*parser
,
514 if (!parser
->line
) /* need to start a new line */
516 if (parser
->cur_section
== NULL
) /* got a line before the first section */
518 parser
->error
= STATUS_WRONG_INF_STYLE
;
522 parser
->line
= InfpCacheAddLine(parser
->cur_section
);
523 if (parser
->line
== NULL
)
533 field
= InfpAddKeyToLine(parser
->line
, parser
->token
);
537 field
= InfpAddFieldToLine(parser
->line
, parser
->token
);
542 parser
->token_len
= 0;
547 parser
->error
= FALSE
;
552 /* close the current line and prepare for parsing a new one */
555 close_current_line(struct parser
*parser
)
561 /* handler for parser LINE_START state */
565 struct parser
*parser
,
570 for (p
= pos
; !is_eof(parser
, p
); p
++)
579 close_current_line(parser
);
583 push_state(parser
, LINE_START
);
584 set_state(parser
, COMMENT
);
588 parser
->start
= p
+ 1;
589 set_state(parser
, SECTION_NAME
);
593 if (!isspace((unsigned char)*p
))
596 set_state(parser
, KEY_NAME
);
602 close_current_line(parser
);
607 /* handler for parser SECTION_NAME state */
611 struct parser
*parser
,
616 for (p
= pos
; !is_eol(parser
, p
); p
++)
620 push_token(parser
, p
);
621 if (add_section_from_token(parser
) == NULL
)
623 push_state(parser
, LINE_START
);
624 set_state(parser
, COMMENT
); /* ignore everything else on the line */
628 parser
->error
= STATUS_BAD_SECTION_NAME_LINE
; /* unfinished section name */
633 /* handler for parser KEY_NAME state */
637 struct parser
*parser
,
640 const CHAR
*p
, *token_end
= parser
->start
;
642 for (p
= pos
; !is_eol(parser
, p
); p
++)
644 if (*p
== ',') break;
649 push_token(parser
, token_end
);
650 if (!add_field_from_token(parser
, 1)) return NULL
;
651 parser
->start
= p
+ 1;
652 push_state(parser
, VALUE_NAME
);
653 set_state(parser
, LEADING_SPACES
);
656 push_token(parser
, token_end
);
657 if (!add_field_from_token(parser
, 0)) return NULL
;
658 push_state(parser
, LINE_START
);
659 set_state(parser
, COMMENT
);
662 push_token(parser
, token_end
);
663 parser
->start
= p
+ 1;
664 push_state(parser
, KEY_NAME
);
665 set_state(parser
, QUOTES
);
668 push_token(parser
, token_end
);
670 push_state(parser
, KEY_NAME
);
671 set_state(parser
, EOL_BACKSLASH
);
674 if (!isspace((unsigned char)*p
)) token_end
= p
+ 1;
677 push_token(parser
, p
);
678 push_state(parser
, KEY_NAME
);
679 set_state(parser
, TRAILING_SPACES
);
685 push_token(parser
, token_end
);
686 set_state(parser
, VALUE_NAME
);
691 /* handler for parser VALUE_NAME state */
695 struct parser
*parser
,
698 const CHAR
*p
, *token_end
= parser
->start
;
700 for (p
= pos
; !is_eol(parser
, p
); p
++)
705 push_token(parser
, token_end
);
706 if (!add_field_from_token(parser
, 0)) return NULL
;
707 push_state(parser
, LINE_START
);
708 set_state(parser
, COMMENT
);
711 push_token(parser
, token_end
);
712 if (!add_field_from_token(parser
, 0)) return NULL
;
713 parser
->start
= p
+ 1;
714 push_state(parser
, VALUE_NAME
);
715 set_state(parser
, LEADING_SPACES
);
718 push_token(parser
, token_end
);
719 parser
->start
= p
+ 1;
720 push_state(parser
, VALUE_NAME
);
721 set_state(parser
, QUOTES
);
724 push_token(parser
, token_end
);
726 push_state(parser
, VALUE_NAME
);
727 set_state(parser
, EOL_BACKSLASH
);
730 if (!isspace((unsigned char)*p
)) token_end
= p
+ 1;
733 push_token(parser
, p
);
734 push_state(parser
, VALUE_NAME
);
735 set_state(parser
, TRAILING_SPACES
);
741 push_token(parser
, token_end
);
742 if (!add_field_from_token(parser
, 0)) return NULL
;
743 set_state(parser
, LINE_START
);
748 /* handler for parser EOL_BACKSLASH state */
752 struct parser
*parser
,
757 for (p
= pos
; !is_eof(parser
, p
); p
++)
766 parser
->start
= p
+ 1;
767 set_state(parser
, LEADING_SPACES
);
774 push_state(parser
, EOL_BACKSLASH
);
775 set_state(parser
, COMMENT
);
779 if (isspace((unsigned char)*p
))
781 push_token(parser
, p
);
793 /* handler for parser QUOTES state */
797 struct parser
*parser
,
800 const CHAR
*p
, *token_end
= parser
->start
;
802 for (p
= pos
; !is_eol(parser
, p
); p
++)
806 if (p
+ 1 < parser
->end
&& p
[1] == '"') /* double quotes */
808 push_token(parser
, p
+ 1);
809 parser
->start
= token_end
= p
+ 2;
812 else /* end of quotes */
814 push_token(parser
, p
);
815 parser
->start
= p
+ 1;
821 push_token(parser
, p
);
827 /* handler for parser LEADING_SPACES state */
830 leading_spaces_state(
831 struct parser
*parser
,
836 for (p
= pos
; !is_eol(parser
, p
); p
++)
841 set_state(parser
, EOL_BACKSLASH
);
844 if (!isspace((unsigned char)*p
))
853 /* handler for parser TRAILING_SPACES state */
856 trailing_spaces_state(
857 struct parser
*parser
,
862 for (p
= pos
; !is_eol(parser
, p
); p
++)
866 set_state(parser
, EOL_BACKSLASH
);
869 if (!isspace((unsigned char)*p
))
877 /* handler for parser COMMENT state */
881 struct parser
*parser
,
886 while (!is_eol(parser
, p
))
893 /* parse a complete buffer */
902 struct parser parser
;
903 const CHAR
* pos
= buffer
;
905 parser
.start
= buffer
;
909 parser
.state
= LINE_START
;
910 parser
.stack_pos
= 0;
911 parser
.cur_section
= NULL
;
914 parser
.token_len
= 0;
916 /* parser main loop */
918 pos
= (parser_funcs
[parser
.state
])(&parser
, pos
);
923 *error_line
= parser
.line_pos
;
927 /* find the [strings] section */
928 file
->StringsSection
= InfpCacheFindSection(file
, "Strings");
933 /* PUBLIC FUNCTIONS *********************************************************/
941 FILEINFORMATION Information
;
944 ULONG FileSize
, Count
;
950 *ErrorLine
= (ULONG
) - 1;
953 // Open the .inf file
955 Status
= ArcOpen((PCHAR
)FileName
, OpenReadOnly
, &FileId
);
956 if (Status
!= ESUCCESS
)
964 Status
= ArcGetFileInformation(FileId
, &Information
);
965 if ((Status
!= ESUCCESS
) || (Information
.EndingAddress
.HighPart
!= 0))
970 FileSize
= Information
.EndingAddress
.LowPart
;
973 // Allocate buffer to cache the file
975 FileBuffer
= FrLdrTempAlloc(FileSize
+ 1, TAG_INF_FILE
);
983 // Read file into memory
985 Status
= ArcRead(FileId
, FileBuffer
, FileSize
, &Count
);
986 if ((Status
!= ESUCCESS
) || (Count
!= FileSize
))
989 FrLdrTempFree(FileBuffer
, TAG_INF_FILE
);
994 // We don't need the file anymore. Close it
999 // Append string terminator
1001 FileBuffer
[FileSize
] = 0;
1004 // Allocate infcache header
1006 Cache
= (PINFCACHE
)FrLdrTempAlloc(sizeof(INFCACHE
), TAG_INF_CACHE
);
1009 FrLdrTempFree(FileBuffer
, TAG_INF_FILE
);
1014 // Initialize inicache header
1016 RtlZeroMemory(Cache
, sizeof(INFCACHE
));
1019 // Parse the inf buffer
1021 Success
= InfpParseBuffer(Cache
,
1023 FileBuffer
+ FileSize
,
1027 FrLdrTempFree(Cache
, TAG_INF_CACHE
);
1032 // Free file buffer, as it has been parsed
1034 FrLdrTempFree(FileBuffer
, TAG_INF_FILE
);
1037 // Return .inf parsed contents
1039 *InfHandle
= (HINF
)Cache
;
1046 InfCloseFile(HINF InfHandle
)
1050 Cache
= (PINFCACHE
)InfHandle
;
1057 while (Cache
->FirstSection
!= NULL
)
1059 Cache
->FirstSection
= InfpCacheFreeSection(Cache
->FirstSection
);
1061 Cache
->LastSection
= NULL
;
1063 FrLdrTempFree(Cache
, TAG_INF_CACHE
);
1072 PINFCONTEXT Context
)
1075 PINFCACHESECTION CacheSection
;
1076 PINFCACHELINE CacheLine
;
1078 if ((InfHandle
== NULL
) || (Section
== NULL
) || (Context
== NULL
))
1080 // DPRINT("Invalid parameter\n");
1084 Cache
= (PINFCACHE
)InfHandle
;
1086 /* Iterate through list of sections */
1087 CacheSection
= Cache
->FirstSection
;
1088 while (Section
!= NULL
)
1090 // DPRINT("Comparing '%S' and '%S'\n", CacheSection->Name, Section);
1092 /* Are the section names the same? */
1093 if (_stricmp(CacheSection
->Name
, Section
) == 0)
1097 CacheLine
= InfpCacheFindKeyLine(CacheSection
, Key
);
1101 CacheLine
= CacheSection
->FirstLine
;
1104 if (CacheLine
== NULL
)
1107 Context
->Inf
= (PVOID
)Cache
;
1108 Context
->Section
= (PVOID
)CacheSection
;
1109 Context
->Line
= (PVOID
)CacheLine
;
1114 /* Get the next section */
1115 CacheSection
= CacheSection
->Next
;
1118 // DPRINT("Section not found\n");
1126 PINFCONTEXT ContextIn
,
1127 PINFCONTEXT ContextOut
)
1129 PINFCACHELINE CacheLine
;
1131 if ((ContextIn
== NULL
) || (ContextOut
== NULL
))
1134 if (ContextIn
->Line
== NULL
)
1137 CacheLine
= (PINFCACHELINE
)ContextIn
->Line
;
1138 if (CacheLine
->Next
== NULL
)
1141 if (ContextIn
!= ContextOut
)
1143 ContextOut
->Inf
= ContextIn
->Inf
;
1144 ContextOut
->Section
= ContextIn
->Section
;
1146 ContextOut
->Line
= (PVOID
)(CacheLine
->Next
);
1153 InfFindFirstMatchLine (
1154 PINFCONTEXT ContextIn
,
1156 PINFCONTEXT ContextOut
)
1158 PINFCACHELINE CacheLine
;
1160 if ((ContextIn
== NULL
) || (ContextOut
== NULL
) || (Key
== NULL
) || (*Key
== 0))
1163 if (ContextIn
->Inf
== NULL
|| ContextIn
->Section
== NULL
)
1166 CacheLine
= ((PINFCACHESECTION
)(ContextIn
->Section
))->FirstLine
;
1167 while (CacheLine
!= NULL
)
1169 if ((CacheLine
->Key
!= NULL
) && (_stricmp(CacheLine
->Key
, Key
) == 0))
1172 if (ContextIn
!= ContextOut
)
1174 ContextOut
->Inf
= ContextIn
->Inf
;
1175 ContextOut
->Section
= ContextIn
->Section
;
1177 ContextOut
->Line
= (PVOID
)CacheLine
;
1182 CacheLine
= CacheLine
->Next
;
1190 InfFindNextMatchLine (
1191 PINFCONTEXT ContextIn
,
1193 PINFCONTEXT ContextOut
)
1195 PINFCACHELINE CacheLine
;
1197 if ((ContextIn
== NULL
) || (ContextOut
== NULL
) || (Key
== NULL
) || (*Key
== 0))
1200 if ((ContextIn
->Inf
== NULL
) || (ContextIn
->Section
== NULL
) || (ContextIn
->Line
== NULL
))
1203 CacheLine
= (PINFCACHELINE
)ContextIn
->Line
;
1204 while (CacheLine
!= NULL
)
1206 if ((CacheLine
->Key
!= NULL
) && (_stricmp(CacheLine
->Key
, Key
) == 0))
1209 if (ContextIn
!= ContextOut
)
1211 ContextOut
->Inf
= ContextIn
->Inf
;
1212 ContextOut
->Section
= ContextIn
->Section
;
1214 ContextOut
->Line
= (PVOID
)CacheLine
;
1219 CacheLine
= CacheLine
->Next
;
1232 PINFCACHESECTION CacheSection
;
1234 if ((InfHandle
== NULL
) || (Section
== NULL
))
1236 // DPRINT("Invalid parameter\n");
1240 Cache
= (PINFCACHE
)InfHandle
;
1242 /* Iterate through list of sections */
1243 CacheSection
= Cache
->FirstSection
;
1244 while (Section
!= NULL
)
1246 // DPRINT("Comparing '%S' and '%S'\n", CacheSection->Name, Section);
1248 /* Are the section names the same? */
1249 if (_stricmp(CacheSection
->Name
, Section
) == 0)
1251 return CacheSection
->LineCount
;
1254 /* Get the next section */
1255 CacheSection
= CacheSection
->Next
;
1258 // DPRINT("Section not found\n");
1264 /* InfGetLineText */
1268 InfGetFieldCount(PINFCONTEXT Context
)
1270 if ((Context
== NULL
) || (Context
->Line
== NULL
))
1273 return ((PINFCACHELINE
)Context
->Line
)->FieldCount
;
1279 PINFCONTEXT Context
,
1281 PUCHAR ReturnBuffer
,
1282 ULONG ReturnBufferSize
,
1283 PULONG RequiredSize
)
1285 PINFCACHELINE CacheLine
;
1286 PINFCACHEFIELD CacheField
;
1291 if ((Context
== NULL
) || (Context
->Line
== NULL
) || (FieldIndex
== 0))
1293 // DPRINT("Invalid parameter\n");
1297 if (RequiredSize
!= NULL
)
1300 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1302 if (FieldIndex
> CacheLine
->FieldCount
)
1305 CacheField
= CacheLine
->FirstField
;
1306 for (Index
= 1; Index
< FieldIndex
; Index
++)
1307 CacheField
= CacheField
->Next
;
1309 Size
= CacheLine
->FieldCount
- FieldIndex
+ 1;
1311 if (RequiredSize
!= NULL
)
1312 *RequiredSize
= Size
;
1314 if (ReturnBuffer
!= NULL
)
1316 if (ReturnBufferSize
< Size
)
1319 /* Copy binary data */
1321 while (CacheField
!= NULL
)
1323 *Ptr
= (UCHAR
)atoi(CacheField
->Data
); //strtoul(CacheField->Data, NULL, 16);
1326 CacheField
= CacheField
->Next
;
1336 PINFCONTEXT Context
,
1340 PINFCACHELINE CacheLine
;
1341 PINFCACHEFIELD CacheField
;
1345 if ((Context
== NULL
) || (Context
->Line
== NULL
) || (IntegerValue
== NULL
))
1347 // DPRINT("Invalid parameter\n");
1351 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1353 if (FieldIndex
> CacheLine
->FieldCount
)
1355 // DPRINT("Invalid parameter\n");
1359 if (FieldIndex
== 0)
1361 Ptr
= CacheLine
->Key
;
1365 CacheField
= CacheLine
->FirstField
;
1366 for (Index
= 1; Index
< FieldIndex
; Index
++)
1367 CacheField
= CacheField
->Next
;
1369 Ptr
= CacheField
->Data
;
1372 *IntegerValue
= atoi(Ptr
); //strtol(Ptr, NULL, 0);
1379 InfGetMultiSzField (
1380 PINFCONTEXT Context
,
1383 ULONG ReturnBufferSize
,
1384 PULONG RequiredSize
)
1386 PINFCACHELINE CacheLine
;
1387 PINFCACHEFIELD CacheField
;
1388 PINFCACHEFIELD FieldPtr
;
1393 if ((Context
== NULL
) || (Context
->Line
== NULL
) || (FieldIndex
== 0))
1395 // DPRINT("Invalid parameter\n");
1399 if (RequiredSize
!= NULL
)
1402 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1404 if (FieldIndex
> CacheLine
->FieldCount
)
1407 CacheField
= CacheLine
->FirstField
;
1408 for (Index
= 1; Index
< FieldIndex
; Index
++)
1409 CacheField
= CacheField
->Next
;
1411 /* Calculate the required buffer size */
1412 FieldPtr
= CacheField
;
1414 while (FieldPtr
!= NULL
)
1416 Size
+= (strlen(FieldPtr
->Data
) + 1);
1417 FieldPtr
= FieldPtr
->Next
;
1421 if (RequiredSize
!= NULL
)
1422 *RequiredSize
= (ULONG
)Size
;
1424 if (ReturnBuffer
!= NULL
)
1426 if (ReturnBufferSize
< Size
)
1429 /* Copy multi-sz string */
1431 FieldPtr
= CacheField
;
1432 while (FieldPtr
!= NULL
)
1434 Size
= strlen(FieldPtr
->Data
) + 1;
1436 strcpy(Ptr
, FieldPtr
->Data
);
1439 FieldPtr
= FieldPtr
->Next
;
1450 PINFCONTEXT Context
,
1453 ULONG ReturnBufferSize
,
1454 PULONG RequiredSize
)
1456 PINFCACHELINE CacheLine
;
1457 PINFCACHEFIELD CacheField
;
1462 if ((Context
== NULL
) || (Context
->Line
== NULL
))
1464 // DPRINT("Invalid parameter\n");
1468 if (RequiredSize
!= NULL
)
1471 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1473 if (FieldIndex
> CacheLine
->FieldCount
)
1476 if (FieldIndex
== 0)
1478 Ptr
= CacheLine
->Key
;
1482 CacheField
= CacheLine
->FirstField
;
1483 for (Index
= 1; Index
< FieldIndex
; Index
++)
1484 CacheField
= CacheField
->Next
;
1486 Ptr
= CacheField
->Data
;
1489 Size
= strlen(Ptr
) + 1;
1491 if (RequiredSize
!= NULL
)
1492 *RequiredSize
= (ULONG
)Size
;
1494 if (ReturnBuffer
!= NULL
)
1496 if (ReturnBufferSize
< Size
)
1499 strcpy(ReturnBuffer
, Ptr
);
1510 PINFCONTEXT Context
,
1514 PINFCACHELINE CacheKey
;
1516 if ((Context
== NULL
) || (Context
->Line
== NULL
) || (Data
== NULL
))
1518 // DPRINT("Invalid parameter\n");
1522 CacheKey
= (PINFCACHELINE
)Context
->Line
;
1524 *Key
= CacheKey
->Key
;
1528 if (CacheKey
->FirstField
== NULL
)
1534 *Data
= CacheKey
->FirstField
->Data
;
1544 PINFCONTEXT Context
,
1548 PINFCACHELINE CacheLine
;
1549 PINFCACHEFIELD CacheField
;
1552 if ((Context
== NULL
) || (Context
->Line
== NULL
) || (Data
== NULL
))
1554 // DPRINT("Invalid parameter\n");
1558 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1560 if (FieldIndex
> CacheLine
->FieldCount
)
1563 if (FieldIndex
== 0)
1565 *Data
= CacheLine
->Key
;
1569 CacheField
= CacheLine
->FirstField
;
1570 for (Index
= 1; Index
< FieldIndex
; Index
++)
1571 CacheField
= CacheField
->Next
;
1573 *Data
= CacheField
->Data
;