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