3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: INF file parser that caches contents of INF file in memory.
5 * COPYRIGHT: Copyright 2002-2006 Royce Mitchell III
6 * Copyright 2003-2019 Eric Kohl
9 /* INCLUDES *****************************************************************/
14 #define CONTROL_Z '\x1a'
15 #define MAX_SECTION_NAME_LEN 255
16 #define MAX_FIELD_LEN 511 /* larger fields get silently truncated */
17 /* actual string limit is MAX_INF_STRING_LENGTH+1 (plus terminating null) under Windows */
18 #define MAX_STRING_LEN (MAX_INF_STRING_LENGTH+1)
20 #define TAG_INF_KEY 'KfnI'
21 #define TAG_INF_FIELD 'ffnI'
22 #define TAG_INF_LINE 'LfnI'
23 #define TAG_INF_SECTION 'SfnI'
24 #define TAG_INF_CACHE 'CfnI'
25 #define TAG_INF_FILE 'FfnI'
27 typedef struct _INFCACHEFIELD
29 struct _INFCACHEFIELD
*Next
;
30 struct _INFCACHEFIELD
*Prev
;
33 } INFCACHEFIELD
, *PINFCACHEFIELD
;
35 typedef struct _INFCACHELINE
37 struct _INFCACHELINE
*Next
;
38 struct _INFCACHELINE
*Prev
;
44 PINFCACHEFIELD FirstField
;
45 PINFCACHEFIELD LastField
;
47 } INFCACHELINE
, *PINFCACHELINE
;
49 typedef struct _INFCACHESECTION
51 struct _INFCACHESECTION
*Next
;
52 struct _INFCACHESECTION
*Prev
;
54 PINFCACHELINE FirstLine
;
55 PINFCACHELINE LastLine
;
60 } INFCACHESECTION
, *PINFCACHESECTION
;
62 typedef struct _INFCACHE
64 PINFCACHESECTION FirstSection
;
65 PINFCACHESECTION LastSection
;
67 PINFCACHESECTION StringsSection
;
68 } INFCACHE
, *PINFCACHE
;
70 /* parser definitions */
73 LINE_START
, /* at beginning of a line */
74 SECTION_NAME
, /* parsing a section name */
75 KEY_NAME
, /* parsing a key name */
76 VALUE_NAME
, /* parsing a value name */
77 EOL_BACKSLASH
, /* backslash at end of line */
78 QUOTES
, /* inside quotes */
79 LEADING_SPACES
, /* leading spaces */
80 TRAILING_SPACES
, /* trailing spaces */
81 COMMENT
, /* inside a comment */
87 const CHAR
*start
; /* start position of item being parsed */
88 const CHAR
*end
; /* end of buffer */
89 PINFCACHE file
; /* file being built */
90 enum parser_state state
; /* current parser state */
91 enum parser_state stack
[4]; /* state stack */
92 int stack_pos
; /* current pos in stack */
94 PINFCACHESECTION cur_section
; /* pointer to the section being parsed*/
95 PINFCACHELINE line
; /* current line */
96 unsigned int line_pos
; /* current line position in file */
97 unsigned int error
; /* error code */
98 unsigned int token_len
; /* current token len */
99 CHAR token
[MAX_FIELD_LEN
+ 1]; /* current token */
102 typedef const CHAR
* (*parser_state_func
)(struct parser
*parser
, const CHAR
*pos
);
104 /* parser state machine functions */
105 static const CHAR
*line_start_state(struct parser
*parser
, const CHAR
*pos
);
106 static const CHAR
*section_name_state(struct parser
*parser
, const CHAR
*pos
);
107 static const CHAR
*key_name_state(struct parser
*parser
, const CHAR
*pos
);
108 static const CHAR
*value_name_state(struct parser
*parser
, const CHAR
*pos
);
109 static const CHAR
*eol_backslash_state(struct parser
*parser
, const CHAR
*pos
);
110 static const CHAR
*quotes_state(struct parser
*parser
, const CHAR
*pos
);
111 static const CHAR
*leading_spaces_state(struct parser
*parser
, const CHAR
*pos
);
112 static const CHAR
*trailing_spaces_state(struct parser
*parser
, const CHAR
*pos
);
113 static const CHAR
*comment_state(struct parser
*parser
, const CHAR
*pos
);
116 const parser_state_func
117 parser_funcs
[NB_PARSER_STATES
] =
119 line_start_state
, /* LINE_START */
120 section_name_state
, /* SECTION_NAME */
121 key_name_state
, /* KEY_NAME */
122 value_name_state
, /* VALUE_NAME */
123 eol_backslash_state
, /* EOL_BACKSLASH */
124 quotes_state
, /* QUOTES */
125 leading_spaces_state
, /* LEADING_SPACES */
126 trailing_spaces_state
, /* TRAILING_SPACES */
127 comment_state
/* COMMENT */
131 /* PRIVATE FUNCTIONS ********************************************************/
139 PINFCACHEFIELD Field
;
147 if (Line
->Key
!= NULL
)
149 FrLdrTempFree(Line
->Key
, TAG_INF_KEY
);
153 /* Remove data fields */
154 while (Line
->FirstField
!= NULL
)
156 Field
= Line
->FirstField
->Next
;
157 FrLdrTempFree(Line
->FirstField
, TAG_INF_FIELD
);
158 Line
->FirstField
= Field
;
160 Line
->LastField
= NULL
;
162 FrLdrTempFree(Line
, TAG_INF_LINE
);
170 InfpCacheFreeSection(
171 PINFCACHESECTION Section
)
173 PINFCACHESECTION Next
;
180 /* Release all keys */
181 Next
= Section
->Next
;
182 while (Section
->FirstLine
!= NULL
)
184 Section
->FirstLine
= InfpCacheFreeLine(Section
->FirstLine
);
186 Section
->LastLine
= NULL
;
188 FrLdrTempFree(Section
, TAG_INF_SECTION
);
196 InfpCacheFindSection(
200 PINFCACHESECTION Section
= NULL
;
202 if (Cache
== NULL
|| Name
== NULL
)
207 /* iterate through list of sections */
208 Section
= Cache
->FirstSection
;
209 while (Section
!= NULL
)
211 if (_stricmp(Section
->Name
, Name
) == 0)
216 /* get the next section*/
217 Section
= Section
->Next
;
230 PINFCACHESECTION Section
= NULL
;
233 if ((Cache
== NULL
) || (Name
== NULL
))
235 // DPRINT("Invalid parameter\n");
239 /* Allocate and initialize the new section */
240 Size
= sizeof(INFCACHESECTION
) + strlen(Name
);
241 Section
= (PINFCACHESECTION
)FrLdrTempAlloc(Size
, TAG_INF_SECTION
);
244 // DPRINT("RtlAllocateHeap() failed\n");
247 memset(Section
, 0, Size
);
249 /* Copy section name */
250 strcpy(Section
->Name
, Name
);
253 if (Cache
->FirstSection
== NULL
)
255 Cache
->FirstSection
= Section
;
256 Cache
->LastSection
= Section
;
260 Cache
->LastSection
->Next
= Section
;
261 Section
->Prev
= Cache
->LastSection
;
262 Cache
->LastSection
= Section
;
271 InfpCacheAddLine(PINFCACHESECTION Section
)
277 // DPRINT("Invalid parameter\n");
281 Line
= (PINFCACHELINE
)FrLdrTempAlloc(sizeof(INFCACHELINE
), TAG_INF_LINE
);
284 // DPRINT("RtlAllocateHeap() failed\n");
287 memset(Line
, 0, sizeof(INFCACHELINE
));
290 if (Section
->FirstLine
== NULL
)
292 Section
->FirstLine
= Line
;
293 Section
->LastLine
= Line
;
297 Section
->LastLine
->Next
= Line
;
298 Line
->Prev
= Section
->LastLine
;
299 Section
->LastLine
= Line
;
301 Section
->LineCount
++;
316 if (Line
->Key
!= NULL
)
319 Line
->Key
= FrLdrTempAlloc(strlen(Key
) + 1, TAG_INF_KEY
);
320 if (Line
->Key
== NULL
)
323 strcpy(Line
->Key
, Key
);
325 return (PVOID
)Line
->Key
;
335 PINFCACHEFIELD Field
;
338 Size
= sizeof(INFCACHEFIELD
) + strlen(Data
);
339 Field
= (PINFCACHEFIELD
)FrLdrTempAlloc(Size
, TAG_INF_FIELD
);
344 memset(Field
, 0, Size
);
346 strcpy(Field
->Data
, Data
);
349 if (Line
->FirstField
== NULL
)
351 Line
->FirstField
= Field
;
352 Line
->LastField
= Field
;
356 Line
->LastField
->Next
= Field
;
357 Field
->Prev
= Line
->LastField
;
358 Line
->LastField
= Field
;
368 InfpCacheFindKeyLine(
369 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
) ||
425 (*ptr
== CONTROL_Z
) ||
427 ((*ptr
== '\r') && (*(ptr
+ 1) == '\n')));
431 /* push data from current token start up to pos into the current token */
435 struct parser
*parser
,
438 SIZE_T len
= pos
- parser
->start
;
439 const CHAR
*src
= parser
->start
;
440 CHAR
*dst
= parser
->token
+ parser
->token_len
;
442 if (len
> MAX_FIELD_LEN
- parser
->token_len
)
443 len
= MAX_FIELD_LEN
- parser
->token_len
;
445 parser
->token_len
+= (ULONG
)len
;
446 for ( ; len
> 0; len
--, dst
++, src
++)
447 *dst
= *src
? (CHAR
)*src
: L
' ';
455 /* add a section with the current token as name */
458 add_section_from_token(struct parser
*parser
)
460 PINFCACHESECTION Section
;
462 if (parser
->token_len
> MAX_SECTION_NAME_LEN
)
464 parser
->error
= FALSE
;
468 Section
= InfpCacheFindSection(parser
->file
, parser
->token
);
471 /* need to create a new one */
472 Section
= InfpCacheAddSection(parser
->file
, parser
->token
);
475 parser
->error
= FALSE
;
480 parser
->token_len
= 0;
481 parser
->cur_section
= Section
;
483 return (PVOID
)Section
;
487 /* add a field containing the current token to the current line */
490 add_field_from_token(
491 struct parser
*parser
,
496 if (!parser
->line
) /* need to start a new line */
498 if (parser
->cur_section
== NULL
) /* got a line before the first section */
500 parser
->error
= STATUS_WRONG_INF_STYLE
;
504 parser
->line
= InfpCacheAddLine(parser
->cur_section
);
505 if (parser
->line
== NULL
)
515 field
= InfpAddKeyToLine(parser
->line
, parser
->token
);
519 field
= InfpAddFieldToLine(parser
->line
, parser
->token
);
524 parser
->token_len
= 0;
529 parser
->error
= FALSE
;
534 /* close the current line and prepare for parsing a new one */
537 close_current_line(struct parser
*parser
)
543 /* handler for parser LINE_START state */
547 struct parser
*parser
,
552 for (p
= pos
; !is_eof(parser
, p
); p
++)
561 close_current_line(parser
);
565 push_state(parser
, LINE_START
);
566 set_state(parser
, COMMENT
);
570 parser
->start
= p
+ 1;
571 set_state(parser
, SECTION_NAME
);
575 if (!isspace((unsigned char)*p
))
578 set_state(parser
, KEY_NAME
);
584 close_current_line(parser
);
589 /* handler for parser SECTION_NAME state */
593 struct parser
*parser
,
598 for (p
= pos
; !is_eol(parser
, p
); p
++)
602 push_token(parser
, p
);
603 if (add_section_from_token(parser
) == NULL
)
605 push_state(parser
, LINE_START
);
606 set_state(parser
, COMMENT
); /* ignore everything else on the line */
610 parser
->error
= STATUS_BAD_SECTION_NAME_LINE
; /* unfinished section name */
615 /* handler for parser KEY_NAME state */
619 struct parser
*parser
,
622 const CHAR
*p
, *token_end
= parser
->start
;
624 for (p
= pos
; !is_eol(parser
, p
); p
++)
626 if (*p
== ',') break;
631 push_token(parser
, token_end
);
632 if (!add_field_from_token(parser
, 1)) return NULL
;
633 parser
->start
= p
+ 1;
634 push_state(parser
, VALUE_NAME
);
635 set_state(parser
, LEADING_SPACES
);
638 push_token(parser
, token_end
);
639 if (!add_field_from_token(parser
, 0)) return NULL
;
640 push_state(parser
, LINE_START
);
641 set_state(parser
, COMMENT
);
644 push_token(parser
, token_end
);
645 parser
->start
= p
+ 1;
646 push_state(parser
, KEY_NAME
);
647 set_state(parser
, QUOTES
);
650 push_token(parser
, token_end
);
652 push_state(parser
, KEY_NAME
);
653 set_state(parser
, EOL_BACKSLASH
);
656 if (!isspace((unsigned char)*p
)) token_end
= p
+ 1;
659 push_token(parser
, p
);
660 push_state(parser
, KEY_NAME
);
661 set_state(parser
, TRAILING_SPACES
);
667 push_token(parser
, token_end
);
668 set_state(parser
, VALUE_NAME
);
673 /* handler for parser VALUE_NAME state */
677 struct parser
*parser
,
680 const CHAR
*p
, *token_end
= parser
->start
;
682 for (p
= pos
; !is_eol(parser
, p
); p
++)
687 push_token(parser
, token_end
);
688 if (!add_field_from_token(parser
, 0)) return NULL
;
689 push_state(parser
, LINE_START
);
690 set_state(parser
, COMMENT
);
693 push_token(parser
, token_end
);
694 if (!add_field_from_token(parser
, 0)) return NULL
;
695 parser
->start
= p
+ 1;
696 push_state(parser
, VALUE_NAME
);
697 set_state(parser
, LEADING_SPACES
);
700 push_token(parser
, token_end
);
701 parser
->start
= p
+ 1;
702 push_state(parser
, VALUE_NAME
);
703 set_state(parser
, QUOTES
);
706 push_token(parser
, token_end
);
708 push_state(parser
, VALUE_NAME
);
709 set_state(parser
, EOL_BACKSLASH
);
712 if (!isspace((unsigned char)*p
)) token_end
= p
+ 1;
715 push_token(parser
, p
);
716 push_state(parser
, VALUE_NAME
);
717 set_state(parser
, TRAILING_SPACES
);
723 push_token(parser
, token_end
);
724 if (!add_field_from_token(parser
, 0)) return NULL
;
725 set_state(parser
, LINE_START
);
730 /* handler for parser EOL_BACKSLASH state */
734 struct parser
*parser
,
739 for (p
= pos
; !is_eof(parser
, p
); p
++)
748 parser
->start
= p
+ 1;
749 set_state(parser
, LEADING_SPACES
);
756 push_state(parser
, EOL_BACKSLASH
);
757 set_state(parser
, COMMENT
);
761 if (isspace((unsigned char)*p
))
763 push_token(parser
, p
);
775 /* handler for parser QUOTES state */
779 struct parser
*parser
,
782 const CHAR
*p
, *token_end
= parser
->start
;
784 for (p
= pos
; !is_eol(parser
, p
); p
++)
788 if (p
+ 1 < parser
->end
&& p
[1] == '"') /* double quotes */
790 push_token(parser
, p
+ 1);
791 parser
->start
= token_end
= p
+ 2;
794 else /* end of quotes */
796 push_token(parser
, p
);
797 parser
->start
= p
+ 1;
803 push_token(parser
, p
);
809 /* handler for parser LEADING_SPACES state */
812 leading_spaces_state(
813 struct parser
*parser
,
818 for (p
= pos
; !is_eol(parser
, p
); p
++)
823 set_state(parser
, EOL_BACKSLASH
);
826 if (!isspace((unsigned char)*p
))
835 /* handler for parser TRAILING_SPACES state */
838 trailing_spaces_state(
839 struct parser
*parser
,
844 for (p
= pos
; !is_eol(parser
, p
); p
++)
848 set_state(parser
, EOL_BACKSLASH
);
851 if (!isspace((unsigned char)*p
))
859 /* handler for parser COMMENT state */
863 struct parser
*parser
,
868 while (!is_eol(parser
, p
))
875 /* parse a complete buffer */
884 struct parser parser
;
885 const CHAR
* pos
= buffer
;
887 parser
.start
= buffer
;
891 parser
.state
= LINE_START
;
892 parser
.stack_pos
= 0;
893 parser
.cur_section
= NULL
;
896 parser
.token_len
= 0;
898 /* parser main loop */
900 pos
= (parser_funcs
[parser
.state
])(&parser
, pos
);
905 *error_line
= parser
.line_pos
;
909 /* find the [strings] section */
910 file
->StringsSection
= InfpCacheFindSection(file
, "Strings");
915 /* PUBLIC FUNCTIONS *********************************************************/
923 FILEINFORMATION Information
;
926 ULONG FileSize
, Count
;
932 *ErrorLine
= (ULONG
) - 1;
935 // Open the .inf file
937 Status
= ArcOpen((PCHAR
)FileName
, OpenReadOnly
, &FileId
);
938 if (Status
!= ESUCCESS
)
946 Status
= ArcGetFileInformation(FileId
, &Information
);
947 if ((Status
!= ESUCCESS
) || (Information
.EndingAddress
.HighPart
!= 0))
952 FileSize
= Information
.EndingAddress
.LowPart
;
955 // Allocate buffer to cache the file
957 FileBuffer
= FrLdrTempAlloc(FileSize
+ 1, TAG_INF_FILE
);
965 // Read file into memory
967 Status
= ArcRead(FileId
, FileBuffer
, FileSize
, &Count
);
968 if ((Status
!= ESUCCESS
) || (Count
!= FileSize
))
971 FrLdrTempFree(FileBuffer
, TAG_INF_FILE
);
976 // We don't need the file anymore. Close it
981 // Append string terminator
983 FileBuffer
[FileSize
] = 0;
986 // Allocate infcache header
988 Cache
= (PINFCACHE
)FrLdrTempAlloc(sizeof(INFCACHE
), TAG_INF_CACHE
);
991 FrLdrTempFree(FileBuffer
, TAG_INF_FILE
);
996 // Initialize inicache header
998 RtlZeroMemory(Cache
, sizeof(INFCACHE
));
1001 // Parse the inf buffer
1003 Success
= InfpParseBuffer(Cache
,
1005 FileBuffer
+ FileSize
,
1009 FrLdrTempFree(Cache
, TAG_INF_CACHE
);
1014 // Free file buffer, as it has been parsed
1016 FrLdrTempFree(FileBuffer
, TAG_INF_FILE
);
1019 // Return .inf parsed contents
1021 *InfHandle
= (HINF
)Cache
;
1028 InfCloseFile(HINF InfHandle
)
1032 Cache
= (PINFCACHE
)InfHandle
;
1039 while (Cache
->FirstSection
!= NULL
)
1041 Cache
->FirstSection
= InfpCacheFreeSection(Cache
->FirstSection
);
1043 Cache
->LastSection
= NULL
;
1045 FrLdrTempFree(Cache
, TAG_INF_CACHE
);
1054 PINFCONTEXT Context
)
1057 PINFCACHESECTION CacheSection
;
1058 PINFCACHELINE CacheLine
;
1060 if ((InfHandle
== NULL
) || (Section
== NULL
) || (Context
== NULL
))
1062 // DPRINT("Invalid parameter\n");
1066 Cache
= (PINFCACHE
)InfHandle
;
1068 /* Iterate through list of sections */
1069 CacheSection
= Cache
->FirstSection
;
1070 while (Section
!= NULL
)
1072 // DPRINT("Comparing '%S' and '%S'\n", CacheSection->Name, Section);
1074 /* Are the section names the same? */
1075 if (_stricmp(CacheSection
->Name
, Section
) == 0)
1079 CacheLine
= InfpCacheFindKeyLine(CacheSection
, Key
);
1083 CacheLine
= CacheSection
->FirstLine
;
1086 if (CacheLine
== NULL
)
1089 Context
->Inf
= (PVOID
)Cache
;
1090 Context
->Section
= (PVOID
)CacheSection
;
1091 Context
->Line
= (PVOID
)CacheLine
;
1096 /* Get the next section */
1097 CacheSection
= CacheSection
->Next
;
1100 // DPRINT("Section not found\n");
1108 PINFCONTEXT ContextIn
,
1109 PINFCONTEXT ContextOut
)
1111 PINFCACHELINE CacheLine
;
1113 if ((ContextIn
== NULL
) || (ContextOut
== NULL
))
1116 if (ContextIn
->Line
== NULL
)
1119 CacheLine
= (PINFCACHELINE
)ContextIn
->Line
;
1120 if (CacheLine
->Next
== NULL
)
1123 if (ContextIn
!= ContextOut
)
1125 ContextOut
->Inf
= ContextIn
->Inf
;
1126 ContextOut
->Section
= ContextIn
->Section
;
1128 ContextOut
->Line
= (PVOID
)(CacheLine
->Next
);
1135 InfFindFirstMatchLine (
1136 PINFCONTEXT ContextIn
,
1138 PINFCONTEXT ContextOut
)
1140 PINFCACHELINE CacheLine
;
1142 if ((ContextIn
== NULL
) || (ContextOut
== NULL
) || (Key
== NULL
) || (*Key
== 0))
1145 if (ContextIn
->Inf
== NULL
|| ContextIn
->Section
== NULL
)
1148 CacheLine
= ((PINFCACHESECTION
)(ContextIn
->Section
))->FirstLine
;
1149 while (CacheLine
!= NULL
)
1151 if ((CacheLine
->Key
!= NULL
) && (_stricmp(CacheLine
->Key
, Key
) == 0))
1154 if (ContextIn
!= ContextOut
)
1156 ContextOut
->Inf
= ContextIn
->Inf
;
1157 ContextOut
->Section
= ContextIn
->Section
;
1159 ContextOut
->Line
= (PVOID
)CacheLine
;
1164 CacheLine
= CacheLine
->Next
;
1172 InfFindNextMatchLine (
1173 PINFCONTEXT ContextIn
,
1175 PINFCONTEXT ContextOut
)
1177 PINFCACHELINE CacheLine
;
1179 if ((ContextIn
== NULL
) || (ContextOut
== NULL
) || (Key
== NULL
) || (*Key
== 0))
1182 if ((ContextIn
->Inf
== NULL
) || (ContextIn
->Section
== NULL
) || (ContextIn
->Line
== NULL
))
1185 CacheLine
= (PINFCACHELINE
)ContextIn
->Line
;
1186 while (CacheLine
!= NULL
)
1188 if ((CacheLine
->Key
!= NULL
) && (_stricmp(CacheLine
->Key
, Key
) == 0))
1191 if (ContextIn
!= ContextOut
)
1193 ContextOut
->Inf
= ContextIn
->Inf
;
1194 ContextOut
->Section
= ContextIn
->Section
;
1196 ContextOut
->Line
= (PVOID
)CacheLine
;
1201 CacheLine
= CacheLine
->Next
;
1214 PINFCACHESECTION CacheSection
;
1216 if ((InfHandle
== NULL
) || (Section
== NULL
))
1218 // DPRINT("Invalid parameter\n");
1222 Cache
= (PINFCACHE
)InfHandle
;
1224 /* Iterate through list of sections */
1225 CacheSection
= Cache
->FirstSection
;
1226 while (Section
!= NULL
)
1228 // DPRINT("Comparing '%S' and '%S'\n", CacheSection->Name, Section);
1230 /* Are the section names the same? */
1231 if (_stricmp(CacheSection
->Name
, Section
) == 0)
1233 return CacheSection
->LineCount
;
1236 /* Get the next section */
1237 CacheSection
= CacheSection
->Next
;
1240 // DPRINT("Section not found\n");
1246 /* InfGetLineText */
1250 InfGetFieldCount(PINFCONTEXT Context
)
1252 if ((Context
== NULL
) || (Context
->Line
== NULL
))
1255 return ((PINFCACHELINE
)Context
->Line
)->FieldCount
;
1261 PINFCONTEXT Context
,
1263 PUCHAR ReturnBuffer
,
1264 ULONG ReturnBufferSize
,
1265 PULONG RequiredSize
)
1267 PINFCACHELINE CacheLine
;
1268 PINFCACHEFIELD CacheField
;
1273 if ((Context
== NULL
) || (Context
->Line
== NULL
) || (FieldIndex
== 0))
1275 // DPRINT("Invalid parameter\n");
1279 if (RequiredSize
!= NULL
)
1282 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1284 if (FieldIndex
> CacheLine
->FieldCount
)
1287 CacheField
= CacheLine
->FirstField
;
1288 for (Index
= 1; Index
< FieldIndex
; Index
++)
1289 CacheField
= CacheField
->Next
;
1291 Size
= CacheLine
->FieldCount
- FieldIndex
+ 1;
1293 if (RequiredSize
!= NULL
)
1294 *RequiredSize
= Size
;
1296 if (ReturnBuffer
!= NULL
)
1298 if (ReturnBufferSize
< Size
)
1301 /* Copy binary data */
1303 while (CacheField
!= NULL
)
1305 *Ptr
= (UCHAR
)atoi(CacheField
->Data
); //strtoul(CacheField->Data, NULL, 16);
1308 CacheField
= CacheField
->Next
;
1318 PINFCONTEXT Context
,
1322 PINFCACHELINE CacheLine
;
1323 PINFCACHEFIELD CacheField
;
1327 if ((Context
== NULL
) || (Context
->Line
== NULL
) || (IntegerValue
== NULL
))
1329 // DPRINT("Invalid parameter\n");
1333 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1335 if (FieldIndex
> CacheLine
->FieldCount
)
1337 // DPRINT("Invalid parameter\n");
1341 if (FieldIndex
== 0)
1343 Ptr
= CacheLine
->Key
;
1347 CacheField
= CacheLine
->FirstField
;
1348 for (Index
= 1; Index
< FieldIndex
; Index
++)
1349 CacheField
= CacheField
->Next
;
1351 Ptr
= CacheField
->Data
;
1354 *IntegerValue
= atoi(Ptr
); //strtol(Ptr, NULL, 0);
1361 InfGetMultiSzField (
1362 PINFCONTEXT Context
,
1365 ULONG ReturnBufferSize
,
1366 PULONG RequiredSize
)
1368 PINFCACHELINE CacheLine
;
1369 PINFCACHEFIELD CacheField
;
1370 PINFCACHEFIELD FieldPtr
;
1375 if ((Context
== NULL
) || (Context
->Line
== NULL
) || (FieldIndex
== 0))
1377 // DPRINT("Invalid parameter\n");
1381 if (RequiredSize
!= NULL
)
1384 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1386 if (FieldIndex
> CacheLine
->FieldCount
)
1389 CacheField
= CacheLine
->FirstField
;
1390 for (Index
= 1; Index
< FieldIndex
; Index
++)
1391 CacheField
= CacheField
->Next
;
1393 /* Calculate the required buffer size */
1394 FieldPtr
= CacheField
;
1396 while (FieldPtr
!= NULL
)
1398 Size
+= (strlen(FieldPtr
->Data
) + 1);
1399 FieldPtr
= FieldPtr
->Next
;
1403 if (RequiredSize
!= NULL
)
1404 *RequiredSize
= (ULONG
)Size
;
1406 if (ReturnBuffer
!= NULL
)
1408 if (ReturnBufferSize
< Size
)
1411 /* Copy multi-sz string */
1413 FieldPtr
= CacheField
;
1414 while (FieldPtr
!= NULL
)
1416 Size
= strlen(FieldPtr
->Data
) + 1;
1418 strcpy(Ptr
, FieldPtr
->Data
);
1421 FieldPtr
= FieldPtr
->Next
;
1432 PINFCONTEXT Context
,
1435 ULONG ReturnBufferSize
,
1436 PULONG RequiredSize
)
1438 PINFCACHELINE CacheLine
;
1439 PINFCACHEFIELD CacheField
;
1444 if ((Context
== NULL
) || (Context
->Line
== NULL
))
1446 // DPRINT("Invalid parameter\n");
1450 if (RequiredSize
!= NULL
)
1453 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1455 if (FieldIndex
> CacheLine
->FieldCount
)
1458 if (FieldIndex
== 0)
1460 Ptr
= CacheLine
->Key
;
1464 CacheField
= CacheLine
->FirstField
;
1465 for (Index
= 1; Index
< FieldIndex
; Index
++)
1466 CacheField
= CacheField
->Next
;
1468 Ptr
= CacheField
->Data
;
1471 Size
= strlen(Ptr
) + 1;
1473 if (RequiredSize
!= NULL
)
1474 *RequiredSize
= (ULONG
)Size
;
1476 if (ReturnBuffer
!= NULL
)
1478 if (ReturnBufferSize
< Size
)
1481 strcpy(ReturnBuffer
, Ptr
);
1492 PINFCONTEXT Context
,
1496 PINFCACHELINE CacheKey
;
1498 if ((Context
== NULL
) || (Context
->Line
== NULL
) || (Data
== NULL
))
1500 // DPRINT("Invalid parameter\n");
1504 CacheKey
= (PINFCACHELINE
)Context
->Line
;
1506 *Key
= CacheKey
->Key
;
1510 if (CacheKey
->FirstField
== NULL
)
1516 *Data
= CacheKey
->FirstField
->Data
;
1526 PINFCONTEXT Context
,
1530 PINFCACHELINE CacheLine
;
1531 PINFCACHEFIELD CacheField
;
1534 if ((Context
== NULL
) || (Context
->Line
== NULL
) || (Data
== NULL
))
1536 // DPRINT("Invalid parameter\n");
1540 CacheLine
= (PINFCACHELINE
)Context
->Line
;
1542 if (FieldIndex
> CacheLine
->FieldCount
)
1545 if (FieldIndex
== 0)
1547 *Data
= CacheLine
->Key
;
1551 CacheField
= CacheLine
->FirstField
;
1552 for (Index
= 1; Index
< FieldIndex
; Index
++)
1553 CacheField
= CacheField
->Next
;
1555 *Data
= CacheField
->Data
;