ReactOS 0.4.15-dev-8119-g4fb2fdb
parser.c
Go to the documentation of this file.
1/*
2 * INF file parsing tests
3 *
4 * Copyright 2002, 2005 Alexandre Julliard for CodeWeavers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include <stdarg.h>
22
23#include "windef.h"
24#include "winbase.h"
25#include "wingdi.h"
26#include "winuser.h"
27#include "winreg.h"
28#include "setupapi.h"
29
30#include "wine/test.h"
31
32/* function pointers */
34static LPCSTR (WINAPI *pSetupGetFieldA)(PINFCONTEXT,DWORD);
35static LPCWSTR (WINAPI *pSetupGetFieldW)(PINFCONTEXT,DWORD);
36static BOOL (WINAPI *pSetupEnumInfSectionsA)( HINF hinf, UINT index, PSTR buffer, DWORD size, UINT *need );
37
38static void init_function_pointers(void)
39{
40 hSetupAPI = GetModuleHandleA("setupapi.dll");
41
42 /* Nice, pSetupGetField is either A or W depending on the Windows version! The actual test
43 * takes care of this difference */
44 pSetupGetFieldA = (void *)GetProcAddress(hSetupAPI, "pSetupGetField");
45 pSetupGetFieldW = (void *)GetProcAddress(hSetupAPI, "pSetupGetField");
46 pSetupEnumInfSectionsA = (void *)GetProcAddress(hSetupAPI, "SetupEnumInfSectionsA" );
47}
48
49static const char tmpfilename[] = ".\\tmp.inf";
50
51/* some large strings */
52#define A255 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
53 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
54 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
55 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
56#define A256 "a" A255
57#define A400 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
58 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
59 "aaaaaaaaaaaaaaaa" A256
60#define A1200 A400 A400 A400
61#define A511 A255 A256
62#define A4096 A256 A256 A256 A256 A256 A256 A256 A256 A256 A256 A256 A256 A256 A256 A256 A256
63#define A4097 "a" A4096
64
65#define STD_HEADER "[Version]\r\nSignature=\"$CHICAGO$\"\r\n"
66
67#define STR_SECTION "[Strings]\nfoo=aaa\nbar=bbb\nloop=%loop2%\nloop2=%loop%\n" \
68 "per%%cent=abcd\nper=1\ncent=2\n22=foo\n" \
69 "big=" A400 "\n" \
70 "mydrive=\"C:\\\"\n" \
71 "verybig=" A1200 "\n"
72
73/* create a new file with specified contents and open it */
74static HINF test_file_contents( const char *data, UINT *err_line )
75{
76 DWORD res;
79 if (handle == INVALID_HANDLE_VALUE) return 0;
80 if (!WriteFile( handle, data, strlen(data), &res, NULL )) trace( "write error\n" );
83}
84
86{
87 static char buffer[MAX_INF_STRING_LENGTH+32];
88 if (SetupGetStringFieldA( context, index, buffer, sizeof(buffer), NULL )) return buffer;
89 return NULL;
90}
91
92static const char *get_line_text( INFCONTEXT *context )
93{
94 static char buffer[MAX_INF_STRING_LENGTH+32];
95 if (SetupGetLineTextA( context, 0, 0, 0, buffer, sizeof(buffer), NULL )) return buffer;
96 return NULL;
97}
98
99
100/* Test various valid/invalid file formats */
101
102static const struct
103{
104 const char *data;
108} invalid_files[] =
109{
110 /* file contents expected error (or 0) errline todo */
111 { "\r\n", ERROR_WRONG_INF_STYLE, 0, FALSE },
112 { "abcd\r\n", ERROR_WRONG_INF_STYLE, 0, TRUE },
113 { "[Version]\r\n", ERROR_WRONG_INF_STYLE, 0, FALSE },
114 { "[Version]\nSignature=", ERROR_WRONG_INF_STYLE, 0, FALSE },
115 { "[Version]\nSignature=foo", ERROR_WRONG_INF_STYLE, 0, FALSE },
116 { "[version]\nsignature=$chicago$", 0, 0, FALSE },
117 { "[VERSION]\nSIGNATURE=$CHICAGO$", 0, 0, FALSE },
118 { "[Version]\nSignature=$chicago$,abcd", 0, 0, FALSE },
119 { "[Version]\nabc=def\nSignature=$chicago$", 0, 0, FALSE },
120 { "[Version]\nabc=def\n[Version]\nSignature=$chicago$", 0, 0, FALSE },
121 { STD_HEADER, 0, 0, FALSE },
122 { STD_HEADER "[]\r\n", 0, 0, FALSE },
123 { STD_HEADER "]\r\n", 0, 0, FALSE },
124 { STD_HEADER "[" A255 "]\r\n", 0, 0, FALSE },
126 { STD_HEADER "\n\n[ab\x1a]\n", ERROR_BAD_SECTION_NAME_LINE, 5, FALSE },
128 { "[abc]\n" STD_HEADER, 0, 0, FALSE },
130 { ";\n;\nabc\r\n" STD_HEADER, ERROR_EXPECTED_SECTION_NAME, 3, FALSE },
131 { ";\n;\nab\nab\n" STD_HEADER, ERROR_EXPECTED_SECTION_NAME, 3, FALSE },
132 { ";aa\n;bb\n" STD_HEADER, 0, 0, FALSE },
133 { STD_HEADER " [TestSection\x00]\n", ERROR_BAD_SECTION_NAME_LINE, 3, FALSE },
134 { STD_HEADER " [Test\x00Section]\n", ERROR_BAD_SECTION_NAME_LINE, 3, FALSE },
135 { STD_HEADER " [TestSection\x00]\n", ERROR_BAD_SECTION_NAME_LINE, 3, FALSE },
136 { STD_HEADER " [Test\x00Section]\n", ERROR_BAD_SECTION_NAME_LINE, 3, FALSE },
137 { "garbage1\ngarbage2\n[abc]\n" STD_HEADER, ERROR_EXPECTED_SECTION_NAME, 1, FALSE },
138 { "garbage1\ngarbage2\n[Strings]\n" STD_HEADER, 0, 0, FALSE },
139 { ";comment\ngarbage1\ngarbage2\n[abc]\n" STD_HEADER, ERROR_EXPECTED_SECTION_NAME, 2, FALSE },
140 { ";comment\ngarbage1\ngarbage2\n[Strings]\n" STD_HEADER, 0, 0, FALSE },
141 { " \t\ngarbage1\ngarbage2\n[abc]\n" STD_HEADER, ERROR_EXPECTED_SECTION_NAME, 2, FALSE },
142 { " \t\ngarbage1\ngarbage2\n[Strings]\n" STD_HEADER, 0, 0, FALSE },
143 { "garbage1\ngarbage2\n" STD_HEADER "[abc]\n", ERROR_EXPECTED_SECTION_NAME, 1, FALSE },
144 { "garbage1\ngarbage2\n" STD_HEADER "[Strings]\n", 0, 0, FALSE },
145 { ";comment\ngarbage1\ngarbage2\n" STD_HEADER "[abc]\n", ERROR_EXPECTED_SECTION_NAME, 2, FALSE },
146 { ";comment\ngarbage1\ngarbage2\n" STD_HEADER "[Strings]\n", 0, 0, FALSE },
147 { " \t\ngarbage1\ngarbage2\n" STD_HEADER "[abc]\n", ERROR_EXPECTED_SECTION_NAME, 2, FALSE },
148 { " \t\ngarbage1\ngarbage2\n" STD_HEADER "[Strings]\n", 0, 0, FALSE },
150
151static void test_invalid_files(void)
152{
153 unsigned int i;
155 HINF hinf;
156 DWORD err;
157
158 for (i = 0; i < ARRAY_SIZE(invalid_files); i++)
159 {
160 SetLastError( 0xdeadbeef );
161 err_line = 0xdeadbeef;
163 err = GetLastError();
164 trace( "hinf=%p err=0x%x line=%d\n", hinf, err, err_line );
165 if (invalid_files[i].error) /* should fail */
166 {
167 ok( hinf == INVALID_HANDLE_VALUE, "file %u: Open succeeded\n", i );
169 {
170 ok( err == invalid_files[i].error, "file %u: Bad error %u/%u\n",
172 ok( err_line == invalid_files[i].err_line, "file %u: Bad error line %d/%d\n",
174 }
175 }
176 else /* should succeed */
177 {
178 ok( hinf != INVALID_HANDLE_VALUE, "file %u: Open failed\n", i );
179 ok( err == 0, "file %u: Error code set to %u\n", i, err );
180 }
181 SetupCloseInfFile( hinf );
182 }
183}
184
185
186/* Test various section names */
187
188static const struct
189{
190 const char *data;
191 const char *section;
192 DWORD error;
193} section_names[] =
194{
195 /* file contents section name error code */
196 { STD_HEADER "[TestSection]", "TestSection", 0 },
197 { STD_HEADER "[TestSection]\n", "TestSection", 0 },
198 { STD_HEADER "[TESTSECTION]\r\n", "TestSection", 0 },
199 { STD_HEADER "[TestSection]\n[abc]", "testsection", 0 },
200 { STD_HEADER ";[TestSection]\n", "TestSection", ERROR_SECTION_NOT_FOUND },
201 { STD_HEADER "[TestSection]\n", "Bad name", ERROR_SECTION_NOT_FOUND },
202 /* spaces */
203 { STD_HEADER "[TestSection] \r\n", "TestSection", 0 },
204 { STD_HEADER " [TestSection]\r\n", "TestSection", 0 },
205 { STD_HEADER " [TestSection] dummy\r\n", "TestSection", 0 },
206 { STD_HEADER " [TestSection] [foo]\r\n", "TestSection", 0 },
207 { STD_HEADER " [ Test Section ] dummy\r\n", " Test Section ", 0 },
208 { STD_HEADER "[TestSection] \032\ndummy", "TestSection", 0 },
209 { STD_HEADER "[TestSection] \n\032dummy", "TestSection", 0 },
210 /* special chars in section name */
211 { STD_HEADER "[Test[Section]\r\n", "Test[Section", 0 },
212 { STD_HEADER "[Test[S]ection]\r\n", "Test[S", 0 },
213 { STD_HEADER "[Test[[[Section]\r\n", "Test[[[Section", 0 },
214 { STD_HEADER "[]\r\n", "", 0 },
215 { STD_HEADER "[[[]\n", "[[", 0 },
216 { STD_HEADER "[Test\"Section]\r\n", "Test\"Section", 0 },
217 { STD_HEADER "[Test\\Section]\r\n", "Test\\Section", 0 },
218 { STD_HEADER "[Test\\ Section]\r\n", "Test\\ Section", 0 },
219 { STD_HEADER "[Test;Section]\r\n", "Test;Section", 0 },
220 /* various control chars */
221 { STD_HEADER " [Test\r\b\tSection] \n", "Test\r\b\tSection", 0 },
222 /* nulls */
224
225static void test_section_names(void)
226{
227 unsigned int i;
229 HINF hinf;
230 DWORD err;
231 LONG ret;
232
233 for (i = 0; i < ARRAY_SIZE(section_names); i++)
234 {
235 SetLastError( 0xdeadbeef );
237 ok( hinf != INVALID_HANDLE_VALUE, "line %u: open failed err %u\n", i, GetLastError() );
238 if (hinf == INVALID_HANDLE_VALUE) continue;
239
241 err = GetLastError();
242 trace( "hinf=%p ret=%d err=0x%x\n", hinf, ret, err );
243 if (ret != -1)
244 {
245 ok( !section_names[i].error, "line %u: section name %s found\n",
247 ok( !err, "line %u: bad error code %u\n", i, err );
248 }
249 else
250 {
251 ok( section_names[i].error, "line %u: section name %s not found\n",
253 ok( err == section_names[i].error, "line %u: bad error %u/%u\n",
255 }
256 SetupCloseInfFile( hinf );
257 }
258}
259
260static void test_enum_sections(void)
261{
262 static const char *contents = STD_HEADER "[s1]\nfoo=bar\n[s2]\nbar=foo\n[s3]\n[strings]\na=b\n";
263
264 BOOL ret;
265 DWORD len;
266 HINF hinf;
267 UINT err, index;
268 char buffer[256];
269
270 if (!pSetupEnumInfSectionsA)
271 {
272 win_skip( "SetupEnumInfSectionsA not available\n" );
273 return;
274 }
275
276 hinf = test_file_contents( contents, &err );
277 ok( hinf != NULL, "Expected valid INF file\n" );
278
279 for (index = 0; ; index++)
280 {
281 SetLastError( 0xdeadbeef );
282 ret = pSetupEnumInfSectionsA( hinf, index, NULL, 0, &len );
283 err = GetLastError();
284 if (!ret && GetLastError() == ERROR_NO_MORE_ITEMS) break;
285 ok( ret, "SetupEnumInfSectionsA failed\n" );
286 ok( len == 3 || len == 8, "wrong len %u\n", len );
287
288 SetLastError( 0xdeadbeef );
289 ret = pSetupEnumInfSectionsA( hinf, index, NULL, sizeof(buffer), &len );
290 err = GetLastError();
291 ok( !ret, "SetupEnumInfSectionsA succeeded\n" );
292 ok( err == ERROR_INVALID_USER_BUFFER, "wrong error %u\n", err );
293 ok( len == 3 || len == 8, "wrong len %u\n", len );
294
295 SetLastError( 0xdeadbeef );
296 ret = pSetupEnumInfSectionsA( hinf, index, buffer, sizeof(buffer), &len );
297 ok( ret, "SetupEnumInfSectionsA failed err %u\n", GetLastError() );
298 ok( len == 3 || len == 8, "wrong len %u\n", len );
299 ok( !lstrcmpiA( buffer, "version" ) || !lstrcmpiA( buffer, "s1" ) ||
300 !lstrcmpiA( buffer, "s2" ) || !lstrcmpiA( buffer, "s3" ) || !lstrcmpiA( buffer, "strings" ),
301 "bad section '%s'\n", buffer );
302 }
303 SetupCloseInfFile( hinf );
304}
305
306
307/* Test various key and value names */
308
309static const struct
310{
311 const char *data;
312 const char *key;
313 const char *fields[10];
314} key_names[] =
315{
316/* file contents expected key expected fields */
317 { "ab=cd", "ab", { "cd" } },
318 { "ab=cd,ef,gh,ij", "ab", { "cd", "ef", "gh", "ij" } },
319 { "ab", "ab", { "ab" } },
320 { "ab,cd", NULL, { "ab", "cd" } },
321 { "ab,cd=ef", NULL, { "ab", "cd=ef" } },
322 { "=abcd,ef", "", { "abcd", "ef" } },
323 /* backslashes */
324 { "ba\\\ncd=ef", "bacd", { "ef" } },
325 { "ab \\ \ncd=ef", "abcd", { "ef" } },
326 { "ab\\\ncd,ef", NULL, { "abcd", "ef" } },
327 { "ab \\ ;cc\ncd=ef", "abcd", { "ef" } },
328 { "ab \\ \\ \ncd=ef", "abcd", { "ef" } },
329 { "ba \\ dc=xx", "ba \\ dc", { "xx" } },
330 { "ba \\\\ \nc=d", "bac", { "d" } },
331 { "a=b\\\\c", "a", { "b\\\\c" } },
332 { "ab=cd \\ ", "ab", { "cd" } },
333 { "ba=c \\ \n \\ \n a", "ba", { "ca" } },
334 { "ba=c \\ \n \\ a", "ba", { "c\\ a" } },
335 { " \\ a= \\ b", "\\ a", { "\\ b" } },
336 /* quotes */
337 { "Ab\"Cd\"=Ef", "AbCd", { "Ef" } },
338 { "Ab\"Cd=Ef\"", "AbCd=Ef", { "AbCd=Ef" } },
339 { "ab\"\"\"cd,ef=gh\"", "ab\"cd,ef=gh", { "ab\"cd,ef=gh" } },
340 { "ab\"\"cd=ef", "abcd", { "ef" } },
341 { "ab\"\"cd=ef,gh", "abcd", { "ef", "gh" } },
342 { "ab=cd\"\"ef", "ab", { "cdef" } },
343 { "ab=cd\",\"ef", "ab", { "cd,ef" } },
344 { "ab=cd\",ef", "ab", { "cd,ef" } },
345 { "ab=cd\",ef\\\nab", "ab", { "cd,ef\\" } },
346
347 /* single quotes (unhandled)*/
348 { "HKLM,A,B,'C',D", NULL, { "HKLM", "A","B","'C'","D" } },
349 /* spaces */
350 { " a b = c , d \n", "a b", { "c", "d" } },
351 { " a b = c ,\" d\" \n", "a b", { "c", " d" } },
352 { " a b\r = c\r\n", "a b", { "c" } },
353 /* empty fields */
354 { "a=b,,,c,,,d", "a", { "b", "", "", "c", "", "", "d" } },
355 { "a=b,\"\",c,\" \",d", "a", { "b", "", "c", " ", "d" } },
356 { "=,,b", "", { "", "", "b" } },
357 { ",=,,b", NULL, { "", "=", "", "b" } },
358 { "a=\n", "a", { "" } },
359 { "=", "", { "" } },
360 /* eof */
361 { "ab=c\032d", "ab", { "c" } },
362 { "ab\032=cd", "ab", { "ab" } },
363 /* nulls */
364 { "abcd=ef\x0gh", "abcd", { "ef" } },
365 /* multiple sections with same name */
366 { "[Test2]\nab\n[Test]\nee=ff\n", "ee", { "ff" } },
367 /* string substitution */
368 { "%foo%=%bar%\n" STR_SECTION, "aaa", { "bbb" } },
369 { "%foo%xx=%bar%yy\n" STR_SECTION, "aaaxx", { "bbbyy" } },
370 { "%% %foo%=%bar%\n" STR_SECTION, "% aaa", { "bbb" } },
371 { "%f\"o\"o%=ccc\n" STR_SECTION, "aaa", { "ccc" } },
372 { "abc=%bar;bla%\n" STR_SECTION, "abc", { "%bar" } },
373 { "loop=%loop%\n" STR_SECTION, "loop", { "%loop2%" } },
374 { "%per%%cent%=100\n" STR_SECTION, "12", { "100" } },
375 { "a=%big%\n" STR_SECTION, "a", { A400 } },
376 { "a=%verybig%\n" STR_SECTION, "a", { A511 } }, /* truncated to 511, not on Vista/W2K8 */
377 { "a=%big%%big%%big%%big%\n" STR_SECTION, "a", { A400 A400 A400 A400 } },
378 { "a=%big%%big%%big%%big%%big%%big%%big%%big%%big%\n" STR_SECTION, "a", { A400 A400 A400 A400 A400 A400 A400 A400 A400 } },
379 { "a=%big%%big%%big%%big%%big%%big%%big%%big%%big%%big%%big%\n" STR_SECTION, "a", { A4097 /*MAX_INF_STRING_LENGTH+1*/ } },
380
381 /* Prove expansion of system entries removes extra \'s and string
382 replacements doesn't */
383 { "ab=\"%24%\"\n" STR_SECTION, "ab", { "C:\\" } },
384 { "ab=\"%mydrive%\"\n" STR_SECTION, "ab", { "C:\\" } },
385 { "ab=\"%24%\\fred\"\n" STR_SECTION, "ab", { "C:\\fred" } },
386 { "ab=\"%mydrive%\\fred\"\n" STR_SECTION,"ab", { "C:\\\\fred" } },
387 /* Confirm duplicate \'s kept */
388 { "ab=\"%24%\\\\fred\"", "ab", { "C:\\\\fred" } },
389 { "ab=C:\\\\FRED", "ab", { "C:\\\\FRED" } },
391
392/* check the key of a certain line */
393static const char *check_key( INFCONTEXT *context, const char *wanted )
394{
395 const char *key = get_string_field( context, 0 );
397
398 if (!key)
399 {
400 ok( !wanted, "missing key %s\n", wanted );
401 ok( err == 0 || err == ERROR_INVALID_PARAMETER, "last error set to %u\n", err );
402 }
403 else
404 {
405 ok( !strcmp( key, wanted ), "bad key %s/%s\n", key, wanted );
406 ok( err == 0, "last error set to %u\n", err );
407 }
408 return key;
409}
410
411static void test_key_names(void)
412{
414 const char *line;
415 unsigned int i, index, count;
417 HINF hinf;
418 DWORD err;
419 BOOL ret;
421
422 for (i = 0; i < ARRAY_SIZE(key_names); i++)
423 {
424 strcpy( buffer, STD_HEADER "[Test]\n" );
426 SetLastError( 0xdeadbeef );
428 ok( hinf != INVALID_HANDLE_VALUE, "line %u: open failed err %u\n", i, GetLastError() );
429 if (hinf == INVALID_HANDLE_VALUE) continue;
430
431 ret = SetupFindFirstLineA( hinf, "Test", 0, &context );
432 ok(ret, "SetupFindFirstLineA failed: le=%u\n", GetLastError());
433 if (!ret)
434 {
435 SetupCloseInfFile( hinf );
436 continue;
437 }
438
440
441 buffer[0] = buffer[1] = 0; /* build the full line */
442 for (index = 0; ; index++)
443 {
444 const char *field = get_string_field( &context, index + 1 );
445 err = GetLastError();
446 if (field)
447 {
448 ok( err == 0, "line %u: bad error %u\n", i, err );
449 if (key_names[i].fields[index])
450 {
451 if (i == 49)
453 !strcmp( field, A1200), /* Vista, W2K8 */
454 "line %u: bad field %s/%s\n",
456 else if (i == 52)
458 !strcmp( field, A4096), /* Win10 >= 1709 */
459 "line %u: bad field %s/%s\n",
461 else /* don't compare drive letter of paths */
462 if (field[0] && field[1] == ':' && field[2] == '\\')
463 ok( !strcmp( field + 1, key_names[i].fields[index] + 1 ),
464 "line %u: bad field %s/%s\n",
466 else
467 ok( !strcmp( field, key_names[i].fields[index] ), "line %u: bad field %s/%s\n",
469 }
470 else
471 ok( 0, "line %u: got extra field %s\n", i, field );
472 strcat( buffer, "," );
473 strcat( buffer, field );
474 }
475 else
476 {
477 ok( err == 0 || err == ERROR_INVALID_PARAMETER,
478 "line %u: bad error %u\n", i, err );
479 if (key_names[i].fields[index])
480 ok( 0, "line %u: missing field %s\n", i, key_names[i].fields[index] );
481 }
482 if (!key_names[i].fields[index]) break;
483 }
485 ok( count == index, "line %u: bad count %d/%d\n", i, index, count );
486
488 ok( line != NULL, "line %u: SetupGetLineText failed\n", i );
489 if (line) ok( !strcmp( line, buffer+1 ), "line %u: bad text %s/%s\n", i, line, buffer+1 );
490
491 SetupCloseInfFile( hinf );
492 }
493
494}
495
496static void test_close_inf_file(void)
497{
498 SetLastError(0xdeadbeef);
500 ok(GetLastError() == 0xdeadbeef ||
501 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
502 "Expected 0xdeadbeef, got %u\n", GetLastError());
503
504 SetLastError(0xdeadbeef);
506 ok(GetLastError() == 0xdeadbeef ||
507 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
508 "Expected 0xdeadbeef, got %u\n", GetLastError());
509}
510
511static const char *contents = "[Version]\n"
512 "Signature=\"$Windows NT$\"\n"
513 "FileVersion=5.1.1.2\n"
514 "[FileBranchInfo]\n"
515 "RTMQFE=\"%RTMGFE_NAME%\",SP1RTM,"A4097"\n"
516 "[Strings]\n"
517 "RTMQFE_NAME = \"RTMQFE\"\n";
518
519static const CHAR getfield_resA[][20] =
520{
521 "RTMQFE",
522 "%RTMGFE_NAME%",
523 "SP1RTM",
524};
525
526static const WCHAR getfield_resW[][20] =
527{
528 {'R','T','M','Q','F','E',0},
529 {'%','R','T','M','G','F','E','_','N','A','M','E','%',0},
530 {'S','P','1','R','T','M',0},
531};
532
533static void test_pSetupGetField(void)
534{
535 UINT err;
536 BOOL ret;
537 HINF hinf;
538 LPCSTR fieldA;
539 LPCWSTR fieldW;
541 int i;
542 int len;
543 BOOL unicode = TRUE;
544
545 SetLastError(0xdeadbeef);
548 {
549 win_skip("Using A-functions instead of W\n");
550 unicode = FALSE;
551 }
552
553 hinf = test_file_contents( contents, &err );
554 ok( hinf != NULL, "Expected valid INF file\n" );
555
556 ret = SetupFindFirstLineA( hinf, "FileBranchInfo", NULL, &context );
557 ok( ret, "Failed to find first line\n" );
558
559 /* native Windows crashes if a NULL context is sent in */
560
561 for ( i = 0; i < 3; i++ )
562 {
563 if (unicode)
564 {
565 fieldW = pSetupGetFieldW( &context, i );
566 ok( fieldW != NULL, "Failed to get field %i\n", i );
567 ok( !lstrcmpW( getfield_resW[i], fieldW ), "Wrong string returned\n" );
568 }
569 else
570 {
571 fieldA = pSetupGetFieldA( &context, i );
572 ok( fieldA != NULL, "Failed to get field %i\n", i );
573 ok( !lstrcmpA( getfield_resA[i], fieldA ), "Wrong string returned\n" );
574 }
575 }
576
577 if (unicode)
578 {
579 fieldW = pSetupGetFieldW( &context, 3 );
580 ok( fieldW != NULL, "Failed to get field 3\n" );
581 len = lstrlenW( fieldW );
582 ok( len == 511 || /* NT4, W2K, XP and W2K3 */
583 len == 4096, /* Vista */
584 "Unexpected length, got %d\n", len );
585
586 fieldW = pSetupGetFieldW( &context, 4 );
587 ok( fieldW == NULL, "Expected NULL, got %p\n", fieldW );
589 "Expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() );
590 }
591 else
592 {
593 fieldA = pSetupGetFieldA( &context, 3 );
594 ok( fieldA != NULL, "Failed to get field 3\n" );
595 len = lstrlenA( fieldA );
596 ok( len == 511, /* Win9x, WinME */
597 "Unexpected length, got %d\n", len );
598
599 fieldA = pSetupGetFieldA( &context, 4 );
600 ok( fieldA == NULL, "Expected NULL, got %p\n", fieldA );
602 "Expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() );
603 }
604
605 SetupCloseInfFile( hinf );
606}
607
608static void test_SetupGetIntField(void)
609{
610 static const struct
611 {
612 const char *key;
613 const char *fields;
614 DWORD index;
615 INT value;
616 DWORD err;
617 } keys[] =
618 {
619 /* key fields index expected int errorcode */
620 { "Key", "48", 1, 48, ERROR_SUCCESS },
621 { "Key", "48", 0, -1, ERROR_INVALID_DATA },
622 { "123", "48", 0, 123, ERROR_SUCCESS },
623 { "Key", "0x4", 1, 4, ERROR_SUCCESS },
624 { "Key", "Field1", 1, -1, ERROR_INVALID_DATA },
625 { "Key", "Field1,34", 2, 34, ERROR_SUCCESS },
626 { "Key", "Field1,,Field3", 2, 0, ERROR_SUCCESS },
627 { "Key", "Field1,", 2, 0, ERROR_SUCCESS }
628 };
629 unsigned int i;
630
631 for (i = 0; i < ARRAY_SIZE(keys); i++)
632 {
633 HINF hinf;
636 UINT err;
637 BOOL retb;
638 INT intfield;
639
640 strcpy( buffer, STD_HEADER "[TestSection]\n" );
641 strcat( buffer, keys[i].key );
642 strcat( buffer, "=" );
643 strcat( buffer, keys[i].fields );
644 hinf = test_file_contents( buffer, &err);
645 ok( hinf != NULL, "Expected valid INF file\n" );
646
647 SetupFindFirstLineA( hinf, "TestSection", keys[i].key, &context );
648 SetLastError( 0xdeadbeef );
649 intfield = -1;
650 retb = SetupGetIntField( &context, keys[i].index, &intfield );
651 if ( keys[i].err == ERROR_SUCCESS )
652 {
653 ok( retb, "%u: Expected success\n", i );
655 GetLastError() == 0xdeadbeef /* win9x, NT4 */,
656 "%u: Expected ERROR_SUCCESS or 0xdeadbeef, got %u\n", i, GetLastError() );
657 }
658 else
659 {
660 ok( !retb, "%u: Expected failure\n", i );
661 ok( GetLastError() == keys[i].err,
662 "%u: Expected %d, got %u\n", i, keys[i].err, GetLastError() );
663 }
664 ok( intfield == keys[i].value, "%u: Expected %d, got %d\n", i, keys[i].value, intfield );
665
666 SetupCloseInfFile( hinf );
667 }
668}
669
670static void test_GLE(void)
671{
672 static const char *inf =
673 "[Version]\n"
674 "Signature=\"$Windows NT$\"\n"
675 "[Sectionname]\n"
676 "Keyname1=Field1,Field2,Field3\n"
677 "\n"
678 "Keyname2=Field4,Field5\n";
679 HINF hinf;
680 UINT err;
682 BOOL retb;
683 LONG retl;
686 DWORD retsize;
687
688 hinf = test_file_contents( inf, &err );
689 ok( hinf != NULL, "Expected valid INF file\n" );
690
691 SetLastError(0xdeadbeef);
692 retb = SetupFindFirstLineA( hinf, "ImNotThere", NULL, &context );
693 ok(!retb, "Expected failure\n");
695 "Expected ERROR_LINE_NOT_FOUND, got %08x\n", GetLastError());
696
697 SetLastError(0xdeadbeef);
698 retb = SetupFindFirstLineA( hinf, "ImNotThere", "ImNotThere", &context );
699 ok(!retb, "Expected failure\n");
701 "Expected ERROR_LINE_NOT_FOUND, got %08x\n", GetLastError());
702
703 SetLastError(0xdeadbeef);
704 retb = SetupFindFirstLineA( hinf, "Sectionname", NULL, &context );
705 ok(retb, "Expected success\n");
707 "Expected ERROR_SUCCESS, got %08x\n", GetLastError());
708
709 SetLastError(0xdeadbeef);
710 retb = SetupFindFirstLineA( hinf, "Sectionname", "ImNotThere", &context );
711 ok(!retb, "Expected failure\n");
713 "Expected ERROR_LINE_NOT_FOUND, got %08x\n", GetLastError());
714
715 SetLastError(0xdeadbeef);
716 retb = SetupFindFirstLineA( hinf, "Sectionname", "Keyname1", &context );
717 ok(retb, "Expected success\n");
719 "Expected ERROR_SUCCESS, got %08x\n", GetLastError());
720
721 SetLastError(0xdeadbeef);
722 retb = SetupFindNextMatchLineA( &context, "ImNotThere", &context );
723 ok(!retb, "Expected failure\n");
725 "Expected ERROR_LINE_NOT_FOUND, got %08x\n", GetLastError());
726
727 SetLastError(0xdeadbeef);
728 retb = SetupFindNextMatchLineA( &context, "Keyname2", &context );
729 ok(retb, "Expected success\n");
731 "Expected ERROR_SUCCESS, got %08x\n", GetLastError());
732
733 SetLastError(0xdeadbeef);
734 retl = SetupGetLineCountA( hinf, "ImNotThere");
735 ok(retl == -1, "Expected -1, got %d\n", retl);
737 "Expected ERROR_SECTION_NOT_FOUND, got %08x\n", GetLastError());
738
739 SetLastError(0xdeadbeef);
740 retl = SetupGetLineCountA( hinf, "Sectionname");
741 ok(retl == 2, "Expected 2, got %d\n", retl);
743 "Expected ERROR_SUCCESS, got %08x\n", GetLastError());
744
745 SetLastError(0xdeadbeef);
746 retb = SetupGetLineTextA( NULL, hinf, "ImNotThere", "ImNotThere", buf, bufsize, &retsize);
747 ok(!retb, "Expected failure\n");
749 "Expected ERROR_LINE_NOT_FOUND, got %08x\n", GetLastError());
750
751 SetLastError(0xdeadbeef);
752 retb = SetupGetLineTextA( NULL, hinf, "Sectionname", "ImNotThere", buf, bufsize, &retsize);
753 ok(!retb, "Expected failure\n");
755 "Expected ERROR_LINE_NOT_FOUND, got %08x\n", GetLastError());
756
757 SetLastError(0xdeadbeef);
758 retb = SetupGetLineTextA( NULL, hinf, "Sectionname", "Keyname1", buf, bufsize, &retsize);
759 ok(retb, "Expected success\n");
761 "Expected ERROR_SUCCESS, got %08x\n", GetLastError());
762
763 SetLastError(0xdeadbeef);
764 retb = SetupGetLineByIndexA( hinf, "ImNotThere", 1, &context );
765 ok(!retb, "Expected failure\n");
767 "Expected ERROR_LINE_NOT_FOUND, got %08x\n", GetLastError());
768
769 SetLastError(0xdeadbeef);
770 retb = SetupGetLineByIndexA( hinf, "Sectionname", 1, &context );
771 ok(retb, "Expected success\n");
773 "Expected ERROR_SUCCESS, got %08x\n", GetLastError());
774
775 SetLastError(0xdeadbeef);
776 retb = SetupGetLineByIndexA( hinf, "Sectionname", 3, &context );
777 ok(!retb, "Expected failure\n");
779 "Expected ERROR_LINE_NOT_FOUND, got %08x\n", GetLastError());
780
781 SetupCloseInfFile( hinf );
782}
783
785{
794 test_GLE();
796}
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define START_TEST(x)
Definition: atltest.h:75
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:33
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
#define GetProcAddress(x, y)
Definition: compat.h:753
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define GENERIC_READ
Definition: compat.h:135
#define FILE_SHARE_READ
Definition: compat.h:136
#define lstrlenW
Definition: compat.h:750
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4242
int WINAPI lstrcmpA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4194
int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4223
BOOL WINAPI SetupFindNextMatchLineA(PINFCONTEXT context_in, PCSTR key, PINFCONTEXT context_out)
Definition: parser.c:1672
void WINAPI SetupCloseInfFile(HINF hinf)
Definition: parser.c:1393
DWORD WINAPI SetupGetFieldCount(PINFCONTEXT context)
Definition: parser.c:1858
BOOL WINAPI SetupGetIntField(PINFCONTEXT context, DWORD index, PINT result)
Definition: parser.c:1933
BOOL WINAPI SetupFindFirstLineA(HINF hinf, PCSTR section, PCSTR key, INFCONTEXT *context)
Definition: parser.c:1564
HINF WINAPI SetupOpenInfFileA(PCSTR name, PCSTR class, DWORD style, UINT *error)
Definition: parser.c:1139
BOOL WINAPI SetupGetLineTextA(PINFCONTEXT context, HINF hinf, PCSTR section_name, PCSTR key_name, PSTR buffer, DWORD size, PDWORD required)
Definition: parser.c:1807
LONG WINAPI SetupGetLineCountA(HINF hinf, PCSTR name)
Definition: parser.c:1475
BOOL WINAPI SetupGetStringFieldA(PINFCONTEXT context, DWORD index, PSTR buffer, DWORD size, PDWORD required)
Definition: parser.c:1871
BOOL WINAPI SetupGetLineByIndexA(HINF hinf, PCSTR section, DWORD index, INFCONTEXT *context)
Definition: parser.c:1515
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint res
Definition: glext.h:9613
GLuint buffer
Definition: glext.h:5915
GLuint index
Definition: glext.h:6031
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLuint GLsizei bufsize
Definition: glext.h:7473
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
struct _INFCONTEXT * PINFCONTEXT
#define INF_STYLE_WIN4
Definition: infsupp.h:41
#define MAX_INF_STRING_LENGTH
Definition: infsupp.h:34
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
#define error(str)
Definition: mkdosfs.c:1605
#define CREATE_ALWAYS
Definition: disk.h:72
#define todo_wine_if(is_todo)
Definition: custom.c:76
static void test_key_names(void)
Definition: parser.c:411
static const char tmpfilename[]
Definition: parser.c:49
static const CHAR getfield_resA[][20]
Definition: parser.c:519
static const struct @1702 section_names[]
const char * fields[10]
Definition: parser.c:313
static void test_invalid_files(void)
Definition: parser.c:151
static void test_pSetupGetField(void)
Definition: parser.c:533
static const struct @1701 invalid_files[]
static const struct @1703 key_names[]
#define A400
Definition: parser.c:57
#define A1200
Definition: parser.c:60
static void test_GLE(void)
Definition: parser.c:670
static void init_function_pointers(void)
Definition: parser.c:38
#define A4097
Definition: parser.c:63
#define STD_HEADER
Definition: parser.c:65
static UINT PSTR DWORD UINT * need
Definition: parser.c:36
static UINT PSTR DWORD size
Definition: parser.c:36
static const char * check_key(INFCONTEXT *context, const char *wanted)
Definition: parser.c:393
static void test_SetupGetIntField(void)
Definition: parser.c:608
static void test_enum_sections(void)
Definition: parser.c:260
static const char * get_string_field(INFCONTEXT *context, DWORD index)
Definition: parser.c:85
const char * data
Definition: parser.c:104
static const WCHAR getfield_resW[][20]
Definition: parser.c:526
BOOL todo
Definition: parser.c:107
#define STR_SECTION
Definition: parser.c:67
static void test_close_inf_file(void)
Definition: parser.c:496
static HINF test_file_contents(const char *data, UINT *err_line)
Definition: parser.c:74
#define A4096
Definition: parser.c:62
#define A511
Definition: parser.c:61
const char * key
Definition: parser.c:312
UINT err_line
Definition: parser.c:106
static void test_section_names(void)
Definition: parser.c:225
static const char * contents
Definition: parser.c:511
#define A256
Definition: parser.c:56
#define A255
Definition: parser.c:52
static HMODULE hSetupAPI
Definition: parser.c:33
static const char * get_line_text(INFCONTEXT *context)
Definition: parser.c:92
unsigned int UINT
Definition: ndis.h:50
#define BOOL
Definition: nt_native.h:43
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define DWORD
Definition: nt_native.h:44
#define GENERIC_WRITE
Definition: nt_native.h:90
long LONG
Definition: pedump.c:60
#define err(...)
#define win_skip
Definition: test.h:163
#define ERROR_WRONG_INF_STYLE
Definition: setupapi.h:291
#define ERROR_BAD_SECTION_NAME_LINE
Definition: setupapi.h:288
#define ERROR_EXPECTED_SECTION_NAME
Definition: setupapi.h:287
#define ERROR_SECTION_NOT_FOUND
Definition: setupapi.h:293
#define ERROR_SECTION_NAME_TOO_LONG
Definition: setupapi.h:289
#define ERROR_LINE_NOT_FOUND
Definition: setupapi.h:294
Definition: http.c:7252
Definition: parser.c:44
Definition: copy.c:22
Definition: parser.c:49
Definition: import.c:81
Definition: parser.c:56
char * PSTR
Definition: typedefs.h:51
int32_t INT
Definition: typedefs.h:58
Definition: pdh_main.c:94
int ret
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define WINAPI
Definition: msvc.h:6
#define ERROR_INVALID_USER_BUFFER
Definition: winerror.h:1091
#define ERROR_INVALID_DATA
Definition: winerror.h:116
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
char CHAR
Definition: xmlstorage.h:175