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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: inffile.c,v 1.1 2003/05/25 21:18:16 ekohl Exp $
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: subsys/system/usetup/infcache.c
23 * PURPOSE: INF file parser that caches contents of INF file in memory
24 * PROGRAMMER: Royce Mitchell III
28 /* INCLUDES *****************************************************************/
38 #define CONTROL_Z '\x1a'
39 #define MAX_SECTION_NAME_LEN 255
40 #define MAX_FIELD_LEN 511 /* larger fields get silently truncated */
41 /* actual string limit is MAX_INF_STRING_LENGTH+1 (plus terminating null) under Windows */
42 #define MAX_STRING_LEN (MAX_INF_STRING_LENGTH+1)
45 typedef struct _INFCACHEFIELD
47 struct _INFCACHEFIELD
*Next
;
48 struct _INFCACHEFIELD
*Prev
;
51 } INFCACHEFIELD
, *PINFCACHEFIELD
;
54 typedef struct _INFCACHELINE
56 struct _INFCACHELINE
*Next
;
57 struct _INFCACHELINE
*Prev
;
63 PINFCACHEFIELD FirstField
;
64 PINFCACHEFIELD LastField
;
66 } INFCACHELINE
, *PINFCACHELINE
;
69 typedef struct _INFCACHESECTION
71 struct _INFCACHESECTION
*Next
;
72 struct _INFCACHESECTION
*Prev
;
74 PINFCACHELINE FirstLine
;
75 PINFCACHELINE LastLine
;
80 } INFCACHESECTION
, *PINFCACHESECTION
;
83 typedef struct _INFCACHE
85 PINFCACHESECTION FirstSection
;
86 PINFCACHESECTION LastSection
;
88 PINFCACHESECTION StringsSection
;
89 } INFCACHE
, *PINFCACHE
;
92 /* parser definitions */
96 LINE_START
, /* at beginning of a line */
97 SECTION_NAME
, /* parsing a section name */
98 KEY_NAME
, /* parsing a key name */
99 VALUE_NAME
, /* parsing a value name */
100 EOL_BACKSLASH
, /* backslash at end of line */
101 QUOTES
, /* inside quotes */
102 LEADING_SPACES
, /* leading spaces */
103 TRAILING_SPACES
, /* trailing spaces */
104 COMMENT
, /* inside a comment */
110 const CHAR
*start
; /* start position of item being parsed */
111 const CHAR
*end
; /* end of buffer */
112 PINFCACHE file
; /* file being built */
113 enum parser_state state
; /* current parser state */
114 enum parser_state stack
[4]; /* state stack */
115 int stack_pos
; /* current pos in stack */
117 PINFCACHESECTION cur_section
; /* pointer to the section being parsed*/
118 PINFCACHELINE line
; /* current line */
119 unsigned int line_pos
; /* current line position in file */
120 unsigned int error
; /* error code */
121 unsigned int token_len
; /* current token len */
122 CHAR token
[MAX_FIELD_LEN
+1]; /* current token */
125 typedef const CHAR
* (*parser_state_func
)( struct parser
*parser
, const CHAR
*pos
);
127 /* parser state machine functions */
128 static const CHAR
*line_start_state( struct parser
*parser
, const CHAR
*pos
);
129 static const CHAR
*section_name_state( struct parser
*parser
, const CHAR
*pos
);
130 static const CHAR
*key_name_state( struct parser
*parser
, const CHAR
*pos
);
131 static const CHAR
*value_name_state( struct parser
*parser
, const CHAR
*pos
);
132 static const CHAR
*eol_backslash_state( struct parser
*parser
, const CHAR
*pos
);
133 static const CHAR
*quotes_state( struct parser
*parser
, const CHAR
*pos
);
134 static const CHAR
*leading_spaces_state( struct parser
*parser
, const CHAR
*pos
);
135 static const CHAR
*trailing_spaces_state( struct parser
*parser
, const CHAR
*pos
);
136 static const CHAR
*comment_state( struct parser
*parser
, const CHAR
*pos
);
138 static const parser_state_func parser_funcs
[NB_PARSER_STATES
] =
140 line_start_state
, /* LINE_START */
141 section_name_state
, /* SECTION_NAME */
142 key_name_state
, /* KEY_NAME */
143 value_name_state
, /* VALUE_NAME */
144 eol_backslash_state
, /* EOL_BACKSLASH */
145 quotes_state
, /* QUOTES */
146 leading_spaces_state
, /* LEADING_SPACES */
147 trailing_spaces_state
, /* TRAILING_SPACES */
148 comment_state
/* COMMENT */
152 /* PRIVATE FUNCTIONS ********************************************************/
155 InfpCacheFreeLine (PINFCACHELINE Line
)
158 PINFCACHEFIELD Field
;
166 if (Line
->Key
!= NULL
)
168 MmFreeMemory (Line
->Key
);
172 /* Remove data fields */
173 while (Line
->FirstField
!= NULL
)
175 Field
= Line
->FirstField
->Next
;
176 MmFreeMemory (Line
->FirstField
);
177 Line
->FirstField
= Field
;
179 Line
->LastField
= NULL
;
187 static PINFCACHESECTION
188 InfpCacheFreeSection (PINFCACHESECTION Section
)
190 PINFCACHESECTION Next
;
197 /* Release all keys */
198 Next
= Section
->Next
;
199 while (Section
->FirstLine
!= NULL
)
201 Section
->FirstLine
= InfpCacheFreeLine (Section
->FirstLine
);
203 Section
->LastLine
= NULL
;
205 MmFreeMemory (Section
);
211 static PINFCACHESECTION
212 InfpCacheFindSection (PINFCACHE Cache
,
215 PINFCACHESECTION Section
= NULL
;
217 if (Cache
== NULL
|| Name
== NULL
)
222 /* iterate through list of sections */
223 Section
= Cache
->FirstSection
;
224 while (Section
!= NULL
)
226 if (stricmp (Section
->Name
, Name
) == 0)
231 /* get the next section*/
232 Section
= Section
->Next
;
239 static PINFCACHESECTION
240 InfpCacheAddSection (PINFCACHE Cache
,
243 PINFCACHESECTION Section
= NULL
;
246 if (Cache
== NULL
|| Name
== NULL
)
248 // DPRINT("Invalid parameter\n");
252 /* Allocate and initialize the new section */
253 Size
= sizeof(INFCACHESECTION
) + strlen (Name
);
254 Section
= (PINFCACHESECTION
)MmAllocateMemory (Size
);
257 // DPRINT("RtlAllocateHeap() failed\n");
260 memset (Section
, 0, Size
);
262 /* Copy section name */
263 strcpy (Section
->Name
, Name
);
266 if (Cache
->FirstSection
== NULL
)
268 Cache
->FirstSection
= Section
;
269 Cache
->LastSection
= Section
;
273 Cache
->LastSection
->Next
= Section
;
274 Section
->Prev
= Cache
->LastSection
;
275 Cache
->LastSection
= Section
;
283 InfpCacheAddLine (PINFCACHESECTION Section
)
289 // DPRINT("Invalid parameter\n");
293 Line
= (PINFCACHELINE
)MmAllocateMemory (sizeof(INFCACHELINE
));
296 // DPRINT("RtlAllocateHeap() failed\n");
299 memset (Line
, 0, sizeof(INFCACHELINE
));
302 if (Section
->FirstLine
== NULL
)
304 Section
->FirstLine
= Line
;
305 Section
->LastLine
= Line
;
309 Section
->LastLine
->Next
= Line
;
310 Line
->Prev
= Section
->LastLine
;
311 Section
->LastLine
= Line
;
313 Section
->LineCount
++;
320 InfpAddKeyToLine (PINFCACHELINE Line
,
326 if (Line
->Key
!= NULL
)
329 Line
->Key
= (PCHAR
)MmAllocateMemory (strlen (Key
) + 1);
330 if (Line
->Key
== NULL
)
333 strcpy (Line
->Key
, Key
);
335 return (PVOID
)Line
->Key
;
340 InfpAddFieldToLine (PINFCACHELINE Line
,
343 PINFCACHEFIELD Field
;
346 Size
= sizeof(INFCACHEFIELD
) + strlen(Data
);
347 Field
= (PINFCACHEFIELD
)MmAllocateMemory (Size
);
352 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
&& stricmp (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 int 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
? (CHAR
)*src
: L
' ';
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
= FALSE
;
469 Section
= InfpCacheFindSection (parser
->file
,
473 /* need to create a new one */
474 Section
= InfpCacheAddSection (parser
->file
,
478 parser
->error
= FALSE
;
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
= FALSE
;
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
, "Strings");
875 /* PUBLIC FUNCTIONS *********************************************************/
878 InfOpenFile(PHINF InfHandle
,
890 *ErrorLine
= (U32
)-1;
893 /* Open the inf file */
894 FileHandle
= FsOpenFile (FileName
);
895 if (FileHandle
== NULL
)
897 // DPRINT("NtOpenFile() failed (Status %lx)\n", Status);
901 // DPRINT("NtOpenFile() successful\n");
903 /* Query file size */
904 FileSize
= FsGetFileSize (FileHandle
);
907 // DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
908 FsCloseFile (FileHandle
);
912 // DPRINT("File size: %lu\n", FileLength);
914 /* Allocate file buffer */
915 FileBuffer
= MmAllocateMemory (FileSize
+ 1);
916 if (FileBuffer
== NULL
)
918 // DPRINT1("RtlAllocateHeap() failed\n");
919 FsCloseFile (FileHandle
);
924 Success
= FsReadFile(FileHandle
, FileSize
, NULL
, FileBuffer
);
926 FsCloseFile (FileHandle
);
929 // DPRINT("FsReadFile() failed\n");
930 MmFreeMemory (FileBuffer
);
934 /* Append string terminator */
935 FileBuffer
[FileSize
] = 0;
937 /* Allocate infcache header */
938 Cache
= (PINFCACHE
)MmAllocateMemory (sizeof(INFCACHE
));
941 // DPRINT("RtlAllocateHeap() failed\n");
942 MmFreeMemory (FileBuffer
);
946 /* Initialize inicache header */
950 /* Parse the inf buffer */
951 Success
= InfpParseBuffer (Cache
,
953 FileBuffer
+ FileSize
,
957 MmFreeMemory (Cache
);
961 /* Free file buffer */
962 MmFreeMemory (FileBuffer
);
964 *InfHandle
= (HINF
)Cache
;
971 InfCloseFile(HINF InfHandle
)
975 Cache
= (PINFCACHE
)InfHandle
;
982 while (Cache
->FirstSection
!= NULL
)
984 Cache
->FirstSection
= InfpCacheFreeSection(Cache
->FirstSection
);
986 Cache
->LastSection
= NULL
;
993 InfFindFirstLine (HINF InfHandle
,
999 PINFCACHESECTION CacheSection
;
1000 PINFCACHELINE CacheLine
;
1002 if (InfHandle
== NULL
|| Section
== NULL
|| Context
== NULL
)
1004 // DPRINT("Invalid parameter\n");
1008 Cache
= (PINFCACHE
)InfHandle
;
1010 /* Iterate through list of sections */
1011 CacheSection
= Cache
->FirstSection
;
1012 while (Section
!= NULL
)
1014 // DPRINT("Comparing '%S' and '%S'\n", CacheSection->Name, Section);
1016 /* Are the section names the same? */
1017 if (stricmp(CacheSection
->Name
, Section
) == 0)
1021 CacheLine
= InfpCacheFindKeyLine (CacheSection
, Key
);
1025 CacheLine
= CacheSection
->FirstLine
;
1028 if (CacheLine
== NULL
)
1031 Context
->Inf
= (PVOID
)Cache
;
1032 Context
->Section
= (PVOID
)CacheSection
;
1033 Context
->Line
= (PVOID
)CacheLine
;
1038 /* Get the next section */
1039 CacheSection
= CacheSection
->Next
;
1042 // DPRINT("Section not found\n");
1049 InfFindNextLine (PINFCONTEXT ContextIn
,
1050 PINFCONTEXT ContextOut
)
1052 PINFCACHELINE CacheLine
;
1054 if (ContextIn
== NULL
|| ContextOut
== NULL
)
1057 if (ContextIn
->Line
== NULL
)
1060 CacheLine
= (PINFCACHELINE
)ContextIn
->Line
;
1061 if (CacheLine
->Next
== NULL
)
1064 if (ContextIn
!= ContextOut
)
1066 ContextOut
->Inf
= ContextIn
->Inf
;
1067 ContextOut
->Section
= ContextIn
->Section
;
1069 ContextOut
->Line
= (PVOID
)(CacheLine
->Next
);
1076 InfFindFirstMatchLine (PINFCONTEXT ContextIn
,
1078 PINFCONTEXT ContextOut
)
1080 PINFCACHELINE CacheLine
;
1082 if (ContextIn
== NULL
|| ContextOut
== NULL
|| Key
== NULL
|| *Key
== 0)
1085 if (ContextIn
->Inf
== NULL
|| ContextIn
->Section
== NULL
)
1088 CacheLine
= ((PINFCACHESECTION
)(ContextIn
->Section
))->FirstLine
;
1089 while (CacheLine
!= NULL
)
1091 if (CacheLine
->Key
!= NULL
&& stricmp (CacheLine
->Key
, Key
) == 0)
1094 if (ContextIn
!= ContextOut
)
1096 ContextOut
->Inf
= ContextIn
->Inf
;
1097 ContextOut
->Section
= ContextIn
->Section
;
1099 ContextOut
->Line
= (PVOID
)CacheLine
;
1104 CacheLine
= CacheLine
->Next
;
1112 InfFindNextMatchLine (PINFCONTEXT ContextIn
,
1114 PINFCONTEXT ContextOut
)
1116 PINFCACHELINE CacheLine
;
1118 if (ContextIn
== NULL
|| ContextOut
== NULL
|| Key
== NULL
|| *Key
== 0)
1121 if (ContextIn
->Inf
== NULL
|| ContextIn
->Section
== NULL
|| ContextIn
->Line
== NULL
)
1124 CacheLine
= (PINFCACHELINE
)ContextIn
->Line
;
1125 while (CacheLine
!= NULL
)
1127 if (CacheLine
->Key
!= NULL
&& stricmp (CacheLine
->Key
, Key
) == 0)
1130 if (ContextIn
!= ContextOut
)
1132 ContextOut
->Inf
= ContextIn
->Inf
;
1133 ContextOut
->Section
= ContextIn
->Section
;
1135 ContextOut
->Line
= (PVOID
)CacheLine
;
1140 CacheLine
= CacheLine
->Next
;
1148 InfGetLineCount(HINF InfHandle
,
1152 PINFCACHESECTION CacheSection
;
1154 if (InfHandle
== NULL
|| Section
== NULL
)
1156 // DPRINT("Invalid parameter\n");
1160 Cache
= (PINFCACHE
)InfHandle
;
1162 /* Iterate through list of sections */
1163 CacheSection
= Cache
->FirstSection
;
1164 while (Section
!= NULL
)
1166 // DPRINT("Comparing '%S' and '%S'\n", CacheSection->Name, Section);
1168 /* Are the section names the same? */
1169 if (stricmp(CacheSection
->Name
, Section
) == 0)
1171 return CacheSection
->LineCount
;
1174 /* Get the next section */
1175 CacheSection
= CacheSection
->Next
;
1178 // DPRINT("Section not found\n");
1184 /* InfGetLineText */
1188 InfGetFieldCount(PINFCONTEXT Context
)
1190 if (Context
== NULL
|| Context
->Line
== NULL
)
1193 return ((PINFCACHELINE
)Context
->Line
)->FieldCount
;
1198 InfGetBinaryField (PINFCONTEXT Context
,
1201 U32 ReturnBufferSize
,
1204 PINFCACHELINE CacheLine
;
1205 PINFCACHEFIELD CacheField
;
1210 if (Context
== NULL
|| Context
->Line
== NULL
|| FieldIndex
== 0)
1212 // DPRINT("Invalid parameter\n");
1216 if (RequiredSize
!= NULL
)
1219 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1221 if (FieldIndex
> CacheLine
->FieldCount
)
1224 CacheField
= CacheLine
->FirstField
;
1225 for (Index
= 1; Index
< FieldIndex
; Index
++)
1226 CacheField
= CacheField
->Next
;
1228 Size
= CacheLine
->FieldCount
- FieldIndex
+ 1;
1230 if (RequiredSize
!= NULL
)
1231 *RequiredSize
= Size
;
1233 if (ReturnBuffer
!= NULL
)
1235 if (ReturnBufferSize
< Size
)
1238 /* Copy binary data */
1240 while (CacheField
!= NULL
)
1242 *Ptr
= (UCHAR
)atoi(CacheField
->Data
); //strtoul (CacheField->Data, NULL, 16);
1245 CacheField
= CacheField
->Next
;
1254 InfGetIntField (PINFCONTEXT Context
,
1258 PINFCACHELINE CacheLine
;
1259 PINFCACHEFIELD CacheField
;
1263 if (Context
== NULL
|| Context
->Line
== NULL
|| IntegerValue
== NULL
)
1265 // DPRINT("Invalid parameter\n");
1269 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1271 if (FieldIndex
> CacheLine
->FieldCount
)
1273 // DPRINT("Invalid parameter\n");
1277 if (FieldIndex
== 0)
1279 Ptr
= CacheLine
->Key
;
1283 CacheField
= CacheLine
->FirstField
;
1284 for (Index
= 1; Index
< FieldIndex
; Index
++)
1285 CacheField
= CacheField
->Next
;
1287 Ptr
= CacheField
->Data
;
1290 *IntegerValue
= atoi (Ptr
); //strtol (Ptr, NULL, 0);
1297 InfGetMultiSzField (PINFCONTEXT Context
,
1300 U32 ReturnBufferSize
,
1303 PINFCACHELINE CacheLine
;
1304 PINFCACHEFIELD CacheField
;
1305 PINFCACHEFIELD FieldPtr
;
1310 if (Context
== NULL
|| Context
->Line
== NULL
|| FieldIndex
== 0)
1312 // DPRINT("Invalid parameter\n");
1316 if (RequiredSize
!= NULL
)
1319 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1321 if (FieldIndex
> CacheLine
->FieldCount
)
1324 CacheField
= CacheLine
->FirstField
;
1325 for (Index
= 1; Index
< FieldIndex
; Index
++)
1326 CacheField
= CacheField
->Next
;
1328 /* Calculate the required buffer size */
1329 FieldPtr
= CacheField
;
1331 while (FieldPtr
!= NULL
)
1333 Size
+= (strlen (FieldPtr
->Data
) + 1);
1334 FieldPtr
= FieldPtr
->Next
;
1338 if (RequiredSize
!= NULL
)
1339 *RequiredSize
= Size
;
1341 if (ReturnBuffer
!= NULL
)
1343 if (ReturnBufferSize
< Size
)
1346 /* Copy multi-sz string */
1348 FieldPtr
= CacheField
;
1349 while (FieldPtr
!= NULL
)
1351 Size
= strlen (FieldPtr
->Data
) + 1;
1353 strcpy (Ptr
, FieldPtr
->Data
);
1356 FieldPtr
= FieldPtr
->Next
;
1366 InfGetStringField (PINFCONTEXT Context
,
1369 U32 ReturnBufferSize
,
1372 PINFCACHELINE CacheLine
;
1373 PINFCACHEFIELD CacheField
;
1378 if (Context
== NULL
|| Context
->Line
== NULL
|| FieldIndex
== 0)
1380 // DPRINT("Invalid parameter\n");
1384 if (RequiredSize
!= NULL
)
1387 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1389 if (FieldIndex
> CacheLine
->FieldCount
)
1392 if (FieldIndex
== 0)
1394 Ptr
= CacheLine
->Key
;
1398 CacheField
= CacheLine
->FirstField
;
1399 for (Index
= 1; Index
< FieldIndex
; Index
++)
1400 CacheField
= CacheField
->Next
;
1402 Ptr
= CacheField
->Data
;
1405 Size
= strlen (Ptr
) + 1;
1407 if (RequiredSize
!= NULL
)
1408 *RequiredSize
= Size
;
1410 if (ReturnBuffer
!= NULL
)
1412 if (ReturnBufferSize
< Size
)
1415 strcpy (ReturnBuffer
, Ptr
);
1425 InfGetData (PINFCONTEXT Context
,
1429 PINFCACHELINE CacheKey
;
1431 if (Context
== NULL
|| Context
->Line
== NULL
|| Data
== NULL
)
1433 // DPRINT("Invalid parameter\n");
1437 CacheKey
= (PINFCACHELINE
)Context
->Line
;
1439 *Key
= CacheKey
->Key
;
1443 if (CacheKey
->FirstField
== NULL
)
1449 *Data
= CacheKey
->FirstField
->Data
;
1458 InfGetDataField (PINFCONTEXT Context
,
1462 PINFCACHELINE CacheLine
;
1463 PINFCACHEFIELD CacheField
;
1466 if (Context
== NULL
|| Context
->Line
== NULL
|| Data
== NULL
)
1468 // DPRINT("Invalid parameter\n");
1472 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1474 if (FieldIndex
> CacheLine
->FieldCount
)
1477 if (FieldIndex
== 0)
1479 *Data
= CacheLine
->Key
;
1483 CacheField
= CacheLine
->FirstField
;
1484 for (Index
= 1; Index
< FieldIndex
; Index
++)
1485 CacheField
= CacheField
->Next
;
1487 *Data
= CacheField
->Data
;