📄 parser.c
字号:
/*
* INF file parsing tests
*
* Copyright 2002, 2005 Alexandre Julliard for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winreg.h"
#include "setupapi.h"
#include "wine/test.h"
static const char tmpfile[] = ".\\tmp.inf";
/* some large strings */
#define A255 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
#define A256 "a" A255
#define A400 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
"aaaaaaaaaaaaaaaa" A256
#define A511 A255 A256
#define A4097 "a" A256 A256 A256 A256 A256 A256 A256 A256 A256 A256 A256 A256 A256 A256 A256 A256
#define STD_HEADER "[Version]\r\nSignature=\"$CHICAGO$\"\r\n"
#define STR_SECTION "[Strings]\nfoo=aaa\nbar=bbb\nloop=%loop2%\nloop2=%loop%\n" \
"per%%cent=abcd\nper=1\ncent=2\n22=foo\n" \
"big=" A400 "\n" \
"verybig=" A400 A400 A400 "\n"
/* create a new file with specified contents and open it */
static HINF test_file_contents( const char *data, UINT *err_line )
{
DWORD res;
HANDLE handle = CreateFileA( tmpfile, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0 );
if (handle == INVALID_HANDLE_VALUE) return 0;
if (!WriteFile( handle, data, strlen(data), &res, NULL )) trace( "write error\n" );
CloseHandle( handle );
return SetupOpenInfFileA( tmpfile, 0, INF_STYLE_WIN4, err_line );
}
static const char *get_string_field( INFCONTEXT *context, DWORD index )
{
static char buffer[MAX_INF_STRING_LENGTH+32];
if (SetupGetStringFieldA( context, index, buffer, sizeof(buffer), NULL )) return buffer;
return NULL;
}
static const char *get_line_text( INFCONTEXT *context )
{
static char buffer[MAX_INF_STRING_LENGTH+32];
if (SetupGetLineTextA( context, 0, 0, 0, buffer, sizeof(buffer), NULL )) return buffer;
return NULL;
}
/* Test various valid/invalid file formats */
static const struct
{
const char *data;
DWORD error;
UINT err_line;
int todo;
} invalid_files[] =
{
/* file contents expected error (or 0) errline todo */
{ "\r\n", ERROR_WRONG_INF_STYLE, 0, 0 },
{ "abcd\r\n", ERROR_WRONG_INF_STYLE, 0, 1 },
{ "[Version]\r\n", ERROR_WRONG_INF_STYLE, 0, 0 },
{ "[Version]\nSignature=", ERROR_WRONG_INF_STYLE, 0, 0 },
{ "[Version]\nSignature=foo", ERROR_WRONG_INF_STYLE, 0, 0 },
{ "[version]\nsignature=$chicago$", 0, 0, 0 },
{ "[VERSION]\nSIGNATURE=$CHICAGO$", 0, 0, 0 },
{ "[Version]\nSignature=$chicago$,abcd", 0, 0, 0 },
{ "[Version]\nabc=def\nSignature=$chicago$", 0, 0, 0 },
{ "[Version]\nabc=def\n[Version]\nSignature=$chicago$", 0, 0, 0 },
{ STD_HEADER, 0, 0, 0 },
{ STD_HEADER "[]\r\n", 0, 0, 0 },
{ STD_HEADER "]\r\n", 0, 0, 0 },
{ STD_HEADER "[" A255 "]\r\n", 0, 0, 0 },
{ STD_HEADER "[ab\r\n", ERROR_BAD_SECTION_NAME_LINE, 3, 0 },
{ STD_HEADER "\n\n[ab\x1a]\n", ERROR_BAD_SECTION_NAME_LINE, 5, 0 },
{ STD_HEADER "[" A256 "]\r\n", ERROR_SECTION_NAME_TOO_LONG, 3, 0 },
{ "[abc]\n" STD_HEADER, 0, 0, 0 },
{ "abc\r\n" STD_HEADER, ERROR_EXPECTED_SECTION_NAME, 1, 0 },
{ ";\n;\nabc\r\n" STD_HEADER, ERROR_EXPECTED_SECTION_NAME, 3, 0 },
{ ";\n;\nab\nab\n" STD_HEADER, ERROR_EXPECTED_SECTION_NAME, 3, 0 },
{ ";aa\n;bb\n" STD_HEADER, 0, 0, 0 },
{ STD_HEADER " [TestSection\x00] \n", ERROR_BAD_SECTION_NAME_LINE, 3, 0 },
{ STD_HEADER " [Test\x00Section] \n", ERROR_BAD_SECTION_NAME_LINE, 3, 0 },
{ STD_HEADER " [TestSection\x00] \n", ERROR_BAD_SECTION_NAME_LINE, 3, 0 },
{ STD_HEADER " [Test\x00Section] \n", ERROR_BAD_SECTION_NAME_LINE, 3, 0 },
};
static void test_invalid_files(void)
{
unsigned int i;
UINT err_line;
HINF hinf;
DWORD err;
for (i = 0; i < sizeof(invalid_files)/sizeof(invalid_files[0]); i++)
{
SetLastError( 0xdeadbeef );
err_line = 0xdeadbeef;
hinf = test_file_contents( invalid_files[i].data, &err_line );
err = GetLastError();
trace( "hinf=%p err=%lx line=%d\n", hinf, err, err_line );
if (invalid_files[i].error) /* should fail */
{
ok( hinf == INVALID_HANDLE_VALUE, "file %u: Open succeeded\n", i );
if (invalid_files[i].todo) todo_wine
{
ok( err == invalid_files[i].error, "file %u: Bad error %lx/%lx\n",
i, err, invalid_files[i].error );
ok( err_line == invalid_files[i].err_line, "file %u: Bad error line %d/%d\n",
i, err_line, invalid_files[i].err_line );
}
else
{
ok( err == invalid_files[i].error, "file %u: Bad error %lx/%lx\n",
i, err, invalid_files[i].error );
ok( err_line == invalid_files[i].err_line, "file %u: Bad error line %d/%d\n",
i, err_line, invalid_files[i].err_line );
}
}
else /* should succeed */
{
ok( hinf != INVALID_HANDLE_VALUE, "file %u: Open failed\n", i );
ok( err == 0, "file %u: Error code set to %lx\n", i, err );
}
if (hinf != INVALID_HANDLE_VALUE) SetupCloseInfFile( hinf );
}
}
/* Test various section names */
static const struct
{
const char *data;
const char *section;
DWORD error;
} section_names[] =
{
/* file contents section name error code */
{ STD_HEADER "[TestSection]", "TestSection", 0 },
{ STD_HEADER "[TestSection]\n", "TestSection", 0 },
{ STD_HEADER "[TESTSECTION]\r\n", "TestSection", 0 },
{ STD_HEADER "[TestSection]\n[abc]", "testsection", 0 },
{ STD_HEADER ";[TestSection]\n", "TestSection", ERROR_SECTION_NOT_FOUND },
{ STD_HEADER "[TestSection]\n", "Bad name", ERROR_SECTION_NOT_FOUND },
/* spaces */
{ STD_HEADER "[TestSection] \r\n", "TestSection", 0 },
{ STD_HEADER " [TestSection]\r\n", "TestSection", 0 },
{ STD_HEADER " [TestSection] dummy\r\n", "TestSection", 0 },
{ STD_HEADER " [TestSection] [foo]\r\n", "TestSection", 0 },
{ STD_HEADER " [ Test Section ] dummy\r\n", " Test Section ", 0 },
{ STD_HEADER "[TestSection] \032\ndummy", "TestSection", 0 },
{ STD_HEADER "[TestSection] \n\032dummy", "TestSection", 0 },
/* special chars in section name */
{ STD_HEADER "[Test[Section]\r\n", "Test[Section", 0 },
{ STD_HEADER "[Test[S]ection]\r\n", "Test[S", 0 },
{ STD_HEADER "[Test[[[Section]\r\n", "Test[[[Section", 0 },
{ STD_HEADER "[]\r\n", "", 0 },
{ STD_HEADER "[[[]\n", "[[", 0 },
{ STD_HEADER "[Test\"Section]\r\n", "Test\"Section", 0 },
{ STD_HEADER "[Test\\Section]\r\n", "Test\\Section", 0 },
{ STD_HEADER "[Test\\ Section]\r\n", "Test\\ Section", 0 },
{ STD_HEADER "[Test;Section]\r\n", "Test;Section", 0 },
/* various control chars */
{ STD_HEADER " [Test\r\b\tSection] \n", "Test\r\b\tSection", 0 },
/* nulls */
};
static void test_section_names(void)
{
unsigned int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -