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.
19 /* $Id: inffile.c 53526 2011-09-01 19:01:19Z tkreuzer $
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 *****************************************************************/
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)
39 typedef struct _INFCACHEFIELD
41 struct _INFCACHEFIELD
*Next
;
42 struct _INFCACHEFIELD
*Prev
;
45 } INFCACHEFIELD
, *PINFCACHEFIELD
;
48 typedef struct _INFCACHELINE
50 struct _INFCACHELINE
*Next
;
51 struct _INFCACHELINE
*Prev
;
57 PINFCACHEFIELD FirstField
;
58 PINFCACHEFIELD LastField
;
60 } INFCACHELINE
, *PINFCACHELINE
;
63 typedef struct _INFCACHESECTION
65 struct _INFCACHESECTION
*Next
;
66 struct _INFCACHESECTION
*Prev
;
68 PINFCACHELINE FirstLine
;
69 PINFCACHELINE LastLine
;
74 } INFCACHESECTION
, *PINFCACHESECTION
;
77 typedef struct _INFCACHE
79 PINFCACHESECTION FirstSection
;
80 PINFCACHESECTION LastSection
;
82 PINFCACHESECTION StringsSection
;
83 } INFCACHE
, *PINFCACHE
;
86 /* parser definitions */
90 LINE_START
, /* at beginning of a line */
91 SECTION_NAME
, /* parsing a section name */
92 KEY_NAME
, /* parsing a key name */
93 VALUE_NAME
, /* parsing a value name */
94 EOL_BACKSLASH
, /* backslash at end of line */
95 QUOTES
, /* inside quotes */
96 LEADING_SPACES
, /* leading spaces */
97 TRAILING_SPACES
, /* trailing spaces */
98 COMMENT
, /* inside a comment */
104 const CHAR
*start
; /* start position of item being parsed */
105 const CHAR
*end
; /* end of buffer */
106 PINFCACHE file
; /* file being built */
107 enum parser_state state
; /* current parser state */
108 enum parser_state stack
[4]; /* state stack */
109 int stack_pos
; /* current pos in stack */
111 PINFCACHESECTION cur_section
; /* pointer to the section being parsed*/
112 PINFCACHELINE line
; /* current line */
113 unsigned int line_pos
; /* current line position in file */
114 unsigned int error
; /* error code */
115 unsigned int token_len
; /* current token len */
116 CHAR token
[MAX_FIELD_LEN
+1]; /* current token */
119 typedef const CHAR
* (*parser_state_func
)( struct parser
*parser
, const CHAR
*pos
);
121 /* parser state machine functions */
122 static const CHAR
*line_start_state( struct parser
*parser
, const CHAR
*pos
);
123 static const CHAR
*section_name_state( struct parser
*parser
, const CHAR
*pos
);
124 static const CHAR
*key_name_state( struct parser
*parser
, const CHAR
*pos
);
125 static const CHAR
*value_name_state( struct parser
*parser
, const CHAR
*pos
);
126 static const CHAR
*eol_backslash_state( struct parser
*parser
, const CHAR
*pos
);
127 static const CHAR
*quotes_state( struct parser
*parser
, const CHAR
*pos
);
128 static const CHAR
*leading_spaces_state( struct parser
*parser
, const CHAR
*pos
);
129 static const CHAR
*trailing_spaces_state( struct parser
*parser
, const CHAR
*pos
);
130 static const CHAR
*comment_state( struct parser
*parser
, const CHAR
*pos
);
132 static const parser_state_func parser_funcs
[NB_PARSER_STATES
] =
134 line_start_state
, /* LINE_START */
135 section_name_state
, /* SECTION_NAME */
136 key_name_state
, /* KEY_NAME */
137 value_name_state
, /* VALUE_NAME */
138 eol_backslash_state
, /* EOL_BACKSLASH */
139 quotes_state
, /* QUOTES */
140 leading_spaces_state
, /* LEADING_SPACES */
141 trailing_spaces_state
, /* TRAILING_SPACES */
142 comment_state
/* COMMENT */
146 /* PRIVATE FUNCTIONS ********************************************************/
149 InfpCacheFreeLine (PINFCACHELINE Line
)
152 PINFCACHEFIELD Field
;
160 if (Line
->Key
!= NULL
)
162 MmHeapFree (Line
->Key
);
166 /* Remove data fields */
167 while (Line
->FirstField
!= NULL
)
169 Field
= Line
->FirstField
->Next
;
170 MmHeapFree (Line
->FirstField
);
171 Line
->FirstField
= Field
;
173 Line
->LastField
= NULL
;
181 static PINFCACHESECTION
182 InfpCacheFreeSection (PINFCACHESECTION Section
)
184 PINFCACHESECTION Next
;
191 /* Release all keys */
192 Next
= Section
->Next
;
193 while (Section
->FirstLine
!= NULL
)
195 Section
->FirstLine
= InfpCacheFreeLine (Section
->FirstLine
);
197 Section
->LastLine
= NULL
;
199 MmHeapFree (Section
);
205 static PINFCACHESECTION
206 InfpCacheFindSection (PINFCACHE Cache
,
209 PINFCACHESECTION Section
= NULL
;
211 if (Cache
== NULL
|| Name
== NULL
)
216 /* iterate through list of sections */
217 Section
= Cache
->FirstSection
;
218 while (Section
!= NULL
)
220 if (_stricmp (Section
->Name
, Name
) == 0)
225 /* get the next section*/
226 Section
= Section
->Next
;
233 static PINFCACHESECTION
234 InfpCacheAddSection (PINFCACHE Cache
,
237 PINFCACHESECTION Section
= NULL
;
240 if (Cache
== NULL
|| Name
== NULL
)
242 // DPRINT("Invalid parameter\n");
246 /* Allocate and initialize the new section */
247 Size
= sizeof(INFCACHESECTION
) + strlen (Name
);
248 Section
= (PINFCACHESECTION
)MmHeapAlloc (Size
);
251 // DPRINT("RtlAllocateHeap() failed\n");
254 memset (Section
, 0, Size
);
256 /* Copy section name */
257 strcpy (Section
->Name
, Name
);
260 if (Cache
->FirstSection
== NULL
)
262 Cache
->FirstSection
= Section
;
263 Cache
->LastSection
= Section
;
267 Cache
->LastSection
->Next
= Section
;
268 Section
->Prev
= Cache
->LastSection
;
269 Cache
->LastSection
= Section
;
277 InfpCacheAddLine (PINFCACHESECTION Section
)
283 // DPRINT("Invalid parameter\n");
287 Line
= (PINFCACHELINE
)MmHeapAlloc (sizeof(INFCACHELINE
));
290 // DPRINT("RtlAllocateHeap() failed\n");
293 memset (Line
, 0, sizeof(INFCACHELINE
));
296 if (Section
->FirstLine
== NULL
)
298 Section
->FirstLine
= Line
;
299 Section
->LastLine
= Line
;
303 Section
->LastLine
->Next
= Line
;
304 Line
->Prev
= Section
->LastLine
;
305 Section
->LastLine
= Line
;
307 Section
->LineCount
++;
314 InfpAddKeyToLine (PINFCACHELINE Line
,
320 if (Line
->Key
!= NULL
)
323 Line
->Key
= MmHeapAlloc(strlen(Key
) + 1);
324 if (Line
->Key
== NULL
)
327 strcpy (Line
->Key
, Key
);
329 return (PVOID
)Line
->Key
;
334 InfpAddFieldToLine (PINFCACHELINE Line
,
337 PINFCACHEFIELD Field
;
340 Size
= sizeof(INFCACHEFIELD
) + strlen(Data
);
341 Field
= (PINFCACHEFIELD
)MmHeapAlloc (Size
);
346 memset (Field
, 0, Size
);
348 strcpy (Field
->Data
, Data
);
351 if (Line
->FirstField
== NULL
)
353 Line
->FirstField
= Field
;
354 Line
->LastField
= Field
;
358 Line
->LastField
->Next
= Field
;
359 Field
->Prev
= Line
->LastField
;
360 Line
->LastField
= Field
;
369 InfpCacheFindKeyLine (PINFCACHESECTION Section
,
374 Line
= Section
->FirstLine
;
377 if (Line
->Key
!= NULL
&& _stricmp (Line
->Key
, Key
) == 0)
389 /* push the current state on the parser stack */
390 __inline
static void push_state( struct parser
*parser
, enum parser_state state
)
392 // assert( parser->stack_pos < sizeof(parser->stack)/sizeof(parser->stack[0]) );
393 parser
->stack
[parser
->stack_pos
++] = state
;
397 /* pop the current state */
398 __inline
static void pop_state( struct parser
*parser
)
400 // assert( parser->stack_pos );
401 parser
->state
= parser
->stack
[--parser
->stack_pos
];
405 /* set the parser state and return the previous one */
406 __inline
static enum parser_state
set_state( struct parser
*parser
, enum parser_state state
)
408 enum parser_state ret
= parser
->state
;
409 parser
->state
= state
;
414 /* check if the pointer points to an end of file */
415 __inline
static int is_eof( struct parser
*parser
, const CHAR
*ptr
)
417 return (ptr
>= parser
->end
|| *ptr
== CONTROL_Z
);
421 /* check if the pointer points to an end of line */
422 __inline
static int is_eol( struct parser
*parser
, const CHAR
*ptr
)
424 return (ptr
>= parser
->end
||
427 (*ptr
== '\r' && *(ptr
+ 1) == '\n'));
431 /* push data from current token start up to pos into the current token */
432 static int push_token( struct parser
*parser
, const CHAR
*pos
)
434 SIZE_T len
= pos
- parser
->start
;
435 const CHAR
*src
= parser
->start
;
436 CHAR
*dst
= parser
->token
+ parser
->token_len
;
438 if (len
> MAX_FIELD_LEN
- parser
->token_len
)
439 len
= MAX_FIELD_LEN
- parser
->token_len
;
441 parser
->token_len
+= len
;
442 for ( ; len
> 0; len
--, dst
++, src
++)
443 *dst
= *src
? (CHAR
)*src
: L
' ';
452 /* add a section with the current token as name */
453 static PVOID
add_section_from_token( struct parser
*parser
)
455 PINFCACHESECTION Section
;
457 if (parser
->token_len
> MAX_SECTION_NAME_LEN
)
459 parser
->error
= FALSE
;
463 Section
= InfpCacheFindSection (parser
->file
,
467 /* need to create a new one */
468 Section
= InfpCacheAddSection (parser
->file
,
472 parser
->error
= FALSE
;
477 parser
->token_len
= 0;
478 parser
->cur_section
= Section
;
480 return (PVOID
)Section
;
484 /* add a field containing the current token to the current line */
485 static struct field
*add_field_from_token( struct parser
*parser
, int is_key
)
489 if (!parser
->line
) /* need to start a new line */
491 if (parser
->cur_section
== NULL
) /* got a line before the first section */
493 parser
->error
= STATUS_WRONG_INF_STYLE
;
497 parser
->line
= InfpCacheAddLine (parser
->cur_section
);
498 if (parser
->line
== NULL
)
508 field
= InfpAddKeyToLine(parser
->line
, parser
->token
);
512 field
= InfpAddFieldToLine(parser
->line
, parser
->token
);
517 parser
->token_len
= 0;
522 parser
->error
= FALSE
;
527 /* close the current line and prepare for parsing a new one */
528 static void close_current_line( struct parser
*parser
)
535 /* handler for parser LINE_START state */
536 static const CHAR
*line_start_state( struct parser
*parser
, const CHAR
*pos
)
540 for (p
= pos
; !is_eof( parser
, p
); p
++)
549 close_current_line( parser
);
553 push_state( parser
, LINE_START
);
554 set_state( parser
, COMMENT
);
558 parser
->start
= p
+ 1;
559 set_state( parser
, SECTION_NAME
);
566 set_state( parser
, KEY_NAME
);
572 close_current_line( parser
);
577 /* handler for parser SECTION_NAME state */
578 static const CHAR
*section_name_state( struct parser
*parser
, const CHAR
*pos
)
582 for (p
= pos
; !is_eol( parser
, p
); p
++)
586 push_token( parser
, p
);
587 if (add_section_from_token( parser
) == NULL
)
589 push_state( parser
, LINE_START
);
590 set_state( parser
, COMMENT
); /* ignore everything else on the line */
594 parser
->error
= STATUS_BAD_SECTION_NAME_LINE
; /* unfinished section name */
599 /* handler for parser KEY_NAME state */
600 static const CHAR
*key_name_state( struct parser
*parser
, const CHAR
*pos
)
602 const CHAR
*p
, *token_end
= parser
->start
;
604 for (p
= pos
; !is_eol( parser
, p
); p
++)
606 if (*p
== ',') break;
611 push_token( parser
, token_end
);
612 if (!add_field_from_token( parser
, 1 )) return NULL
;
613 parser
->start
= p
+ 1;
614 push_state( parser
, VALUE_NAME
);
615 set_state( parser
, LEADING_SPACES
);
618 push_token( parser
, token_end
);
619 if (!add_field_from_token( parser
, 0 )) return NULL
;
620 push_state( parser
, LINE_START
);
621 set_state( parser
, COMMENT
);
624 push_token( parser
, token_end
);
625 parser
->start
= p
+ 1;
626 push_state( parser
, KEY_NAME
);
627 set_state( parser
, QUOTES
);
630 push_token( parser
, token_end
);
632 push_state( parser
, KEY_NAME
);
633 set_state( parser
, EOL_BACKSLASH
);
636 if (!isspace(*p
)) token_end
= p
+ 1;
639 push_token( parser
, p
);
640 push_state( parser
, KEY_NAME
);
641 set_state( parser
, TRAILING_SPACES
);
647 push_token( parser
, token_end
);
648 set_state( parser
, VALUE_NAME
);
653 /* handler for parser VALUE_NAME state */
654 static const CHAR
*value_name_state( struct parser
*parser
, const CHAR
*pos
)
656 const CHAR
*p
, *token_end
= parser
->start
;
658 for (p
= pos
; !is_eol( parser
, p
); p
++)
663 push_token( parser
, token_end
);
664 if (!add_field_from_token( parser
, 0 )) return NULL
;
665 push_state( parser
, LINE_START
);
666 set_state( parser
, COMMENT
);
669 push_token( parser
, token_end
);
670 if (!add_field_from_token( parser
, 0 )) return NULL
;
671 parser
->start
= p
+ 1;
672 push_state( parser
, VALUE_NAME
);
673 set_state( parser
, LEADING_SPACES
);
676 push_token( parser
, token_end
);
677 parser
->start
= p
+ 1;
678 push_state( parser
, VALUE_NAME
);
679 set_state( parser
, QUOTES
);
682 push_token( parser
, token_end
);
684 push_state( parser
, VALUE_NAME
);
685 set_state( parser
, EOL_BACKSLASH
);
688 if (!isspace(*p
)) token_end
= p
+ 1;
691 push_token( parser
, p
);
692 push_state( parser
, VALUE_NAME
);
693 set_state( parser
, TRAILING_SPACES
);
699 push_token( parser
, token_end
);
700 if (!add_field_from_token( parser
, 0 )) return NULL
;
701 set_state( parser
, LINE_START
);
706 /* handler for parser EOL_BACKSLASH state */
707 static const CHAR
*eol_backslash_state( struct parser
*parser
, const CHAR
*pos
)
711 for (p
= pos
; !is_eof( parser
, p
); p
++)
720 parser
->start
= p
+ 1;
721 set_state( parser
, LEADING_SPACES
);
728 push_state( parser
, EOL_BACKSLASH
);
729 set_state( parser
, COMMENT
);
735 push_token( parser
, p
);
747 /* handler for parser QUOTES state */
748 static const CHAR
*quotes_state( struct parser
*parser
, const CHAR
*pos
)
750 const CHAR
*p
, *token_end
= parser
->start
;
752 for (p
= pos
; !is_eol( parser
, p
); p
++)
756 if (p
+1 < parser
->end
&& p
[1] == '"') /* double quotes */
758 push_token( parser
, p
+ 1 );
759 parser
->start
= token_end
= p
+ 2;
762 else /* end of quotes */
764 push_token( parser
, p
);
765 parser
->start
= p
+ 1;
771 push_token( parser
, p
);
777 /* handler for parser LEADING_SPACES state */
778 static const CHAR
*leading_spaces_state( struct parser
*parser
, const CHAR
*pos
)
782 for (p
= pos
; !is_eol( parser
, p
); p
++)
787 set_state( parser
, EOL_BACKSLASH
);
799 /* handler for parser TRAILING_SPACES state */
800 static const CHAR
*trailing_spaces_state( struct parser
*parser
, const CHAR
*pos
)
804 for (p
= pos
; !is_eol( parser
, p
); p
++)
808 set_state( parser
, EOL_BACKSLASH
);
819 /* handler for parser COMMENT state */
820 static const CHAR
*comment_state( struct parser
*parser
, const CHAR
*pos
)
824 while (!is_eol( parser
, p
))
831 /* parse a complete buffer */
833 InfpParseBuffer (PINFCACHE file
,
838 struct parser parser
;
839 const CHAR
*pos
= buffer
;
841 parser
.start
= buffer
;
845 parser
.state
= LINE_START
;
846 parser
.stack_pos
= 0;
847 parser
.cur_section
= NULL
;
850 parser
.token_len
= 0;
852 /* parser main loop */
854 pos
= (parser_funcs
[parser
.state
])(&parser
, pos
);
859 *error_line
= parser
.line_pos
;
863 /* find the [strings] section */
864 file
->StringsSection
= InfpCacheFindSection (file
, "Strings");
869 /* PUBLIC FUNCTIONS *********************************************************/
872 InfOpenFile(PHINF InfHandle
,
876 FILEINFORMATION Information
;
879 ULONG FileSize
, Count
;
885 *ErrorLine
= (ULONG
)-1;
888 // Open the .inf file
890 FileId
= FsOpenFile(FileName
);
899 ret
= ArcGetFileInformation(FileId
, &Information
);
900 if (ret
!= ESUCCESS
|| Information
.EndingAddress
.HighPart
!= 0)
905 FileSize
= Information
.EndingAddress
.LowPart
;
908 // Allocate buffer to cache the file
910 FileBuffer
= MmHeapAlloc(FileSize
+ 1);
918 // Read file into memory
920 ret
= ArcRead(FileId
, FileBuffer
, FileSize
, &Count
);
921 if (ret
!= ESUCCESS
|| Count
!= FileSize
)
924 MmHeapFree(FileBuffer
);
929 // We don't need the file anymore. Close it
934 // Append string terminator
936 FileBuffer
[FileSize
] = 0;
939 // Allocate infcache header
941 Cache
= (PINFCACHE
)MmHeapAlloc(sizeof(INFCACHE
));
944 MmHeapFree (FileBuffer
);
949 // Initialize inicache header
951 RtlZeroMemory(Cache
, sizeof(INFCACHE
));
954 // Parse the inf buffer
956 Success
= InfpParseBuffer(Cache
,
958 FileBuffer
+ FileSize
,
967 // Free file buffer, as it has been parsed
969 MmHeapFree(FileBuffer
);
972 // Return .inf parsed contents
974 *InfHandle
= (HINF
)Cache
;
981 InfCloseFile(HINF InfHandle
)
985 Cache
= (PINFCACHE
)InfHandle
;
992 while (Cache
->FirstSection
!= NULL
)
994 Cache
->FirstSection
= InfpCacheFreeSection(Cache
->FirstSection
);
996 Cache
->LastSection
= NULL
;
1003 InfFindFirstLine (HINF InfHandle
,
1006 PINFCONTEXT Context
)
1009 PINFCACHESECTION CacheSection
;
1010 PINFCACHELINE CacheLine
;
1012 if (InfHandle
== NULL
|| Section
== NULL
|| Context
== NULL
)
1014 // DPRINT("Invalid parameter\n");
1018 Cache
= (PINFCACHE
)InfHandle
;
1020 /* Iterate through list of sections */
1021 CacheSection
= Cache
->FirstSection
;
1022 while (Section
!= NULL
)
1024 // DPRINT("Comparing '%S' and '%S'\n", CacheSection->Name, Section);
1026 /* Are the section names the same? */
1027 if (_stricmp(CacheSection
->Name
, Section
) == 0)
1031 CacheLine
= InfpCacheFindKeyLine (CacheSection
, Key
);
1035 CacheLine
= CacheSection
->FirstLine
;
1038 if (CacheLine
== NULL
)
1041 Context
->Inf
= (PVOID
)Cache
;
1042 Context
->Section
= (PVOID
)CacheSection
;
1043 Context
->Line
= (PVOID
)CacheLine
;
1048 /* Get the next section */
1049 CacheSection
= CacheSection
->Next
;
1052 // DPRINT("Section not found\n");
1059 InfFindNextLine (PINFCONTEXT ContextIn
,
1060 PINFCONTEXT ContextOut
)
1062 PINFCACHELINE CacheLine
;
1064 if (ContextIn
== NULL
|| ContextOut
== NULL
)
1067 if (ContextIn
->Line
== NULL
)
1070 CacheLine
= (PINFCACHELINE
)ContextIn
->Line
;
1071 if (CacheLine
->Next
== NULL
)
1074 if (ContextIn
!= ContextOut
)
1076 ContextOut
->Inf
= ContextIn
->Inf
;
1077 ContextOut
->Section
= ContextIn
->Section
;
1079 ContextOut
->Line
= (PVOID
)(CacheLine
->Next
);
1086 InfFindFirstMatchLine (PINFCONTEXT ContextIn
,
1088 PINFCONTEXT ContextOut
)
1090 PINFCACHELINE CacheLine
;
1092 if (ContextIn
== NULL
|| ContextOut
== NULL
|| Key
== NULL
|| *Key
== 0)
1095 if (ContextIn
->Inf
== NULL
|| ContextIn
->Section
== NULL
)
1098 CacheLine
= ((PINFCACHESECTION
)(ContextIn
->Section
))->FirstLine
;
1099 while (CacheLine
!= NULL
)
1101 if (CacheLine
->Key
!= NULL
&& _stricmp (CacheLine
->Key
, Key
) == 0)
1104 if (ContextIn
!= ContextOut
)
1106 ContextOut
->Inf
= ContextIn
->Inf
;
1107 ContextOut
->Section
= ContextIn
->Section
;
1109 ContextOut
->Line
= (PVOID
)CacheLine
;
1114 CacheLine
= CacheLine
->Next
;
1122 InfFindNextMatchLine (PINFCONTEXT ContextIn
,
1124 PINFCONTEXT ContextOut
)
1126 PINFCACHELINE CacheLine
;
1128 if (ContextIn
== NULL
|| ContextOut
== NULL
|| Key
== NULL
|| *Key
== 0)
1131 if (ContextIn
->Inf
== NULL
|| ContextIn
->Section
== NULL
|| ContextIn
->Line
== NULL
)
1134 CacheLine
= (PINFCACHELINE
)ContextIn
->Line
;
1135 while (CacheLine
!= NULL
)
1137 if (CacheLine
->Key
!= NULL
&& _stricmp (CacheLine
->Key
, Key
) == 0)
1140 if (ContextIn
!= ContextOut
)
1142 ContextOut
->Inf
= ContextIn
->Inf
;
1143 ContextOut
->Section
= ContextIn
->Section
;
1145 ContextOut
->Line
= (PVOID
)CacheLine
;
1150 CacheLine
= CacheLine
->Next
;
1158 InfGetLineCount(HINF InfHandle
,
1162 PINFCACHESECTION CacheSection
;
1164 if (InfHandle
== NULL
|| Section
== NULL
)
1166 // DPRINT("Invalid parameter\n");
1170 Cache
= (PINFCACHE
)InfHandle
;
1172 /* Iterate through list of sections */
1173 CacheSection
= Cache
->FirstSection
;
1174 while (Section
!= NULL
)
1176 // DPRINT("Comparing '%S' and '%S'\n", CacheSection->Name, Section);
1178 /* Are the section names the same? */
1179 if (_stricmp(CacheSection
->Name
, Section
) == 0)
1181 return CacheSection
->LineCount
;
1184 /* Get the next section */
1185 CacheSection
= CacheSection
->Next
;
1188 // DPRINT("Section not found\n");
1194 /* InfGetLineText */
1198 InfGetFieldCount(PINFCONTEXT Context
)
1200 if (Context
== NULL
|| Context
->Line
== NULL
)
1203 return ((PINFCACHELINE
)Context
->Line
)->FieldCount
;
1208 InfGetBinaryField (PINFCONTEXT Context
,
1210 PUCHAR ReturnBuffer
,
1211 ULONG ReturnBufferSize
,
1212 PULONG RequiredSize
)
1214 PINFCACHELINE CacheLine
;
1215 PINFCACHEFIELD CacheField
;
1220 if (Context
== NULL
|| Context
->Line
== NULL
|| FieldIndex
== 0)
1222 // DPRINT("Invalid parameter\n");
1226 if (RequiredSize
!= NULL
)
1229 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1231 if (FieldIndex
> CacheLine
->FieldCount
)
1234 CacheField
= CacheLine
->FirstField
;
1235 for (Index
= 1; Index
< FieldIndex
; Index
++)
1236 CacheField
= CacheField
->Next
;
1238 Size
= CacheLine
->FieldCount
- FieldIndex
+ 1;
1240 if (RequiredSize
!= NULL
)
1241 *RequiredSize
= Size
;
1243 if (ReturnBuffer
!= NULL
)
1245 if (ReturnBufferSize
< Size
)
1248 /* Copy binary data */
1250 while (CacheField
!= NULL
)
1252 *Ptr
= (UCHAR
)atoi(CacheField
->Data
); //strtoul (CacheField->Data, NULL, 16);
1255 CacheField
= CacheField
->Next
;
1264 InfGetIntField (PINFCONTEXT Context
,
1268 PINFCACHELINE CacheLine
;
1269 PINFCACHEFIELD CacheField
;
1273 if (Context
== NULL
|| Context
->Line
== NULL
|| IntegerValue
== NULL
)
1275 // DPRINT("Invalid parameter\n");
1279 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1281 if (FieldIndex
> CacheLine
->FieldCount
)
1283 // DPRINT("Invalid parameter\n");
1287 if (FieldIndex
== 0)
1289 Ptr
= CacheLine
->Key
;
1293 CacheField
= CacheLine
->FirstField
;
1294 for (Index
= 1; Index
< FieldIndex
; Index
++)
1295 CacheField
= CacheField
->Next
;
1297 Ptr
= CacheField
->Data
;
1300 *IntegerValue
= atoi (Ptr
); //strtol (Ptr, NULL, 0);
1307 InfGetMultiSzField (PINFCONTEXT Context
,
1310 ULONG ReturnBufferSize
,
1311 PULONG RequiredSize
)
1313 PINFCACHELINE CacheLine
;
1314 PINFCACHEFIELD CacheField
;
1315 PINFCACHEFIELD FieldPtr
;
1320 if (Context
== NULL
|| Context
->Line
== NULL
|| FieldIndex
== 0)
1322 // DPRINT("Invalid parameter\n");
1326 if (RequiredSize
!= NULL
)
1329 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1331 if (FieldIndex
> CacheLine
->FieldCount
)
1334 CacheField
= CacheLine
->FirstField
;
1335 for (Index
= 1; Index
< FieldIndex
; Index
++)
1336 CacheField
= CacheField
->Next
;
1338 /* Calculate the required buffer size */
1339 FieldPtr
= CacheField
;
1341 while (FieldPtr
!= NULL
)
1343 Size
+= (strlen (FieldPtr
->Data
) + 1);
1344 FieldPtr
= FieldPtr
->Next
;
1348 if (RequiredSize
!= NULL
)
1349 *RequiredSize
= Size
;
1351 if (ReturnBuffer
!= NULL
)
1353 if (ReturnBufferSize
< Size
)
1356 /* Copy multi-sz string */
1358 FieldPtr
= CacheField
;
1359 while (FieldPtr
!= NULL
)
1361 Size
= strlen (FieldPtr
->Data
) + 1;
1363 strcpy (Ptr
, FieldPtr
->Data
);
1366 FieldPtr
= FieldPtr
->Next
;
1376 InfGetStringField (PINFCONTEXT Context
,
1379 ULONG ReturnBufferSize
,
1380 PULONG RequiredSize
)
1382 PINFCACHELINE CacheLine
;
1383 PINFCACHEFIELD CacheField
;
1388 if (Context
== NULL
|| Context
->Line
== NULL
|| FieldIndex
== 0)
1390 // DPRINT("Invalid parameter\n");
1394 if (RequiredSize
!= NULL
)
1397 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1399 if (FieldIndex
> CacheLine
->FieldCount
)
1402 if (FieldIndex
== 0)
1404 Ptr
= CacheLine
->Key
;
1408 CacheField
= CacheLine
->FirstField
;
1409 for (Index
= 1; Index
< FieldIndex
; Index
++)
1410 CacheField
= CacheField
->Next
;
1412 Ptr
= CacheField
->Data
;
1415 Size
= strlen (Ptr
) + 1;
1417 if (RequiredSize
!= NULL
)
1418 *RequiredSize
= Size
;
1420 if (ReturnBuffer
!= NULL
)
1422 if (ReturnBufferSize
< Size
)
1425 strcpy (ReturnBuffer
, Ptr
);
1435 InfGetData (PINFCONTEXT Context
,
1439 PINFCACHELINE CacheKey
;
1441 if (Context
== NULL
|| Context
->Line
== NULL
|| Data
== NULL
)
1443 // DPRINT("Invalid parameter\n");
1447 CacheKey
= (PINFCACHELINE
)Context
->Line
;
1449 *Key
= CacheKey
->Key
;
1453 if (CacheKey
->FirstField
== NULL
)
1459 *Data
= CacheKey
->FirstField
->Data
;
1468 InfGetDataField (PINFCONTEXT Context
,
1472 PINFCACHELINE CacheLine
;
1473 PINFCACHEFIELD CacheField
;
1476 if (Context
== NULL
|| Context
->Line
== NULL
|| Data
== NULL
)
1478 // DPRINT("Invalid parameter\n");
1482 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1484 if (FieldIndex
> CacheLine
->FieldCount
)
1487 if (FieldIndex
== 0)
1489 *Data
= CacheLine
->Key
;
1493 CacheField
= CacheLine
->FirstField
;
1494 for (Index
= 1; Index
< FieldIndex
; Index
++)
1495 CacheField
= CacheField
->Next
;
1497 *Data
= CacheField
->Data
;