ReactOS  0.4.14-dev-556-g4c5b21f
inffile.c
Go to the documentation of this file.
1 /*
2  * PROJECT: FreeLoader
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
7  */
8 
9 /* INCLUDES *****************************************************************/
10 
11 #include <freeldr.h>
12 #include "inffile.h"
13 
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)
19 
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'
26 
27 typedef struct _INFCACHEFIELD
28 {
31 
32  CHAR Data[1];
34 
35 typedef struct _INFCACHELINE
36 {
39 
41 
43 
46 
48 
49 typedef struct _INFCACHESECTION
50 {
53 
56 
58 
59  CHAR Name[1];
61 
62 typedef struct _INFCACHE
63 {
66 
69 
70 /* parser definitions */
72 {
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 */
83 };
84 
85 struct parser
86 {
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 */
93 
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 */
100 };
101 
102 typedef const CHAR * (*parser_state_func)(struct parser *parser, const CHAR *pos);
103 
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);
114 
115 static
116 const parser_state_func
118 {
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 */
128 };
129 
130 
131 /* PRIVATE FUNCTIONS ********************************************************/
132 
133 static
137 {
138  PINFCACHELINE Next;
139  PINFCACHEFIELD Field;
140 
141  if (Line == NULL)
142  {
143  return NULL;
144  }
145 
146  Next = Line->Next;
147  if (Line->Key != NULL)
148  {
150  Line->Key = NULL;
151  }
152 
153  /* Remove data fields */
154  while (Line->FirstField != NULL)
155  {
156  Field = Line->FirstField->Next;
157  FrLdrTempFree(Line->FirstField, TAG_INF_FIELD);
158  Line->FirstField = Field;
159  }
160  Line->LastField = NULL;
161 
163 
164  return Next;
165 }
166 
167 
168 static
171  PINFCACHESECTION Section)
172 {
173  PINFCACHESECTION Next;
174 
175  if (Section == NULL)
176  {
177  return NULL;
178  }
179 
180  /* Release all keys */
181  Next = Section->Next;
182  while (Section->FirstLine != NULL)
183  {
184  Section->FirstLine = InfpCacheFreeLine(Section->FirstLine);
185  }
186  Section->LastLine = NULL;
187 
188  FrLdrTempFree(Section, TAG_INF_SECTION);
189 
190  return Next;
191 }
192 
193 
194 static
198  PCSTR Name)
199 {
200  PINFCACHESECTION Section = NULL;
201 
202  if (Cache == NULL || Name == NULL)
203  {
204  return NULL;
205  }
206 
207  /* iterate through list of sections */
208  Section = Cache->FirstSection;
209  while (Section != NULL)
210  {
211  if (_stricmp(Section->Name, Name) == 0)
212  {
213  return Section;
214  }
215 
216  /* get the next section*/
217  Section = Section->Next;
218  }
219 
220  return NULL;
221 }
222 
223 
224 static
228  PCHAR Name)
229 {
230  PINFCACHESECTION Section = NULL;
231  SIZE_T Size;
232 
233  if ((Cache == NULL) || (Name == NULL))
234  {
235 // DPRINT("Invalid parameter\n");
236  return NULL;
237  }
238 
239  /* Allocate and initialize the new section */
240  Size = sizeof(INFCACHESECTION) + strlen(Name);
242  if (Section == NULL)
243  {
244 // DPRINT("RtlAllocateHeap() failed\n");
245  return NULL;
246  }
247  memset(Section, 0, Size);
248 
249  /* Copy section name */
250  strcpy(Section->Name, Name);
251 
252  /* Append section */
253  if (Cache->FirstSection == NULL)
254  {
255  Cache->FirstSection = Section;
256  Cache->LastSection = Section;
257  }
258  else
259  {
260  Cache->LastSection->Next = Section;
261  Section->Prev = Cache->LastSection;
262  Cache->LastSection = Section;
263  }
264 
265  return Section;
266 }
267 
268 
269 static
272 {
274 
275  if (Section == NULL)
276  {
277 // DPRINT("Invalid parameter\n");
278  return NULL;
279  }
280 
282  if (Line == NULL)
283  {
284 // DPRINT("RtlAllocateHeap() failed\n");
285  return NULL;
286  }
287  memset(Line, 0, sizeof(INFCACHELINE));
288 
289  /* Append line */
290  if (Section->FirstLine == NULL)
291  {
292  Section->FirstLine = Line;
293  Section->LastLine = Line;
294  }
295  else
296  {
297  Section->LastLine->Next = Line;
298  Line->Prev = Section->LastLine;
299  Section->LastLine = Line;
300  }
301  Section->LineCount++;
302 
303  return Line;
304 }
305 
306 
307 static
308 PVOID
311  PCHAR Key)
312 {
313  if (Line == NULL)
314  return NULL;
315 
316  if (Line->Key != NULL)
317  return NULL;
318 
319  Line->Key = FrLdrTempAlloc(strlen(Key) + 1, TAG_INF_KEY);
320  if (Line->Key == NULL)
321  return NULL;
322 
323  strcpy(Line->Key, Key);
324 
325  return (PVOID)Line->Key;
326 }
327 
328 
329 static
330 PVOID
333  PCHAR Data)
334 {
335  PINFCACHEFIELD Field;
336  SIZE_T Size;
337 
338  Size = sizeof(INFCACHEFIELD) + strlen(Data);
340  if (Field == NULL)
341  {
342  return NULL;
343  }
344  memset(Field, 0, Size);
345 
346  strcpy(Field->Data, Data);
347 
348  /* Append key */
349  if (Line->FirstField == NULL)
350  {
351  Line->FirstField = Field;
352  Line->LastField = Field;
353  }
354  else
355  {
356  Line->LastField->Next = Field;
357  Field->Prev = Line->LastField;
358  Line->LastField = Field;
359  }
360  Line->FieldCount++;
361 
362  return (PVOID)Field;
363 }
364 
365 
366 static
369  PINFCACHESECTION Section,
370  PCSTR Key)
371 {
373 
374  Line = Section->FirstLine;
375  while (Line != NULL)
376  {
377  if ((Line->Key != NULL) && (_stricmp(Line->Key, Key) == 0))
378  {
379  return Line;
380  }
381 
382  Line = Line->Next;
383  }
384 
385  return NULL;
386 }
387 
388 
389 /* push the current state on the parser stack */
390 __inline static void push_state(struct parser *parser, enum parser_state state)
391 {
392 // assert(parser->stack_pos < sizeof(parser->stack)/sizeof(parser->stack[0]));
394 }
395 
396 
397 /* pop the current state */
398 __inline static void pop_state(struct parser *parser)
399 {
400 // assert( parser->stack_pos );
402 }
403 
404 
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)
407 {
408  enum parser_state ret = parser->state;
409  parser->state = state;
410  return ret;
411 }
412 
413 
414 /* check if the pointer points to an end of file */
415 __inline static int is_eof(struct parser *parser, const CHAR *ptr)
416 {
417  return (ptr >= parser->end || *ptr == CONTROL_Z);
418 }
419 
420 
421 /* check if the pointer points to an end of line */
422 __inline static int is_eol(struct parser *parser, const CHAR *ptr)
423 {
424  return ((ptr >= parser->end) ||
425  (*ptr == CONTROL_Z) ||
426  (*ptr == '\n') ||
427  ((*ptr == '\r') && (*(ptr + 1) == '\n')));
428 }
429 
430 
431 /* push data from current token start up to pos into the current token */
432 static
433 int
435  struct parser *parser,
436  const CHAR *pos)
437 {
438  SIZE_T len = pos - parser->start;
439  const CHAR *src = parser->start;
441 
444 
445  parser->token_len += (ULONG)len;
446  for ( ; len > 0; len--, dst++, src++)
447  *dst = *src ? (CHAR)*src : L' ';
448  *dst = 0;
449  parser->start = pos;
450 
451  return 0;
452 }
453 
454 
455 /* add a section with the current token as name */
456 static
457 PVOID
459 {
460  PINFCACHESECTION Section;
461 
463  {
464  parser->error = FALSE;
465  return NULL;
466  }
467 
469  if (Section == NULL)
470  {
471  /* need to create a new one */
473  if (Section == NULL)
474  {
475  parser->error = FALSE;
476  return NULL;
477  }
478  }
479 
480  parser->token_len = 0;
481  parser->cur_section = Section;
482 
483  return (PVOID)Section;
484 }
485 
486 
487 /* add a field containing the current token to the current line */
488 static
489 struct field*
491  struct parser *parser,
492  int is_key)
493 {
494  PVOID field;
495 
496  if (!parser->line) /* need to start a new line */
497  {
498  if (parser->cur_section == NULL) /* got a line before the first section */
499  {
501  return NULL;
502  }
503 
505  if (parser->line == NULL)
506  goto error;
507  }
508  else
509  {
510 // assert(!is_key);
511  }
512 
513  if (is_key)
514  {
516  }
517  else
518  {
520  }
521 
522  if (field != NULL)
523  {
524  parser->token_len = 0;
525  return field;
526  }
527 
528 error:
529  parser->error = FALSE;
530  return NULL;
531 }
532 
533 
534 /* close the current line and prepare for parsing a new one */
535 static
536 VOID
538 {
539  parser->line = NULL;
540 }
541 
542 
543 /* handler for parser LINE_START state */
544 static
545 const CHAR*
547  struct parser *parser,
548  const CHAR *pos)
549 {
550  const CHAR *p;
551 
552  for (p = pos; !is_eof(parser, p); p++)
553  {
554  switch(*p)
555  {
556  case '\r':
557  continue;
558 
559  case '\n':
560  parser->line_pos++;
562  break;
563 
564  case ';':
567  return p + 1;
568 
569  case '[':
570  parser->start = p + 1;
572  return p + 1;
573 
574  default:
575  if (!isspace((unsigned char)*p))
576  {
577  parser->start = p;
579  return p;
580  }
581  break;
582  }
583  }
585  return NULL;
586 }
587 
588 
589 /* handler for parser SECTION_NAME state */
590 static
591 const CHAR*
593  struct parser *parser,
594  const CHAR *pos)
595 {
596  const CHAR *p;
597 
598  for (p = pos; !is_eol(parser, p); p++)
599  {
600  if (*p == ']')
601  {
602  push_token(parser, p);
604  return NULL;
606  set_state(parser, COMMENT); /* ignore everything else on the line */
607  return p + 1;
608  }
609  }
610  parser->error = STATUS_BAD_SECTION_NAME_LINE; /* unfinished section name */
611  return NULL;
612 }
613 
614 
615 /* handler for parser KEY_NAME state */
616 static
617 const CHAR*
619  struct parser *parser,
620  const CHAR *pos)
621 {
622  const CHAR *p, *token_end = parser->start;
623 
624  for (p = pos; !is_eol(parser, p); p++)
625  {
626  if (*p == ',') break;
627  switch(*p)
628  {
629 
630  case '=':
631  push_token(parser, token_end);
632  if (!add_field_from_token(parser, 1)) return NULL;
633  parser->start = p + 1;
636  return p + 1;
637  case ';':
638  push_token(parser, token_end);
639  if (!add_field_from_token(parser, 0)) return NULL;
642  return p + 1;
643  case '"':
644  push_token(parser, token_end);
645  parser->start = p + 1;
648  return p + 1;
649  case '\\':
650  push_token(parser, token_end);
651  parser->start = p;
654  return p;
655  default:
656  if (!isspace((unsigned char)*p)) token_end = p + 1;
657  else
658  {
659  push_token(parser, p);
662  return p;
663  }
664  break;
665  }
666  }
667  push_token(parser, token_end);
669  return p;
670 }
671 
672 
673 /* handler for parser VALUE_NAME state */
674 static
675 const CHAR*
677  struct parser *parser,
678  const CHAR *pos)
679 {
680  const CHAR *p, *token_end = parser->start;
681 
682  for (p = pos; !is_eol(parser, p); p++)
683  {
684  switch(*p)
685  {
686  case ';':
687  push_token(parser, token_end);
688  if (!add_field_from_token(parser, 0)) return NULL;
691  return p + 1;
692  case ',':
693  push_token(parser, token_end);
694  if (!add_field_from_token(parser, 0)) return NULL;
695  parser->start = p + 1;
698  return p + 1;
699  case '"':
700  push_token(parser, token_end);
701  parser->start = p + 1;
704  return p + 1;
705  case '\\':
706  push_token(parser, token_end);
707  parser->start = p;
710  return p;
711  default:
712  if (!isspace((unsigned char)*p)) token_end = p + 1;
713  else
714  {
715  push_token(parser, p);
718  return p;
719  }
720  break;
721  }
722  }
723  push_token(parser, token_end);
724  if (!add_field_from_token(parser, 0)) return NULL;
726  return p;
727 }
728 
729 
730 /* handler for parser EOL_BACKSLASH state */
731 static
732 const CHAR*
734  struct parser *parser,
735  const CHAR *pos )
736 {
737  const CHAR *p;
738 
739  for (p = pos; !is_eof(parser, p); p++)
740  {
741  switch(*p)
742  {
743  case '\r':
744  continue;
745 
746  case '\n':
747  parser->line_pos++;
748  parser->start = p + 1;
750  return p + 1;
751 
752  case '\\':
753  continue;
754 
755  case ';':
758  return p + 1;
759 
760  default:
761  if (isspace((unsigned char)*p))
762  continue;
763  push_token(parser, p);
764  pop_state(parser);
765  return p;
766  }
767  }
768  parser->start = p;
769  pop_state(parser);
770 
771  return p;
772 }
773 
774 
775 /* handler for parser QUOTES state */
776 static
777 const CHAR*
779  struct parser *parser,
780  const CHAR *pos )
781 {
782  const CHAR *p, *token_end = parser->start;
783 
784  for (p = pos; !is_eol(parser, p); p++)
785  {
786  if (*p == '"')
787  {
788  if (p + 1 < parser->end && p[1] == '"') /* double quotes */
789  {
790  push_token(parser, p + 1);
791  parser->start = token_end = p + 2;
792  p++;
793  }
794  else /* end of quotes */
795  {
796  push_token(parser, p);
797  parser->start = p + 1;
798  pop_state(parser);
799  return p + 1;
800  }
801  }
802  }
803  push_token(parser, p);
804  pop_state(parser);
805  return p;
806 }
807 
808 
809 /* handler for parser LEADING_SPACES state */
810 static
811 const CHAR*
813  struct parser *parser,
814  const CHAR *pos )
815 {
816  const CHAR *p;
817 
818  for (p = pos; !is_eol(parser, p); p++)
819  {
820  if (*p == '\\')
821  {
822  parser->start = p;
824  return p;
825  }
826  if (!isspace((unsigned char)*p))
827  break;
828  }
829  parser->start = p;
830  pop_state(parser);
831  return p;
832 }
833 
834 
835 /* handler for parser TRAILING_SPACES state */
836 static
837 const CHAR*
839  struct parser *parser,
840  const CHAR *pos )
841 {
842  const CHAR *p;
843 
844  for (p = pos; !is_eol(parser, p); p++)
845  {
846  if (*p == '\\')
847  {
849  return p;
850  }
851  if (!isspace((unsigned char)*p))
852  break;
853  }
854  pop_state(parser);
855  return p;
856 }
857 
858 
859 /* handler for parser COMMENT state */
860 static
861 const CHAR*
863  struct parser *parser,
864  const CHAR *pos )
865 {
866  const CHAR *p = pos;
867 
868  while (!is_eol(parser, p))
869  p++;
870  pop_state(parser);
871  return p;
872 }
873 
874 
875 /* parse a complete buffer */
876 static
877 BOOLEAN
879  PINFCACHE file,
880  PCCHAR buffer,
881  PCCHAR end,
882  PULONG error_line)
883 {
884  struct parser parser;
885  const CHAR* pos = buffer;
886 
887  parser.start = buffer;
888  parser.end = end;
889  parser.file = file;
890  parser.line = NULL;
892  parser.stack_pos = 0;
894  parser.line_pos = 1;
895  parser.error = TRUE;
896  parser.token_len = 0;
897 
898  /* parser main loop */
899  while (pos)
901 
902  if (parser.error)
903  {
904  if (error_line)
905  *error_line = parser.line_pos;
906  return parser.error;
907  }
908 
909  /* find the [strings] section */
910  file->StringsSection = InfpCacheFindSection(file, "Strings");
911 
912  return TRUE;
913 }
914 
915 /* PUBLIC FUNCTIONS *********************************************************/
916 
917 BOOLEAN
919  PHINF InfHandle,
920  PCSTR FileName,
921  PULONG ErrorLine)
922 {
924  ULONG FileId;
925  PCHAR FileBuffer;
930 
931  *InfHandle = NULL;
932  *ErrorLine = (ULONG) - 1;
933 
934  //
935  // Open the .inf file
936  //
937  Status = ArcOpen((PSTR)FileName, OpenReadOnly, &FileId);
938  if (Status != ESUCCESS)
939  {
940  return FALSE;
941  }
942 
943  //
944  // Query file size
945  //
947  if ((Status != ESUCCESS) || (Information.EndingAddress.HighPart != 0))
948  {
949  ArcClose(FileId);
950  return FALSE;
951  }
952  FileSize = Information.EndingAddress.LowPart;
953 
954  //
955  // Allocate buffer to cache the file
956  //
957  FileBuffer = FrLdrTempAlloc(FileSize + 1, TAG_INF_FILE);
958  if (!FileBuffer)
959  {
960  ArcClose(FileId);
961  return FALSE;
962  }
963 
964  //
965  // Read file into memory
966  //
967  Status = ArcRead(FileId, FileBuffer, FileSize, &Count);
968  if ((Status != ESUCCESS) || (Count != FileSize))
969  {
970  ArcClose(FileId);
971  FrLdrTempFree(FileBuffer, TAG_INF_FILE);
972  return FALSE;
973  }
974 
975  //
976  // We don't need the file anymore. Close it
977  //
978  ArcClose(FileId);
979 
980  //
981  // Append string terminator
982  //
983  FileBuffer[FileSize] = 0;
984 
985  //
986  // Allocate infcache header
987  //
989  if (!Cache)
990  {
991  FrLdrTempFree(FileBuffer, TAG_INF_FILE);
992  return FALSE;
993  }
994 
995  //
996  // Initialize inicache header
997  //
998  RtlZeroMemory(Cache, sizeof(INFCACHE));
999 
1000  //
1001  // Parse the inf buffer
1002  //
1004  FileBuffer,
1005  FileBuffer + FileSize,
1006  ErrorLine);
1007  if (!Success)
1008  {
1010  Cache = NULL;
1011  }
1012 
1013  //
1014  // Free file buffer, as it has been parsed
1015  //
1016  FrLdrTempFree(FileBuffer, TAG_INF_FILE);
1017 
1018  //
1019  // Return .inf parsed contents
1020  //
1021  *InfHandle = (HINF)Cache;
1022 
1023  return Success;
1024 }
1025 
1026 
1027 VOID
1028 InfCloseFile(HINF InfHandle)
1029 {
1030  PINFCACHE Cache;
1031 
1032  Cache = (PINFCACHE)InfHandle;
1033 
1034  if (Cache == NULL)
1035  {
1036  return;
1037  }
1038 
1039  while (Cache->FirstSection != NULL)
1040  {
1041  Cache->FirstSection = InfpCacheFreeSection(Cache->FirstSection);
1042  }
1043  Cache->LastSection = NULL;
1044 
1046 }
1047 
1048 
1049 BOOLEAN
1051  HINF InfHandle,
1052  PCSTR Section,
1053  PCSTR Key,
1055 {
1056  PINFCACHE Cache;
1057  PINFCACHESECTION CacheSection;
1058  PINFCACHELINE CacheLine;
1059 
1060  if ((InfHandle == NULL) || (Section == NULL) || (Context == NULL))
1061  {
1062 // DPRINT("Invalid parameter\n");
1063  return FALSE;
1064  }
1065 
1066  Cache = (PINFCACHE)InfHandle;
1067 
1068  /* Iterate through list of sections */
1069  CacheSection = Cache->FirstSection;
1070  while (CacheSection != NULL)
1071  {
1072 // DPRINT("Comparing '%s' and '%s'\n", CacheSection->Name, Section);
1073 
1074  /* Are the section names the same? */
1075  if (_stricmp(CacheSection->Name, Section) == 0)
1076  {
1077  if (Key != NULL)
1078  {
1079  CacheLine = InfpCacheFindKeyLine(CacheSection, Key);
1080  }
1081  else
1082  {
1083  CacheLine = CacheSection->FirstLine;
1084  }
1085 
1086  if (CacheLine == NULL)
1087  return FALSE;
1088 
1089  Context->Inf = (PVOID)Cache;
1090  Context->Section = (PVOID)CacheSection;
1091  Context->Line = (PVOID)CacheLine;
1092 
1093  return TRUE;
1094  }
1095 
1096  /* Get the next section */
1097  CacheSection = CacheSection->Next;
1098  }
1099 
1100 // DPRINT("Section not found\n");
1101 
1102  return FALSE;
1103 }
1104 
1105 
1106 BOOLEAN
1108  PINFCONTEXT ContextIn,
1109  PINFCONTEXT ContextOut)
1110 {
1111  PINFCACHELINE CacheLine;
1112 
1113  if ((ContextIn == NULL) || (ContextOut == NULL))
1114  return FALSE;
1115 
1116  if (ContextIn->Line == NULL)
1117  return FALSE;
1118 
1119  CacheLine = (PINFCACHELINE)ContextIn->Line;
1120  if (CacheLine->Next == NULL)
1121  return FALSE;
1122 
1123  if (ContextIn != ContextOut)
1124  {
1125  ContextOut->Inf = ContextIn->Inf;
1126  ContextOut->Section = ContextIn->Section;
1127  }
1128  ContextOut->Line = (PVOID)(CacheLine->Next);
1129 
1130  return TRUE;
1131 }
1132 
1133 
1134 BOOLEAN
1136  PINFCONTEXT ContextIn,
1137  PCHAR Key,
1138  PINFCONTEXT ContextOut)
1139 {
1140  PINFCACHELINE CacheLine;
1141 
1142  if ((ContextIn == NULL) || (ContextOut == NULL) || (Key == NULL) || (*Key == 0))
1143  return FALSE;
1144 
1145  if (ContextIn->Inf == NULL || ContextIn->Section == NULL)
1146  return FALSE;
1147 
1148  CacheLine = ((PINFCACHESECTION)(ContextIn->Section))->FirstLine;
1149  while (CacheLine != NULL)
1150  {
1151  if ((CacheLine->Key != NULL) && (_stricmp(CacheLine->Key, Key) == 0))
1152  {
1153 
1154  if (ContextIn != ContextOut)
1155  {
1156  ContextOut->Inf = ContextIn->Inf;
1157  ContextOut->Section = ContextIn->Section;
1158  }
1159  ContextOut->Line = (PVOID)CacheLine;
1160 
1161  return TRUE;
1162  }
1163 
1164  CacheLine = CacheLine->Next;
1165  }
1166 
1167  return FALSE;
1168 }
1169 
1170 
1171 BOOLEAN
1173  PINFCONTEXT ContextIn,
1174  PCHAR Key,
1175  PINFCONTEXT ContextOut)
1176 {
1177  PINFCACHELINE CacheLine;
1178 
1179  if ((ContextIn == NULL) || (ContextOut == NULL) || (Key == NULL) || (*Key == 0))
1180  return FALSE;
1181 
1182  if ((ContextIn->Inf == NULL) || (ContextIn->Section == NULL) || (ContextIn->Line == NULL))
1183  return FALSE;
1184 
1185  CacheLine = (PINFCACHELINE)ContextIn->Line;
1186  while (CacheLine != NULL)
1187  {
1188  if ((CacheLine->Key != NULL) && (_stricmp(CacheLine->Key, Key) == 0))
1189  {
1190 
1191  if (ContextIn != ContextOut)
1192  {
1193  ContextOut->Inf = ContextIn->Inf;
1194  ContextOut->Section = ContextIn->Section;
1195  }
1196  ContextOut->Line = (PVOID)CacheLine;
1197 
1198  return TRUE;
1199  }
1200 
1201  CacheLine = CacheLine->Next;
1202  }
1203 
1204  return FALSE;
1205 }
1206 
1207 
1208 LONG
1210  HINF InfHandle,
1211  PCHAR Section)
1212 {
1213  PINFCACHE Cache;
1214  PINFCACHESECTION CacheSection;
1215 
1216  if ((InfHandle == NULL) || (Section == NULL))
1217  {
1218 // DPRINT("Invalid parameter\n");
1219  return -1;
1220  }
1221 
1222  Cache = (PINFCACHE)InfHandle;
1223 
1224  /* Iterate through list of sections */
1225  CacheSection = Cache->FirstSection;
1226  while (CacheSection != NULL)
1227  {
1228 // DPRINT("Comparing '%s' and '%s'\n", CacheSection->Name, Section);
1229 
1230  /* Are the section names the same? */
1231  if (_stricmp(CacheSection->Name, Section) == 0)
1232  {
1233  return CacheSection->LineCount;
1234  }
1235 
1236  /* Get the next section */
1237  CacheSection = CacheSection->Next;
1238  }
1239 
1240 // DPRINT("Section not found\n");
1241 
1242  return -1;
1243 }
1244 
1245 
1246 /* InfGetLineText */
1247 
1248 
1249 LONG
1251 {
1252  if ((Context == NULL) || (Context->Line == NULL))
1253  return 0;
1254 
1255  return ((PINFCACHELINE)Context->Line)->FieldCount;
1256 }
1257 
1258 
1259 BOOLEAN
1262  ULONG FieldIndex,
1263  PUCHAR ReturnBuffer,
1266 {
1267  PINFCACHELINE CacheLine;
1268  PINFCACHEFIELD CacheField;
1269  ULONG Index;
1270  ULONG Size;
1271  PUCHAR Ptr;
1272 
1273  if ((Context == NULL) || (Context->Line == NULL) || (FieldIndex == 0))
1274  {
1275 // DPRINT("Invalid parameter\n");
1276  return FALSE;
1277  }
1278 
1279  if (RequiredSize != NULL)
1280  *RequiredSize = 0;
1281 
1282  CacheLine = (PINFCACHELINE)Context->Line;
1283 
1284  if (FieldIndex > CacheLine->FieldCount)
1285  return FALSE;
1286 
1287  CacheField = CacheLine->FirstField;
1288  for (Index = 1; Index < FieldIndex; Index++)
1289  CacheField = CacheField->Next;
1290 
1291  Size = CacheLine->FieldCount - FieldIndex + 1;
1292 
1293  if (RequiredSize != NULL)
1294  *RequiredSize = Size;
1295 
1296  if (ReturnBuffer != NULL)
1297  {
1298  if (ReturnBufferSize < Size)
1299  return FALSE;
1300 
1301  /* Copy binary data */
1302  Ptr = ReturnBuffer;
1303  while (CacheField != NULL)
1304  {
1305  *Ptr = (UCHAR)atoi(CacheField->Data); //strtoul(CacheField->Data, NULL, 16);
1306 
1307  Ptr++;
1308  CacheField = CacheField->Next;
1309  }
1310  }
1311 
1312  return TRUE;
1313 }
1314 
1315 
1316 BOOLEAN
1319  ULONG FieldIndex,
1320  PLONG IntegerValue)
1321 {
1322  PINFCACHELINE CacheLine;
1323  PINFCACHEFIELD CacheField;
1324  ULONG Index;
1325  PCHAR Ptr;
1326 
1327  if ((Context == NULL) || (Context->Line == NULL) || (IntegerValue == NULL))
1328  {
1329 // DPRINT("Invalid parameter\n");
1330  return FALSE;
1331  }
1332 
1333  CacheLine = (PINFCACHELINE)Context->Line;
1334 
1335  if (FieldIndex > CacheLine->FieldCount)
1336  {
1337 // DPRINT("Invalid parameter\n");
1338  return FALSE;
1339  }
1340 
1341  if (FieldIndex == 0)
1342  {
1343  Ptr = CacheLine->Key;
1344  }
1345  else
1346  {
1347  CacheField = CacheLine->FirstField;
1348  for (Index = 1; Index < FieldIndex; Index++)
1349  CacheField = CacheField->Next;
1350 
1351  Ptr = CacheField->Data;
1352  }
1353 
1354  *IntegerValue = atoi(Ptr); //strtol(Ptr, NULL, 0);
1355 
1356  return TRUE;
1357 }
1358 
1359 
1360 BOOLEAN
1363  ULONG FieldIndex,
1364  PCHAR ReturnBuffer,
1367 {
1368  PINFCACHELINE CacheLine;
1369  PINFCACHEFIELD CacheField;
1370  PINFCACHEFIELD FieldPtr;
1371  ULONG Index;
1372  SIZE_T Size;
1373  PCHAR Ptr;
1374 
1375  if ((Context == NULL) || (Context->Line == NULL) || (FieldIndex == 0))
1376  {
1377 // DPRINT("Invalid parameter\n");
1378  return FALSE;
1379  }
1380 
1381  if (RequiredSize != NULL)
1382  *RequiredSize = 0;
1383 
1384  CacheLine = (PINFCACHELINE)Context->Line;
1385 
1386  if (FieldIndex > CacheLine->FieldCount)
1387  return FALSE;
1388 
1389  CacheField = CacheLine->FirstField;
1390  for (Index = 1; Index < FieldIndex; Index++)
1391  CacheField = CacheField->Next;
1392 
1393  /* Calculate the required buffer size */
1394  FieldPtr = CacheField;
1395  Size = 0;
1396  while (FieldPtr != NULL)
1397  {
1398  Size += (strlen(FieldPtr->Data) + 1);
1399  FieldPtr = FieldPtr->Next;
1400  }
1401  Size++;
1402 
1403  if (RequiredSize != NULL)
1404  *RequiredSize = (ULONG)Size;
1405 
1406  if (ReturnBuffer != NULL)
1407  {
1408  if (ReturnBufferSize < Size)
1409  return FALSE;
1410 
1411  /* Copy multi-sz string */
1412  Ptr = ReturnBuffer;
1413  FieldPtr = CacheField;
1414  while (FieldPtr != NULL)
1415  {
1416  Size = strlen(FieldPtr->Data) + 1;
1417 
1418  strcpy(Ptr, FieldPtr->Data);
1419 
1420  Ptr = Ptr + Size;
1421  FieldPtr = FieldPtr->Next;
1422  }
1423  *Ptr = 0;
1424  }
1425 
1426  return TRUE;
1427 }
1428 
1429 
1430 BOOLEAN
1433  ULONG FieldIndex,
1434  PCHAR ReturnBuffer,
1437 {
1438  PINFCACHELINE CacheLine;
1439  PINFCACHEFIELD CacheField;
1440  ULONG Index;
1441  PCHAR Ptr;
1442  SIZE_T Size;
1443 
1444  if ((Context == NULL) || (Context->Line == NULL))
1445  {
1446 // DPRINT("Invalid parameter\n");
1447  return FALSE;
1448  }
1449 
1450  if (RequiredSize != NULL)
1451  *RequiredSize = 0;
1452 
1453  CacheLine = (PINFCACHELINE)Context->Line;
1454 
1455  if (FieldIndex > CacheLine->FieldCount)
1456  return FALSE;
1457 
1458  if (FieldIndex == 0)
1459  {
1460  Ptr = CacheLine->Key;
1461  }
1462  else
1463  {
1464  CacheField = CacheLine->FirstField;
1465  for (Index = 1; Index < FieldIndex; Index++)
1466  CacheField = CacheField->Next;
1467 
1468  Ptr = CacheField->Data;
1469  }
1470 
1471  Size = strlen(Ptr) + 1;
1472 
1473  if (RequiredSize != NULL)
1474  *RequiredSize = (ULONG)Size;
1475 
1476  if (ReturnBuffer != NULL)
1477  {
1478  if (ReturnBufferSize < Size)
1479  return FALSE;
1480 
1481  strcpy(ReturnBuffer, Ptr);
1482  }
1483 
1484  return TRUE;
1485 }
1486 
1487 
1488 
1489 
1490 BOOLEAN
1493  PCHAR *Key,
1494  PCHAR *Data)
1495 {
1496  PINFCACHELINE CacheKey;
1497 
1498  if ((Context == NULL) || (Context->Line == NULL) || (Data == NULL))
1499  {
1500 // DPRINT("Invalid parameter\n");
1501  return FALSE;
1502  }
1503 
1504  CacheKey = (PINFCACHELINE)Context->Line;
1505  if (Key != NULL)
1506  *Key = CacheKey->Key;
1507 
1508  if (Data != NULL)
1509  {
1510  if (CacheKey->FirstField == NULL)
1511  {
1512  *Data = NULL;
1513  }
1514  else
1515  {
1516  *Data = CacheKey->FirstField->Data;
1517  }
1518  }
1519 
1520  return TRUE;
1521 }
1522 
1523 
1524 BOOLEAN
1527  ULONG FieldIndex,
1528  PCSTR *Data)
1529 {
1530  PINFCACHELINE CacheLine;
1531  PINFCACHEFIELD CacheField;
1532  ULONG Index;
1533 
1534  if ((Context == NULL) || (Context->Line == NULL) || (Data == NULL))
1535  {
1536 // DPRINT("Invalid parameter\n");
1537  return FALSE;
1538  }
1539 
1540  CacheLine = (PINFCACHELINE)Context->Line;
1541 
1542  if (FieldIndex > CacheLine->FieldCount)
1543  return FALSE;
1544 
1545  if (FieldIndex == 0)
1546  {
1547  *Data = CacheLine->Key;
1548  }
1549  else
1550  {
1551  CacheField = CacheLine->FirstField;
1552  for (Index = 1; Index < FieldIndex; Index++)
1553  CacheField = CacheField->Next;
1554 
1555  *Data = CacheField->Data;
1556  }
1557 
1558  return TRUE;
1559 }
1560 
1561 
1562 /* EOF */
LONG LineCount
Definition: inffile.c:57
signed char * PCHAR
Definition: retypes.h:7
int stack_pos
Definition: inffile.c:92
#define TAG_INF_SECTION
Definition: inffile.c:23
#define isspace(c)
Definition: acclib.h:69
const CHAR *(* parser_state_func)(struct parser *parser, const CHAR *pos)
Definition: inffile.c:102
const CHAR * start
Definition: inffile.c:87
#define TAG_INF_CACHE
Definition: inffile.c:24
CHAR Name[1]
Definition: inffile.c:59
#define TRUE
Definition: types.h:120
LONG InfGetLineCount(HINF InfHandle, PCHAR Section)
Definition: inffile.c:1209
struct _INFCACHEFIELD * Prev
Definition: inffile.c:30
struct _INFCACHESECTION * PINFCACHESECTION
BOOLEAN InfFindFirstMatchLine(PINFCONTEXT ContextIn, PCHAR Key, PINFCONTEXT ContextOut)
Definition: inffile.c:1135
#define error(str)
Definition: mkdosfs.c:1605
Definition: arc.h:32
Definition: fatfs.h:173
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
struct _INFCACHELINE * PINFCACHELINE
#define STATUS_BAD_SECTION_NAME_LINE
Definition: inffile.h:11
static PINFCACHESECTION InfpCacheAddSection(PINFCACHE Cache, PCHAR Name)
Definition: inffile.c:226
struct _INFCACHEFIELD * Next
Definition: inffile.c:29
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
enum parser_state state
Definition: import.c:100
ULONG FieldCount
Definition: inffile.c:40
static PINFCACHELINE InfpCacheFreeLine(PINFCACHELINE Line)
Definition: inffile.c:135
static PINFCACHELINE InfpCacheAddLine(PINFCACHESECTION Section)
Definition: inffile.c:271
#define TAG_INF_LINE
Definition: inffile.c:22
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
_In_ DWORD _In_ DWORD ReturnBufferSize
Definition: setupapi.h:1892
GLuint buffer
Definition: glext.h:5915
ULONG ARC_STATUS
Definition: arc.h:4
GLuint GLuint end
Definition: gl.h:1545
PVOID HINF
Definition: infsupp.h:21
static __inline enum parser_state set_state(struct parser *parser, enum parser_state state)
Definition: inffile.c:406
static const CHAR * trailing_spaces_state(struct parser *parser, const CHAR *pos)
Definition: inffile.c:838
static PINFCACHESECTION InfpCacheFindSection(PINFCACHE Cache, PCSTR Name)
Definition: inffile.c:196
#define _stricmp
Definition: cat.c:22
struct _INFCACHEFIELD * PINFCACHEFIELD
PINFCACHESECTION LastSection
Definition: inffile.c:65
static const CHAR * key_name_state(struct parser *parser, const CHAR *pos)
Definition: inffile.c:618
VOID InfCloseFile(HINF InfHandle)
Definition: inffile.c:1028
struct _INFCACHESECTION * Next
Definition: inffile.c:51
BOOLEAN InfGetIntField(PINFCONTEXT Context, ULONG FieldIndex, PLONG IntegerValue)
Definition: inffile.c:1317
static PVOID InfpAddFieldToLine(PINFCACHELINE Line, PCHAR Data)
Definition: inffile.c:331
static const CHAR * leading_spaces_state(struct parser *parser, const CHAR *pos)
Definition: inffile.c:812
#define MAX_FIELD_LEN
Definition: inffile.c:16
while(1)
Definition: macro.lex.yy.c:740
PINFCACHEFIELD FirstField
Definition: inffile.c:44
#define STATUS_WRONG_INF_STYLE
Definition: inffile.h:13
BOOLEAN InfFindNextMatchLine(PINFCONTEXT ContextIn, PCHAR Key, PINFCONTEXT ContextOut)
Definition: inffile.c:1172
PULONG * PHINF
Definition: inffile.h:18
struct _INFCACHELINE * Prev
Definition: inffile.c:38
long LONG
Definition: pedump.c:60
BOOLEAN InfGetMultiSzField(PINFCONTEXT Context, ULONG FieldIndex, PCHAR ReturnBuffer, ULONG ReturnBufferSize, PULONG RequiredSize)
Definition: inffile.c:1361
PINFCACHELINE line
Definition: inffile.c:95
static PVOID ptr
Definition: dispmode.c:27
static VOID close_current_line(struct parser *parser)
Definition: inffile.c:537
FORCEINLINE PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: mm.h:177
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
static const CHAR * value_name_state(struct parser *parser, const CHAR *pos)
Definition: inffile.c:676
BOOLEAN InfGetData(PINFCONTEXT Context, PCHAR *Key, PCHAR *Data)
Definition: inffile.c:1491
void * PVOID
Definition: retypes.h:9
struct _INFCACHEFIELD INFCACHEFIELD
_Inout_ PRTL_BUFFER _In_ SIZE_T RequiredSize
static const CHAR * comment_state(struct parser *parser, const CHAR *pos)
Definition: inffile.c:862
BOOLEAN InfGetStringField(PINFCONTEXT Context, ULONG FieldIndex, PCHAR ReturnBuffer, ULONG ReturnBufferSize, PULONG RequiredSize)
Definition: inffile.c:1431
Definition: _stack.h:47
static const CHAR * section_name_state(struct parser *parser, const CHAR *pos)
Definition: inffile.c:592
struct _INFCACHESECTION * Prev
Definition: inffile.c:52
struct _INFCACHESECTION INFCACHESECTION
if(!(yy_init))
Definition: macro.lex.yy.c:714
PINFCACHEFIELD LastField
Definition: inffile.c:45
Definition: parser.c:43
BOOLEAN InfFindNextLine(PINFCONTEXT ContextIn, PINFCONTEXT ContextOut)
Definition: inffile.c:1107
_In_ DWORD FieldIndex
Definition: setupapi.h:1890
struct _INFCACHE * PINFCACHE
static struct field * add_field_from_token(struct parser *parser, int is_key)
Definition: inffile.c:490
const char file[]
Definition: icontest.c:11
static const UCHAR Index[8]
Definition: usbohci.c:18
#define MAX_SECTION_NAME_LEN
Definition: inffile.c:15
unsigned int token_len
Definition: inffile.c:98
struct _INFCACHELINE INFCACHELINE
unsigned int error
Definition: inffile.c:97
PINFCACHE file
Definition: inffile.c:89
static __inline void push_state(struct parser *parser, enum parser_state state)
Definition: inffile.c:390
enum parser_state stack[4]
Definition: inffile.c:91
Definition: ncftp.h:79
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:236
unsigned char UCHAR
Definition: xmlstorage.h:181
int ret
static __inline int is_eol(struct parser *parser, const CHAR *ptr)
Definition: inffile.c:422
static const WCHAR L[]
Definition: oid.c:1250
CHAR Data[1]
Definition: inffile.c:32
static int state
Definition: maze.c:121
#define TAG_INF_FIELD
Definition: inffile.c:21
GLenum GLsizei len
Definition: glext.h:6722
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
GLenum src
Definition: glext.h:6340
PINFCACHESECTION cur_section
Definition: inffile.c:94
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
Status
Definition: gdiplustypes.h:24
const CHAR * end
Definition: inffile.c:88
PINFCACHELINE FirstLine
Definition: inffile.c:54
Definition: inffile.c:78
ULONG_PTR SIZE_T
Definition: typedefs.h:78
static int push_token(struct parser *parser, const CHAR *pos)
Definition: inffile.c:434
struct _INFCACHE INFCACHE
parser_state
Definition: import.c:64
CHAR token[MAX_FIELD_LEN+1]
Definition: inffile.c:99
static __inline int is_eof(struct parser *parser, const CHAR *ptr)
Definition: inffile.c:415
signed char * PSTR
Definition: retypes.h:7
GLenum GLenum dst
Definition: glext.h:6340
UINT Section
Definition: infsupp.h:26
static __inline void pop_state(struct parser *parser)
Definition: inffile.c:398
unsigned int * PULONG
Definition: retypes.h:1
PINFCACHESECTION FirstSection
Definition: inffile.c:64
ARC_STATUS ArcClose(ULONG FileId)
Definition: fs.c:218
PINFCACHESECTION StringsSection
Definition: inffile.c:67
struct _INFCACHELINE * Next
Definition: inffile.c:37
Definition: import.c:86
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
ARC_STATUS ArcGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: fs.c:250
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
ARC_STATUS ArcOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: fs.c:56
PINFCACHELINE LastLine
Definition: inffile.c:55
static PVOID InfpAddKeyToLine(PINFCACHELINE Line, PCHAR Key)
Definition: inffile.c:309
BOOLEAN InfFindFirstLine(HINF InfHandle, PCSTR Section, PCSTR Key, PINFCONTEXT Context)
Definition: inffile.c:1050
unsigned int ULONG
Definition: retypes.h:1
static const parser_state_func parser_funcs[NB_PARSER_STATES]
Definition: inffile.c:117
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
HINF Inf
Definition: infsupp.h:24
static const CHAR * quotes_state(struct parser *parser, const CHAR *pos)
Definition: inffile.c:778
const char * PCSTR
Definition: typedefs.h:51
static const CHAR * line_start_state(struct parser *parser, const CHAR *pos)
Definition: inffile.c:546
GLfloat GLfloat p
Definition: glext.h:8902
#define TAG_INF_KEY
Definition: inffile.c:20
#define CONTROL_Z
Definition: inffile.c:14
static PINFCACHELINE InfpCacheFindKeyLine(PINFCACHESECTION Section, PCSTR Key)
Definition: inffile.c:368
BOOLEAN InfGetBinaryField(PINFCONTEXT Context, ULONG FieldIndex, PUCHAR ReturnBuffer, ULONG ReturnBufferSize, PULONG RequiredSize)
Definition: inffile.c:1260
unsigned int line_pos
Definition: inffile.c:96
static const CHAR * eol_backslash_state(struct parser *parser, const CHAR *pos)
Definition: inffile.c:733
#define memset(x, y, z)
Definition: compat.h:39
signed int * PLONG
Definition: retypes.h:5
LONG InfGetFieldCount(PINFCONTEXT Context)
Definition: inffile.c:1250
BOOLEAN InfGetDataField(PINFCONTEXT Context, ULONG FieldIndex, PCSTR *Data)
Definition: inffile.c:1525
static BOOLEAN InfpParseBuffer(PINFCACHE file, PCCHAR buffer, PCCHAR end, PULONG error_line)
Definition: inffile.c:878
UINT Line
Definition: infsupp.h:27
PCHAR Key
Definition: inffile.c:42
struct Line Line
BOOLEAN InfOpenFile(PHINF InfHandle, PCSTR FileName, PULONG ErrorLine)
Definition: inffile.c:918
Iosb Information
Definition: create.c:4377
#define TAG_INF_FILE
Definition: inffile.c:25
static PINFCACHESECTION InfpCacheFreeSection(PINFCACHESECTION Section)
Definition: inffile.c:170
static PVOID add_section_from_token(struct parser *parser)
Definition: inffile.c:458
Definition: fci.c:126
FORCEINLINE VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: mm.h:186