3 * Copyright (C) 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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: infcache.c,v 1.9 2004/12/30 16:02:12 royce Exp $
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS hive maker
22 * FILE: tools/mkhive/infcache.c
23 * PURPOSE: INF file parser that caches contents of INF file in memory
24 * PROGRAMMER: Royce Mitchell III
28 /* INCLUDES *****************************************************************/
39 #define CONTROL_Z '\x1a'
40 #define MAX_SECTION_NAME_LEN 255
41 #define MAX_FIELD_LEN 511 /* larger fields get silently truncated */
42 /* actual string limit is MAX_INF_STRING_LENGTH+1 (plus terminating null) under Windows */
43 #define MAX_STRING_LEN (MAX_INF_STRING_LENGTH+1)
46 typedef struct _INFCACHEFIELD
48 struct _INFCACHEFIELD
*Next
;
49 struct _INFCACHEFIELD
*Prev
;
52 } INFCACHEFIELD
, *PINFCACHEFIELD
;
55 typedef struct _INFCACHELINE
57 struct _INFCACHELINE
*Next
;
58 struct _INFCACHELINE
*Prev
;
64 PINFCACHEFIELD FirstField
;
65 PINFCACHEFIELD LastField
;
67 } INFCACHELINE
, *PINFCACHELINE
;
70 typedef struct _INFCACHESECTION
72 struct _INFCACHESECTION
*Next
;
73 struct _INFCACHESECTION
*Prev
;
75 PINFCACHELINE FirstLine
;
76 PINFCACHELINE LastLine
;
81 } INFCACHESECTION
, *PINFCACHESECTION
;
84 typedef struct _INFCACHE
86 PINFCACHESECTION FirstSection
;
87 PINFCACHESECTION LastSection
;
89 PINFCACHESECTION StringsSection
;
90 } INFCACHE
, *PINFCACHE
;
93 /* parser definitions */
97 LINE_START
, /* at beginning of a line */
98 SECTION_NAME
, /* parsing a section name */
99 KEY_NAME
, /* parsing a key name */
100 VALUE_NAME
, /* parsing a value name */
101 EOL_BACKSLASH
, /* backslash at end of line */
102 QUOTES
, /* inside quotes */
103 LEADING_SPACES
, /* leading spaces */
104 TRAILING_SPACES
, /* trailing spaces */
105 COMMENT
, /* inside a comment */
111 const CHAR
*start
; /* start position of item being parsed */
112 const CHAR
*end
; /* end of buffer */
113 PINFCACHE file
; /* file being built */
114 enum parser_state state
; /* current parser state */
115 enum parser_state stack
[4]; /* state stack */
116 int stack_pos
; /* current pos in stack */
118 PINFCACHESECTION cur_section
; /* pointer to the section being parsed*/
119 PINFCACHELINE line
; /* current line */
120 unsigned int line_pos
; /* current line position in file */
121 unsigned int error
; /* error code */
122 unsigned int token_len
; /* current token len */
123 CHAR token
[MAX_FIELD_LEN
+1]; /* current token */
126 typedef const CHAR
* (*parser_state_func
)( struct parser
*parser
, const CHAR
*pos
);
128 /* parser state machine functions */
129 static const CHAR
*line_start_state( struct parser
*parser
, const CHAR
*pos
);
130 static const CHAR
*section_name_state( struct parser
*parser
, const CHAR
*pos
);
131 static const CHAR
*key_name_state( struct parser
*parser
, const CHAR
*pos
);
132 static const CHAR
*value_name_state( struct parser
*parser
, const CHAR
*pos
);
133 static const CHAR
*eol_backslash_state( struct parser
*parser
, const CHAR
*pos
);
134 static const CHAR
*quotes_state( struct parser
*parser
, const CHAR
*pos
);
135 static const CHAR
*leading_spaces_state( struct parser
*parser
, const CHAR
*pos
);
136 static const CHAR
*trailing_spaces_state( struct parser
*parser
, const CHAR
*pos
);
137 static const CHAR
*comment_state( struct parser
*parser
, const CHAR
*pos
);
139 static const parser_state_func parser_funcs
[NB_PARSER_STATES
] =
141 line_start_state
, /* LINE_START */
142 section_name_state
, /* SECTION_NAME */
143 key_name_state
, /* KEY_NAME */
144 value_name_state
, /* VALUE_NAME */
145 eol_backslash_state
, /* EOL_BACKSLASH */
146 quotes_state
, /* QUOTES */
147 leading_spaces_state
, /* LEADING_SPACES */
148 trailing_spaces_state
, /* TRAILING_SPACES */
149 comment_state
/* COMMENT */
153 /* PRIVATE FUNCTIONS ********************************************************/
156 InfpCacheFreeLine (PINFCACHELINE Line
)
159 PINFCACHEFIELD Field
;
167 if (Line
->Key
!= NULL
)
173 /* Remove data fields */
174 while (Line
->FirstField
!= NULL
)
176 Field
= Line
->FirstField
->Next
;
177 free (Line
->FirstField
);
178 Line
->FirstField
= Field
;
180 Line
->LastField
= NULL
;
188 static PINFCACHESECTION
189 InfpCacheFreeSection (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
;
212 static PINFCACHESECTION
213 InfpCacheFindSection (PINFCACHE Cache
,
216 PINFCACHESECTION Section
= NULL
;
218 if (Cache
== NULL
|| Name
== NULL
)
223 /* iterate through list of sections */
224 Section
= Cache
->FirstSection
;
225 while (Section
!= NULL
)
227 if (strcasecmp (Section
->Name
, Name
) == 0)
232 /* get the next section*/
233 Section
= Section
->Next
;
240 static PINFCACHESECTION
241 InfpCacheAddSection (PINFCACHE Cache
,
244 PINFCACHESECTION Section
= NULL
;
247 if (Cache
== NULL
|| Name
== NULL
)
249 DPRINT ("Invalid parameter\n");
253 /* Allocate and initialize the new section */
254 Size
= sizeof(INFCACHESECTION
) + strlen (Name
);
255 Section
= (PINFCACHESECTION
)malloc (Size
);
258 DPRINT ("RtlAllocateHeap() failed\n");
261 memset (Section
, 0, Size
);
263 /* Copy section name */
264 strcpy (Section
->Name
, Name
);
267 if (Cache
->FirstSection
== NULL
)
269 Cache
->FirstSection
= Section
;
270 Cache
->LastSection
= Section
;
274 Cache
->LastSection
->Next
= Section
;
275 Section
->Prev
= Cache
->LastSection
;
276 Cache
->LastSection
= Section
;
284 InfpCacheAddLine (PINFCACHESECTION Section
)
290 DPRINT("Invalid parameter\n");
294 Line
= (PINFCACHELINE
)malloc (sizeof(INFCACHELINE
));
297 DPRINT("RtlAllocateHeap() failed\n");
300 memset (Line
, 0, sizeof(INFCACHELINE
));
303 if (Section
->FirstLine
== NULL
)
305 Section
->FirstLine
= Line
;
306 Section
->LastLine
= Line
;
310 Section
->LastLine
->Next
= Line
;
311 Line
->Prev
= Section
->LastLine
;
312 Section
->LastLine
= Line
;
314 Section
->LineCount
++;
321 InfpAddKeyToLine (PINFCACHELINE Line
,
327 if (Line
->Key
!= NULL
)
330 Line
->Key
= (PCHAR
)malloc (strlen (Key
) + 1);
331 if (Line
->Key
== NULL
)
334 strcpy (Line
->Key
, Key
);
336 return (PVOID
)Line
->Key
;
341 InfpAddFieldToLine (PINFCACHELINE Line
,
344 PINFCACHEFIELD Field
;
347 Size
= sizeof(INFCACHEFIELD
) + strlen(Data
);
348 Field
= (PINFCACHEFIELD
)malloc (Size
);
353 memset (Field
, 0, Size
);
354 strcpy (Field
->Data
, Data
);
357 if (Line
->FirstField
== NULL
)
359 Line
->FirstField
= Field
;
360 Line
->LastField
= Field
;
364 Line
->LastField
->Next
= Field
;
365 Field
->Prev
= Line
->LastField
;
366 Line
->LastField
= Field
;
375 InfpCacheFindKeyLine (PINFCACHESECTION Section
,
380 Line
= Section
->FirstLine
;
383 if (Line
->Key
!= NULL
&& strcasecmp (Line
->Key
, Key
) == 0)
395 /* push the current state on the parser stack */
396 inline static void push_state( struct parser
*parser
, enum parser_state state
)
398 // assert( parser->stack_pos < sizeof(parser->stack)/sizeof(parser->stack[0]) );
399 parser
->stack
[parser
->stack_pos
++] = state
;
403 /* pop the current state */
404 inline static void pop_state( struct parser
*parser
)
406 // assert( parser->stack_pos );
407 parser
->state
= parser
->stack
[--parser
->stack_pos
];
411 /* set the parser state and return the previous one */
412 inline static enum parser_state
set_state( struct parser
*parser
, enum parser_state state
)
414 enum parser_state ret
= parser
->state
;
415 parser
->state
= state
;
420 /* check if the pointer points to an end of file */
421 inline static int is_eof( struct parser
*parser
, const CHAR
*ptr
)
423 return (ptr
>= parser
->end
|| *ptr
== CONTROL_Z
);
427 /* check if the pointer points to an end of line */
428 inline static int is_eol( struct parser
*parser
, const CHAR
*ptr
)
430 return (ptr
>= parser
->end
||
433 (*ptr
== '\r' && *(ptr
+ 1) == '\n'));
437 /* push data from current token start up to pos into the current token */
438 static int push_token( struct parser
*parser
, const CHAR
*pos
)
440 ULONG len
= pos
- parser
->start
;
441 const CHAR
*src
= parser
->start
;
442 CHAR
*dst
= parser
->token
+ parser
->token_len
;
444 if (len
> MAX_FIELD_LEN
- parser
->token_len
)
445 len
= MAX_FIELD_LEN
- parser
->token_len
;
447 parser
->token_len
+= len
;
448 for ( ; len
> 0; len
--, dst
++, src
++)
449 *dst
= *src
? *src
: ' ';
458 /* add a section with the current token as name */
459 static PVOID
add_section_from_token( struct parser
*parser
)
461 PINFCACHESECTION Section
;
463 if (parser
->token_len
> MAX_SECTION_NAME_LEN
)
465 parser
->error
= STATUS_SECTION_NAME_TOO_LONG
;
469 Section
= InfpCacheFindSection (parser
->file
,
473 /* need to create a new one */
474 Section
= InfpCacheAddSection (parser
->file
,
478 parser
->error
= STATUS_NOT_ENOUGH_MEMORY
;
483 parser
->token_len
= 0;
484 parser
->cur_section
= Section
;
486 return (PVOID
)Section
;
490 /* add a field containing the current token to the current line */
491 static struct field
*add_field_from_token( struct parser
*parser
, int is_key
)
495 if (!parser
->line
) /* need to start a new line */
497 if (parser
->cur_section
== NULL
) /* got a line before the first section */
499 parser
->error
= STATUS_WRONG_INF_STYLE
;
503 parser
->line
= InfpCacheAddLine (parser
->cur_section
);
504 if (parser
->line
== NULL
)
514 field
= InfpAddKeyToLine(parser
->line
, parser
->token
);
518 field
= InfpAddFieldToLine(parser
->line
, parser
->token
);
523 parser
->token_len
= 0;
528 parser
->error
= STATUS_NOT_ENOUGH_MEMORY
;
533 /* close the current line and prepare for parsing a new one */
534 static void close_current_line( struct parser
*parser
)
541 /* handler for parser LINE_START state */
542 static const CHAR
*line_start_state( struct parser
*parser
, const CHAR
*pos
)
546 for (p
= pos
; !is_eof( parser
, p
); p
++)
555 close_current_line( parser
);
559 push_state( parser
, LINE_START
);
560 set_state( parser
, COMMENT
);
564 parser
->start
= p
+ 1;
565 set_state( parser
, SECTION_NAME
);
572 set_state( parser
, KEY_NAME
);
578 close_current_line( parser
);
583 /* handler for parser SECTION_NAME state */
584 static const CHAR
*section_name_state( struct parser
*parser
, const CHAR
*pos
)
588 for (p
= pos
; !is_eol( parser
, p
); p
++)
592 push_token( parser
, p
);
593 if (add_section_from_token( parser
) == NULL
)
595 push_state( parser
, LINE_START
);
596 set_state( parser
, COMMENT
); /* ignore everything else on the line */
600 parser
->error
= STATUS_BAD_SECTION_NAME_LINE
; /* unfinished section name */
605 /* handler for parser KEY_NAME state */
606 static const CHAR
*key_name_state( struct parser
*parser
, const CHAR
*pos
)
608 const CHAR
*p
, *token_end
= parser
->start
;
610 for (p
= pos
; !is_eol( parser
, p
); p
++)
612 if (*p
== ',') break;
617 push_token( parser
, token_end
);
618 if (!add_field_from_token( parser
, 1 )) return NULL
;
619 parser
->start
= p
+ 1;
620 push_state( parser
, VALUE_NAME
);
621 set_state( parser
, LEADING_SPACES
);
624 push_token( parser
, token_end
);
625 if (!add_field_from_token( parser
, 0 )) return NULL
;
626 push_state( parser
, LINE_START
);
627 set_state( parser
, COMMENT
);
630 push_token( parser
, token_end
);
631 parser
->start
= p
+ 1;
632 push_state( parser
, KEY_NAME
);
633 set_state( parser
, QUOTES
);
636 push_token( parser
, token_end
);
638 push_state( parser
, KEY_NAME
);
639 set_state( parser
, EOL_BACKSLASH
);
642 if (!isspace(*p
)) token_end
= p
+ 1;
645 push_token( parser
, p
);
646 push_state( parser
, KEY_NAME
);
647 set_state( parser
, TRAILING_SPACES
);
653 push_token( parser
, token_end
);
654 set_state( parser
, VALUE_NAME
);
659 /* handler for parser VALUE_NAME state */
660 static const CHAR
*value_name_state( struct parser
*parser
, const CHAR
*pos
)
662 const CHAR
*p
, *token_end
= parser
->start
;
664 for (p
= pos
; !is_eol( parser
, p
); p
++)
669 push_token( parser
, token_end
);
670 if (!add_field_from_token( parser
, 0 )) return NULL
;
671 push_state( parser
, LINE_START
);
672 set_state( parser
, COMMENT
);
675 push_token( parser
, token_end
);
676 if (!add_field_from_token( parser
, 0 )) return NULL
;
677 parser
->start
= p
+ 1;
678 push_state( parser
, VALUE_NAME
);
679 set_state( parser
, LEADING_SPACES
);
682 push_token( parser
, token_end
);
683 parser
->start
= p
+ 1;
684 push_state( parser
, VALUE_NAME
);
685 set_state( parser
, QUOTES
);
688 push_token( parser
, token_end
);
690 push_state( parser
, VALUE_NAME
);
691 set_state( parser
, EOL_BACKSLASH
);
694 if (!isspace(*p
)) token_end
= p
+ 1;
697 push_token( parser
, p
);
698 push_state( parser
, VALUE_NAME
);
699 set_state( parser
, TRAILING_SPACES
);
705 push_token( parser
, token_end
);
706 if (!add_field_from_token( parser
, 0 )) return NULL
;
707 set_state( parser
, LINE_START
);
712 /* handler for parser EOL_BACKSLASH state */
713 static const CHAR
*eol_backslash_state( struct parser
*parser
, const CHAR
*pos
)
717 for (p
= pos
; !is_eof( parser
, p
); p
++)
726 parser
->start
= p
+ 1;
727 set_state( parser
, LEADING_SPACES
);
734 push_state( parser
, EOL_BACKSLASH
);
735 set_state( parser
, COMMENT
);
741 push_token( parser
, p
);
753 /* handler for parser QUOTES state */
754 static const CHAR
*quotes_state( struct parser
*parser
, const CHAR
*pos
)
756 const CHAR
*p
, *token_end
= parser
->start
;
758 for (p
= pos
; !is_eol( parser
, p
); p
++)
762 if (p
+1 < parser
->end
&& p
[1] == '"') /* double quotes */
764 push_token( parser
, p
+ 1 );
765 parser
->start
= token_end
= p
+ 2;
768 else /* end of quotes */
770 push_token( parser
, p
);
771 parser
->start
= p
+ 1;
777 push_token( parser
, p
);
783 /* handler for parser LEADING_SPACES state */
784 static const CHAR
*leading_spaces_state( struct parser
*parser
, const CHAR
*pos
)
788 for (p
= pos
; !is_eol( parser
, p
); p
++)
793 set_state( parser
, EOL_BACKSLASH
);
805 /* handler for parser TRAILING_SPACES state */
806 static const CHAR
*trailing_spaces_state( struct parser
*parser
, const CHAR
*pos
)
810 for (p
= pos
; !is_eol( parser
, p
); p
++)
814 set_state( parser
, EOL_BACKSLASH
);
825 /* handler for parser COMMENT state */
826 static const CHAR
*comment_state( struct parser
*parser
, const CHAR
*pos
)
830 while (!is_eol( parser
, p
))
837 /* parse a complete buffer */
839 InfpParseBuffer (PINFCACHE file
,
844 struct parser parser
;
845 const CHAR
*pos
= buffer
;
847 parser
.start
= buffer
;
851 parser
.state
= LINE_START
;
852 parser
.stack_pos
= 0;
853 parser
.cur_section
= NULL
;
856 parser
.token_len
= 0;
858 /* parser main loop */
860 pos
= (parser_funcs
[parser
.state
])(&parser
, pos
);
865 *error_line
= parser
.line_pos
;
869 /* find the [strings] section */
870 file
->StringsSection
= InfpCacheFindSection (file
,
878 /* PUBLIC FUNCTIONS *********************************************************/
881 InfOpenFile(PHINF InfHandle
,
891 *ErrorLine
= (ULONG
)-1;
893 /* Open the inf file */
894 File
= fopen (FileName
, "rb");
897 DPRINT("fopen() failed\n");
901 DPRINT("fopen() successful\n");
903 /* Query file size */
904 fseek (File
, 0, SEEK_END
);
905 FileLength
= ftell (File
);
906 fseek (File
, 0, SEEK_SET
);
908 DPRINT("File size: %lu\n", FileLength
);
910 /* Allocate file buffer */
911 FileBuffer
= malloc (FileLength
+ 1);
912 if (FileBuffer
== NULL
)
914 DPRINT1("malloc() failed\n");
920 if (fread (FileBuffer
, FileLength
, 1, File
) < 0)
922 DPRINT ("fread() failed\n");
930 /* Append string terminator */
931 FileBuffer
[FileLength
] = 0;
933 /* Allocate infcache header */
934 Cache
= (PINFCACHE
)malloc (sizeof(INFCACHE
));
937 DPRINT("malloc() failed\n");
942 /* Initialize inicache header */
943 memset (Cache
, 0, sizeof(INFCACHE
));
945 /* Parse the inf buffer */
946 if (!InfpParseBuffer (Cache
,
948 FileBuffer
+ FileLength
,
956 /* Free file buffer */
959 *InfHandle
= (HINF
)Cache
;
966 InfCloseFile(HINF InfHandle
)
970 Cache
= (PINFCACHE
)InfHandle
;
977 while (Cache
->FirstSection
!= NULL
)
979 Cache
->FirstSection
= InfpCacheFreeSection(Cache
->FirstSection
);
981 Cache
->LastSection
= NULL
;
988 InfFindFirstLine (HINF InfHandle
,
994 PINFCACHESECTION CacheSection
;
995 PINFCACHELINE CacheLine
;
997 if (InfHandle
== NULL
|| Section
== NULL
|| Context
== NULL
)
999 DPRINT("Invalid parameter\n");
1003 Cache
= (PINFCACHE
)InfHandle
;
1005 /* Iterate through list of sections */
1006 CacheSection
= Cache
->FirstSection
;
1007 while (CacheSection
!= NULL
)
1009 DPRINT("Comparing '%s' and '%s'\n", CacheSection
->Name
, Section
);
1011 /* Are the section names the same? */
1012 if (strcasecmp(CacheSection
->Name
, Section
) == 0)
1016 CacheLine
= InfpCacheFindKeyLine (CacheSection
, (PCHAR
)Key
);
1020 CacheLine
= CacheSection
->FirstLine
;
1023 if (CacheLine
== NULL
)
1026 Context
->Inf
= (PVOID
)Cache
;
1027 Context
->Section
= (PVOID
)CacheSection
;
1028 Context
->Line
= (PVOID
)CacheLine
;
1033 /* Get the next section */
1034 CacheSection
= CacheSection
->Next
;
1037 DPRINT("Section not found\n");
1044 InfFindNextLine (PINFCONTEXT ContextIn
,
1045 PINFCONTEXT ContextOut
)
1047 PINFCACHELINE CacheLine
;
1049 if (ContextIn
== NULL
|| ContextOut
== NULL
)
1052 if (ContextIn
->Line
== NULL
)
1055 CacheLine
= (PINFCACHELINE
)ContextIn
->Line
;
1056 if (CacheLine
->Next
== NULL
)
1059 if (ContextIn
!= ContextOut
)
1061 ContextOut
->Inf
= ContextIn
->Inf
;
1062 ContextOut
->Section
= ContextIn
->Section
;
1064 ContextOut
->Line
= (PVOID
)(CacheLine
->Next
);
1071 InfFindFirstMatchLine (PINFCONTEXT ContextIn
,
1073 PINFCONTEXT ContextOut
)
1075 PINFCACHELINE CacheLine
;
1077 if (ContextIn
== NULL
|| ContextOut
== NULL
|| Key
== NULL
|| *Key
== 0)
1080 if (ContextIn
->Inf
== NULL
|| ContextIn
->Section
== NULL
)
1083 CacheLine
= ((PINFCACHESECTION
)(ContextIn
->Section
))->FirstLine
;
1084 while (CacheLine
!= NULL
)
1086 if (CacheLine
->Key
!= NULL
&& strcasecmp (CacheLine
->Key
, Key
) == 0)
1089 if (ContextIn
!= ContextOut
)
1091 ContextOut
->Inf
= ContextIn
->Inf
;
1092 ContextOut
->Section
= ContextIn
->Section
;
1094 ContextOut
->Line
= (PVOID
)CacheLine
;
1099 CacheLine
= CacheLine
->Next
;
1107 InfFindNextMatchLine (PINFCONTEXT ContextIn
,
1109 PINFCONTEXT ContextOut
)
1111 PINFCACHELINE CacheLine
;
1113 if (ContextIn
== NULL
|| ContextOut
== NULL
|| Key
== NULL
|| *Key
== 0)
1116 if (ContextIn
->Inf
== NULL
|| ContextIn
->Section
== NULL
|| ContextIn
->Line
== NULL
)
1119 CacheLine
= (PINFCACHELINE
)ContextIn
->Line
;
1120 while (CacheLine
!= NULL
)
1122 if (CacheLine
->Key
!= NULL
&& strcasecmp (CacheLine
->Key
, Key
) == 0)
1125 if (ContextIn
!= ContextOut
)
1127 ContextOut
->Inf
= ContextIn
->Inf
;
1128 ContextOut
->Section
= ContextIn
->Section
;
1130 ContextOut
->Line
= (PVOID
)CacheLine
;
1135 CacheLine
= CacheLine
->Next
;
1143 InfGetLineCount(HINF InfHandle
,
1147 PINFCACHESECTION CacheSection
;
1149 if (InfHandle
== NULL
|| Section
== NULL
)
1151 DPRINT("Invalid parameter\n");
1155 Cache
= (PINFCACHE
)InfHandle
;
1157 /* Iterate through list of sections */
1158 CacheSection
= Cache
->FirstSection
;
1159 while (Section
!= NULL
)
1161 DPRINT("Comparing '%s' and '%s'\n", CacheSection
->Name
, Section
);
1163 /* Are the section names the same? */
1164 if (strcasecmp(CacheSection
->Name
, Section
) == 0)
1166 return CacheSection
->LineCount
;
1169 /* Get the next section */
1170 CacheSection
= CacheSection
->Next
;
1173 DPRINT("Section not found\n");
1179 /* InfGetLineText */
1183 InfGetFieldCount(PINFCONTEXT Context
)
1185 if (Context
== NULL
|| Context
->Line
== NULL
)
1188 return ((PINFCACHELINE
)Context
->Line
)->FieldCount
;
1193 InfGetBinaryField (PINFCONTEXT Context
,
1195 PUCHAR ReturnBuffer
,
1196 ULONG ReturnBufferSize
,
1197 PULONG RequiredSize
)
1199 PINFCACHELINE CacheLine
;
1200 PINFCACHEFIELD CacheField
;
1205 if (Context
== NULL
|| Context
->Line
== NULL
|| FieldIndex
== 0)
1207 DPRINT("Invalid parameter\n");
1211 if (RequiredSize
!= NULL
)
1214 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1216 if (FieldIndex
> CacheLine
->FieldCount
)
1219 CacheField
= CacheLine
->FirstField
;
1220 for (Index
= 1; Index
< FieldIndex
; Index
++)
1221 CacheField
= CacheField
->Next
;
1223 Size
= CacheLine
->FieldCount
- FieldIndex
+ 1;
1225 if (RequiredSize
!= NULL
)
1226 *RequiredSize
= Size
;
1228 if (ReturnBuffer
!= NULL
)
1230 if (ReturnBufferSize
< Size
)
1233 /* Copy binary data */
1235 while (CacheField
!= NULL
)
1237 *Ptr
= (UCHAR
)strtoul (CacheField
->Data
, NULL
, 16);
1240 CacheField
= CacheField
->Next
;
1249 InfGetIntField (PINFCONTEXT Context
,
1253 PINFCACHELINE CacheLine
;
1254 PINFCACHEFIELD CacheField
;
1258 if (Context
== NULL
|| Context
->Line
== NULL
|| IntegerValue
== NULL
)
1260 DPRINT("Invalid parameter\n");
1264 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1266 if (FieldIndex
> CacheLine
->FieldCount
)
1268 DPRINT("Invalid parameter\n");
1272 if (FieldIndex
== 0)
1274 Ptr
= CacheLine
->Key
;
1278 CacheField
= CacheLine
->FirstField
;
1279 for (Index
= 1; Index
< FieldIndex
; Index
++)
1280 CacheField
= CacheField
->Next
;
1282 Ptr
= CacheField
->Data
;
1285 *IntegerValue
= strtol (Ptr
, NULL
, 0);
1292 InfGetMultiSzField (PINFCONTEXT Context
,
1295 ULONG ReturnBufferSize
,
1296 PULONG RequiredSize
)
1298 PINFCACHELINE CacheLine
;
1299 PINFCACHEFIELD CacheField
;
1300 PINFCACHEFIELD FieldPtr
;
1305 if (Context
== NULL
|| Context
->Line
== NULL
|| FieldIndex
== 0)
1307 DPRINT("Invalid parameter\n");
1311 if (RequiredSize
!= NULL
)
1314 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1316 if (FieldIndex
> CacheLine
->FieldCount
)
1319 CacheField
= CacheLine
->FirstField
;
1320 for (Index
= 1; Index
< FieldIndex
; Index
++)
1321 CacheField
= CacheField
->Next
;
1323 /* Calculate the required buffer size */
1324 FieldPtr
= CacheField
;
1326 while (FieldPtr
!= NULL
)
1328 Size
+= (strlen (FieldPtr
->Data
) + 1);
1329 FieldPtr
= FieldPtr
->Next
;
1333 if (RequiredSize
!= NULL
)
1334 *RequiredSize
= Size
;
1336 if (ReturnBuffer
!= NULL
)
1338 if (ReturnBufferSize
< Size
)
1341 /* Copy multi-sz string */
1343 FieldPtr
= CacheField
;
1344 while (FieldPtr
!= NULL
)
1346 Size
= strlen (FieldPtr
->Data
) + 1;
1348 strcpy (Ptr
, FieldPtr
->Data
);
1351 FieldPtr
= FieldPtr
->Next
;
1361 InfGetStringField (PINFCONTEXT Context
,
1364 ULONG ReturnBufferSize
,
1365 PULONG RequiredSize
)
1367 PINFCACHELINE CacheLine
;
1368 PINFCACHEFIELD CacheField
;
1373 if (Context
== NULL
|| Context
->Line
== NULL
|| FieldIndex
== 0)
1375 DPRINT("Invalid parameter\n");
1379 if (RequiredSize
!= NULL
)
1382 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1384 if (FieldIndex
> CacheLine
->FieldCount
)
1387 if (FieldIndex
== 0)
1389 Ptr
= CacheLine
->Key
;
1393 CacheField
= CacheLine
->FirstField
;
1394 for (Index
= 1; Index
< FieldIndex
; Index
++)
1395 CacheField
= CacheField
->Next
;
1397 Ptr
= CacheField
->Data
;
1400 Size
= strlen (Ptr
) + 1;
1402 if (RequiredSize
!= NULL
)
1403 *RequiredSize
= Size
;
1405 if (ReturnBuffer
!= NULL
)
1407 if (ReturnBufferSize
< Size
)
1410 strcpy (ReturnBuffer
, Ptr
);
1420 InfGetData (PINFCONTEXT Context
,
1424 PINFCACHELINE CacheKey
;
1426 if (Context
== NULL
|| Context
->Line
== NULL
|| Data
== NULL
)
1428 DPRINT("Invalid parameter\n");
1432 CacheKey
= (PINFCACHELINE
)Context
->Line
;
1434 *Key
= CacheKey
->Key
;
1438 if (CacheKey
->FirstField
== NULL
)
1444 *Data
= CacheKey
->FirstField
->Data
;
1453 InfGetDataField (PINFCONTEXT Context
,
1457 PINFCACHELINE CacheLine
;
1458 PINFCACHEFIELD CacheField
;
1461 if (Context
== NULL
|| Context
->Line
== NULL
|| Data
== NULL
)
1463 DPRINT("Invalid parameter\n");
1467 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1469 if (FieldIndex
> CacheLine
->FieldCount
)
1472 if (FieldIndex
== 0)
1474 *Data
= CacheLine
->Key
;
1478 CacheField
= CacheLine
->FirstField
;
1479 for (Index
= 1; Index
< FieldIndex
; Index
++)
1480 CacheField
= CacheField
->Next
;
1482 *Data
= CacheField
->Data
;