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 || *ptr == CONTROL_Z || *ptr == '\r' /*'\n'*/);
433 /* push data from current token start up to pos into the current token */
434 static int push_token( struct parser *parser, const CHAR *pos )
436 int len = pos - parser->start;
437 const CHAR *src = parser->start;
438 CHAR *dst = parser->token + parser->token_len;
440 if (len > MAX_FIELD_LEN - parser->token_len)
441 len = MAX_FIELD_LEN - parser->token_len;
443 parser->token_len += len;
444 for ( ; len > 0; len--, dst++, src++)
445 *dst = *src ? *src : ' ';
454 /* add a section with the current token as name */
455 static PVOID add_section_from_token( struct parser *parser )
457 PINFCACHESECTION Section;
459 if (parser->token_len > MAX_SECTION_NAME_LEN)
461 parser->error = STATUS_SECTION_NAME_TOO_LONG;
465 Section = InfpCacheFindSection (parser->file,
469 /* need to create a new one */
470 Section= InfpCacheAddSection (parser->file,
474 parser->error = STATUS_NOT_ENOUGH_MEMORY;
479 parser->token_len = 0;
480 parser->cur_section = Section;
482 return (PVOID)Section;
486 /* add a field containing the current token to the current line */
487 static struct field *add_field_from_token( struct parser *parser, int is_key )
492 if (!parser->line) /* need to start a new line */
494 if (parser->cur_section == NULL) /* got a line before the first section */
496 parser->error = STATUS_WRONG_INF_STYLE;
500 parser->line = InfpCacheAddLine (parser->cur_section);
501 if (parser->line == NULL)
511 field = InfpAddKeyToLine(parser->line, parser->token);
515 field = InfpAddFieldToLine(parser->line, parser->token);
520 parser->token_len = 0;
525 parser->error = STATUS_NOT_ENOUGH_MEMORY;
530 /* close the current line and prepare for parsing a new one */
531 static void close_current_line( struct parser *parser )
538 /* handler for parser LINE_START state */
539 static const CHAR *line_start_state( struct parser *parser, const CHAR *pos )
543 for (p = pos; !is_eof( parser, p ); p++)
551 close_current_line( parser );
554 push_state( parser, LINE_START );
555 set_state( parser, COMMENT );
558 parser->start = p + 1;
559 set_state( parser, SECTION_NAME );
565 set_state( parser, KEY_NAME );
571 close_current_line( parser );
576 /* handler for parser SECTION_NAME state */
577 static const CHAR *section_name_state( struct parser *parser, const CHAR *pos )
581 for (p = pos; !is_eol( parser, p ); p++)
585 push_token( parser, p );
586 if (add_section_from_token( parser ) == NULL)
588 push_state( parser, LINE_START );
589 set_state( parser, COMMENT ); /* ignore everything else on the line */
593 parser->error = STATUS_BAD_SECTION_NAME_LINE; /* unfinished section name */
598 /* handler for parser KEY_NAME state */
599 static const CHAR *key_name_state( struct parser *parser, const CHAR *pos )
601 const CHAR *p, *token_end = parser->start;
603 for (p = pos; !is_eol( parser, p ); p++)
605 if (*p == ',') break;
610 push_token( parser, token_end );
611 if (!add_field_from_token( parser, 1 )) return NULL;
612 parser->start = p + 1;
613 push_state( parser, VALUE_NAME );
614 set_state( parser, LEADING_SPACES );
617 push_token( parser, token_end );
618 if (!add_field_from_token( parser, 0 )) return NULL;
619 push_state( parser, LINE_START );
620 set_state( parser, COMMENT );
623 push_token( parser, token_end );
624 parser->start = p + 1;
625 push_state( parser, KEY_NAME );
626 set_state( parser, QUOTES );
629 push_token( parser, token_end );
631 push_state( parser, KEY_NAME );
632 set_state( parser, EOL_BACKSLASH );
635 if (!isspace(*p)) token_end = p + 1;
638 push_token( parser, p );
639 push_state( parser, KEY_NAME );
640 set_state( parser, TRAILING_SPACES );
646 push_token( parser, token_end );
647 set_state( parser, VALUE_NAME );
652 /* handler for parser VALUE_NAME state */
653 static const CHAR *value_name_state( struct parser *parser, const CHAR *pos )
655 const CHAR *p, *token_end = parser->start;
657 for (p = pos; !is_eol( parser, p ); p++)
662 push_token( parser, token_end );
663 if (!add_field_from_token( parser, 0 )) return NULL;
664 push_state( parser, LINE_START );
665 set_state( parser, COMMENT );
668 push_token( parser, token_end );
669 if (!add_field_from_token( parser, 0 )) return NULL;
670 parser->start = p + 1;
671 push_state( parser, VALUE_NAME );
672 set_state( parser, LEADING_SPACES );
675 push_token( parser, token_end );
676 parser->start = p + 1;
677 push_state( parser, VALUE_NAME );
678 set_state( parser, QUOTES );
681 push_token( parser, token_end );
683 push_state( parser, VALUE_NAME );
684 set_state( parser, EOL_BACKSLASH );
687 if (!isspace(*p)) token_end = p + 1;
690 push_token( parser, p );
691 push_state( parser, VALUE_NAME );
692 set_state( parser, TRAILING_SPACES );
698 push_token( parser, token_end );
699 if (!add_field_from_token( parser, 0 )) return NULL;
700 set_state( parser, LINE_START );
705 /* handler for parser EOL_BACKSLASH state */
706 static const CHAR *eol_backslash_state( struct parser *parser, const CHAR *pos )
710 for (p = pos; !is_eof( parser, p ); p++)
717 // parser->start = p + 1;
718 parser->start = p + 2;
719 set_state( parser, LEADING_SPACES );
725 push_state( parser, EOL_BACKSLASH );
726 set_state( parser, COMMENT );
731 push_token( parser, p );
743 /* handler for parser QUOTES state */
744 static const CHAR *quotes_state( struct parser *parser, const CHAR *pos )
746 const CHAR *p, *token_end = parser->start;
748 for (p = pos; !is_eol( parser, p ); p++)
752 if (p+1 < parser->end && p[1] == '"') /* double quotes */
754 push_token( parser, p + 1 );
755 parser->start = token_end = p + 2;
758 else /* end of quotes */
760 push_token( parser, p );
761 parser->start = p + 1;
767 push_token( parser, p );
773 /* handler for parser LEADING_SPACES state */
774 static const CHAR *leading_spaces_state( struct parser *parser, const CHAR *pos )
778 for (p = pos; !is_eol( parser, p ); p++)
783 set_state( parser, EOL_BACKSLASH );
795 /* handler for parser TRAILING_SPACES state */
796 static const CHAR *trailing_spaces_state( struct parser *parser, const CHAR *pos )
800 for (p = pos; !is_eol( parser, p ); p++)
804 set_state( parser, EOL_BACKSLASH );
815 /* handler for parser COMMENT state */
816 static const CHAR *comment_state( struct parser *parser, const CHAR *pos )
820 while (!is_eol( parser, p ))
827 /* parse a complete buffer */
829 InfpParseBuffer (PINFCACHE file,
834 struct parser parser;
835 const CHAR *pos = buffer;
837 parser.start = buffer;
841 parser.state = LINE_START;
842 parser.stack_pos = 0;
843 parser.cur_section = NULL;
846 parser.token_len = 0;
848 /* parser main loop */
850 pos = (parser_funcs[parser.state])(&parser, pos);
855 *error_line = parser.line_pos;
859 /* find the [strings] section */
860 file->StringsSection = InfpCacheFindSection (file,
868 /* PUBLIC FUNCTIONS *********************************************************/
871 InfOpenFile(PHINF InfHandle,
881 *ErrorLine = (ULONG)-1;
883 /* Open the inf file */
884 File = fopen (FileName, "rb");
887 DPRINT("fopen() failed\n");
891 DPRINT("fopen() successful\n");
893 /* Query file size */
894 fseek (File, 0, SEEK_END);
895 FileLength = ftell (File);
896 fseek (File, 0, SEEK_SET);
898 DPRINT("File size: %lu\n", FileLength);
900 /* Allocate file buffer */
901 FileBuffer = malloc (FileLength + 1);
902 if (FileBuffer == NULL)
904 DPRINT1("malloc() failed\n");
910 if (fread (FileBuffer, FileLength, 1, File) < 0)
912 DPRINT ("fread() failed\n");
920 /* Append string terminator */
921 FileBuffer[FileLength] = 0;
923 /* Allocate infcache header */
924 Cache = (PINFCACHE)malloc (sizeof(INFCACHE));
927 DPRINT("malloc() failed\n");
932 /* Initialize inicache header */
933 memset (Cache, 0, sizeof(INFCACHE));
935 /* Parse the inf buffer */
936 if (!InfpParseBuffer (Cache,
938 FileBuffer + FileLength,
946 /* Free file buffer */
949 *InfHandle = (HINF)Cache;
956 InfCloseFile(HINF InfHandle)
960 Cache = (PINFCACHE)InfHandle;
967 while (Cache->FirstSection != NULL)
969 Cache->FirstSection = InfpCacheFreeSection(Cache->FirstSection);
971 Cache->LastSection = NULL;
978 InfFindFirstLine (HINF InfHandle,
984 PINFCACHESECTION CacheSection;
985 PINFCACHELINE CacheLine;
987 if (InfHandle == NULL || Section == NULL || Context == NULL)
989 DPRINT("Invalid parameter\n");
993 Cache = (PINFCACHE)InfHandle;
995 /* Iterate through list of sections */
996 CacheSection = Cache->FirstSection;
997 while (Section != NULL)
999 DPRINT("Comparing '%s' and '%s'\n", CacheSection->Name, Section);
1001 /* Are the section names the same? */
1002 if (strcasecmp(CacheSection->Name, Section) == 0)
1006 CacheLine = InfpCacheFindKeyLine (CacheSection, (PCHAR)Key);
1010 CacheLine = CacheSection->FirstLine;
1013 if (CacheLine == NULL)
1016 Context->Inf = (PVOID)Cache;
1017 Context->Section = (PVOID)CacheSection;
1018 Context->Line = (PVOID)CacheLine;
1023 /* Get the next section */
1024 CacheSection = CacheSection->Next;
1027 DPRINT("Section not found\n");
1034 InfFindNextLine (PINFCONTEXT ContextIn,
1035 PINFCONTEXT ContextOut)
1037 PINFCACHELINE CacheLine;
1039 if (ContextIn == NULL || ContextOut == NULL)
1042 if (ContextIn->Line == NULL)
1045 CacheLine = (PINFCACHELINE)ContextIn->Line;
1046 if (CacheLine->Next == NULL)
1049 if (ContextIn != ContextOut)
1051 ContextOut->Inf = ContextIn->Inf;
1052 ContextOut->Section = ContextIn->Section;
1054 ContextOut->Line = (PVOID)(CacheLine->Next);
1061 InfFindFirstMatchLine (PINFCONTEXT ContextIn,
1063 PINFCONTEXT ContextOut)
1065 PINFCACHELINE CacheLine;
1067 if (ContextIn == NULL || ContextOut == NULL || Key == NULL || *Key == 0)
1070 if (ContextIn->Inf == NULL || ContextIn->Section == NULL)
1073 CacheLine = ((PINFCACHESECTION)(ContextIn->Section))->FirstLine;
1074 while (CacheLine != NULL)
1076 if (CacheLine->Key != NULL && strcasecmp (CacheLine->Key, Key) == 0)
1079 if (ContextIn != ContextOut)
1081 ContextOut->Inf = ContextIn->Inf;
1082 ContextOut->Section = ContextIn->Section;
1084 ContextOut->Line = (PVOID)CacheLine;
1089 CacheLine = CacheLine->Next;
1097 InfFindNextMatchLine (PINFCONTEXT ContextIn,
1099 PINFCONTEXT ContextOut)
1101 PINFCACHELINE CacheLine;
1103 if (ContextIn == NULL || ContextOut == NULL || Key == NULL || *Key == 0)
1106 if (ContextIn->Inf == NULL || ContextIn->Section == NULL || ContextIn->Line == NULL)
1109 CacheLine = (PINFCACHELINE)ContextIn->Line;
1110 while (CacheLine != NULL)
1112 if (CacheLine->Key != NULL && strcasecmp (CacheLine->Key, Key) == 0)
1115 if (ContextIn != ContextOut)
1117 ContextOut->Inf = ContextIn->Inf;
1118 ContextOut->Section = ContextIn->Section;
1120 ContextOut->Line = (PVOID)CacheLine;
1125 CacheLine = CacheLine->Next;
1133 InfGetLineCount(HINF InfHandle,
1137 PINFCACHESECTION CacheSection;
1139 if (InfHandle == NULL || Section == NULL)
1141 DPRINT("Invalid parameter\n");
1145 Cache = (PINFCACHE)InfHandle;
1147 /* Iterate through list of sections */
1148 CacheSection = Cache->FirstSection;
1149 while (Section != NULL)
1151 DPRINT("Comparing '%s' and '%s'\n", CacheSection->Name, Section);
1153 /* Are the section names the same? */
1154 if (strcasecmp(CacheSection->Name, Section) == 0)
1156 return CacheSection->LineCount;
1159 /* Get the next section */
1160 CacheSection = CacheSection->Next;
1163 DPRINT("Section not found\n");
1169 /* InfGetLineText */
1173 InfGetFieldCount(PINFCONTEXT Context)
1175 if (Context == NULL || Context->Line == NULL)
1178 return ((PINFCACHELINE)Context->Line)->FieldCount;
1183 InfGetBinaryField (PINFCONTEXT Context,
1185 PUCHAR ReturnBuffer,
1186 ULONG ReturnBufferSize,
1187 PULONG RequiredSize)
1189 PINFCACHELINE CacheLine;
1190 PINFCACHEFIELD CacheField;
1195 if (Context == NULL || Context->Line == NULL || FieldIndex == 0)
1197 DPRINT("Invalid parameter\n");
1201 if (RequiredSize != NULL)
1204 CacheLine = (PINFCACHELINE)Context->Line;
1206 if (FieldIndex > CacheLine->FieldCount)
1209 CacheField = CacheLine->FirstField;
1210 for (Index = 1; Index < FieldIndex; Index++)
1211 CacheField = CacheField->Next;
1213 Size = CacheLine->FieldCount - FieldIndex + 1;
1215 if (RequiredSize != NULL)
1216 *RequiredSize = Size;
1218 if (ReturnBuffer != NULL)
1220 if (ReturnBufferSize < Size)
1223 /* Copy binary data */
1225 while (CacheField != NULL)
1227 *Ptr = (UCHAR)strtoul (CacheField->Data, NULL, 16);
1230 CacheField = CacheField->Next;
1239 InfGetIntField (PINFCONTEXT Context,
1243 PINFCACHELINE CacheLine;
1244 PINFCACHEFIELD CacheField;
1248 if (Context == NULL || Context->Line == NULL || IntegerValue == NULL)
1250 DPRINT("Invalid parameter\n");
1254 CacheLine = (PINFCACHELINE)Context->Line;
1256 if (FieldIndex > CacheLine->FieldCount)
1258 DPRINT("Invalid parameter\n");
1262 if (FieldIndex == 0)
1264 Ptr = CacheLine->Key;
1268 CacheField = CacheLine->FirstField;
1269 for (Index = 1; Index < FieldIndex; Index++)
1270 CacheField = CacheField->Next;
1272 Ptr = CacheField->Data;
1275 *IntegerValue = strtol (Ptr, NULL, 0);
1282 InfGetMultiSzField (PINFCONTEXT Context,
1285 ULONG ReturnBufferSize,
1286 PULONG RequiredSize)
1288 PINFCACHELINE CacheLine;
1289 PINFCACHEFIELD CacheField;
1290 PINFCACHEFIELD FieldPtr;
1295 if (Context == NULL || Context->Line == NULL || FieldIndex == 0)
1297 DPRINT("Invalid parameter\n");
1301 if (RequiredSize != NULL)
1304 CacheLine = (PINFCACHELINE)Context->Line;
1306 if (FieldIndex > CacheLine->FieldCount)
1309 CacheField = CacheLine->FirstField;
1310 for (Index = 1; Index < FieldIndex; Index++)
1311 CacheField = CacheField->Next;
1313 /* Calculate the required buffer size */
1314 FieldPtr = CacheField;
1316 while (FieldPtr != NULL)
1318 Size += (strlen (FieldPtr->Data) + 1);
1319 FieldPtr = FieldPtr->Next;
1323 if (RequiredSize != NULL)
1324 *RequiredSize = Size;
1326 if (ReturnBuffer != NULL)
1328 if (ReturnBufferSize < Size)
1331 /* Copy multi-sz string */
1333 FieldPtr = CacheField;
1334 while (FieldPtr != NULL)
1336 Size = strlen (FieldPtr->Data) + 1;
1338 strcpy (Ptr, FieldPtr->Data);
1341 FieldPtr = FieldPtr->Next;
1351 InfGetStringField (PINFCONTEXT Context,
1354 ULONG ReturnBufferSize,
1355 PULONG RequiredSize)
1357 PINFCACHELINE CacheLine;
1358 PINFCACHEFIELD CacheField;
1363 if (Context == NULL || Context->Line == NULL || FieldIndex == 0)
1365 DPRINT("Invalid parameter\n");
1369 if (RequiredSize != NULL)
1372 CacheLine = (PINFCACHELINE)Context->Line;
1374 if (FieldIndex > CacheLine->FieldCount)
1377 if (FieldIndex == 0)
1379 Ptr = CacheLine->Key;
1383 CacheField = CacheLine->FirstField;
1384 for (Index = 1; Index < FieldIndex; Index++)
1385 CacheField = CacheField->Next;
1387 Ptr = CacheField->Data;
1390 Size = strlen (Ptr) + 1;
1392 if (RequiredSize != NULL)
1393 *RequiredSize = Size;
1395 if (ReturnBuffer != NULL)
1397 if (ReturnBufferSize < Size)
1400 strcpy (ReturnBuffer, Ptr);
1410 InfGetData (PINFCONTEXT Context,
1414 PINFCACHELINE CacheKey;
1416 if (Context == NULL || Context->Line == NULL || Data == NULL)
1418 DPRINT("Invalid parameter\n");
1422 CacheKey = (PINFCACHELINE)Context->Line;
1424 *Key = CacheKey->Key;
1428 if (CacheKey->FirstField == NULL)
1434 *Data = CacheKey->FirstField->Data;
1443 InfGetDataField (PINFCONTEXT Context,
1447 PINFCACHELINE CacheLine;
1448 PINFCACHEFIELD CacheField;
1451 if (Context == NULL || Context->Line == NULL || Data == NULL)
1453 DPRINT("Invalid parameter\n");
1457 CacheLine = (PINFCACHELINE)Context->Line;
1459 if (FieldIndex > CacheLine->FieldCount)
1462 if (FieldIndex == 0)
1464 *Data = CacheLine->Key;
1468 CacheField = CacheLine->FirstField;
1469 for (Index = 1; Index < FieldIndex; Index++)
1470 CacheField = CacheField->Next;
1472 *Data = CacheField->Data;