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.
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 *****************************************************************/
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)
172 /* Remove data fields */
173 while (Line->FirstField != NULL)
175 Field = Line->FirstField->Next;
176 free (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;
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 (strcasecmp (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)malloc (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)malloc (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)malloc (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)malloc (Size);
352 memset (Field, 0, Size);
353 strcpy (Field->Data, Data);
356 if (Line->FirstField == NULL)
358 Line->FirstField = Field;
359 Line->LastField = Field;
363 Line->LastField->Next = Field;
364 Field->Prev = Line->LastField;
365 Line->LastField = Field;
374 InfpCacheFindKeyLine (PINFCACHESECTION Section,
379 Line = Section->FirstLine;
382 if (Line->Key != NULL && strcasecmp (Line->Key, Key) == 0)
394 /* push the current state on the parser stack */
395 inline static void push_state( struct parser *parser, enum parser_state state )
397 // assert( parser->stack_pos < sizeof(parser->stack)/sizeof(parser->stack[0]) );
398 parser->stack[parser->stack_pos++] = state;
402 /* pop the current state */
403 inline static void pop_state( struct parser *parser )
405 // assert( parser->stack_pos );
406 parser->state = parser->stack[--parser->stack_pos];
410 /* set the parser state and return the previous one */
411 inline static enum parser_state set_state( struct parser *parser, enum parser_state state )
413 enum parser_state ret = parser->state;
414 parser->state = state;
419 /* check if the pointer points to an end of file */
420 inline static int is_eof( struct parser *parser, const CHAR *ptr )
422 return (ptr >= parser->end || *ptr == CONTROL_Z);
426 /* check if the pointer points to an end of line */
427 inline static int is_eol( struct parser *parser, const CHAR *ptr )
429 return (ptr >= parser->end ||
432 (*ptr == '\r' && *(ptr + 1) == '\n'));
436 /* push data from current token start up to pos into the current token */
437 static int push_token( struct parser *parser, const CHAR *pos )
439 int len = pos - parser->start;
440 const CHAR *src = parser->start;
441 CHAR *dst = parser->token + parser->token_len;
443 if (len > MAX_FIELD_LEN - parser->token_len)
444 len = MAX_FIELD_LEN - parser->token_len;
446 parser->token_len += len;
447 for ( ; len > 0; len--, dst++, src++)
448 *dst = *src ? *src : ' ';
457 /* add a section with the current token as name */
458 static PVOID add_section_from_token( struct parser *parser )
460 PINFCACHESECTION Section;
462 if (parser->token_len > MAX_SECTION_NAME_LEN)
464 parser->error = STATUS_SECTION_NAME_TOO_LONG;
468 Section = InfpCacheFindSection (parser->file,
472 /* need to create a new one */
473 Section= InfpCacheAddSection (parser->file,
477 parser->error = STATUS_NOT_ENOUGH_MEMORY;
482 parser->token_len = 0;
483 parser->cur_section = Section;
485 return (PVOID)Section;
489 /* add a field containing the current token to the current line */
490 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 (Section != 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;