ReactOS 0.4.16-dev-336-gb667d82
inf.c
Go to the documentation of this file.
1/*
2 * Copyright 2016 Michael Müller
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#include <stdarg.h>
20#include <string.h>
21
22#include "windef.h"
23#include "winbase.h"
24#include "winuser.h"
25
26#include "inseng_private.h"
27
28#include "wine/list.h"
29
31{
32 struct list entry;
33 char *key;
34 char *value;
35
37};
38
40{
41 struct list entry;
42 char *name;
43 struct list values;
44
45 struct inf_file *file;
46};
47
49{
50 char *content;
52 struct list sections;
53};
54
55static void inf_value_free(struct inf_value *value)
56{
58}
59
61{
62 struct inf_value *val, *val_next;
63 LIST_FOR_EACH_ENTRY_SAFE(val, val_next, &section->values, struct inf_value, entry)
64 {
65 list_remove(&val->entry);
67 }
68
70}
71
72static const char *get_substitution(struct inf_file *inf, const char *name, int len)
73{
74 struct inf_section *sec;
75 struct inf_value *value = NULL;
76
77 sec = inf_get_section(inf, "Strings");
78 if (!sec) return NULL;
79
80 while (inf_section_next_value(sec, &value))
81 {
82 if (strlen(value->key) == len && !strncasecmp(value->key, name, len))
83 return value->value;
84 }
85
86 return NULL;
87}
88
89static int expand_variables_buffer(struct inf_file *inf, const char *str, char *output)
90{
91 const char *p, *var_start = NULL;
92 int var_len = 0, len = 0;
93 const char *substitution;
94
95 for (p = str; *p; p++)
96 {
97 if (*p != '%')
98 {
99 if (var_start)
100 var_len++;
101 else
102 {
103 if (output)
104 *output++ = *p;
105 len++;
106 }
107
108 continue;
109 }
110
111 if (!var_start)
112 {
113 var_start = p;
114 var_len = 0;
115
116 continue;
117 }
118
119 if (!var_len)
120 {
121 /* just an escaped % */
122 if (output)
123 *output++ = '%';
124 len += 1;
125
126 var_start = NULL;
127 continue;
128 }
129
130 substitution = get_substitution(inf, var_start + 1, var_len);
131 if (!substitution)
132 {
133 if (output)
134 {
135 memcpy(output, var_start, var_len + 2);
136 output += var_len + 2;
137 }
138 len += var_len + 2;
139 }
140 else
141 {
142 int sub_len = strlen(substitution);
143
144 if (output)
145 {
146 memcpy(output, substitution, sub_len);
147 output += sub_len;
148 }
149 len += sub_len;
150 }
151
152 var_start = NULL;
153 }
154
155 if (output) *output = 0;
156 return len + 1;
157}
158
159static char *expand_variables(struct inf_file *inf, const char *str)
160{
161 char *buffer;
162 int len;
163
166 if (!len) return NULL;
167
169 return buffer;
170}
171
172void inf_free(struct inf_file *inf)
173{
174 struct inf_section *sec, *sec_next;
175 LIST_FOR_EACH_ENTRY_SAFE(sec, sec_next, &inf->sections, struct inf_section, entry)
176 {
177 list_remove(&sec->entry);
178 inf_section_free(sec);
179 }
180
181 heap_free(inf->content);
182 heap_free(inf);
183}
184
185BOOL inf_next_section(struct inf_file *inf, struct inf_section **sec)
186{
187 struct list *next_entry, *cur_position;
188
189 if (*sec)
190 cur_position = &(*sec)->entry;
191 else
192 cur_position = &inf->sections;
193
194 next_entry = list_next(&inf->sections, cur_position);
195 if (!next_entry) return FALSE;
196
197 *sec = CONTAINING_RECORD(next_entry, struct inf_section, entry);
198 return TRUE;
199}
200
201struct inf_section *inf_get_section(struct inf_file *inf, const char *name)
202{
203 struct inf_section *sec = NULL;
204
205 while (inf_next_section(inf, &sec))
206 {
207 if (!strcasecmp(sec->name, name))
208 return sec;
209 }
210
211 return NULL;
212}
213
215{
216 return strdupA(section->name);
217}
218
220{
221 struct list *next_entry, *cur_position;
222
223 if (*value)
224 cur_position = &(*value)->entry;
225 else
226 cur_position = &sec->values;
227
228 next_entry = list_next(&sec->values, cur_position);
229 if (!next_entry) return FALSE;
230
231 *value = CONTAINING_RECORD(next_entry, struct inf_value, entry);
232 return TRUE;
233}
234
235struct inf_value *inf_get_value(struct inf_section *sec, const char *key)
236{
237 struct inf_value *value = NULL;
238
239 while (inf_section_next_value(sec, &value))
240 {
241 if (!strcasecmp(value->key, key))
242 return value;
243 }
244
245 return NULL;
246}
247
249{
250 return strdupA(value->key);
251}
252
254{
255 return expand_variables(value->section->file, value->value);
256}
257
258char *trim(char *str, char **last_chr, BOOL strip_quotes)
259{
260 char *last;
261
262 for (; *str; str++)
263 {
264 if (*str != '\t' && *str != ' ')
265 break;
266 }
267
268 if (!*str)
269 {
270 if (last_chr) *last_chr = str;
271 return str;
272 }
273
274 last = str + strlen(str) - 1;
275
276 for (; last > str; last--)
277 {
278 if (*last != '\t' && *last != ' ')
279 break;
280 *last = 0;
281 }
282
283 if (strip_quotes && last != str)
284 {
285 if (*last == '"' && *str == '"')
286 {
287 str++;
288 *last = 0;
289 }
290 }
291
292 if (last_chr) *last_chr = last;
293 return str;
294}
295
296static char *get_next_line(char **str, char **last_chr)
297{
298 BOOL in_next_line = FALSE;
299 char *start, *next;
300
301 start = *str;
302 if (!start || !*start) return NULL;
303
304 for (next = start; *next; next++)
305 {
306 if (*next == '\n' || *next == '\r')
307 {
308 *next = 0;
309 in_next_line = TRUE;
310 }
311 else if (in_next_line)
312 {
313 break;
314 }
315 }
316
317 *str = next;
318 return trim(start, last_chr, FALSE);
319}
320
321/* This function only fails in case of an memory allocation error
322 * and does not touch section in case the parsing failed. */
323static HRESULT inf_section_parse(struct inf_file *inf, char *line, char *last_chr, struct inf_section **section)
324{
325 struct inf_section *sec;
326 char *comment;
327 char *name;
328
329 if (*line != '[')
330 return S_OK;
331
332 line++;
333
334 comment = strchr(line, ';');
335 if (comment)
336 {
337 *comment = 0;
338 line = trim(line, &last_chr, FALSE);
339 }
340
341 if (*last_chr != ']')
342 return S_OK;
343
344 *last_chr = 0;
345 name = trim(line, NULL, FALSE);
346 if (!name) return S_OK;
347
348 sec = heap_alloc_zero(sizeof(*sec));
349 if (!sec) return E_OUTOFMEMORY;
350
351 sec->name = name;
352 sec->file = inf;
353 list_init(&sec->values);
354
355 list_add_tail(&inf->sections, &sec->entry);
356
357 *section = sec;
358 return S_OK;
359}
360
361static HRESULT inf_value_parse(struct inf_section *sec, char *line)
362{
363 struct inf_value *key_val;
364 char *key, *value, *del;
365
366 del = strchr(line, '=');
367 if (!del) return S_OK;
368
369 *del = 0;
370 key = line;
371 value = del + 1;
372
373 key = trim(key, NULL, FALSE);
374 value = trim(value, NULL, TRUE);
375
376 key_val = heap_alloc_zero(sizeof(*key_val));
377 if (!key_val) return E_OUTOFMEMORY;
378
379 key_val->key = key;
380 key_val->value = value;
381 key_val->section = sec;
382
383 list_add_tail(&sec->values, &key_val->entry);
384 return S_OK;
385}
386
388{
389 struct inf_section *section = NULL;
390 char *content = inf->content;
391 char *line, *last_chr;
392 HRESULT hr = S_OK;
393
394 while (SUCCEEDED(hr) && (line = get_next_line(&content, &last_chr)))
395 {
396 if (*line == '[')
397 hr = inf_section_parse(inf, line, last_chr, &section);
398 else if (strchr(line, '=') && section)
400 }
401
402 return hr;
403}
404
405HRESULT inf_load(const char *path, struct inf_file **inf_file)
406{
408 struct inf_file *inf;
409 HRESULT hr = E_FAIL;
410 HANDLE file;
411 DWORD read;
412
414 if (file == INVALID_HANDLE_VALUE) return E_FAIL;
415
416 inf = heap_alloc_zero(sizeof(*inf));
417 if (!inf) goto error;
418
420 goto error;
421
422 inf->size = file_size.QuadPart;
423
424 inf->content = heap_alloc_zero(inf->size);
425 if (!inf->content) goto error;
426
427 list_init(&inf->sections);
428
429 if (!ReadFile(file, inf->content, inf->size, &read, NULL) || read != inf->size)
430 goto error;
431
432 hr = inf_process_content(inf);
433 if (FAILED(hr)) goto error;
434
436 *inf_file = inf;
437 return S_OK;
438
439error:
440 if (inf) inf_free(inf);
442 return hr;
443}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define read
Definition: acwin.h:96
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
static void strip_quotes(WCHAR *word, WCHAR **end)
Definition: xcopy.c:701
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static void list_init(struct list_entry *head)
Definition: list.h:51
static VOID del(LPHIST_ENTRY item)
Definition: history.c:199
Definition: list.h:37
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
content
Definition: atl_ax.c:994
#define CloseHandle
Definition: compat.h:739
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define GENERIC_READ
Definition: compat.h:135
#define GetFileSizeEx
Definition: compat.h:757
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
static LPSTR strdupA(LPCSTR str)
Definition: mimeole.c:482
#define strncasecmp
Definition: fake.h:10
#define strcasecmp
Definition: fake.h:9
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint start
Definition: gl.h:1545
GLuint buffer
Definition: glext.h:5915
GLboolean GLenum GLenum GLvoid * values
Definition: glext.h:5666
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
static char * get_next_line(char **str, char **last_chr)
Definition: inf.c:296
char * inf_section_get_name(struct inf_section *section)
Definition: inf.c:214
static int expand_variables_buffer(struct inf_file *inf, const char *str, char *output)
Definition: inf.c:89
BOOL inf_section_next_value(struct inf_section *sec, struct inf_value **value)
Definition: inf.c:219
char * inf_value_get_value(struct inf_value *value)
Definition: inf.c:253
char * trim(char *str, char **last_chr, BOOL strip_quotes)
Definition: inf.c:258
struct inf_section * inf_get_section(struct inf_file *inf, const char *name)
Definition: inf.c:201
void inf_free(struct inf_file *inf)
Definition: inf.c:172
BOOL inf_next_section(struct inf_file *inf, struct inf_section **sec)
Definition: inf.c:185
static HRESULT inf_process_content(struct inf_file *inf)
Definition: inf.c:387
static const char * get_substitution(struct inf_file *inf, const char *name, int len)
Definition: inf.c:72
static HRESULT inf_value_parse(struct inf_section *sec, char *line)
Definition: inf.c:361
static void inf_value_free(struct inf_value *value)
Definition: inf.c:55
static char * expand_variables(struct inf_file *inf, const char *str)
Definition: inf.c:159
struct inf_value * inf_get_value(struct inf_section *sec, const char *key)
Definition: inf.c:235
char * inf_value_get_key(struct inf_value *value)
Definition: inf.c:248
static void inf_section_free(struct inf_section *section)
Definition: inf.c:60
static HRESULT inf_section_parse(struct inf_file *inf, char *line, char *last_chr, struct inf_section **section)
Definition: inf.c:323
HRESULT inf_load(const char *path, struct inf_file **inf_file)
Definition: inf.c:405
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
uint32_t entry
Definition: isohybrid.c:63
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define comment(fmt, arg1)
Definition: rebar.c:847
static UINT UINT last
Definition: font.c:45
static unsigned __int64 next
Definition: rand_nt.c:6
static unsigned int file_size
Definition: regtests2xml.c:47
const WCHAR * str
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:204
__WINE_SERVER_LIST_INLINE struct list * list_next(const struct list *list, const struct list *elem)
Definition: list.h:115
HRESULT hr
Definition: shlfolder.c:183
Definition: fci.c:127
Definition: inf.c:49
struct list sections
Definition: inf.c:52
DWORD size
Definition: inf.c:51
char * content
Definition: inf.c:50
struct list entry
Definition: inf.c:41
struct list values
Definition: inf.c:43
char * name
Definition: inf.c:42
struct inf_file * file
Definition: inf.c:45
Definition: inf.c:31
struct list entry
Definition: inf.c:32
char * value
Definition: inf.c:34
char * key
Definition: inf.c:33
struct inf_section * section
Definition: inf.c:36
Definition: copy.c:22
Definition: parser.c:49
Definition: name.c:39
Definition: parser.c:56
const WCHAR * name
Definition: parser.c:57
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
Definition: pdh_main.c:94