Sync to trunk r38250
[reactos.git] / reactos / lib / inflib / infget.c
1 /*
2 * PROJECT: .inf file parser
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PROGRAMMER: Royce Mitchell III
5 * Eric Kohl
6 * Ge van Geldorp <gvg@reactos.org>
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include "inflib.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16
17 INFSTATUS
18 InfpFindFirstLine(PINFCACHE Cache,
19 PCTSTR Section,
20 PCTSTR Key,
21 PINFCONTEXT *Context)
22 {
23 PINFCACHESECTION CacheSection;
24 PINFCACHELINE CacheLine;
25
26 if (Cache == NULL || Section == NULL || Context == NULL)
27 {
28 DPRINT1("Invalid parameter\n");
29 return INF_STATUS_INVALID_PARAMETER;
30 }
31
32 CacheSection = InfpFindSection(Cache, Section);
33 if (NULL == CacheSection)
34 {
35 DPRINT("Section not found\n");
36 return INF_STATUS_NOT_FOUND;
37 }
38
39 if (Key != NULL)
40 {
41 CacheLine = InfpFindKeyLine(CacheSection, Key);
42 }
43 else
44 {
45 CacheLine = CacheSection->FirstLine;
46 }
47
48 if (NULL == CacheLine)
49 {
50 DPRINT("Key not found\n");
51 return INF_STATUS_NOT_FOUND;
52 }
53
54 *Context = MALLOC(sizeof(INFCONTEXT));
55 if (NULL == *Context)
56 {
57 DPRINT1("MALLOC() failed\n");
58 return INF_STATUS_NO_MEMORY;
59 }
60 (*Context)->Inf = (PVOID)Cache;
61 (*Context)->Section = (PVOID)CacheSection;
62 (*Context)->Line = (PVOID)CacheLine;
63
64 return INF_STATUS_SUCCESS;
65 }
66
67
68 INFSTATUS
69 InfpFindNextLine(PINFCONTEXT ContextIn,
70 PINFCONTEXT ContextOut)
71 {
72 PINFCACHELINE CacheLine;
73
74 if (ContextIn == NULL || ContextOut == NULL)
75 return INF_STATUS_INVALID_PARAMETER;
76
77 if (ContextIn->Line == NULL)
78 return INF_STATUS_INVALID_PARAMETER;
79
80 CacheLine = (PINFCACHELINE)ContextIn->Line;
81 if (CacheLine->Next == NULL)
82 return INF_STATUS_NOT_FOUND;
83
84 if (ContextIn != ContextOut)
85 {
86 ContextOut->Inf = ContextIn->Inf;
87 ContextOut->Section = ContextIn->Section;
88 }
89 ContextOut->Line = (PVOID)(CacheLine->Next);
90
91 return INF_STATUS_SUCCESS;
92 }
93
94
95 INFSTATUS
96 InfpFindFirstMatchLine(PINFCONTEXT ContextIn,
97 PCTSTR Key,
98 PINFCONTEXT ContextOut)
99 {
100 PINFCACHELINE CacheLine;
101
102 if (ContextIn == NULL || ContextOut == NULL || Key == NULL || *Key == 0)
103 return INF_STATUS_INVALID_PARAMETER;
104
105 if (ContextIn->Inf == NULL || ContextIn->Section == NULL)
106 return INF_STATUS_INVALID_PARAMETER;
107
108 CacheLine = ((PINFCACHESECTION)(ContextIn->Section))->FirstLine;
109 while (CacheLine != NULL)
110 {
111 if (CacheLine->Key != NULL && _tcsicmp (CacheLine->Key, Key) == 0)
112 {
113
114 if (ContextIn != ContextOut)
115 {
116 ContextOut->Inf = ContextIn->Inf;
117 ContextOut->Section = ContextIn->Section;
118 }
119 ContextOut->Line = (PVOID)CacheLine;
120
121 return INF_STATUS_SUCCESS;
122 }
123
124 CacheLine = CacheLine->Next;
125 }
126
127 return INF_STATUS_NOT_FOUND;
128 }
129
130
131 INFSTATUS
132 InfpFindNextMatchLine(PINFCONTEXT ContextIn,
133 PCTSTR Key,
134 PINFCONTEXT ContextOut)
135 {
136 PINFCACHELINE CacheLine;
137
138 if (ContextIn == NULL || ContextOut == NULL || Key == NULL || *Key == 0)
139 return INF_STATUS_INVALID_PARAMETER;
140
141 if (ContextIn->Inf == NULL || ContextIn->Section == NULL || ContextIn->Line == NULL)
142 return INF_STATUS_INVALID_PARAMETER;
143
144 CacheLine = (PINFCACHELINE)ContextIn->Line;
145 while (CacheLine != NULL)
146 {
147 if (CacheLine->Key != NULL && _tcsicmp (CacheLine->Key, Key) == 0)
148 {
149
150 if (ContextIn != ContextOut)
151 {
152 ContextOut->Inf = ContextIn->Inf;
153 ContextOut->Section = ContextIn->Section;
154 }
155 ContextOut->Line = (PVOID)CacheLine;
156
157 return INF_STATUS_SUCCESS;
158 }
159
160 CacheLine = CacheLine->Next;
161 }
162
163 return INF_STATUS_NOT_FOUND;
164 }
165
166
167 LONG
168 InfpGetLineCount(HINF InfHandle,
169 PCTSTR Section)
170 {
171 PINFCACHE Cache;
172 PINFCACHESECTION CacheSection;
173
174 if (InfHandle == NULL || Section == NULL)
175 {
176 DPRINT("Invalid parameter\n");
177 return -1;
178 }
179
180 Cache = (PINFCACHE)InfHandle;
181
182 /* Iterate through list of sections */
183 CacheSection = Cache->FirstSection;
184 while (CacheSection != NULL)
185 {
186 /* Are the section names the same? */
187 if (_tcsicmp(CacheSection->Name, Section) == 0)
188 {
189 return CacheSection->LineCount;
190 }
191
192 /* Get the next section */
193 CacheSection = CacheSection->Next;
194 }
195
196 DPRINT("Section not found\n");
197
198 return -1;
199 }
200
201
202 /* InfpGetLineText */
203
204
205 LONG
206 InfpGetFieldCount(PINFCONTEXT Context)
207 {
208 if (Context == NULL || Context->Line == NULL)
209 return 0;
210
211 return ((PINFCACHELINE)Context->Line)->FieldCount;
212 }
213
214
215 INFSTATUS
216 InfpGetBinaryField(PINFCONTEXT Context,
217 ULONG FieldIndex,
218 PUCHAR ReturnBuffer,
219 ULONG ReturnBufferSize,
220 PULONG RequiredSize)
221 {
222 PINFCACHELINE CacheLine;
223 PINFCACHEFIELD CacheField;
224 ULONG Index;
225 ULONG Size;
226 PUCHAR Ptr;
227
228 if (Context == NULL || Context->Line == NULL || FieldIndex == 0)
229 {
230 DPRINT("Invalid parameter\n");
231 return INF_STATUS_INVALID_PARAMETER;
232 }
233
234 if (RequiredSize != NULL)
235 *RequiredSize = 0;
236
237 CacheLine = (PINFCACHELINE)Context->Line;
238
239 if (FieldIndex > (ULONG)CacheLine->FieldCount)
240 return INF_STATUS_NOT_FOUND;
241
242 CacheField = CacheLine->FirstField;
243 for (Index = 1; Index < FieldIndex; Index++)
244 CacheField = CacheField->Next;
245
246 Size = CacheLine->FieldCount - FieldIndex + 1;
247
248 if (RequiredSize != NULL)
249 *RequiredSize = Size;
250
251 if (ReturnBuffer != NULL)
252 {
253 if (ReturnBufferSize < Size)
254 return INF_STATUS_BUFFER_OVERFLOW;
255
256 /* Copy binary data */
257 Ptr = ReturnBuffer;
258 while (CacheField != NULL)
259 {
260 *Ptr = (UCHAR)_tcstoul (CacheField->Data, NULL, 16);
261
262 Ptr++;
263 CacheField = CacheField->Next;
264 }
265 }
266
267 return INF_STATUS_SUCCESS;
268 }
269
270
271 INFSTATUS
272 InfpGetIntField(PINFCONTEXT Context,
273 ULONG FieldIndex,
274 INT* IntegerValue)
275 {
276 PINFCACHELINE CacheLine;
277 PINFCACHEFIELD CacheField;
278 ULONG Index;
279 PTCHAR Ptr;
280
281 if (Context == NULL || Context->Line == NULL || IntegerValue == NULL)
282 {
283 DPRINT("Invalid parameter\n");
284 return INF_STATUS_INVALID_PARAMETER;
285 }
286
287 CacheLine = (PINFCACHELINE)Context->Line;
288
289 if (FieldIndex > (ULONG)CacheLine->FieldCount)
290 {
291 DPRINT("Invalid parameter\n");
292 return INF_STATUS_INVALID_PARAMETER;
293 }
294
295 if (FieldIndex == 0)
296 {
297 Ptr = CacheLine->Key;
298 }
299 else
300 {
301 CacheField = CacheLine->FirstField;
302 for (Index = 1; Index < FieldIndex; Index++)
303 CacheField = CacheField->Next;
304
305 Ptr = CacheField->Data;
306 }
307
308 *IntegerValue = _tcstol(Ptr, NULL, 0);
309
310 return INF_STATUS_SUCCESS;
311 }
312
313
314 INFSTATUS
315 InfpGetMultiSzField(PINFCONTEXT Context,
316 ULONG FieldIndex,
317 PTSTR ReturnBuffer,
318 ULONG ReturnBufferSize,
319 PULONG RequiredSize)
320 {
321 PINFCACHELINE CacheLine;
322 PINFCACHEFIELD CacheField;
323 PINFCACHEFIELD FieldPtr;
324 ULONG Index;
325 ULONG Size;
326 PTCHAR Ptr;
327
328 if (Context == NULL || Context->Line == NULL || FieldIndex == 0)
329 {
330 DPRINT("Invalid parameter\n");
331 return INF_STATUS_INVALID_PARAMETER;
332 }
333
334 if (RequiredSize != NULL)
335 *RequiredSize = 0;
336
337 CacheLine = (PINFCACHELINE)Context->Line;
338
339 if (FieldIndex > (ULONG)CacheLine->FieldCount)
340 return INF_STATUS_INVALID_PARAMETER;
341
342 CacheField = CacheLine->FirstField;
343 for (Index = 1; Index < FieldIndex; Index++)
344 CacheField = CacheField->Next;
345
346 /* Calculate the required buffer size */
347 FieldPtr = CacheField;
348 Size = 0;
349 while (FieldPtr != NULL)
350 {
351 Size += (_tcslen (FieldPtr->Data) + 1);
352 FieldPtr = FieldPtr->Next;
353 }
354 Size++;
355
356 if (RequiredSize != NULL)
357 *RequiredSize = Size;
358
359 if (ReturnBuffer != NULL)
360 {
361 if (ReturnBufferSize < Size)
362 return INF_STATUS_BUFFER_OVERFLOW;
363
364 /* Copy multi-sz string */
365 Ptr = ReturnBuffer;
366 FieldPtr = CacheField;
367 while (FieldPtr != NULL)
368 {
369 Size = _tcslen (FieldPtr->Data) + 1;
370
371 _tcscpy (Ptr, FieldPtr->Data);
372
373 Ptr = Ptr + Size;
374 FieldPtr = FieldPtr->Next;
375 }
376 *Ptr = 0;
377 }
378
379 return INF_STATUS_SUCCESS;
380 }
381
382
383 INFSTATUS
384 InfpGetStringField(PINFCONTEXT Context,
385 ULONG FieldIndex,
386 PTSTR ReturnBuffer,
387 ULONG ReturnBufferSize,
388 PULONG RequiredSize)
389 {
390 PINFCACHELINE CacheLine;
391 PINFCACHEFIELD CacheField;
392 ULONG Index;
393 PTCHAR Ptr;
394 ULONG Size;
395
396 if (Context == NULL || Context->Line == NULL || FieldIndex == 0)
397 {
398 DPRINT("Invalid parameter\n");
399 return INF_STATUS_INVALID_PARAMETER;
400 }
401
402 if (RequiredSize != NULL)
403 *RequiredSize = 0;
404
405 CacheLine = (PINFCACHELINE)Context->Line;
406
407 if (FieldIndex > (ULONG)CacheLine->FieldCount)
408 return INF_STATUS_INVALID_PARAMETER;
409
410 if (FieldIndex == 0)
411 {
412 Ptr = CacheLine->Key;
413 }
414 else
415 {
416 CacheField = CacheLine->FirstField;
417 for (Index = 1; Index < FieldIndex; Index++)
418 CacheField = CacheField->Next;
419
420 Ptr = CacheField->Data;
421 }
422
423 Size = _tcslen (Ptr) + 1;
424
425 if (RequiredSize != NULL)
426 *RequiredSize = Size;
427
428 if (ReturnBuffer != NULL)
429 {
430 if (ReturnBufferSize < Size)
431 return INF_STATUS_BUFFER_OVERFLOW;
432
433 _tcscpy (ReturnBuffer, Ptr);
434 }
435
436 return INF_STATUS_SUCCESS;
437 }
438
439
440 INFSTATUS
441 InfpGetData(PINFCONTEXT Context,
442 PTCHAR *Key,
443 PTCHAR *Data)
444 {
445 PINFCACHELINE CacheKey;
446
447 if (Context == NULL || Context->Line == NULL || Data == NULL)
448 {
449 DPRINT("Invalid parameter\n");
450 return INF_STATUS_INVALID_PARAMETER;
451 }
452
453 CacheKey = (PINFCACHELINE)Context->Line;
454 if (Key != NULL)
455 *Key = CacheKey->Key;
456
457 if (Data != NULL)
458 {
459 if (CacheKey->FirstField == NULL)
460 {
461 *Data = NULL;
462 }
463 else
464 {
465 *Data = CacheKey->FirstField->Data;
466 }
467 }
468
469 return INF_STATUS_SUCCESS;
470 }
471
472
473 INFSTATUS
474 InfpGetDataField(PINFCONTEXT Context,
475 ULONG FieldIndex,
476 PTCHAR *Data)
477 {
478 PINFCACHELINE CacheLine;
479 PINFCACHEFIELD CacheField;
480 ULONG Index;
481
482 if (Context == NULL || Context->Line == NULL || Data == NULL)
483 {
484 DPRINT("Invalid parameter\n");
485 return INF_STATUS_INVALID_PARAMETER;
486 }
487
488 CacheLine = (PINFCACHELINE)Context->Line;
489
490 if (FieldIndex > (ULONG)CacheLine->FieldCount)
491 return INF_STATUS_INVALID_PARAMETER;
492
493 if (FieldIndex == 0)
494 {
495 *Data = CacheLine->Key;
496 }
497 else
498 {
499 CacheField = CacheLine->FirstField;
500 for (Index = 1; Index < FieldIndex; Index++)
501 CacheField = CacheField->Next;
502
503 *Data = CacheField->Data;
504 }
505
506 return INF_STATUS_SUCCESS;
507 }
508
509 VOID
510 InfpFreeContext(PINFCONTEXT Context)
511 {
512 FREE(Context);
513 }
514
515 /* EOF */