ReactOS  0.4.14-dev-49-gfb4591c
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 
30 struct inf_value
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 
48 struct inf_file
49 {
50  char *content;
52  struct list sections;
53 };
54 
55 static void inf_value_free(struct inf_value *value)
56 {
58 }
59 
60 static void inf_section_free(struct inf_section *section)
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 
72 static 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 
89 static 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 
159 static char *expand_variables(struct inf_file *inf, const char *str)
160 {
161  char *buffer;
162  int len;
163 
165  buffer = heap_alloc(len);
166  if (!len) return NULL;
167 
169  return buffer;
170 }
171 
172 void 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 
185 BOOL 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 
201 struct 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 
235 struct 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 
258 char *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 
296 static 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. */
323 static 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 
361 static 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 
405 HRESULT 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 
419  if (!GetFileSizeEx(file, &file_size))
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 
435  CloseHandle(file);
436  *inf_file = inf;
437  return S_OK;
438 
439 error:
440  if (inf) inf_free(inf);
441  CloseHandle(file);
442  return hr;
443 }
static void inf_section_free(struct inf_section *section)
Definition: inf.c:60
#define TRUE
Definition: types.h:120
static UCHAR ULONG UCHAR ULONG UCHAR * output
Definition: bcrypt.c:29
#define CloseHandle
Definition: compat.h:398
struct inf_value * inf_get_value(struct inf_section *sec, const char *key)
Definition: inf.c:235
static char * get_next_line(char **str, char **last_chr)
Definition: inf.c:296
HRESULT hr
Definition: shlfolder.c:183
#define error(str)
Definition: mkdosfs.c:1605
#define strcasecmp
Definition: fake.h:9
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
POINT last
Definition: font.c:46
static HRESULT inf_section_parse(struct inf_file *inf, char *line, char *last_chr, struct inf_section **section)
Definition: inf.c:323
char * key
Definition: inf.c:33
GLboolean GLenum GLenum GLvoid * values
Definition: glext.h:5666
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
GLuint buffer
Definition: glext.h:5915
static HRESULT inf_value_parse(struct inf_section *sec, char *line)
Definition: inf.c:361
char * inf_value_get_value(struct inf_value *value)
Definition: inf.c:253
Definition: parser.c:55
#define E_FAIL
Definition: ddrawi.h:102
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
const WCHAR * name
Definition: parser.c:57
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
char * inf_section_get_name(struct inf_section *section)
Definition: inf.c:214
struct inf_section * inf_get_section(struct inf_file *inf, const char *name)
Definition: inf.c:201
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
void inf_free(struct inf_file *inf)
Definition: inf.c:172
unsigned int BOOL
Definition: ntddk_ex.h:94
DWORD size
Definition: inf.c:51
struct list entry
Definition: inf.c:41
content
Definition: atl_ax.c:994
const WCHAR * str
#define strncasecmp
Definition: fake.h:10
smooth NULL
Definition: ftsmooth.c:416
Definition: parser.c:48
static int expand_variables_buffer(struct inf_file *inf, const char *str, char *output)
Definition: inf.c:89
#define OPEN_EXISTING
Definition: compat.h:426
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
GLuint GLfloat * val
Definition: glext.h:7180
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
LONG HRESULT
Definition: typedefs.h:77
BOOL inf_next_section(struct inf_file *inf, struct inf_section **sec)
Definition: inf.c:185
const char file[]
Definition: icontest.c:11
unsigned long DWORD
Definition: ntddk_ex.h:95
static void inf_value_free(struct inf_value *value)
Definition: inf.c:55
#define GetFileSizeEx
Definition: compat.h:414
char line[200]
Definition: main.c:97
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
HRESULT inf_load(const char *path, struct inf_file **inf_file)
Definition: inf.c:405
struct list values
Definition: inf.c:43
HKEY key
Definition: reg.c:42
Definition: id3.c:18
uint32_t entry
Definition: isohybrid.c:63
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
Definition: _list.h:228
static HRESULT inf_process_content(struct inf_file *inf)
Definition: inf.c:387
#define GENERIC_READ
Definition: compat.h:124
GLsizei const GLfloat * value
Definition: glext.h:6069
char * value
Definition: inf.c:34
static VOID del(LPHIST_ENTRY item)
Definition: history.c:199
#define S_OK
Definition: intsafe.h:59
char * content
Definition: inf.c:50
static unsigned __int64 next
Definition: rand_nt.c:6
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:204
BOOL inf_section_next_value(struct inf_section *sec, struct inf_value **value)
Definition: inf.c:219
static const char * get_substitution(struct inf_file *inf, const char *name, int len)
Definition: inf.c:72
static char * expand_variables(struct inf_file *inf, const char *str)
Definition: inf.c:159
GLuint start
Definition: gl.h:1545
Definition: inf.c:30
Definition: services.c:325
struct list sections
Definition: inf.c:52
char * strchr(const char *String, int ch)
Definition: utclib.c:501
struct list entry
Definition: inf.c:32
Definition: name.c:36
__WINE_SERVER_LIST_INLINE struct list * list_next(const struct list *list, const struct list *elem)
Definition: list.h:115
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
char * inf_value_get_key(struct inf_value *value)
Definition: inf.c:248
static void strip_quotes(WCHAR *word, WCHAR **end)
Definition: xcopy.c:701
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:399
GLfloat GLfloat p
Definition: glext.h:8902
char * trim(char *str, char **last_chr, BOOL strip_quotes)
Definition: inf.c:258
BOOL WINAPI ReadFile(IN HANDLE hFile, IN LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:123
char * name
Definition: inf.c:42
static LPSTR strdupA(LPCSTR str)
Definition: mimeole.c:482
struct inf_file * file
Definition: inf.c:45
Definition: inf.c:48
struct inf_section * section
Definition: inf.c:36
#define file_size(inode)
Definition: reiserfs_fs.h:1869
_CRTIMP int __cdecl read(_In_ int _FileHandle, _Out_writes_bytes_(_MaxCharCount) void *_DstBuf, _In_ unsigned int _MaxCharCount)
#define SUCCEEDED(hr)
Definition: intsafe.h:57
Definition: path.c:42
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
Definition: fci.c:126
GLuint const GLchar * name
Definition: glext.h:6031