From d221b534b9a5ac7d352f4fb01965ca2a25c1ba3b Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sun, 22 Sep 2013 16:30:18 +0000 Subject: [PATCH] [MSI] * Sync with Wine 1.7.1. CORE-7469 svn path=/trunk/; revision=60307 --- reactos/dll/win32/msi/CMakeLists.txt | 4 - reactos/dll/win32/msi/action.c | 83 ++- reactos/dll/win32/msi/cond.tab.c | 845 +++++++++++---------- reactos/dll/win32/msi/cond.y | 10 +- reactos/dll/win32/msi/custom.c | 7 +- reactos/dll/win32/msi/database.c | 6 + reactos/dll/win32/msi/dialog.c | 713 ++++++++++++++---- reactos/dll/win32/msi/events.c | 453 ------------ reactos/dll/win32/msi/files.c | 10 +- reactos/dll/win32/msi/media.c | 25 +- reactos/dll/win32/msi/msi_main.c | 1 + reactos/dll/win32/msi/msipriv.h | 19 +- reactos/dll/win32/msi/package.c | 24 +- reactos/dll/win32/msi/patch.c | 22 +- reactos/dll/win32/msi/query.h | 13 + reactos/dll/win32/msi/script.c | 19 +- reactos/dll/win32/msi/sql.tab.c | 1021 +++++++++++++------------- reactos/dll/win32/msi/sql.tab.h | 16 +- reactos/dll/win32/msi/sql.y | 23 +- reactos/dll/win32/msi/table.c | 16 +- reactos/media/doc/README.WINE | 2 +- 21 files changed, 1735 insertions(+), 1597 deletions(-) delete mode 100644 reactos/dll/win32/msi/events.c diff --git a/reactos/dll/win32/msi/CMakeLists.txt b/reactos/dll/win32/msi/CMakeLists.txt index b8ba0f34668..0a6098d8bf8 100644 --- a/reactos/dll/win32/msi/CMakeLists.txt +++ b/reactos/dll/win32/msi/CMakeLists.txt @@ -24,7 +24,6 @@ list(APPEND SOURCE dialog.c distinct.c drop.c - events.c files.c font.c format.c @@ -62,12 +61,9 @@ if(MSVC) endif() add_library(msi SHARED ${SOURCE}) - add_idl_headers(msi_idlheader msiserver.idl) add_typelib(msiserver.idl) - set_source_files_properties(msi.rc PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/msiserver.tlb) - set_module_type(msi win32dll) target_link_libraries(msi uuid ${PSEH_LIB} wine) add_dependencies(msi msi_idlheader) diff --git a/reactos/dll/win32/msi/action.c b/reactos/dll/win32/msi/action.c index 740fb5d85f1..6c291bac434 100644 --- a/reactos/dll/win32/msi/action.c +++ b/reactos/dll/win32/msi/action.c @@ -336,6 +336,8 @@ UINT msi_parse_command_line( MSIPACKAGE *package, LPCWSTR szCommandLine, len = ptr2 - ptr; if (!len) return ERROR_INVALID_COMMAND_LINE; + while (ptr[len - 1] == ' ') len--; + prop = msi_alloc( (len + 1) * sizeof(WCHAR) ); memcpy( prop, ptr, len * sizeof(WCHAR) ); prop[len] = 0; @@ -411,18 +413,16 @@ static BOOL ui_sequence_exists( MSIPACKAGE *package ) static const WCHAR query [] = { 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', '`','I','n','s','t','a','l','l','U','I','S','e','q','u','e','n','c','e','`',' ', - 'W','H','E','R','E',' ','`','S','e','q','u','e','n','c','e','`',' ','>',' ','0',' ', - 'O','R','D','E','R',' ','B','Y',' ','`','S','e','q','u','e','n','c','e','`',0}; + 'W','H','E','R','E',' ','`','S','e','q','u','e','n','c','e','`',' ','>',' ','0',0}; MSIQUERY *view; - UINT rc; + DWORD count = 0; - rc = MSI_DatabaseOpenViewW(package->db, query, &view); - if (rc == ERROR_SUCCESS) + if (!(MSI_DatabaseOpenViewW( package->db, query, &view ))) { - msiobj_release(&view->hdr); - return TRUE; + MSI_IterateRecords( view, &count, NULL, package ); + msiobj_release( &view->hdr ); } - return FALSE; + return count != 0; } UINT msi_set_sourcedir_props(MSIPACKAGE *package, BOOL replace) @@ -639,14 +639,12 @@ static UINT ACTION_ProcessUISequence(MSIPACKAGE *package) /******************************************************** * ACTION helper functions and functions that perform the actions *******************************************************/ -static BOOL ACTION_HandleCustomAction( MSIPACKAGE* package, LPCWSTR action, - UINT* rc, UINT script, BOOL force ) +static BOOL ACTION_HandleCustomAction( MSIPACKAGE *package, LPCWSTR action, UINT *rc, UINT script ) { BOOL ret=FALSE; UINT arc; - arc = ACTION_CustomAction(package, action, script, force); - + arc = ACTION_CustomAction( package, action, script ); if (arc != ERROR_CALL_NOT_IMPLEMENTED) { *rc = arc; @@ -2309,9 +2307,12 @@ static WCHAR *get_install_location( MSIPACKAGE *package ) WCHAR *path; if (!package->ProductCode) return NULL; - if (MSIREG_OpenInstallProps( package->ProductCode, package->Context, NULL, &hkey, FALSE )) - return NULL; - path = msi_reg_get_val_str( hkey, szInstallLocation ); + if (MSIREG_OpenInstallProps( package->ProductCode, package->Context, NULL, &hkey, FALSE )) return NULL; + if ((path = msi_reg_get_val_str( hkey, szInstallLocation )) && !path[0]) + { + msi_free( path ); + path = NULL; + } RegCloseKey( hkey ); return path; } @@ -2366,14 +2367,21 @@ void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL loa static UINT ACTION_CostFinalize(MSIPACKAGE *package) { - static const WCHAR query[] = { - 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', - '`','C','o','n','d','i','t','i','o','n','`',0}; - static const WCHAR szOutOfDiskSpace[] = { - 'O','u','t','O','f','D','i','s','k','S','p','a','c','e',0}; + static const WCHAR query[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + '`','C','o','n','d','i','t','i','o','n','`',0}; + static const WCHAR szOutOfDiskSpace[] = + {'O','u','t','O','f','D','i','s','k','S','p','a','c','e',0}; + static const WCHAR szPrimaryFolder[] = + {'P','R','I','M','A','R','Y','F','O','L','D','E','R',0}; + static const WCHAR szPrimaryVolumePath[] = + {'P','r','i','m','a','r','y','V','o','l','u','m','e','P','a','t','h',0}; + static const WCHAR szPrimaryVolumeSpaceAvailable[] = + {'P','r','i','m','a','r','y','V','o','l','u','m','e','S','p','a','c','e', + 'A','v','a','i','l','a','b','l','e',0}; MSICOMPONENT *comp; MSIQUERY *view; - LPWSTR level; + WCHAR *level, *primary_key, *primary_folder; UINT rc; TRACE("Building directory properties\n"); @@ -2416,10 +2424,35 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package) msi_set_property( package->db, szCostingComplete, szOne, -1 ); /* set default run level if not set */ level = msi_dup_property( package->db, szInstallLevel ); - if (!level) - msi_set_property( package->db, szInstallLevel, szOne, -1 ); + if (!level) msi_set_property( package->db, szInstallLevel, szOne, -1 ); msi_free(level); + if ((primary_key = msi_dup_property( package->db, szPrimaryFolder ))) + { + if ((primary_folder = msi_dup_property( package->db, primary_key ))) + { + if (((primary_folder[0] >= 'A' && primary_folder[0] <= 'Z') || + (primary_folder[0] >= 'a' && primary_folder[0] <= 'z')) && primary_folder[1] == ':') + { + ULARGE_INTEGER free; + + primary_folder[2] = 0; + if (GetDiskFreeSpaceExW( primary_folder, &free, NULL, NULL )) + { + static const WCHAR fmtW[] = {'%','l','u',0}; + WCHAR buf[21]; + + sprintfW( buf, fmtW, free.QuadPart / 512 ); + msi_set_property( package->db, szPrimaryVolumeSpaceAvailable, buf, -1 ); + } + toupperW( primary_folder[0] ); + msi_set_property( package->db, szPrimaryVolumePath, primary_folder, 2 ); + } + msi_free( primary_folder ); + } + msi_free( primary_key ); + } + /* FIXME: check volume disk space */ msi_set_property( package->db, szOutOfDiskSpace, szZero, -1 ); @@ -7619,7 +7652,7 @@ UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action, UINT script) handled = ACTION_HandleStandardAction(package, action, &rc); if (!handled) - handled = ACTION_HandleCustomAction(package, action, &rc, script, TRUE); + handled = ACTION_HandleCustomAction(package, action, &rc, script); if (!handled) { @@ -7641,7 +7674,7 @@ UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action, UINT scrip handled = ACTION_HandleStandardAction(package, action, &rc); if (!handled) - handled = ACTION_HandleCustomAction(package, action, &rc, script, FALSE); + handled = ACTION_HandleCustomAction(package, action, &rc, script); if( !handled && ACTION_DialogBox(package, action) == ERROR_SUCCESS ) handled = TRUE; diff --git a/reactos/dll/win32/msi/cond.tab.c b/reactos/dll/win32/msi/cond.tab.c index 3a0b5337b65..d4676a8aa05 100644 --- a/reactos/dll/win32/msi/cond.tab.c +++ b/reactos/dll/win32/msi/cond.tab.c @@ -1,10 +1,8 @@ +/* A Bison parser, made by GNU Bison 2.5. */ -/* A Bison parser, made by GNU Bison 2.4.1. */ - -/* Skeleton implementation for Bison's Yacc-like parsers in C +/* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -46,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.4.1" +#define YYBISON_VERSION "2.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -75,7 +73,7 @@ /* Copy the first part of user declarations. */ -/* Line 189 of yacc.c */ +/* Line 268 of yacc.c */ #line 1 "cond.y" @@ -125,11 +123,6 @@ #include //#include "wine/list.h" -#define YYLEX_PARAM info -#define YYPARSE_PARAM info - -static int cond_error(const char *str); - WINE_DEFAULT_DEBUG_CHANNEL(msi); typedef struct tag_yyinput @@ -149,6 +142,7 @@ struct cond_str { static LPWSTR COND_GetString( COND_input *info, const struct cond_str *str ); static LPWSTR COND_GetLiteral( COND_input *info, const struct cond_str *str ); static int cond_lex( void *COND_lval, COND_input *info); +static int cond_error( COND_input *info, const char *str); static void *cond_alloc( COND_input *cond, unsigned int sz ); static void *cond_track_mem( COND_input *cond, void *ptr, unsigned int sz ); @@ -193,8 +187,8 @@ static BOOL num_from_prop( LPCWSTR p, INT *val ) -/* Line 189 of yacc.c */ -#line 194 "cond.tab.c" +/* Line 268 of yacc.c */ +#line 188 "cond.tab.c" /* Enabling traces. */ #ifndef YYDEBUG @@ -268,8 +262,8 @@ static BOOL num_from_prop( LPCWSTR p, INT *val ) typedef union YYSTYPE { -/* Line 214 of yacc.c */ -#line 116 "cond.y" +/* Line 293 of yacc.c */ +#line 114 "cond.y" struct cond_str str; LPWSTR string; @@ -277,8 +271,8 @@ typedef union YYSTYPE -/* Line 214 of yacc.c */ -#line 278 "cond.tab.c" +/* Line 293 of yacc.c */ +#line 272 "cond.tab.c" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -289,8 +283,8 @@ typedef union YYSTYPE /* Copy the second part of user declarations. */ -/* Line 264 of yacc.c */ -#line 290 "cond.tab.c" +/* Line 343 of yacc.c */ +#line 284 "cond.tab.c" #ifdef short # undef short @@ -340,7 +334,7 @@ typedef short int yytype_int16; #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ -# if YYENABLE_NLS +# if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) @@ -393,11 +387,11 @@ YYID (yyi) # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # endif @@ -420,24 +414,24 @@ YYID (yyi) # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif -# if (defined __cplusplus && ! defined _STDLIB_H \ +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif @@ -466,23 +460,7 @@ union yyalloc ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif +# define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of @@ -502,6 +480,26 @@ union yyalloc #endif +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + /* YYFINAL -- State number of the termination state. */ #define YYFINAL 28 /* YYLAST -- Last index in YYTABLE. */ @@ -594,12 +592,12 @@ static const yytype_int8 yyrhs[] = /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 140, 140, 146, 153, 157, 161, 165, 169, 176, - 180, 187, 191, 195, 200, 204, 213, 222, 226, 230, - 234, 238, 243, 248, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 277, 281, 288, 298, 302, 311, 320, 333, - 345, 358, 375, 385 + 0, 138, 138, 144, 151, 155, 159, 163, 167, 174, + 178, 185, 189, 193, 198, 202, 211, 220, 224, 228, + 232, 236, 241, 246, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, + 270, 271, 275, 279, 286, 296, 300, 309, 318, 331, + 343, 356, 373, 383 }; #endif @@ -656,8 +654,8 @@ static const yytype_uint8 yyr2[] = 1, 2, 1, 1 }; -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero +/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { @@ -700,8 +698,7 @@ static const yytype_int8 yypgoto[] = /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ + number is the opposite. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -1 static const yytype_uint8 yytable[] = { @@ -715,6 +712,12 @@ static const yytype_uint8 yytable[] = 66, 69 }; +#define yypact_value_is_default(yystate) \ + ((yystate) == (-15)) + +#define yytable_value_is_error(yytable_value) \ + YYID (0) + static const yytype_int8 yycheck[] = { 7, 1, 11, 12, 13, 14, 15, 16, 17, 18, @@ -752,9 +755,18 @@ static const yytype_uint8 yystos[] = /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ + Once GCC version 2 has supplanted version 1, this can go. However, + YYFAIL appears to be in use. Nevertheless, it is formally deprecated + in Bison 2.4.2's NEWS entry, where a plan to phase it out is + discussed. */ #define YYFAIL goto yyerrlab +#if defined YYFAIL + /* This is here to suppress warnings from the GCC cpp's + -Wunused-macros. Normally we don't worry about that warning, but + some users do, and we want to make it easy for users to remove + YYFAIL uses, which will produce warnings from Bison 2.5. */ +#endif #define YYRECOVERING() (!!yyerrstatus) @@ -764,13 +776,12 @@ do \ { \ yychar = (Token); \ yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ else \ { \ - yyerror (YY_("syntax error: cannot back up")); \ + yyerror (info, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) @@ -806,19 +817,10 @@ while (YYID (0)) #endif -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ +/* This macro is provided for backward compatibility. */ #ifndef YY_LOCATION_PRINT -# if YYLTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) #endif @@ -827,7 +829,7 @@ while (YYID (0)) #ifdef YYLEX_PARAM # define YYLEX yylex (&yylval, YYLEX_PARAM) #else -# define YYLEX yylex (&yylval) +# define YYLEX yylex (&yylval, info) #endif /* Enable debugging if requested. */ @@ -850,7 +852,7 @@ do { \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ - Type, Value); \ + Type, Value, info); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) @@ -864,17 +866,19 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, COND_input *info) #else static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep) +yy_symbol_value_print (yyoutput, yytype, yyvaluep, info) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; + COND_input *info; #endif { if (!yyvaluep) return; + YYUSE (info); # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); @@ -896,13 +900,14 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, COND_input *info) #else static void -yy_symbol_print (yyoutput, yytype, yyvaluep) +yy_symbol_print (yyoutput, yytype, yyvaluep, info) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; + COND_input *info; #endif { if (yytype < YYNTOKENS) @@ -910,7 +915,7 @@ yy_symbol_print (yyoutput, yytype, yyvaluep) else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - yy_symbol_value_print (yyoutput, yytype, yyvaluep); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, info); YYFPRINTF (yyoutput, ")"); } @@ -953,12 +958,13 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +yy_reduce_print (YYSTYPE *yyvsp, int yyrule, COND_input *info) #else static void -yy_reduce_print (yyvsp, yyrule) +yy_reduce_print (yyvsp, yyrule, info) YYSTYPE *yyvsp; int yyrule; + COND_input *info; #endif { int yynrhs = yyr2[yyrule]; @@ -972,7 +978,7 @@ yy_reduce_print (yyvsp, yyrule) YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) - ); + , info); YYFPRINTF (stderr, "\n"); } } @@ -980,7 +986,7 @@ yy_reduce_print (yyvsp, yyrule) # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ - yy_reduce_print (yyvsp, Rule); \ + yy_reduce_print (yyvsp, Rule, info); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that @@ -1010,7 +1016,6 @@ int yydebug; # define YYMAXDEPTH 10000 #endif - #if YYERROR_VERBOSE @@ -1113,115 +1118,142 @@ yytnamerr (char *yyres, const char *yystr) } # endif -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) { - int yyn = yypact[yystate]; + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = 0; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else + /* There are many possibilities here to consider: + - Assume YYFAIL is not used. It's too flawed to consider. See + + for details. YYERROR is fine as it does not invoke this + function. + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } - - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - - if (yysize_overflow) - return YYSIZE_MAXIMUM; - - if (yyresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - } - return yysize; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; } #endif /* YYERROR_VERBOSE */ - /*-----------------------------------------------. | Release the memory associated to this symbol. | @@ -1231,16 +1263,18 @@ yysyntax_error (char *yyresult, int yystate, int yychar) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, COND_input *info) #else static void -yydestruct (yymsg, yytype, yyvaluep) +yydestruct (yymsg, yytype, yyvaluep, info) const char *yymsg; int yytype; YYSTYPE *yyvaluep; + COND_input *info; #endif { YYUSE (yyvaluep); + YYUSE (info); if (!yymsg) yymsg = "Deleting"; @@ -1254,6 +1288,7 @@ yydestruct (yymsg, yytype, yyvaluep) } } + /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus @@ -1263,19 +1298,16 @@ int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus -int yyparse (void); +int yyparse (COND_input *info); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ - - - -/*-------------------------. -| yyparse or yypush_parse. | -`-------------------------*/ +/*----------. +| yyparse. | +`----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ @@ -1291,11 +1323,11 @@ yyparse (YYPARSE_PARAM) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int -yyparse (void) +yyparse (COND_input *info) #else int -yyparse () - +yyparse (info) + COND_input *info; #endif #endif { @@ -1462,7 +1494,7 @@ yybackup: /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) + if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ @@ -1493,8 +1525,8 @@ yybackup: yyn = yytable[yyn]; if (yyn <= 0) { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; + if (yytable_value_is_error (yyn)) + goto yyerrlab; yyn = -yyn; goto yyreduce; } @@ -1549,128 +1581,128 @@ yyreduce: { case 2: -/* Line 1455 of yacc.c */ -#line 141 "cond.y" +/* Line 1806 of yacc.c */ +#line 139 "cond.y" { COND_input* cond = (COND_input*) info; cond->result = (yyvsp[(1) - (1)].value); - ;} + } break; case 3: -/* Line 1455 of yacc.c */ -#line 146 "cond.y" +/* Line 1806 of yacc.c */ +#line 144 "cond.y" { COND_input* cond = (COND_input*) info; cond->result = MSICONDITION_NONE; - ;} + } break; case 4: -/* Line 1455 of yacc.c */ -#line 154 "cond.y" +/* Line 1806 of yacc.c */ +#line 152 "cond.y" { (yyval.value) = (yyvsp[(1) - (1)].value); - ;} + } break; case 5: -/* Line 1455 of yacc.c */ -#line 158 "cond.y" +/* Line 1806 of yacc.c */ +#line 156 "cond.y" { (yyval.value) = (yyvsp[(1) - (3)].value) || (yyvsp[(3) - (3)].value); - ;} + } break; case 6: -/* Line 1455 of yacc.c */ -#line 162 "cond.y" +/* Line 1806 of yacc.c */ +#line 160 "cond.y" { (yyval.value) = !(yyvsp[(1) - (3)].value) || (yyvsp[(3) - (3)].value); - ;} + } break; case 7: -/* Line 1455 of yacc.c */ -#line 166 "cond.y" +/* Line 1806 of yacc.c */ +#line 164 "cond.y" { (yyval.value) = ( (yyvsp[(1) - (3)].value) || (yyvsp[(3) - (3)].value) ) && !( (yyvsp[(1) - (3)].value) && (yyvsp[(3) - (3)].value) ); - ;} + } break; case 8: -/* Line 1455 of yacc.c */ -#line 170 "cond.y" +/* Line 1806 of yacc.c */ +#line 168 "cond.y" { (yyval.value) = ( (yyvsp[(1) - (3)].value) && (yyvsp[(3) - (3)].value) ) || ( !(yyvsp[(1) - (3)].value) && !(yyvsp[(3) - (3)].value) ); - ;} + } break; case 9: -/* Line 1455 of yacc.c */ -#line 177 "cond.y" +/* Line 1806 of yacc.c */ +#line 175 "cond.y" { (yyval.value) = (yyvsp[(1) - (1)].value); - ;} + } break; case 10: -/* Line 1455 of yacc.c */ -#line 181 "cond.y" +/* Line 1806 of yacc.c */ +#line 179 "cond.y" { (yyval.value) = (yyvsp[(1) - (3)].value) && (yyvsp[(3) - (3)].value); - ;} + } break; case 11: -/* Line 1455 of yacc.c */ -#line 188 "cond.y" +/* Line 1806 of yacc.c */ +#line 186 "cond.y" { (yyval.value) = (yyvsp[(2) - (2)].value) ? 0 : 1; - ;} + } break; case 12: -/* Line 1455 of yacc.c */ -#line 192 "cond.y" +/* Line 1806 of yacc.c */ +#line 190 "cond.y" { (yyval.value) = (yyvsp[(1) - (1)].value) ? 1 : 0; - ;} + } break; case 13: -/* Line 1455 of yacc.c */ -#line 196 "cond.y" +/* Line 1806 of yacc.c */ +#line 194 "cond.y" { (yyval.value) = ((yyvsp[(1) - (1)].string) && (yyvsp[(1) - (1)].string)[0]) ? 1 : 0; cond_free( (yyvsp[(1) - (1)].string) ); - ;} + } break; case 14: -/* Line 1455 of yacc.c */ -#line 201 "cond.y" +/* Line 1806 of yacc.c */ +#line 199 "cond.y" { (yyval.value) = compare_int( (yyvsp[(1) - (3)].value), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].value) ); - ;} + } break; case 15: -/* Line 1455 of yacc.c */ -#line 205 "cond.y" +/* Line 1806 of yacc.c */ +#line 203 "cond.y" { int num; if (num_from_prop( (yyvsp[(1) - (3)].string), &num )) @@ -1678,13 +1710,13 @@ yyreduce: else (yyval.value) = ((yyvsp[(2) - (3)].value) == COND_NE || (yyvsp[(2) - (3)].value) == COND_INE ); cond_free( (yyvsp[(1) - (3)].string) ); - ;} + } break; case 16: -/* Line 1455 of yacc.c */ -#line 214 "cond.y" +/* Line 1806 of yacc.c */ +#line 212 "cond.y" { int num; if (num_from_prop( (yyvsp[(3) - (3)].string), &num )) @@ -1692,243 +1724,243 @@ yyreduce: else (yyval.value) = ((yyvsp[(2) - (3)].value) == COND_NE || (yyvsp[(2) - (3)].value) == COND_INE ); cond_free( (yyvsp[(3) - (3)].string) ); - ;} + } break; case 17: -/* Line 1455 of yacc.c */ -#line 223 "cond.y" +/* Line 1806 of yacc.c */ +#line 221 "cond.y" { (yyval.value) = compare_and_free_strings( (yyvsp[(1) - (3)].string), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].string), TRUE ); - ;} + } break; case 18: -/* Line 1455 of yacc.c */ -#line 227 "cond.y" +/* Line 1806 of yacc.c */ +#line 225 "cond.y" { (yyval.value) = compare_and_free_strings( (yyvsp[(1) - (3)].string), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].string), TRUE ); - ;} + } break; case 19: -/* Line 1455 of yacc.c */ -#line 231 "cond.y" +/* Line 1806 of yacc.c */ +#line 229 "cond.y" { (yyval.value) = compare_and_free_strings( (yyvsp[(1) - (3)].string), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].string), TRUE ); - ;} + } break; case 20: -/* Line 1455 of yacc.c */ -#line 235 "cond.y" +/* Line 1806 of yacc.c */ +#line 233 "cond.y" { (yyval.value) = compare_and_free_strings( (yyvsp[(1) - (3)].string), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].string), FALSE ); - ;} + } break; case 21: -/* Line 1455 of yacc.c */ -#line 239 "cond.y" +/* Line 1806 of yacc.c */ +#line 237 "cond.y" { (yyval.value) = 0; cond_free( (yyvsp[(1) - (3)].string) ); - ;} + } break; case 22: -/* Line 1455 of yacc.c */ -#line 244 "cond.y" +/* Line 1806 of yacc.c */ +#line 242 "cond.y" { (yyval.value) = 0; cond_free( (yyvsp[(3) - (3)].string) ); - ;} + } break; case 23: -/* Line 1455 of yacc.c */ -#line 249 "cond.y" +/* Line 1806 of yacc.c */ +#line 247 "cond.y" { (yyval.value) = (yyvsp[(2) - (3)].value); - ;} + } break; case 24: -/* Line 1455 of yacc.c */ -#line 256 "cond.y" - { (yyval.value) = COND_EQ; ;} +/* Line 1806 of yacc.c */ +#line 254 "cond.y" + { (yyval.value) = COND_EQ; } break; case 25: -/* Line 1455 of yacc.c */ -#line 257 "cond.y" - { (yyval.value) = COND_NE; ;} +/* Line 1806 of yacc.c */ +#line 255 "cond.y" + { (yyval.value) = COND_NE; } break; case 26: -/* Line 1455 of yacc.c */ -#line 258 "cond.y" - { (yyval.value) = COND_LT; ;} +/* Line 1806 of yacc.c */ +#line 256 "cond.y" + { (yyval.value) = COND_LT; } break; case 27: -/* Line 1455 of yacc.c */ -#line 259 "cond.y" - { (yyval.value) = COND_GT; ;} +/* Line 1806 of yacc.c */ +#line 257 "cond.y" + { (yyval.value) = COND_GT; } break; case 28: -/* Line 1455 of yacc.c */ -#line 260 "cond.y" - { (yyval.value) = COND_LE; ;} +/* Line 1806 of yacc.c */ +#line 258 "cond.y" + { (yyval.value) = COND_LE; } break; case 29: -/* Line 1455 of yacc.c */ -#line 261 "cond.y" - { (yyval.value) = COND_GE; ;} +/* Line 1806 of yacc.c */ +#line 259 "cond.y" + { (yyval.value) = COND_GE; } break; case 30: -/* Line 1455 of yacc.c */ -#line 262 "cond.y" - { (yyval.value) = COND_SS; ;} +/* Line 1806 of yacc.c */ +#line 260 "cond.y" + { (yyval.value) = COND_SS; } break; case 31: -/* Line 1455 of yacc.c */ -#line 263 "cond.y" - { (yyval.value) = COND_IEQ; ;} +/* Line 1806 of yacc.c */ +#line 261 "cond.y" + { (yyval.value) = COND_IEQ; } break; case 32: -/* Line 1455 of yacc.c */ -#line 264 "cond.y" - { (yyval.value) = COND_INE; ;} +/* Line 1806 of yacc.c */ +#line 262 "cond.y" + { (yyval.value) = COND_INE; } break; case 33: -/* Line 1455 of yacc.c */ -#line 265 "cond.y" - { (yyval.value) = COND_ILT; ;} +/* Line 1806 of yacc.c */ +#line 263 "cond.y" + { (yyval.value) = COND_ILT; } break; case 34: -/* Line 1455 of yacc.c */ -#line 266 "cond.y" - { (yyval.value) = COND_IGT; ;} +/* Line 1806 of yacc.c */ +#line 264 "cond.y" + { (yyval.value) = COND_IGT; } break; case 35: -/* Line 1455 of yacc.c */ -#line 267 "cond.y" - { (yyval.value) = COND_ILE; ;} +/* Line 1806 of yacc.c */ +#line 265 "cond.y" + { (yyval.value) = COND_ILE; } break; case 36: -/* Line 1455 of yacc.c */ -#line 268 "cond.y" - { (yyval.value) = COND_IGE; ;} +/* Line 1806 of yacc.c */ +#line 266 "cond.y" + { (yyval.value) = COND_IGE; } break; case 37: -/* Line 1455 of yacc.c */ -#line 269 "cond.y" - { (yyval.value) = COND_ISS; ;} +/* Line 1806 of yacc.c */ +#line 267 "cond.y" + { (yyval.value) = COND_ISS; } break; case 38: -/* Line 1455 of yacc.c */ -#line 270 "cond.y" - { (yyval.value) = COND_LHS; ;} +/* Line 1806 of yacc.c */ +#line 268 "cond.y" + { (yyval.value) = COND_LHS; } break; case 39: -/* Line 1455 of yacc.c */ -#line 271 "cond.y" - { (yyval.value) = COND_RHS; ;} +/* Line 1806 of yacc.c */ +#line 269 "cond.y" + { (yyval.value) = COND_RHS; } break; case 40: -/* Line 1455 of yacc.c */ -#line 272 "cond.y" - { (yyval.value) = COND_ILHS; ;} +/* Line 1806 of yacc.c */ +#line 270 "cond.y" + { (yyval.value) = COND_ILHS; } break; case 41: -/* Line 1455 of yacc.c */ -#line 273 "cond.y" - { (yyval.value) = COND_IRHS; ;} +/* Line 1806 of yacc.c */ +#line 271 "cond.y" + { (yyval.value) = COND_IRHS; } break; case 42: -/* Line 1455 of yacc.c */ -#line 278 "cond.y" +/* Line 1806 of yacc.c */ +#line 276 "cond.y" { (yyval.string) = (yyvsp[(1) - (1)].string); - ;} + } break; case 43: -/* Line 1455 of yacc.c */ -#line 282 "cond.y" +/* Line 1806 of yacc.c */ +#line 280 "cond.y" { (yyval.string) = (yyvsp[(1) - (1)].string); - ;} + } break; case 44: -/* Line 1455 of yacc.c */ -#line 289 "cond.y" +/* Line 1806 of yacc.c */ +#line 287 "cond.y" { COND_input* cond = (COND_input*) info; (yyval.string) = COND_GetLiteral( cond, &(yyvsp[(1) - (1)].str) ); if( !(yyval.string) ) YYABORT; - ;} + } break; case 45: -/* Line 1455 of yacc.c */ -#line 299 "cond.y" +/* Line 1806 of yacc.c */ +#line 297 "cond.y" { (yyval.value) = (yyvsp[(1) - (1)].value); - ;} + } break; case 46: -/* Line 1455 of yacc.c */ -#line 303 "cond.y" +/* Line 1806 of yacc.c */ +#line 301 "cond.y" { COND_input* cond = (COND_input*) info; INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN; @@ -1936,13 +1968,13 @@ yyreduce: MSI_GetComponentStateW(cond->package, (yyvsp[(2) - (2)].string), &install, &action ); (yyval.value) = action; cond_free( (yyvsp[(2) - (2)].string) ); - ;} + } break; case 47: -/* Line 1455 of yacc.c */ -#line 312 "cond.y" +/* Line 1806 of yacc.c */ +#line 310 "cond.y" { COND_input* cond = (COND_input*) info; INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN; @@ -1950,13 +1982,13 @@ yyreduce: MSI_GetComponentStateW(cond->package, (yyvsp[(2) - (2)].string), &install, &action ); (yyval.value) = install; cond_free( (yyvsp[(2) - (2)].string) ); - ;} + } break; case 48: -/* Line 1455 of yacc.c */ -#line 321 "cond.y" +/* Line 1806 of yacc.c */ +#line 319 "cond.y" { COND_input* cond = (COND_input*) info; INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN; @@ -1968,13 +2000,13 @@ yyreduce: (yyval.value) = action; cond_free( (yyvsp[(2) - (2)].string) ); - ;} + } break; case 49: -/* Line 1455 of yacc.c */ -#line 334 "cond.y" +/* Line 1806 of yacc.c */ +#line 332 "cond.y" { COND_input* cond = (COND_input*) info; INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN; @@ -1982,13 +2014,13 @@ yyreduce: MSI_GetFeatureStateW(cond->package, (yyvsp[(2) - (2)].string), &install, &action ); (yyval.value) = install; cond_free( (yyvsp[(2) - (2)].string) ); - ;} + } break; case 50: -/* Line 1455 of yacc.c */ -#line 346 "cond.y" +/* Line 1806 of yacc.c */ +#line 344 "cond.y" { COND_input* cond = (COND_input*) info; UINT len; @@ -2000,13 +2032,13 @@ yyreduce: (yyval.string) = cond_track_mem( cond, (yyval.string), len ); } cond_free( (yyvsp[(1) - (1)].string) ); - ;} + } break; case 51: -/* Line 1455 of yacc.c */ -#line 359 "cond.y" +/* Line 1806 of yacc.c */ +#line 357 "cond.y" { COND_input* cond = (COND_input*) info; UINT len = GetEnvironmentVariableW( (yyvsp[(2) - (2)].string), NULL, 0 ); @@ -2019,25 +2051,25 @@ yyreduce: GetEnvironmentVariableW( (yyvsp[(2) - (2)].string), (yyval.string), len ); } cond_free( (yyvsp[(2) - (2)].string) ); - ;} + } break; case 52: -/* Line 1455 of yacc.c */ -#line 376 "cond.y" +/* Line 1806 of yacc.c */ +#line 374 "cond.y" { COND_input* cond = (COND_input*) info; (yyval.string) = COND_GetString( cond, &(yyvsp[(1) - (1)].str) ); if( !(yyval.string) ) YYABORT; - ;} + } break; case 53: -/* Line 1455 of yacc.c */ -#line 386 "cond.y" +/* Line 1806 of yacc.c */ +#line 384 "cond.y" { COND_input* cond = (COND_input*) info; LPWSTR szNum = COND_GetString( cond, &(yyvsp[(1) - (1)].str) ); @@ -2045,15 +2077,26 @@ yyreduce: YYABORT; (yyval.value) = atoiW( szNum ); cond_free( szNum ); - ;} + } break; -/* Line 1455 of yacc.c */ -#line 2051 "cond.tab.c" +/* Line 1806 of yacc.c */ +#line 2083 "cond.tab.c" default: break; } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); @@ -2081,44 +2124,47 @@ yyreduce: | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE - yyerror (YY_("syntax error")); + yyerror (info, YY_("syntax error")); #else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) - { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - } - } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (yymsg); - } - else - { - yyerror (YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (info, yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; } +# undef YYSYNTAX_ERROR #endif } @@ -2138,7 +2184,7 @@ yyerrlab: else { yydestruct ("Error: discarding", - yytoken, &yylval); + yytoken, &yylval, info); yychar = YYEMPTY; } } @@ -2177,7 +2223,7 @@ yyerrlab1: for (;;) { yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) + if (!yypact_value_is_default (yyn)) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) @@ -2194,7 +2240,7 @@ yyerrlab1: yydestruct ("Error: popping", - yystos[yystate], yyvsp); + yystos[yystate], yyvsp, info); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); @@ -2229,15 +2275,20 @@ yyabortlab: | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: - yyerror (YY_("memory exhausted")); + yyerror (info, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, info); + } /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); @@ -2245,7 +2296,7 @@ yyreturn: while (yyssp != yyss) { yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp); + yystos[*yyssp], yyvsp, info); YYPOPSTACK (1); } #ifndef yyoverflow @@ -2262,8 +2313,8 @@ yyreturn: -/* Line 1675 of yacc.c */ -#line 396 "cond.y" +/* Line 2067 of yacc.c */ +#line 394 "cond.y" @@ -2669,7 +2720,7 @@ static void cond_free( void *ptr ) } } -static int cond_error(const char *str) +static int cond_error( COND_input *info, const char *str ) { TRACE("%s\n", str ); return 0; diff --git a/reactos/dll/win32/msi/cond.y b/reactos/dll/win32/msi/cond.y index 97bb002aefb..fa5582566e4 100644 --- a/reactos/dll/win32/msi/cond.y +++ b/reactos/dll/win32/msi/cond.y @@ -42,11 +42,6 @@ #include "wine/unicode.h" #include "wine/list.h" -#define YYLEX_PARAM info -#define YYPARSE_PARAM info - -static int cond_error(const char *str); - WINE_DEFAULT_DEBUG_CHANNEL(msi); typedef struct tag_yyinput @@ -66,6 +61,7 @@ struct cond_str { static LPWSTR COND_GetString( COND_input *info, const struct cond_str *str ); static LPWSTR COND_GetLiteral( COND_input *info, const struct cond_str *str ); static int cond_lex( void *COND_lval, COND_input *info); +static int cond_error( COND_input *info, const char *str); static void *cond_alloc( COND_input *cond, unsigned int sz ); static void *cond_track_mem( COND_input *cond, void *ptr, unsigned int sz ); @@ -110,6 +106,8 @@ static BOOL num_from_prop( LPCWSTR p, INT *val ) %} +%lex-param { COND_input *info } +%parse-param { COND_input *info } %pure-parser %union @@ -798,7 +796,7 @@ static void cond_free( void *ptr ) } } -static int cond_error(const char *str) +static int cond_error( COND_input *info, const char *str ) { TRACE("%s\n", str ); return 0; diff --git a/reactos/dll/win32/msi/custom.c b/reactos/dll/win32/msi/custom.c index 9944f54c34f..ecc3b53afbb 100644 --- a/reactos/dll/win32/msi/custom.c +++ b/reactos/dll/win32/msi/custom.c @@ -881,6 +881,7 @@ static UINT HANDLE_CustomType50( MSIPACKAGE *package, const WCHAR *source, const TRACE("exe %s arg %s\n", debugstr_w(exe), debugstr_w(arg)); handle = execute_command( exe, arg, szCRoot ); + msi_free( exe ); msi_free( arg ); if (handle == INVALID_HANDLE_VALUE) return ERROR_SUCCESS; return wait_process_handle( package, type, handle, action ); @@ -1120,7 +1121,7 @@ static UINT HANDLE_CustomType53_54( MSIPACKAGE *package, const WCHAR *source, co return wait_thread_handle( info ); } -static BOOL action_type_matches_script( MSIPACKAGE *package, UINT type, UINT script ) +static BOOL action_type_matches_script( UINT type, UINT script ) { switch (script) { @@ -1174,7 +1175,7 @@ static UINT defer_custom_action( MSIPACKAGE *package, const WCHAR *action, UINT return ERROR_SUCCESS; } -UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL execute) +UINT ACTION_CustomAction( MSIPACKAGE *package, LPCWSTR action, UINT script ) { static const WCHAR query[] = { 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', @@ -1214,7 +1215,7 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL if (type & msidbCustomActionTypeNoImpersonate) WARN("msidbCustomActionTypeNoImpersonate not handled\n"); - if (!execute || !action_type_matches_script( package, type, script )) + if (!action_type_matches_script( type, script )) { rc = defer_custom_action( package, action, type ); goto end; diff --git a/reactos/dll/win32/msi/database.c b/reactos/dll/win32/msi/database.c index 731427dde78..f10889db2de 100644 --- a/reactos/dll/win32/msi/database.c +++ b/reactos/dll/win32/msi/database.c @@ -1380,7 +1380,10 @@ static UINT merge_verify_colnames(MSIQUERY *dbview, MSIQUERY *mergeview) r = MSI_ViewGetColumnInfo(mergeview, MSICOLINFO_NAMES, &mergerec); if (r != ERROR_SUCCESS) + { + msiobj_release(&dbrec->hdr); return r; + } count = MSI_RecordGetFieldCount(dbrec); for (i = 1; i <= count; i++) @@ -1405,7 +1408,10 @@ static UINT merge_verify_colnames(MSIQUERY *dbview, MSIQUERY *mergeview) r = MSI_ViewGetColumnInfo(mergeview, MSICOLINFO_TYPES, &mergerec); if (r != ERROR_SUCCESS) + { + msiobj_release(&dbrec->hdr); return r; + } count = MSI_RecordGetFieldCount(dbrec); for (i = 1; i <= count; i++) diff --git a/reactos/dll/win32/msi/dialog.c b/reactos/dll/win32/msi/dialog.c index bb84b37e208..403a0974fca 100644 --- a/reactos/dll/win32/msi/dialog.c +++ b/reactos/dll/win32/msi/dialog.c @@ -2,6 +2,7 @@ * Implementation of the Microsoft Installer (msi.dll) * * Copyright 2005 Mike McCormack for CodeWeavers + * Copyright 2005 Aric Stewart for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -43,6 +44,7 @@ #include #include #include +#include #include #include @@ -55,6 +57,7 @@ struct msi_control_tag; typedef struct msi_control_tag msi_control; typedef UINT (*msi_handler)( msi_dialog *, msi_control *, WPARAM ); typedef void (*msi_update)( msi_dialog *, msi_control * ); +typedef UINT (*control_event_handler)( msi_dialog *, const WCHAR *, const WCHAR * ); struct msi_control_tag { @@ -88,7 +91,7 @@ struct msi_dialog_tag { MSIPACKAGE *package; msi_dialog *parent; - msi_dialog_event_handler event_handler; + control_event_handler event_handler; BOOL finished; INT scale; DWORD attributes; @@ -103,6 +106,15 @@ struct msi_dialog_tag WCHAR name[1]; }; +struct subscriber +{ + struct list entry; + msi_dialog *dialog; + WCHAR *event; + WCHAR *control; + WCHAR *attribute; +}; + typedef UINT (*msi_dialog_control_func)( msi_dialog *dialog, MSIRECORD *rec ); struct control_handler { @@ -148,6 +160,7 @@ static const WCHAR szVolumeSelectCombo[] = { 'V','o','l','u','m','e','S','e','l' static const WCHAR szSelectionDescription[] = {'S','e','l','e','c','t','i','o','n','D','e','s','c','r','i','p','t','i','o','n',0}; static const WCHAR szSelectionPath[] = {'S','e','l','e','c','t','i','o','n','P','a','t','h',0}; static const WCHAR szProperty[] = {'P','r','o','p','e','r','t','y',0}; +static const WCHAR szHyperLink[] = {'H','y','p','e','r','L','i','n','k',0}; /* dialog sequencing */ @@ -249,16 +262,6 @@ static LPWSTR msi_dialog_dup_property( msi_dialog *dialog, LPCWSTR property, BOO return prop; } -msi_dialog *msi_dialog_get_parent( msi_dialog *dialog ) -{ - return dialog->parent; -} - -LPWSTR msi_dialog_get_name( msi_dialog *dialog ) -{ - return dialog->name; -} - /* * msi_dialog_get_style * @@ -407,9 +410,9 @@ static void msi_destroy_control( msi_control *t ) msi_free( t ); } -static msi_control *msi_dialog_create_window( msi_dialog *dialog, - MSIRECORD *rec, DWORD exstyle, LPCWSTR szCls, LPCWSTR name, LPCWSTR text, - DWORD style, HWND parent ) +static msi_control *dialog_create_window( msi_dialog *dialog, MSIRECORD *rec, DWORD exstyle, + const WCHAR *szCls, const WCHAR *name, const WCHAR *text, + DWORD style, HWND parent ) { DWORD x, y, width, height; LPWSTR font = NULL, title_font = NULL; @@ -618,24 +621,29 @@ static MSIFEATURE *msi_seltree_get_selected_feature( msi_control *control ) return msi_seltree_feature_from_item( control->hwnd, info->selected ); } -/* called from the Control Event subscription code */ -void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control, - LPCWSTR attribute, MSIRECORD *rec ) +static void dialog_handle_event( msi_dialog *dialog, const WCHAR *control, + const WCHAR *attribute, MSIRECORD *rec ) { msi_control* ctrl; - LPCWSTR font_text, text = NULL; - LPWSTR font; ctrl = msi_dialog_find_control( dialog, control ); if (!ctrl) return; if( !strcmpW( attribute, szText ) ) { + const WCHAR *font_text, *text = NULL; + WCHAR *font, *text_fmt = NULL; + font_text = MSI_RecordGetString( rec , 1 ); font = msi_dialog_get_style( font_text, &text ); - if (!text) text = szEmpty; + deformat_string( dialog->package, text, &text_fmt ); + if (text_fmt) text = text_fmt; + else text = szEmpty; + SetWindowTextW( ctrl->hwnd, text ); + msi_free( font ); + msi_free( text_fmt ); msi_dialog_check_messages( NULL ); } else if( !strcmpW( attribute, szProgress ) ) @@ -713,27 +721,65 @@ void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control, } } -static void msi_dialog_map_events(msi_dialog* dialog, LPCWSTR control) +static void event_subscribe( msi_dialog *dialog, const WCHAR *event, const WCHAR *control, const WCHAR *attribute ) { - static const WCHAR Query[] = { - 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + struct subscriber *sub; + + TRACE("event %s control %s attribute %s\n", debugstr_w(event), debugstr_w(control), debugstr_w(attribute)); + + LIST_FOR_EACH_ENTRY( sub, &dialog->package->subscriptions, struct subscriber, entry ) + { + if (!strcmpiW( sub->event, event ) && + !strcmpiW( sub->control, control ) && + !strcmpiW( sub->attribute, attribute )) + { + TRACE("already subscribed\n"); + return; + }; + } + if (!(sub = msi_alloc( sizeof(*sub) ))) return; + sub->dialog = dialog; + sub->event = strdupW( event ); + sub->control = strdupW( control ); + sub->attribute = strdupW( attribute ); + list_add_tail( &dialog->package->subscriptions, &sub->entry ); +} + +struct dialog_control +{ + msi_dialog *dialog; + const WCHAR *control; +}; + +static UINT map_event( MSIRECORD *row, void *param ) +{ + struct dialog_control *dc = param; + const WCHAR *event = MSI_RecordGetString( row, 3 ); + const WCHAR *attribute = MSI_RecordGetString( row, 4 ); + + event_subscribe( dc->dialog, event, dc->control, attribute ); + return ERROR_SUCCESS; +} + +static void dialog_map_events( msi_dialog *dialog, const WCHAR *control ) +{ + static const WCHAR queryW[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', '`','E','v','e','n','t','M','a','p','p','i','n','g','`',' ', - 'W','H','E','R','E',' ', - '`','D','i','a','l','o','g','_','`',' ','=',' ','\'','%','s','\'',' ', - 'A','N','D',' ', - '`','C','o','n','t','r','o','l','_','`',' ','=',' ','\'','%','s','\'',0 + 'W','H','E','R','E',' ','`','D','i','a','l','o','g','_','`',' ','=',' ','\'','%','s','\'',' ', + 'A','N','D',' ','`','C','o','n','t','r','o','l','_','`',' ','=',' ','\'','%','s','\'',0}; + MSIQUERY *view; + struct dialog_control dialog_control = + { + dialog, + control }; - MSIRECORD *row; - LPCWSTR event, attribute; - row = MSI_QueryGetRecord( dialog->package->db, Query, dialog->name, control ); - if (!row) - return; - - event = MSI_RecordGetString( row, 3 ); - attribute = MSI_RecordGetString( row, 4 ); - ControlEvent_SubscribeToEvent( dialog->package, dialog, event, control, attribute ); - msiobj_release( &row->hdr ); + if (!MSI_OpenQuery( dialog->package->db, &view, queryW, dialog->name, control )) + { + MSI_IterateRecords( view, NULL, map_event, &dialog_control ); + msiobj_release( &view->hdr ); + } } /* everything except radio buttons */ @@ -758,10 +804,9 @@ static msi_control *msi_dialog_add_control( msi_dialog *dialog, if( attributes & msidbControlAttributesSunken ) exstyle |= WS_EX_CLIENTEDGE; - msi_dialog_map_events(dialog, name); + dialog_map_events( dialog, name ); - return msi_dialog_create_window( dialog, rec, exstyle, szCls, name, - text, style, dialog->hwnd ); + return dialog_create_window( dialog, rec, exstyle, szCls, name, text, style, dialog->hwnd ); } struct msi_text_info @@ -856,9 +901,7 @@ static UINT msi_dialog_text_control( msi_dialog *dialog, MSIRECORD *rec ) (LONG_PTR)MSIText_WndProc ); SetPropW( control->hwnd, szButtonData, info ); - ControlEvent_SubscribeToEvent( dialog->package, dialog, - szSelectionPath, control_name, szSelectionPath ); - + event_subscribe( dialog, szSelectionPath, control_name, szSelectionPath ); return ERROR_SUCCESS; } @@ -916,7 +959,7 @@ static UINT msi_dialog_send_event( msi_dialog *dialog, LPCWSTR event, LPCWSTR ar deformat_string( dialog->package, event, &event_fmt ); deformat_string( dialog->package, arg, &arg_fmt ); - dialog->event_handler( dialog->package, event_fmt, arg_fmt, dialog ); + dialog->event_handler( dialog, event_fmt, arg_fmt ); msi_free( event_fmt ); msi_free( arg_fmt ); @@ -1137,7 +1180,7 @@ static UINT msi_dialog_line_control( msi_dialog *dialog, MSIRECORD *rec ) if( attributes & msidbControlAttributesSunken ) exstyle |= WS_EX_CLIENTEDGE; - msi_dialog_map_events(dialog, name); + dialog_map_events( dialog, name ); control = msi_alloc( FIELD_OFFSET(msi_control, name[strlenW( name ) + 1] )); if (!control) @@ -2072,8 +2115,7 @@ static UINT msi_dialog_progress_bar( msi_dialog *dialog, MSIRECORD *rec ) if( !control ) return ERROR_FUNCTION_FAILED; - ControlEvent_SubscribeToEvent( dialog->package, dialog, - szSetProgress, control->name, szProgress ); + event_subscribe( dialog, szSetProgress, control->name, szProgress ); return ERROR_SUCCESS; } @@ -2234,8 +2276,8 @@ static UINT msi_dialog_create_radiobutton( MSIRECORD *rec, LPVOID param ) if( ~attributes & msidbControlAttributesEnabled ) style |= WS_DISABLED; - control = msi_dialog_create_window( dialog, rec, 0, szButton, name, text, - style, group->parent->hwnd ); + control = dialog_create_window( dialog, rec, 0, szButton, name, text, style, + group->parent->hwnd ); if (!control) return ERROR_FUNCTION_FAILED; control->handler = msi_dialog_radiogroup_handler; @@ -2618,7 +2660,7 @@ static UINT msi_dialog_seltree_handler( msi_dialog *dialog, rec = MSI_CreateRecord( 1 ); MSI_RecordSetStringW( rec, 1, MSI_RecordGetString( row, 4 ) ); - ControlEvent_FireSubscribedEvent( dialog->package, szSelectionDescription, rec ); + msi_event_fire( dialog->package, szSelectionDescription, rec ); dir = MSI_RecordGetString( row, 7 ); if (dir) @@ -2634,7 +2676,7 @@ static UINT msi_dialog_seltree_handler( msi_dialog *dialog, else MSI_RecordSetStringW( rec, 1, NULL ); - ControlEvent_FireSubscribedEvent( dialog->package, szSelectionPath, rec ); + msi_event_fire( dialog->package, szSelectionPath, rec ); done: msiobj_release(&row->hdr); @@ -2678,8 +2720,7 @@ static UINT msi_dialog_selection_tree( msi_dialog *dialog, MSIRECORD *rec ) (LONG_PTR)MSISelectionTree_WndProc ); SetPropW( control->hwnd, szButtonData, info ); - ControlEvent_SubscribeToEvent( dialog->package, dialog, - szSelectionPath, control_name, szProperty ); + event_subscribe( dialog, szSelectionPath, control_name, szProperty ); /* initialize it */ msi_seltree_create_imagelist( control->hwnd ); @@ -3310,6 +3351,80 @@ static UINT msi_dialog_volumeselect_combo( msi_dialog *dialog, MSIRECORD *rec ) return ERROR_SUCCESS; } +static UINT msi_dialog_hyperlink_handler( msi_dialog *dialog, msi_control *control, WPARAM param ) +{ + static const WCHAR hrefW[] = {'h','r','e','f'}; + static const WCHAR openW[] = {'o','p','e','n',0}; + int len, len_href = sizeof(hrefW) / sizeof(hrefW[0]); + const WCHAR *p, *q; + WCHAR quote = 0; + LITEM item; + + item.mask = LIF_ITEMINDEX | LIF_URL; + item.iLink = 0; + item.szUrl[0] = 0; + + SendMessageW( control->hwnd, LM_GETITEM, 0, (LPARAM)&item ); + + p = item.szUrl; + while (*p && *p != '<') p++; + if (!*p++) return ERROR_SUCCESS; + if (toupperW( *p++ ) != 'A' || !isspaceW( *p++ )) return ERROR_SUCCESS; + while (*p && isspaceW( *p )) p++; + + len = strlenW( p ); + if (len > len_href && !memicmpW( p, hrefW, len_href )) + { + p += len_href; + while (*p && isspaceW( *p )) p++; + if (!*p || *p++ != '=') return ERROR_SUCCESS; + while (*p && isspaceW( *p )) p++; + + if (*p == '\"' || *p == '\'') quote = *p++; + q = p; + if (quote) + { + while (*q && *q != quote) q++; + if (*q != quote) return ERROR_SUCCESS; + } + else + { + while (*q && *q != '>' && !isspaceW( *q )) q++; + if (!*q) return ERROR_SUCCESS; + } + item.szUrl[q - item.szUrl] = 0; + ShellExecuteW( NULL, openW, p, NULL, NULL, SW_SHOWNORMAL ); + } + return ERROR_SUCCESS; +} + +static UINT msi_dialog_hyperlink( msi_dialog *dialog, MSIRECORD *rec ) +{ + msi_control *control; + DWORD style = WS_CHILD | WS_TABSTOP | WS_GROUP; + const WCHAR *text = MSI_RecordGetString( rec, 10 ); + int len = strlenW( text ); + LITEM item; + + control = msi_dialog_add_control( dialog, rec, WC_LINK, style ); + if (!control) + return ERROR_FUNCTION_FAILED; + + control->attributes = MSI_RecordGetInteger( rec, 8 ); + control->handler = msi_dialog_hyperlink_handler; + + item.mask = LIF_ITEMINDEX | LIF_STATE | LIF_URL; + item.iLink = 0; + item.state = LIS_ENABLED; + item.stateMask = LIS_ENABLED; + if (len < L_MAX_URL_LENGTH) strcpyW( item.szUrl, text ); + else item.szUrl[0] = 0; + + SendMessageW( control->hwnd, LM_SETITEM, 0, (LPARAM)&item ); + + return ERROR_SUCCESS; +} + static const struct control_handler msi_dialog_handler[] = { { szText, msi_dialog_text_control }, @@ -3332,6 +3447,7 @@ static const struct control_handler msi_dialog_handler[] = { szDirectoryList, msi_dialog_directory_list }, { szVolumeCostList, msi_dialog_volumecost_list }, { szVolumeSelectCombo, msi_dialog_volumeselect_combo }, + { szHyperLink, msi_dialog_hyperlink } }; #define NUM_CONTROL_TYPES (sizeof msi_dialog_handler/sizeof msi_dialog_handler[0]) @@ -3556,6 +3672,7 @@ static LRESULT msi_dialog_oncreate( HWND hwnd, LPCREATESTRUCTW cs ) if (!dialog->default_font) { dialog->default_font = strdupW(dfv); + msiobj_release( &rec->hdr ); if (!dialog->default_font) return -1; } @@ -3619,7 +3736,7 @@ static LRESULT msi_dialog_onnotify( msi_dialog *dialog, LPARAM param ) return 0; } -static void msi_dialog_setfocus( msi_dialog *dialog ) +static void dialog_setfocus( msi_dialog *dialog ) { HWND hwnd = dialog->hWndFocus; @@ -3653,11 +3770,11 @@ static LRESULT WINAPI MSIDialog_WndProc( HWND hwnd, UINT msg, if( LOWORD(wParam) == WA_INACTIVE ) dialog->hWndFocus = GetFocus(); else - msi_dialog_setfocus( dialog ); + dialog_setfocus( dialog ); return 0; case WM_SETFOCUS: - msi_dialog_setfocus( dialog ); + dialog_setfocus( dialog ); return 0; /* bounce back to our subclassed static control */ @@ -3673,6 +3790,57 @@ static LRESULT WINAPI MSIDialog_WndProc( HWND hwnd, UINT msg, return DefWindowProcW(hwnd, msg, wParam, lParam); } +static void process_pending_messages( HWND hdlg ) +{ + MSG msg; + + while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) + { + if (hdlg && IsDialogMessageW( hdlg, &msg )) continue; + TranslateMessage( &msg ); + DispatchMessageW( &msg ); + } +} + +static UINT dialog_run_message_loop( msi_dialog *dialog ) +{ + DWORD style; + HWND hwnd; + + if( uiThreadId != GetCurrentThreadId() ) + return SendMessageW( hMsiHiddenWindow, WM_MSI_DIALOG_CREATE, 0, (LPARAM) dialog ); + + /* create the dialog window, don't show it yet */ + style = WS_OVERLAPPED; + if( dialog->attributes & msidbDialogAttributesVisible ) + style |= WS_VISIBLE; + + hwnd = CreateWindowW( szMsiDialogClass, dialog->name, style, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + NULL, NULL, NULL, dialog ); + if( !hwnd ) + { + ERR("Failed to create dialog %s\n", debugstr_w( dialog->name )); + return ERROR_FUNCTION_FAILED; + } + + ShowWindow( hwnd, SW_SHOW ); + /* UpdateWindow( hwnd ); - and causes the transparent static controls not to paint */ + + if( dialog->attributes & msidbDialogAttributesModal ) + { + while( !dialog->finished ) + { + MsgWaitForMultipleObjects( 0, NULL, 0, INFINITE, QS_ALLINPUT ); + process_pending_messages( dialog->hwnd ); + } + } + else + return ERROR_IO_PENDING; + + return ERROR_SUCCESS; +} + static LRESULT WINAPI MSIHiddenWindowProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { @@ -3683,7 +3851,7 @@ static LRESULT WINAPI MSIHiddenWindowProc( HWND hwnd, UINT msg, switch (msg) { case WM_MSI_DIALOG_CREATE: - return msi_dialog_run_message_loop( dialog ); + return dialog_run_message_loop( dialog ); case WM_MSI_DIALOG_DESTROY: msi_dialog_destroy( dialog ); return 0; @@ -3691,7 +3859,7 @@ static LRESULT WINAPI MSIHiddenWindowProc( HWND hwnd, UINT msg, return DefWindowProcW( hwnd, msg, wParam, lParam ); } -static BOOL msi_dialog_register_class( void ) +static BOOL dialog_register_class( void ) { WNDCLASSW cls; @@ -3723,25 +3891,21 @@ static BOOL msi_dialog_register_class( void ) return TRUE; } -/* functions that interface to other modules within MSI */ - -msi_dialog *msi_dialog_create( MSIPACKAGE* package, - LPCWSTR szDialogName, msi_dialog *parent, - msi_dialog_event_handler event_handler ) +static msi_dialog *dialog_create( MSIPACKAGE *package, const WCHAR *name, msi_dialog *parent, + control_event_handler event_handler ) { MSIRECORD *rec = NULL; msi_dialog *dialog; - TRACE("%p %s\n", package, debugstr_w(szDialogName)); + TRACE("%s\n", debugstr_w(name)); - if (!hMsiHiddenWindow) - msi_dialog_register_class(); + if (!hMsiHiddenWindow) dialog_register_class(); /* allocate the structure for the dialog to use */ - dialog = msi_alloc_zero( FIELD_OFFSET( msi_dialog, name[strlenW( szDialogName ) + 1] )); + dialog = msi_alloc_zero( FIELD_OFFSET( msi_dialog, name[strlenW( name ) + 1] )); if( !dialog ) return NULL; - strcpyW( dialog->name, szDialogName ); + strcpyW( dialog->name, name ); dialog->parent = parent; msiobj_addref( &package->hdr ); dialog->package = package; @@ -3766,19 +3930,6 @@ msi_dialog *msi_dialog_create( MSIPACKAGE* package, return dialog; } -static void msi_process_pending_messages( HWND hdlg ) -{ - MSG msg; - - while( PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ) ) - { - if( hdlg && IsDialogMessageW( hdlg, &msg )) - continue; - TranslateMessage( &msg ); - DispatchMessageW( &msg ); - } -} - void msi_dialog_end_dialog( msi_dialog *dialog ) { TRACE("%p\n", dialog); @@ -3809,7 +3960,7 @@ void msi_dialog_check_messages( HANDLE handle ) /* there's two choices for the UI thread */ while (1) { - msi_process_pending_messages( NULL ); + process_pending_messages( NULL ); if( !handle ) break; @@ -3824,51 +3975,34 @@ void msi_dialog_check_messages( HANDLE handle ) } } -UINT msi_dialog_run_message_loop( msi_dialog *dialog ) -{ - DWORD style; - HWND hwnd; - - if( uiThreadId != GetCurrentThreadId() ) - return SendMessageW( hMsiHiddenWindow, WM_MSI_DIALOG_CREATE, 0, (LPARAM) dialog ); - - /* create the dialog window, don't show it yet */ - style = WS_OVERLAPPED; - if( dialog->attributes & msidbDialogAttributesVisible ) - style |= WS_VISIBLE; - - hwnd = CreateWindowW( szMsiDialogClass, dialog->name, style, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - NULL, NULL, NULL, dialog ); - if( !hwnd ) - { - ERR("Failed to create dialog %s\n", debugstr_w( dialog->name )); - return ERROR_FUNCTION_FAILED; - } - - ShowWindow( hwnd, SW_SHOW ); - /* UpdateWindow( hwnd ); - and causes the transparent static controls not to paint */ - - if( dialog->attributes & msidbDialogAttributesModal ) - { - while( !dialog->finished ) - { - MsgWaitForMultipleObjects( 0, NULL, 0, INFINITE, QS_ALLINPUT ); - msi_process_pending_messages( dialog->hwnd ); - } - } - else - return ERROR_IO_PENDING; - - return ERROR_SUCCESS; -} - -static void msi_dialog_do_preview( msi_dialog *dialog ) +static void dialog_do_preview( msi_dialog *dialog ) { TRACE("\n"); dialog->attributes |= msidbDialogAttributesVisible; dialog->attributes &= ~msidbDialogAttributesModal; - msi_dialog_run_message_loop( dialog ); + dialog_run_message_loop( dialog ); +} + +static void free_subscriber( struct subscriber *sub ) +{ + msi_free( sub->event ); + msi_free( sub->control ); + msi_free( sub->attribute ); + msi_free( sub ); +} + +static void event_cleanup_subscriptions( MSIPACKAGE *package, const WCHAR *dialog ) +{ + struct list *item, *next; + + LIST_FOR_EACH_SAFE( item, next, &package->subscriptions ) + { + struct subscriber *sub = LIST_ENTRY( item, struct subscriber, entry ); + + if (strcmpW( sub->dialog->name, dialog )) continue; + list_remove( &sub->entry ); + free_subscriber( sub ); + } } void msi_dialog_destroy( msi_dialog *dialog ) @@ -3888,7 +4022,7 @@ void msi_dialog_destroy( msi_dialog *dialog ) DestroyWindow( dialog->hwnd ); /* unsubscribe events */ - ControlEvent_CleanupDialogSubscriptions(dialog->package, dialog->name); + event_cleanup_subscriptions( dialog->package, dialog->name ); /* destroy the list of controls */ while( !list_empty( &dialog->controls ) ) @@ -3925,8 +4059,19 @@ void msi_dialog_unregister_class( void ) uiThreadId = 0; } -static UINT error_dialog_handler(MSIPACKAGE *package, LPCWSTR event, - LPCWSTR argument, msi_dialog* dialog) +void msi_event_cleanup_all_subscriptions( MSIPACKAGE *package ) +{ + struct list *item, *next; + + LIST_FOR_EACH_SAFE( item, next, &package->subscriptions ) + { + struct subscriber *sub = LIST_ENTRY( item, struct subscriber, entry ); + list_remove( &sub->entry ); + free_subscriber( sub ); + } +} + +static UINT error_dialog_handler( msi_dialog *dialog, const WCHAR *event, const WCHAR *argument ) { static const WCHAR end_dialog[] = {'E','n','d','D','i','a','l','o','g',0}; static const WCHAR error_abort[] = {'E','r','r','o','r','A','b','o','r','t',0}; @@ -3942,10 +4087,10 @@ static UINT error_dialog_handler(MSIPACKAGE *package, LPCWSTR event, if ( !strcmpW( argument, error_abort ) || !strcmpW( argument, error_cancel ) || !strcmpW( argument, error_no ) ) { - msi_set_property( package->db, result_prop, error_abort, -1 ); + msi_set_property( dialog->package->db, result_prop, error_abort, -1 ); } - ControlEvent_CleanupSubscriptions(package); + msi_event_cleanup_all_subscriptions( dialog->package ); msi_dialog_end_dialog( dialog ); return ERROR_SUCCESS; @@ -4007,13 +4152,12 @@ UINT msi_spawn_error_dialog( MSIPACKAGE *package, LPWSTR error_dialog, LPWSTR er if ( r != ERROR_SUCCESS ) return r; - dialog = msi_dialog_create( package, error_dialog, package->dialog, - error_dialog_handler ); + dialog = dialog_create( package, error_dialog, package->dialog, error_dialog_handler ); if ( !dialog ) return ERROR_FUNCTION_FAILED; dialog->finished = FALSE; - r = msi_dialog_run_message_loop( dialog ); + r = dialog_run_message_loop( dialog ); if ( r != ERROR_SUCCESS ) goto done; @@ -4092,8 +4236,7 @@ UINT WINAPI MsiEnableUIPreview( MSIHANDLE hdb, MSIHANDLE *phPreview ) return r; } -static UINT preview_event_handler( MSIPACKAGE *package, LPCWSTR event, - LPCWSTR argument, msi_dialog *dialog ) +static UINT preview_event_handler( msi_dialog *dialog, const WCHAR *event, const WCHAR *argument ) { MESSAGE("Preview dialog event '%s' (arg='%s')\n", debugstr_w(event), debugstr_w(argument)); return ERROR_SUCCESS; @@ -4110,9 +4253,9 @@ static UINT MSI_PreviewDialogW( MSIPREVIEW *preview, LPCWSTR szDialogName ) /* an empty name means we should just destroy the current preview dialog */ if (szDialogName) { - dialog = msi_dialog_create( preview->package, szDialogName, NULL, preview_event_handler ); + dialog = dialog_create( preview->package, szDialogName, NULL, preview_event_handler ); if (dialog) - msi_dialog_do_preview( dialog ); + dialog_do_preview( dialog ); else r = ERROR_FUNCTION_FAILED; } @@ -4165,3 +4308,303 @@ UINT WINAPI MsiPreviewBillboardA( MSIHANDLE hPreview, LPCSTR szControlName, LPCS FIXME("%d %s %s\n", hPreview, debugstr_a(szControlName), debugstr_a(szBillboard)); return ERROR_CALL_NOT_IMPLEMENTED; } + +typedef UINT (*event_handler)( msi_dialog *, const WCHAR * ); + +struct control_event +{ + const WCHAR *event; + event_handler handler; +}; + +static UINT dialog_event_handler( msi_dialog *, const WCHAR *, const WCHAR * ); + +/* create a dialog box and run it if it's modal */ +static UINT event_do_dialog( MSIPACKAGE *package, const WCHAR *name, msi_dialog *parent, BOOL destroy_modeless ) +{ + msi_dialog *dialog; + UINT r; + + /* create a new dialog */ + dialog = dialog_create( package, name, parent, dialog_event_handler ); + if (dialog) + { + /* kill the current modeless dialog */ + if (destroy_modeless && package->dialog) + { + msi_dialog_destroy( package->dialog ); + package->dialog = NULL; + } + + /* modeless dialogs return an error message */ + r = dialog_run_message_loop( dialog ); + if (r == ERROR_SUCCESS) + msi_dialog_destroy( dialog ); + else + package->dialog = dialog; + } + else r = ERROR_FUNCTION_FAILED; + return r; +} + +/* end a modal dialog box */ +static UINT event_end_dialog( msi_dialog *dialog, const WCHAR *argument ) +{ + static const WCHAR exitW[] = {'E','x','i','t',0}; + static const WCHAR retryW[] = {'R','e','t','r','y',0}; + static const WCHAR ignoreW[] = {'I','g','n','o','r','e',0}; + static const WCHAR returnW[] = {'R','e','t','u','r','n',0}; + + if (!strcmpW( argument, exitW )) + dialog->package->CurrentInstallState = ERROR_INSTALL_USEREXIT; + else if (!strcmpW( argument, retryW )) + dialog->package->CurrentInstallState = ERROR_INSTALL_SUSPEND; + else if (!strcmpW( argument, ignoreW )) + dialog->package->CurrentInstallState = ERROR_SUCCESS; + else if (!strcmpW( argument, returnW )) + { + msi_dialog *parent = dialog->parent; + msi_free( dialog->package->next_dialog ); + dialog->package->next_dialog = (parent) ? strdupW( parent->name ) : NULL; + dialog->package->CurrentInstallState = ERROR_SUCCESS; + } + else + { + ERR("Unknown argument string %s\n", debugstr_w(argument)); + dialog->package->CurrentInstallState = ERROR_FUNCTION_FAILED; + } + event_cleanup_subscriptions( dialog->package, dialog->name ); + msi_dialog_end_dialog( dialog ); + return ERROR_SUCCESS; +} + +/* transition from one modal dialog to another modal dialog */ +static UINT event_new_dialog( msi_dialog *dialog, const WCHAR *argument ) +{ + /* store the name of the next dialog, and signal this one to end */ + dialog->package->next_dialog = strdupW( argument ); + msi_event_cleanup_all_subscriptions( dialog->package ); + msi_dialog_end_dialog( dialog ); + return ERROR_SUCCESS; +} + +/* create a new child dialog of an existing modal dialog */ +static UINT event_spawn_dialog( msi_dialog *dialog, const WCHAR *argument ) +{ + /* don't destroy a modeless dialogs that might be our parent */ + event_do_dialog( dialog->package, argument, dialog, FALSE ); + if (dialog->package->CurrentInstallState != ERROR_SUCCESS) msi_dialog_end_dialog( dialog ); + return ERROR_SUCCESS; +} + +/* creates a dialog that remains up for a period of time based on a condition */ +static UINT event_spawn_wait_dialog( msi_dialog *dialog, const WCHAR *argument ) +{ + FIXME("doing nothing\n"); + return ERROR_SUCCESS; +} + +static UINT event_do_action( msi_dialog *dialog, const WCHAR *argument ) +{ + ACTION_PerformAction( dialog->package, argument, SCRIPT_NONE ); + return ERROR_SUCCESS; +} + +static UINT event_add_local( msi_dialog *dialog, const WCHAR *argument ) +{ + MSIFEATURE *feature; + + LIST_FOR_EACH_ENTRY( feature, &dialog->package->features, MSIFEATURE, entry ) + { + if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll )) + { + if (feature->ActionRequest != INSTALLSTATE_LOCAL) + msi_set_property( dialog->package->db, szPreselected, szOne, -1 ); + MSI_SetFeatureStateW( dialog->package, feature->Feature, INSTALLSTATE_LOCAL ); + } + } + return ERROR_SUCCESS; +} + +static UINT event_remove( msi_dialog *dialog, const WCHAR *argument ) +{ + MSIFEATURE *feature; + + LIST_FOR_EACH_ENTRY( feature, &dialog->package->features, MSIFEATURE, entry ) + { + if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll )) + { + if (feature->ActionRequest != INSTALLSTATE_ABSENT) + msi_set_property( dialog->package->db, szPreselected, szOne, -1 ); + MSI_SetFeatureStateW( dialog->package, feature->Feature, INSTALLSTATE_ABSENT ); + } + } + return ERROR_SUCCESS; +} + +static UINT event_add_source( msi_dialog *dialog, const WCHAR *argument ) +{ + MSIFEATURE *feature; + + LIST_FOR_EACH_ENTRY( feature, &dialog->package->features, MSIFEATURE, entry ) + { + if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll )) + { + if (feature->ActionRequest != INSTALLSTATE_SOURCE) + msi_set_property( dialog->package->db, szPreselected, szOne, -1 ); + MSI_SetFeatureStateW( dialog->package, feature->Feature, INSTALLSTATE_SOURCE ); + } + } + return ERROR_SUCCESS; +} + +void msi_event_fire( MSIPACKAGE *package, const WCHAR *event, MSIRECORD *rec ) +{ + struct subscriber *sub; + + TRACE("firing event %s\n", debugstr_w(event)); + + LIST_FOR_EACH_ENTRY( sub, &package->subscriptions, struct subscriber, entry ) + { + if (strcmpiW( sub->event, event )) continue; + dialog_handle_event( sub->dialog, sub->control, sub->attribute, rec ); + } +} + +static UINT event_set_target_path( msi_dialog *dialog, const WCHAR *argument ) +{ + WCHAR *path = msi_dup_property( dialog->package->db, argument ); + MSIRECORD *rec = MSI_CreateRecord( 1 ); + UINT r = ERROR_SUCCESS; + + MSI_RecordSetStringW( rec, 1, path ); + msi_event_fire( dialog->package, szSelectionPath, rec ); + if (path) + { + /* failure to set the path halts the executing of control events */ + r = MSI_SetTargetPathW( dialog->package, argument, path ); + msi_free( path ); + } + msi_free( &rec->hdr ); + return r; +} + +static UINT event_reset( msi_dialog *dialog, const WCHAR *argument ) +{ + msi_dialog_reset( dialog ); + return ERROR_SUCCESS; +} + +/* Return ERROR_SUCCESS if dialog is process and ERROR_FUNCTION_FAILED + * if the given parameter is not a dialog box + */ +UINT ACTION_DialogBox( MSIPACKAGE *package, const WCHAR *dialog ) +{ + UINT r; + + if (package->next_dialog) ERR("Already got next dialog... ignoring it\n"); + package->next_dialog = NULL; + + /* Dialogs are chained by filling in the next_dialog member + * of the package structure, then terminating the current dialog. + * The code below sees the next_dialog member set, and runs the + * next dialog. + * We fall out of the loop below if we come across a modeless + * dialog, as it returns ERROR_IO_PENDING when we try to run + * its message loop. + */ + r = event_do_dialog( package, dialog, NULL, TRUE ); + while (r == ERROR_SUCCESS && package->next_dialog) + { + WCHAR *name = package->next_dialog; + + package->next_dialog = NULL; + r = event_do_dialog( package, name, NULL, TRUE ); + msi_free( name ); + } + if (r == ERROR_IO_PENDING) r = ERROR_SUCCESS; + return r; +} + +static UINT event_set_install_level( msi_dialog *dialog, const WCHAR *argument ) +{ + int level = atolW( argument ); + + TRACE("setting install level to %d\n", level); + return MSI_SetInstallLevel( dialog->package, level ); +} + +static UINT event_directory_list_up( msi_dialog *dialog, const WCHAR *argument ) +{ + return msi_dialog_directorylist_up( dialog ); +} + +static UINT event_reinstall_mode( msi_dialog *dialog, const WCHAR *argument ) +{ + return msi_set_property( dialog->package->db, szReinstallMode, argument, -1 ); +} + +static UINT event_reinstall( msi_dialog *dialog, const WCHAR *argument ) +{ + return msi_set_property( dialog->package->db, szReinstall, argument, -1 ); +} + +static UINT event_validate_product_id( msi_dialog *dialog, const WCHAR *argument ) +{ + return msi_validate_product_id( dialog->package ); +} + +static const WCHAR end_dialogW[] = {'E','n','d','D','i','a','l','o','g',0}; +static const WCHAR new_dialogW[] = {'N','e','w','D','i','a','l','o','g',0}; +static const WCHAR spawn_dialogW[] = {'S','p','a','w','n','D','i','a','l','o','g',0}; +static const WCHAR spawn_wait_dialogW[] = {'S','p','a','w','n','W','a','i','t','D','i','a','l','o','g',0}; +static const WCHAR do_actionW[] = {'D','o','A','c','t','i','o','n',0}; +static const WCHAR add_localW[] = {'A','d','d','L','o','c','a','l',0}; +static const WCHAR removeW[] = {'R','e','m','o','v','e',0}; +static const WCHAR add_sourceW[] = {'A','d','d','S','o','u','r','c','e',0}; +static const WCHAR set_target_pathW[] = {'S','e','t','T','a','r','g','e','t','P','a','t','h',0}; +static const WCHAR resetW[] = {'R','e','s','e','t',0}; +static const WCHAR set_install_levelW[] = {'S','e','t','I','n','s','t','a','l','l','L','e','v','e','l',0}; +static const WCHAR directory_list_upW[] = {'D','i','r','e','c','t','o','r','y','L','i','s','t','U','p',0}; +static const WCHAR selection_browseW[] = {'S','e','l','e','c','t','i','o','n','B','r','o','w','s','e',0}; +static const WCHAR reinstall_modeW[] = {'R','e','i','n','s','t','a','l','l','M','o','d','e',0}; +static const WCHAR reinstallW[] = {'R','e','i','n','s','t','a','l','l',0}; +static const WCHAR validate_product_idW[] = {'V','a','l','i','d','a','t','e','P','r','o','d','u','c','t','I','D',0}; + +static const struct control_event control_events[] = +{ + { end_dialogW, event_end_dialog }, + { new_dialogW, event_new_dialog }, + { spawn_dialogW, event_spawn_dialog }, + { spawn_wait_dialogW, event_spawn_wait_dialog }, + { do_actionW, event_do_action }, + { add_localW, event_add_local }, + { removeW, event_remove }, + { add_sourceW, event_add_source }, + { set_target_pathW, event_set_target_path }, + { resetW, event_reset }, + { set_install_levelW, event_set_install_level }, + { directory_list_upW, event_directory_list_up }, + { selection_browseW, event_spawn_dialog }, + { reinstall_modeW, event_reinstall_mode }, + { reinstallW, event_reinstall }, + { validate_product_idW, event_validate_product_id }, + { NULL, NULL } +}; + +static UINT dialog_event_handler( msi_dialog *dialog, const WCHAR *event, const WCHAR *argument ) +{ + unsigned int i; + + TRACE("handling event %s\n", debugstr_w(event)); + + if (!event) return ERROR_SUCCESS; + + for (i = 0; control_events[i].event; i++) + { + if (!strcmpW( control_events[i].event, event )) + return control_events[i].handler( dialog, argument ); + } + FIXME("unhandled event %s arg(%s)\n", debugstr_w(event), debugstr_w(argument)); + return ERROR_SUCCESS; +} diff --git a/reactos/dll/win32/msi/events.c b/reactos/dll/win32/msi/events.c deleted file mode 100644 index b5b69d05819..00000000000 --- a/reactos/dll/win32/msi/events.c +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Implementation of the Microsoft Installer (msi.dll) - * - * Copyright 2005 Aric Stewart 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 - */ - -#define WIN32_NO_STATUS -#define _INC_WINDOWS -#define COM_NO_WINDOWS_H - -//#include -//#include - -//#include -//#include "winbase.h" -//#include "winerror.h" -//#include "winreg.h" -//#include "msi.h" -#include "msipriv.h" - -#include -#include - -WINE_DEFAULT_DEBUG_CHANNEL(msi); - -typedef UINT (*EVENTHANDLER)(MSIPACKAGE*,LPCWSTR,msi_dialog *); - -struct control_events -{ - const WCHAR *event; - EVENTHANDLER handler; -}; - -struct subscriber { - struct list entry; - msi_dialog *dialog; - LPWSTR event; - LPWSTR control; - LPWSTR attribute; -}; - -static UINT ControlEvent_HandleControlEvent(MSIPACKAGE *, LPCWSTR, LPCWSTR, msi_dialog*); - -/* - * Create a dialog box and run it if it's modal - */ -static UINT event_do_dialog( MSIPACKAGE *package, LPCWSTR name, msi_dialog *parent, BOOL destroy_modeless ) -{ - msi_dialog *dialog; - UINT r; - - /* create a new dialog */ - dialog = msi_dialog_create( package, name, parent, - ControlEvent_HandleControlEvent ); - if( dialog ) - { - /* kill the current modeless dialog */ - if( destroy_modeless && package->dialog ) - { - msi_dialog_destroy( package->dialog ); - package->dialog = NULL; - } - - /* modeless dialogs return an error message */ - r = msi_dialog_run_message_loop( dialog ); - if( r == ERROR_SUCCESS ) - msi_dialog_destroy( dialog ); - else - package->dialog = dialog; - } - else - r = ERROR_FUNCTION_FAILED; - - return r; -} - - -/* - * End a modal dialog box - */ -static UINT ControlEvent_EndDialog(MSIPACKAGE* package, LPCWSTR argument, - msi_dialog* dialog) -{ - static const WCHAR szExit[] = {'E','x','i','t',0}; - static const WCHAR szRetry[] = {'R','e','t','r','y',0}; - static const WCHAR szIgnore[] = {'I','g','n','o','r','e',0}; - static const WCHAR szReturn[] = {'R','e','t','u','r','n',0}; - - if (!strcmpW( argument, szExit )) - package->CurrentInstallState = ERROR_INSTALL_USEREXIT; - else if (!strcmpW( argument, szRetry )) - package->CurrentInstallState = ERROR_INSTALL_SUSPEND; - else if (!strcmpW( argument, szIgnore )) - package->CurrentInstallState = ERROR_SUCCESS; - else if (!strcmpW( argument, szReturn )) - { - msi_dialog *parent = msi_dialog_get_parent(dialog); - msi_free(package->next_dialog); - package->next_dialog = (parent) ? strdupW(msi_dialog_get_name(parent)) : NULL; - package->CurrentInstallState = ERROR_SUCCESS; - } - else - { - ERR("Unknown argument string %s\n",debugstr_w(argument)); - package->CurrentInstallState = ERROR_FUNCTION_FAILED; - } - - ControlEvent_CleanupDialogSubscriptions(package, msi_dialog_get_name( dialog )); - msi_dialog_end_dialog( dialog ); - return ERROR_SUCCESS; -} - -/* - * transition from one modal dialog to another modal dialog - */ -static UINT ControlEvent_NewDialog(MSIPACKAGE* package, LPCWSTR argument, - msi_dialog *dialog) -{ - /* store the name of the next dialog, and signal this one to end */ - package->next_dialog = strdupW(argument); - ControlEvent_CleanupSubscriptions(package); - msi_dialog_end_dialog( dialog ); - return ERROR_SUCCESS; -} - -/* - * Create a new child dialog of an existing modal dialog - */ -static UINT ControlEvent_SpawnDialog(MSIPACKAGE* package, LPCWSTR argument, - msi_dialog *dialog) -{ - /* don't destroy a modeless dialogs that might be our parent */ - event_do_dialog( package, argument, dialog, FALSE ); - if( package->CurrentInstallState != ERROR_SUCCESS ) - msi_dialog_end_dialog( dialog ); - return ERROR_SUCCESS; -} - -/* - * Creates a dialog that remains up for a period of time - * based on a condition - */ -static UINT ControlEvent_SpawnWaitDialog(MSIPACKAGE* package, LPCWSTR argument, - msi_dialog* dialog) -{ - FIXME("Doing Nothing\n"); - return ERROR_SUCCESS; -} - -static UINT ControlEvent_DoAction(MSIPACKAGE* package, LPCWSTR argument, - msi_dialog* dialog) -{ - ACTION_PerformAction(package, argument, SCRIPT_NONE); - return ERROR_SUCCESS; -} - -static UINT ControlEvent_AddLocal( MSIPACKAGE *package, LPCWSTR argument, msi_dialog *dialog ) -{ - MSIFEATURE *feature; - - LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry ) - { - if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll )) - { - if (feature->ActionRequest != INSTALLSTATE_LOCAL) - msi_set_property( package->db, szPreselected, szOne, -1 ); - MSI_SetFeatureStateW( package, feature->Feature, INSTALLSTATE_LOCAL ); - } - } - return ERROR_SUCCESS; -} - -static UINT ControlEvent_Remove( MSIPACKAGE *package, LPCWSTR argument, msi_dialog *dialog ) -{ - MSIFEATURE *feature; - - LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry ) - { - if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll )) - { - if (feature->ActionRequest != INSTALLSTATE_ABSENT) - msi_set_property( package->db, szPreselected, szOne, -1 ); - MSI_SetFeatureStateW( package, feature->Feature, INSTALLSTATE_ABSENT ); - } - } - return ERROR_SUCCESS; -} - -static UINT ControlEvent_AddSource( MSIPACKAGE *package, LPCWSTR argument, msi_dialog *dialog ) -{ - MSIFEATURE *feature; - - LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry ) - { - if (!strcmpW( argument, feature->Feature ) || !strcmpW( argument, szAll )) - { - if (feature->ActionRequest != INSTALLSTATE_SOURCE) - msi_set_property( package->db, szPreselected, szOne, -1 ); - MSI_SetFeatureStateW( package, feature->Feature, INSTALLSTATE_SOURCE ); - } - } - return ERROR_SUCCESS; -} - -static UINT ControlEvent_SetTargetPath(MSIPACKAGE* package, LPCWSTR argument, - msi_dialog* dialog) -{ - static const WCHAR szSelectionPath[] = {'S','e','l','e','c','t','i','o','n','P','a','t','h',0}; - LPWSTR path = msi_dup_property( package->db, argument ); - MSIRECORD *rec = MSI_CreateRecord( 1 ); - UINT r = ERROR_SUCCESS; - - MSI_RecordSetStringW( rec, 1, path ); - ControlEvent_FireSubscribedEvent( package, szSelectionPath, rec ); - if (path) - { - /* failure to set the path halts the executing of control events */ - r = MSI_SetTargetPathW(package, argument, path); - msi_free(path); - } - msi_free(&rec->hdr); - return r; -} - -static UINT ControlEvent_Reset(MSIPACKAGE* package, LPCWSTR argument, - msi_dialog* dialog) -{ - msi_dialog_reset(dialog); - return ERROR_SUCCESS; -} - -/* - * Subscribed events - */ -static void free_subscriber( struct subscriber *sub ) -{ - msi_free(sub->event); - msi_free(sub->control); - msi_free(sub->attribute); - msi_free(sub); -} - -VOID ControlEvent_SubscribeToEvent( MSIPACKAGE *package, msi_dialog *dialog, - LPCWSTR event, LPCWSTR control, LPCWSTR attribute ) -{ - struct subscriber *sub; - - TRACE("event %s control %s attribute %s\n", debugstr_w(event), debugstr_w(control), debugstr_w(attribute)); - - LIST_FOR_EACH_ENTRY( sub, &package->subscriptions, struct subscriber, entry ) - { - if (!strcmpiW( sub->event, event ) && - !strcmpiW( sub->control, control ) && - !strcmpiW( sub->attribute, attribute )) - { - TRACE("already subscribed\n"); - return; - }; - } - if (!(sub = msi_alloc( sizeof(*sub) ))) return; - sub->dialog = dialog; - sub->event = strdupW(event); - sub->control = strdupW(control); - sub->attribute = strdupW(attribute); - list_add_tail( &package->subscriptions, &sub->entry ); -} - -VOID ControlEvent_FireSubscribedEvent( MSIPACKAGE *package, LPCWSTR event, MSIRECORD *rec ) -{ - struct subscriber *sub; - - TRACE("Firing event %s\n", debugstr_w(event)); - - LIST_FOR_EACH_ENTRY( sub, &package->subscriptions, struct subscriber, entry ) - { - if (strcmpiW( sub->event, event )) continue; - msi_dialog_handle_event( sub->dialog, sub->control, sub->attribute, rec ); - } -} - -VOID ControlEvent_CleanupDialogSubscriptions(MSIPACKAGE *package, LPWSTR dialog) -{ - struct list *i, *t; - struct subscriber *sub; - - LIST_FOR_EACH_SAFE( i, t, &package->subscriptions ) - { - sub = LIST_ENTRY( i, struct subscriber, entry ); - - if (strcmpW( msi_dialog_get_name( sub->dialog ), dialog )) - continue; - - list_remove( &sub->entry ); - free_subscriber( sub ); - } -} - -VOID ControlEvent_CleanupSubscriptions(MSIPACKAGE *package) -{ - struct list *i, *t; - struct subscriber *sub; - - LIST_FOR_EACH_SAFE( i, t, &package->subscriptions ) - { - sub = LIST_ENTRY( i, struct subscriber, entry ); - - list_remove( &sub->entry ); - free_subscriber( sub ); - } -} - -/* - * ACTION_DialogBox() - * - * Return ERROR_SUCCESS if dialog is process and ERROR_FUNCTION_FAILED - * if the given parameter is not a dialog box - */ -UINT ACTION_DialogBox( MSIPACKAGE* package, LPCWSTR szDialogName ) -{ - UINT r = ERROR_SUCCESS; - - if( package->next_dialog ) - ERR("Already a next dialog... ignoring it\n"); - package->next_dialog = NULL; - - /* - * Dialogs are chained by filling in the next_dialog member - * of the package structure, then terminating the current dialog. - * The code below sees the next_dialog member set, and runs the - * next dialog. - * We fall out of the loop below if we come across a modeless - * dialog, as it returns ERROR_IO_PENDING when we try to run - * its message loop. - */ - r = event_do_dialog( package, szDialogName, NULL, TRUE ); - while( r == ERROR_SUCCESS && package->next_dialog ) - { - LPWSTR name = package->next_dialog; - - package->next_dialog = NULL; - r = event_do_dialog( package, name, NULL, TRUE ); - msi_free( name ); - } - - if( r == ERROR_IO_PENDING ) - r = ERROR_SUCCESS; - - return r; -} - -static UINT ControlEvent_SetInstallLevel(MSIPACKAGE* package, LPCWSTR argument, - msi_dialog* dialog) -{ - int iInstallLevel = atolW(argument); - - TRACE("Setting install level: %i\n", iInstallLevel); - - return MSI_SetInstallLevel( package, iInstallLevel ); -} - -static UINT ControlEvent_DirectoryListUp(MSIPACKAGE *package, LPCWSTR argument, - msi_dialog *dialog) -{ - return msi_dialog_directorylist_up( dialog ); -} - -static UINT ControlEvent_ReinstallMode(MSIPACKAGE *package, LPCWSTR argument, - msi_dialog *dialog) -{ - return msi_set_property( package->db, szReinstallMode, argument, -1 ); -} - -static UINT ControlEvent_Reinstall( MSIPACKAGE *package, LPCWSTR argument, - msi_dialog *dialog ) -{ - return msi_set_property( package->db, szReinstall, argument, -1 ); -} - -static UINT ControlEvent_ValidateProductID(MSIPACKAGE *package, LPCWSTR argument, - msi_dialog *dialog) -{ - return msi_validate_product_id( package ); -} - -static const WCHAR end_dialogW[] = {'E','n','d','D','i','a','l','o','g',0}; -static const WCHAR new_dialogW[] = {'N','e','w','D','i','a','l','o','g',0}; -static const WCHAR spawn_dialogW[] = {'S','p','a','w','n','D','i','a','l','o','g',0}; -static const WCHAR spawn_wait_dialogW[] = {'S','p','a','w','n','W','a','i','t','D','i','a','l','o','g',0}; -static const WCHAR do_actionW[] = {'D','o','A','c','t','i','o','n',0}; -static const WCHAR add_localW[] = {'A','d','d','L','o','c','a','l',0}; -static const WCHAR removeW[] = {'R','e','m','o','v','e',0}; -static const WCHAR add_sourceW[] = {'A','d','d','S','o','u','r','c','e',0}; -static const WCHAR set_target_pathW[] = {'S','e','t','T','a','r','g','e','t','P','a','t','h',0}; -static const WCHAR resetW[] = {'R','e','s','e','t',0}; -static const WCHAR set_install_levelW[] = {'S','e','t','I','n','s','t','a','l','l','L','e','v','e','l',0}; -static const WCHAR directory_list_upW[] = {'D','i','r','e','c','t','o','r','y','L','i','s','t','U','p',0}; -static const WCHAR selection_browseW[] = {'S','e','l','e','c','t','i','o','n','B','r','o','w','s','e',0}; -static const WCHAR reinstall_modeW[] = {'R','e','i','n','s','t','a','l','l','M','o','d','e',0}; -static const WCHAR reinstallW[] = {'R','e','i','n','s','t','a','l','l',0}; -static const WCHAR validate_product_idW[] = {'V','a','l','i','d','a','t','e','P','r','o','d','u','c','t','I','D',0}; - -static const struct control_events control_events[] = -{ - { end_dialogW, ControlEvent_EndDialog }, - { new_dialogW, ControlEvent_NewDialog }, - { spawn_dialogW, ControlEvent_SpawnDialog }, - { spawn_wait_dialogW, ControlEvent_SpawnWaitDialog }, - { do_actionW, ControlEvent_DoAction }, - { add_localW, ControlEvent_AddLocal }, - { removeW, ControlEvent_Remove }, - { add_sourceW, ControlEvent_AddSource }, - { set_target_pathW, ControlEvent_SetTargetPath }, - { resetW, ControlEvent_Reset }, - { set_install_levelW, ControlEvent_SetInstallLevel }, - { directory_list_upW, ControlEvent_DirectoryListUp }, - { selection_browseW, ControlEvent_SpawnDialog }, - { reinstall_modeW, ControlEvent_ReinstallMode }, - { reinstallW, ControlEvent_Reinstall }, - { validate_product_idW, ControlEvent_ValidateProductID }, - { NULL, NULL } -}; - -UINT ControlEvent_HandleControlEvent( MSIPACKAGE *package, LPCWSTR event, - LPCWSTR argument, msi_dialog *dialog ) -{ - unsigned int i; - - TRACE("handling control event %s\n", debugstr_w(event)); - - if (!event) return ERROR_SUCCESS; - - for (i = 0; control_events[i].event; i++) - { - if (!strcmpW( control_events[i].event, event )) - return control_events[i].handler( package, argument, dialog ); - } - FIXME("unhandled control event %s arg(%s)\n", debugstr_w(event), debugstr_w(argument)); - return ERROR_SUCCESS; -} diff --git a/reactos/dll/win32/msi/files.c b/reactos/dll/win32/msi/files.c index d29cbabbc98..075fe251bef 100644 --- a/reactos/dll/win32/msi/files.c +++ b/reactos/dll/win32/msi/files.c @@ -250,13 +250,15 @@ static UINT msi_create_directory( MSIPACKAGE *package, const WCHAR *dir ) return ERROR_SUCCESS; } -static MSIFILE *find_file( MSIPACKAGE *package, const WCHAR *filename ) +static MSIFILE *find_file( MSIPACKAGE *package, UINT disk_id, const WCHAR *filename ) { MSIFILE *file; LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry ) { - if (file->state != msifs_installed && !strcmpiW( filename, file->File )) return file; + if (file->disk_id == disk_id && + file->state != msifs_installed && + !strcmpiW( filename, file->File )) return file; } return NULL; } @@ -269,7 +271,7 @@ static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action, if (action == MSICABEXTRACT_BEGINEXTRACT) { - if (!(f = find_file( package, file ))) + if (!(f = find_file( package, disk_id, file ))) { TRACE("unknown file in cabinet (%s)\n", debugstr_w(file)); return FALSE; @@ -398,7 +400,7 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package) } else if (file->state != msifs_installed && !(file->Attributes & msidbFileAttributesPatchAdded)) { - ERR("compressed file wasn't installed (%s)\n", debugstr_w(file->TargetPath)); + ERR("compressed file wasn't installed (%s)\n", debugstr_w(file->File)); rc = ERROR_INSTALL_FAILURE; goto done; } diff --git a/reactos/dll/win32/msi/media.c b/reactos/dll/win32/msi/media.c index 0473bb864d4..1dc3a96dcec 100644 --- a/reactos/dll/win32/msi/media.c +++ b/reactos/dll/win32/msi/media.c @@ -362,8 +362,29 @@ static INT_PTR cabinet_next_cabinet(FDINOTIFICATIONTYPE fdint, if (strcmpiW( mi->cabinet, cab )) { - ERR("Continuous cabinet does not match the next cabinet in the Media table\n"); - goto done; + char *next_cab; + ULONG length; + + WARN("Continuous cabinet %s does not match the next cabinet %s in the media table => use latter one\n", debugstr_w(cab), debugstr_w(mi->cabinet)); + + /* Use cabinet name from the media table */ + next_cab = strdupWtoA(mi->cabinet); + /* Modify path to cabinet file with full filename (psz3 points to a 256 bytes buffer that can be modified contrary to psz1 and psz2) */ + length = strlen(pfdin->psz3) + 1 + strlen(next_cab) + 1; + if (length > 256) + { + WARN("Cannot update next cabinet filename with a string size %u > 256\n", length); + msi_free(next_cab); + goto done; + } + else + { + strcat(pfdin->psz3, "\\"); + strcat(pfdin->psz3, next_cab); + } + /* Path psz3 and cabinet psz1 are concatenated by FDI so just reset psz1 */ + *pfdin->psz1 = 0; + msi_free(next_cab); } if (!(cabinet_file = get_cabinet_filename(mi))) diff --git a/reactos/dll/win32/msi/msi_main.c b/reactos/dll/win32/msi/msi_main.c index 42d86003ddb..c0d3fde6927 100644 --- a/reactos/dll/win32/msi/msi_main.c +++ b/reactos/dll/win32/msi/msi_main.c @@ -80,6 +80,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) IsWow64Process( GetCurrentProcess(), &is_wow64 ); break; case DLL_PROCESS_DETACH: + if (lpvReserved) break; msi_dialog_unregister_class(); msi_free_handle_table(); msi_free( gszLogFile ); diff --git a/reactos/dll/win32/msi/msipriv.h b/reactos/dll/win32/msi/msipriv.h index 28dc4a43f6c..cbb23dcc9b0 100644 --- a/reactos/dll/win32/msi/msipriv.h +++ b/reactos/dll/win32/msi/msipriv.h @@ -934,18 +934,9 @@ extern LONG msi_reg_set_val_dword( HKEY hkey, LPCWSTR name, DWORD val ) DECLSPEC extern LONG msi_reg_set_subkey_val( HKEY hkey, LPCWSTR path, LPCWSTR name, LPCWSTR val ) DECLSPEC_HIDDEN; /* msi dialog interface */ -typedef UINT (*msi_dialog_event_handler)( MSIPACKAGE*, LPCWSTR, LPCWSTR, msi_dialog* ); -extern msi_dialog *msi_dialog_create( MSIPACKAGE*, LPCWSTR, msi_dialog*, msi_dialog_event_handler ) DECLSPEC_HIDDEN; -extern UINT msi_dialog_run_message_loop( msi_dialog* ) DECLSPEC_HIDDEN; -extern void msi_dialog_end_dialog( msi_dialog* ) DECLSPEC_HIDDEN; extern void msi_dialog_check_messages( HANDLE ) DECLSPEC_HIDDEN; extern void msi_dialog_destroy( msi_dialog* ) DECLSPEC_HIDDEN; extern void msi_dialog_unregister_class( void ) DECLSPEC_HIDDEN; -extern void msi_dialog_handle_event( msi_dialog*, LPCWSTR, LPCWSTR, MSIRECORD * ) DECLSPEC_HIDDEN; -extern UINT msi_dialog_reset( msi_dialog *dialog ) DECLSPEC_HIDDEN; -extern UINT msi_dialog_directorylist_up( msi_dialog *dialog ) DECLSPEC_HIDDEN; -extern msi_dialog *msi_dialog_get_parent( msi_dialog *dialog ) DECLSPEC_HIDDEN; -extern LPWSTR msi_dialog_get_name( msi_dialog *dialog ) DECLSPEC_HIDDEN; extern UINT msi_spawn_error_dialog( MSIPACKAGE*, LPWSTR, LPWSTR ) DECLSPEC_HIDDEN; /* summary information */ @@ -977,7 +968,7 @@ extern HINSTANCE msi_hInstance DECLSPEC_HIDDEN; extern UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action, UINT script) DECLSPEC_HIDDEN; extern UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action, UINT script) DECLSPEC_HIDDEN; extern void ACTION_FinishCustomActions( const MSIPACKAGE* package) DECLSPEC_HIDDEN; -extern UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action, UINT script, BOOL execute) DECLSPEC_HIDDEN; +extern UINT ACTION_CustomAction(MSIPACKAGE *, const WCHAR *, UINT) DECLSPEC_HIDDEN; /* actions in other modules */ extern UINT ACTION_AppSearch(MSIPACKAGE *package) DECLSPEC_HIDDEN; @@ -1066,12 +1057,8 @@ extern BOOL msi_cabextract(MSIPACKAGE* package, MSIMEDIAINFO *mi, LPVOID data) D extern UINT msi_add_cabinet_stream(MSIPACKAGE *, UINT, IStorage *, const WCHAR *) DECLSPEC_HIDDEN; /* control event stuff */ -extern VOID ControlEvent_FireSubscribedEvent(MSIPACKAGE *package, LPCWSTR event, - MSIRECORD *data) DECLSPEC_HIDDEN; -extern VOID ControlEvent_CleanupDialogSubscriptions(MSIPACKAGE *package, LPWSTR dialog) DECLSPEC_HIDDEN; -extern VOID ControlEvent_CleanupSubscriptions(MSIPACKAGE *package) DECLSPEC_HIDDEN; -extern VOID ControlEvent_SubscribeToEvent(MSIPACKAGE *package, msi_dialog *dialog, - LPCWSTR event, LPCWSTR control, LPCWSTR attribute) DECLSPEC_HIDDEN; +extern void msi_event_fire(MSIPACKAGE *, const WCHAR *, MSIRECORD *) DECLSPEC_HIDDEN; +extern void msi_event_cleanup_all_subscriptions( MSIPACKAGE * ) DECLSPEC_HIDDEN; /* OLE automation */ typedef enum tid_t { diff --git a/reactos/dll/win32/msi/package.c b/reactos/dll/win32/msi/package.c index e6d5b6a5f23..bfa6ed8723a 100644 --- a/reactos/dll/win32/msi/package.c +++ b/reactos/dll/win32/msi/package.c @@ -346,7 +346,7 @@ static void free_package_structures( MSIPACKAGE *package ) remove_tracked_tempfiles(package); /* cleanup control event subscriptions */ - ControlEvent_CleanupSubscriptions( package ); + msi_event_cleanup_all_subscriptions( package ); } static void MSI_FreePackage( MSIOBJECTHDR *arg) @@ -874,14 +874,14 @@ static VOID set_installer_properties(MSIPACKAGE *package) break; case VER_PLATFORM_WIN32_NT: msi_set_property( package->db, szVersionNT, verstr, len ); - len = sprintfW( verstr, szFormat,OSVersion.wProductType ); - msi_set_property( package->db, szMsiNTProductType, verstr, len ); + len = sprintfW( bufstr, szFormat,OSVersion.wProductType ); + msi_set_property( package->db, szMsiNTProductType, bufstr, len ); break; } - len = sprintfW( verstr, szFormat, OSVersion.dwBuildNumber ); - msi_set_property( package->db, szWindowsBuild, verstr, len ); - len = sprintfW( verstr, szFormat, OSVersion.wServicePackMajor ); - msi_set_property( package->db, szServicePackLevel, verstr, len ); + len = sprintfW( bufstr, szFormat, OSVersion.dwBuildNumber ); + msi_set_property( package->db, szWindowsBuild, bufstr, len ); + len = sprintfW( bufstr, szFormat, OSVersion.wServicePackMajor ); + msi_set_property( package->db, szServicePackLevel, bufstr, len ); len = sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION ); msi_set_property( package->db, szVersionMsi, bufstr, len ); @@ -1025,7 +1025,7 @@ static VOID set_installer_properties(MSIPACKAGE *package) if ((computername = msi_alloc( len * sizeof(WCHAR) ))) { if (GetComputerNameW( computername, &len )) - msi_set_property( package->db, szComputerName, computername, len - 1 ); + msi_set_property( package->db, szComputerName, computername, len ); msi_free( computername ); } } @@ -1942,7 +1942,7 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC MSI_RecordSetStringW(uirow, 1, deformated); msi_free(deformated); - ControlEvent_FireSubscribedEvent(package, szActionData, uirow); + msi_event_fire( package, szActionData, uirow ); msiobj_release(&uirow->hdr); if (package->action_progress_increment) @@ -1950,7 +1950,7 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC uirow = MSI_CreateRecord(2); MSI_RecordSetInteger(uirow, 1, 2); MSI_RecordSetInteger(uirow, 2, package->action_progress_increment); - ControlEvent_FireSubscribedEvent(package, szSetProgress, uirow); + msi_event_fire( package, szSetProgress, uirow ); msiobj_release(&uirow->hdr); } break; @@ -1961,13 +1961,13 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC MSI_RecordSetStringW(uirow, 1, deformated); msi_free(deformated); - ControlEvent_FireSubscribedEvent(package, szActionText, uirow); + msi_event_fire( package, szActionText, uirow ); msiobj_release(&uirow->hdr); break; case INSTALLMESSAGE_PROGRESS: - ControlEvent_FireSubscribedEvent(package, szSetProgress, record); + msi_event_fire( package, szSetProgress, record ); break; } diff --git a/reactos/dll/win32/msi/patch.c b/reactos/dll/win32/msi/patch.c index 10263626f73..7735589c671 100644 --- a/reactos/dll/win32/msi/patch.c +++ b/reactos/dll/win32/msi/patch.c @@ -48,22 +48,22 @@ static BOOL match_language( MSIPACKAGE *package, LANGID langid ) return FALSE; } -static UINT check_transform_applicable( MSIPACKAGE *package, IStorage *patch ) +static UINT check_transform_applicable( MSIPACKAGE *package, IStorage *transform ) { - LPWSTR prod_code, patch_product, template = NULL; + WCHAR *package_product, *transform_product, *template = NULL; UINT ret = ERROR_FUNCTION_FAILED; - prod_code = msi_dup_property( package->db, szProductCode ); - patch_product = msi_get_suminfo_product( patch ); + package_product = msi_dup_property( package->db, szProductCode ); + transform_product = msi_get_suminfo_product( transform ); - TRACE("db = %s patch = %s\n", debugstr_w(prod_code), debugstr_w(patch_product)); + TRACE("package = %s transform = %s\n", debugstr_w(package_product), debugstr_w(transform_product)); - if (strstrW( patch_product, prod_code )) + if (!transform_product || strstrW( transform_product, package_product )) { MSISUMMARYINFO *si; const WCHAR *p; - si = MSI_GetSummaryInformationW( patch, 0 ); + si = MSI_GetSummaryInformationW( transform, 0 ); if (!si) { ERR("no summary information!\n"); @@ -94,8 +94,8 @@ static UINT check_transform_applicable( MSIPACKAGE *package, IStorage *patch ) } end: - msi_free( patch_product ); - msi_free( prod_code ); + msi_free( transform_product ); + msi_free( package_product ); msi_free( template ); return ret; } @@ -555,7 +555,6 @@ static UINT set_patch_offsets( MSIDATABASE *db ) pos = patch_offset_list_create(); patch_offset_get_files( db, last_sequence, pos ); patch_offset_get_patches( db, last_sequence, pos ); - if (pos->count) { UINT offset = db->media_transform_offset - pos->min; last_sequence = offset + pos->max; @@ -563,7 +562,8 @@ static UINT set_patch_offsets( MSIDATABASE *db ) /* FIXME: this is for the patch table, which is not yet properly transformed */ last_sequence += pos->min; pos->offset_to_apply = offset; - patch_offset_modify_db( db, pos ); + if (pos->count) + patch_offset_modify_db( db, pos ); MSI_RecordSetInteger( rec, 2, last_sequence ); r = MSI_ViewModify( view, MSIMODIFY_UPDATE, rec ); diff --git a/reactos/dll/win32/msi/query.h b/reactos/dll/win32/msi/query.h index c0de82bd706..c154b6c1ec6 100644 --- a/reactos/dll/win32/msi/query.h +++ b/reactos/dll/win32/msi/query.h @@ -96,6 +96,19 @@ struct expr } u; }; +typedef struct +{ + MSIDATABASE *db; + LPCWSTR command; + DWORD n, len; + UINT r; + MSIVIEW **view; /* View structure for the resulting query. This value + * tracks the view currently being created so we can free + * this view on syntax error. + */ + struct list *mem; +} SQL_input; + UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview, struct list *mem ) DECLSPEC_HIDDEN; diff --git a/reactos/dll/win32/msi/script.c b/reactos/dll/win32/msi/script.c index 7a4642ab4d3..7f61d911f17 100644 --- a/reactos/dll/win32/msi/script.c +++ b/reactos/dll/win32/msi/script.c @@ -277,6 +277,20 @@ static HRESULT create_activescriptsite(MsiActiveScriptSite **obj) return S_OK; } +static UINT map_return_value(LONG val) +{ + switch (val) + { + case 0: + case IDOK: + case IDIGNORE: return ERROR_SUCCESS; + case IDCANCEL: return ERROR_INSTALL_USEREXIT; + case IDRETRY: return ERROR_INSTALL_SUSPEND; + case IDABORT: + default: return ERROR_INSTALL_FAILURE; + } +} + /* * Call a script. */ @@ -358,13 +372,10 @@ DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function hr = IDispatch_Invoke(pDispatch, dispid, &IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparamsNoArgs, &var, NULL, NULL); if (FAILED(hr)) goto done; - /* Check return value, if it's not IDOK we failed */ hr = VariantChangeType(&var, &var, 0, VT_I4); if (FAILED(hr)) goto done; - if (V_I4(&var) == IDOK) - ret = ERROR_SUCCESS; - else ret = ERROR_INSTALL_FAILURE; + ret = map_return_value(V_I4(&var)); VariantClear(&var); } else { diff --git a/reactos/dll/win32/msi/sql.tab.c b/reactos/dll/win32/msi/sql.tab.c index f64d8ccced7..27213d21369 100644 --- a/reactos/dll/win32/msi/sql.tab.c +++ b/reactos/dll/win32/msi/sql.tab.c @@ -1,10 +1,8 @@ +/* A Bison parser, made by GNU Bison 2.5. */ -/* A Bison parser, made by GNU Bison 2.4.1. */ - -/* Skeleton implementation for Bison's Yacc-like parsers in C +/* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -46,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.4.1" +#define YYBISON_VERSION "2.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -72,9 +70,10 @@ #define yydebug sql_debug #define yynerrs sql_nerrs + /* Copy the first part of user declarations. */ -/* Line 189 of yacc.c */ +/* Line 268 of yacc.c */ #line 1 "sql.y" @@ -115,29 +114,12 @@ #include #include -#define YYLEX_PARAM info -#define YYPARSE_PARAM info - -static int sql_error(const char *str); - WINE_DEFAULT_DEBUG_CHANNEL(msi); -typedef struct tag_SQL_input -{ - MSIDATABASE *db; - LPCWSTR command; - DWORD n, len; - UINT r; - MSIVIEW **view; /* View structure for the resulting query. This value - * tracks the view currently being created so we can free - * this view on syntax error. - */ - struct list *mem; -} SQL_input; - static UINT SQL_getstring( void *info, const struct sql_str *strdata, LPWSTR *str ); static INT SQL_getint( void *info ); static int sql_lex( void *SQL_lval, SQL_input *info ); +static int sql_error( SQL_input *info, const char *str); static LPWSTR parser_add_table( void *info, LPCWSTR list, LPCWSTR table ); static void *parser_alloc( void *info, unsigned int sz ); @@ -158,8 +140,8 @@ static struct expr * EXPR_wildcard( void *info ); -/* Line 189 of yacc.c */ -#line 161 "sql.tab.c" +/* Line 268 of yacc.c */ +#line 142 "sql.tab.c" /* Enabling traces. */ #ifndef YYDEBUG @@ -256,8 +238,8 @@ static struct expr * EXPR_wildcard( void *info ); typedef union YYSTYPE { -/* Line 214 of yacc.c */ -#line 83 "sql.y" +/* Line 293 of yacc.c */ +#line 68 "sql.y" struct sql_str str; LPWSTR string; @@ -269,8 +251,8 @@ typedef union YYSTYPE -/* Line 214 of yacc.c */ -#line 272 "sql.tab.c" +/* Line 293 of yacc.c */ +#line 253 "sql.tab.c" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -281,8 +263,8 @@ typedef union YYSTYPE /* Copy the second part of user declarations. */ -/* Line 264 of yacc.c */ -#line 276 "sql.tab.c" +/* Line 343 of yacc.c */ +#line 265 "sql.tab.c" #ifdef short # undef short @@ -332,7 +314,7 @@ typedef short int yytype_int16; #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ -# if YYENABLE_NLS +# if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) @@ -385,11 +367,11 @@ YYID (yyi) # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # endif @@ -412,24 +394,24 @@ YYID (yyi) # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif -# if (defined __cplusplus && ! defined _STDLIB_H \ +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif @@ -458,23 +440,7 @@ union yyalloc ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif +# define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of @@ -494,6 +460,26 @@ union yyalloc #endif +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + /* YYFINAL -- State number of the termination state. */ #define YYFINAL 36 /* YYLAST -- Last index in YYTABLE. */ @@ -606,15 +592,15 @@ static const yytype_int8 yyrhs[] = /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 132, 132, 140, 141, 142, 143, 144, 145, 146, - 150, 161, 175, 192, 208, 219, 233, 247, 258, 269, - 283, 287, 294, 309, 319, 329, 336, 345, 349, 353, - 360, 364, 371, 375, 379, 383, 387, 391, 395, 402, - 411, 415, 430, 450, 451, 455, 462, 463, 467, 474, - 486, 499, 503, 515, 530, 534, 543, 549, 555, 561, - 567, 573, 579, 585, 591, 597, 603, 612, 613, 617, - 624, 635, 636, 644, 652, 658, 664, 670, 679, 688, - 694, 703, 709, 715, 724, 731, 739, 747 + 0, 117, 117, 125, 126, 127, 128, 129, 130, 131, + 135, 146, 160, 177, 193, 204, 218, 232, 243, 254, + 268, 272, 279, 294, 304, 314, 321, 330, 334, 338, + 345, 349, 356, 360, 364, 368, 372, 376, 380, 387, + 396, 400, 415, 435, 436, 440, 447, 448, 452, 459, + 471, 484, 488, 500, 515, 519, 528, 534, 540, 546, + 552, 558, 564, 570, 576, 582, 588, 597, 598, 602, + 609, 620, 621, 629, 637, 643, 649, 655, 664, 673, + 679, 688, 694, 700, 709, 716, 724, 732 }; #endif @@ -687,8 +673,8 @@ static const yytype_uint8 yyr2[] = 1, 3, 1, 1, 1, 1, 1, 1 }; -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero +/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { @@ -753,8 +739,7 @@ static const yytype_int8 yypgoto[] = /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ + number is the opposite. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -85 static const yytype_int16 yytable[] = { @@ -776,6 +761,12 @@ static const yytype_int16 yytable[] = 58, 74, 147, 0, 110, 150, 153 }; +#define yypact_value_is_default(yystate) \ + ((yystate) == (-80)) + +#define yytable_value_is_error(yytable_value) \ + YYID (0) + static const yytype_int16 yycheck[] = { 6, 7, 20, 82, 57, 49, 53, 4, 20, 7, @@ -830,9 +821,18 @@ static const yytype_uint8 yystos[] = /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ + Once GCC version 2 has supplanted version 1, this can go. However, + YYFAIL appears to be in use. Nevertheless, it is formally deprecated + in Bison 2.4.2's NEWS entry, where a plan to phase it out is + discussed. */ #define YYFAIL goto yyerrlab +#if defined YYFAIL + /* This is here to suppress warnings from the GCC cpp's + -Wunused-macros. Normally we don't worry about that warning, but + some users do, and we want to make it easy for users to remove + YYFAIL uses, which will produce warnings from Bison 2.5. */ +#endif #define YYRECOVERING() (!!yyerrstatus) @@ -842,13 +842,12 @@ do \ { \ yychar = (Token); \ yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ else \ { \ - yyerror (YY_("syntax error: cannot back up")); \ + yyerror (info, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) @@ -884,19 +883,10 @@ while (YYID (0)) #endif -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ +/* This macro is provided for backward compatibility. */ #ifndef YY_LOCATION_PRINT -# if YYLTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) #endif @@ -905,7 +895,7 @@ while (YYID (0)) #ifdef YYLEX_PARAM # define YYLEX yylex (&yylval, YYLEX_PARAM) #else -# define YYLEX yylex (&yylval) +# define YYLEX yylex (&yylval, info) #endif /* Enable debugging if requested. */ @@ -928,7 +918,7 @@ do { \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ - Type, Value); \ + Type, Value, info); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) @@ -942,17 +932,19 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, SQL_input *info) #else static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep) +yy_symbol_value_print (yyoutput, yytype, yyvaluep, info) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; + SQL_input *info; #endif { if (!yyvaluep) return; + YYUSE (info); # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); @@ -974,13 +966,14 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, SQL_input *info) #else static void -yy_symbol_print (yyoutput, yytype, yyvaluep) +yy_symbol_print (yyoutput, yytype, yyvaluep, info) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; + SQL_input *info; #endif { if (yytype < YYNTOKENS) @@ -988,7 +981,7 @@ yy_symbol_print (yyoutput, yytype, yyvaluep) else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - yy_symbol_value_print (yyoutput, yytype, yyvaluep); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, info); YYFPRINTF (yyoutput, ")"); } @@ -1031,12 +1024,13 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +yy_reduce_print (YYSTYPE *yyvsp, int yyrule, SQL_input *info) #else static void -yy_reduce_print (yyvsp, yyrule) +yy_reduce_print (yyvsp, yyrule, info) YYSTYPE *yyvsp; int yyrule; + SQL_input *info; #endif { int yynrhs = yyr2[yyrule]; @@ -1050,7 +1044,7 @@ yy_reduce_print (yyvsp, yyrule) YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) - ); + , info); YYFPRINTF (stderr, "\n"); } } @@ -1058,7 +1052,7 @@ yy_reduce_print (yyvsp, yyrule) # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ - yy_reduce_print (yyvsp, Rule); \ + yy_reduce_print (yyvsp, Rule, info); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that @@ -1088,7 +1082,6 @@ int yydebug; # define YYMAXDEPTH 10000 #endif - #if YYERROR_VERBOSE @@ -1191,115 +1184,142 @@ yytnamerr (char *yyres, const char *yystr) } # endif -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) { - int yyn = yypact[yystate]; + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = 0; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else + /* There are many possibilities here to consider: + - Assume YYFAIL is not used. It's too flawed to consider. See + + for details. YYERROR is fine as it does not invoke this + function. + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } - - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - - if (yysize_overflow) - return YYSIZE_MAXIMUM; - - if (yyresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - } - return yysize; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; } #endif /* YYERROR_VERBOSE */ - /*-----------------------------------------------. | Release the memory associated to this symbol. | @@ -1309,16 +1329,18 @@ yysyntax_error (char *yyresult, int yystate, int yychar) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, SQL_input *info) #else static void -yydestruct (yymsg, yytype, yyvaluep) +yydestruct (yymsg, yytype, yyvaluep, info) const char *yymsg; int yytype; YYSTYPE *yyvaluep; + SQL_input *info; #endif { YYUSE (yyvaluep); + YYUSE (info); if (!yymsg) yymsg = "Deleting"; @@ -1332,6 +1354,7 @@ yydestruct (yymsg, yytype, yyvaluep) } } + /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus @@ -1341,19 +1364,16 @@ int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus -int yyparse (void); +int yyparse (SQL_input *info); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ - - - -/*-------------------------. -| yyparse or yypush_parse. | -`-------------------------*/ +/*----------. +| yyparse. | +`----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ @@ -1369,11 +1389,11 @@ yyparse (YYPARSE_PARAM) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int -yyparse (void) +yyparse (SQL_input *info) #else int -yyparse () - +yyparse (info) + SQL_input *info; #endif #endif { @@ -1540,7 +1560,7 @@ yybackup: /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) + if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ @@ -1571,8 +1591,8 @@ yybackup: yyn = yytable[yyn]; if (yyn <= 0) { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; + if (yytable_value_is_error (yyn)) + goto yyerrlab; yyn = -yyn; goto yyreduce; } @@ -1627,18 +1647,18 @@ yyreduce: { case 2: -/* Line 1455 of yacc.c */ -#line 133 "sql.y" +/* Line 1806 of yacc.c */ +#line 118 "sql.y" { SQL_input* sql = (SQL_input*) info; *sql->view = (yyvsp[(1) - (1)].query); - ;} + } break; case 10: -/* Line 1455 of yacc.c */ -#line 151 "sql.y" +/* Line 1806 of yacc.c */ +#line 136 "sql.y" { SQL_input *sql = (SQL_input*) info; MSIVIEW *insert = NULL; @@ -1648,13 +1668,13 @@ yyreduce: YYABORT; PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), insert ); - ;} + } break; case 11: -/* Line 1455 of yacc.c */ -#line 162 "sql.y" +/* Line 1806 of yacc.c */ +#line 147 "sql.y" { SQL_input *sql = (SQL_input*) info; MSIVIEW *insert = NULL; @@ -1664,13 +1684,13 @@ yyreduce: YYABORT; PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), insert ); - ;} + } break; case 12: -/* Line 1455 of yacc.c */ -#line 176 "sql.y" +/* Line 1806 of yacc.c */ +#line 161 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW *create = NULL; @@ -1686,13 +1706,13 @@ yyreduce: } PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), create ); - ;} + } break; case 13: -/* Line 1455 of yacc.c */ -#line 193 "sql.y" +/* Line 1806 of yacc.c */ +#line 178 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW *create = NULL; @@ -1704,13 +1724,13 @@ yyreduce: YYABORT; PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), create ); - ;} + } break; case 14: -/* Line 1455 of yacc.c */ -#line 209 "sql.y" +/* Line 1806 of yacc.c */ +#line 194 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW *update = NULL; @@ -1720,13 +1740,13 @@ yyreduce: YYABORT; PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), update ); - ;} + } break; case 15: -/* Line 1455 of yacc.c */ -#line 220 "sql.y" +/* Line 1806 of yacc.c */ +#line 205 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW *update = NULL; @@ -1736,13 +1756,13 @@ yyreduce: YYABORT; PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), update ); - ;} + } break; case 16: -/* Line 1455 of yacc.c */ -#line 234 "sql.y" +/* Line 1806 of yacc.c */ +#line 219 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW *delete = NULL; @@ -1752,13 +1772,13 @@ yyreduce: YYABORT; PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), delete ); - ;} + } break; case 17: -/* Line 1455 of yacc.c */ -#line 248 "sql.y" +/* Line 1806 of yacc.c */ +#line 233 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW *alter = NULL; @@ -1768,13 +1788,13 @@ yyreduce: YYABORT; PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), alter ); - ;} + } break; case 18: -/* Line 1455 of yacc.c */ -#line 259 "sql.y" +/* Line 1806 of yacc.c */ +#line 244 "sql.y" { SQL_input *sql = (SQL_input *)info; MSIVIEW *alter = NULL; @@ -1784,13 +1804,13 @@ yyreduce: YYABORT; PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), alter ); - ;} + } break; case 19: -/* Line 1455 of yacc.c */ -#line 270 "sql.y" +/* Line 1806 of yacc.c */ +#line 255 "sql.y" { SQL_input *sql = (SQL_input *)info; MSIVIEW *alter = NULL; @@ -1800,31 +1820,31 @@ yyreduce: YYABORT; PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), alter ); - ;} + } break; case 20: -/* Line 1455 of yacc.c */ -#line 284 "sql.y" +/* Line 1806 of yacc.c */ +#line 269 "sql.y" { (yyval.integer) = 1; - ;} + } break; case 21: -/* Line 1455 of yacc.c */ -#line 288 "sql.y" +/* Line 1806 of yacc.c */ +#line 273 "sql.y" { (yyval.integer) = -1; - ;} + } break; case 22: -/* Line 1455 of yacc.c */ -#line 295 "sql.y" +/* Line 1806 of yacc.c */ +#line 280 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW* drop = NULL; @@ -1835,25 +1855,25 @@ yyreduce: YYABORT; PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), drop ); - ;} + } break; case 23: -/* Line 1455 of yacc.c */ -#line 310 "sql.y" +/* Line 1806 of yacc.c */ +#line 295 "sql.y" { if( SQL_MarkPrimaryKeys( &(yyvsp[(1) - (4)].column_list), (yyvsp[(4) - (4)].column_list) ) ) (yyval.column_list) = (yyvsp[(1) - (4)].column_list); else (yyval.column_list) = NULL; - ;} + } break; case 24: -/* Line 1455 of yacc.c */ -#line 320 "sql.y" +/* Line 1806 of yacc.c */ +#line 305 "sql.y" { column_info *ci; @@ -1862,161 +1882,161 @@ yyreduce: ci->next = (yyvsp[(3) - (3)].column_list); (yyval.column_list) = (yyvsp[(1) - (3)].column_list); - ;} + } break; case 25: -/* Line 1455 of yacc.c */ -#line 330 "sql.y" +/* Line 1806 of yacc.c */ +#line 315 "sql.y" { (yyval.column_list) = (yyvsp[(1) - (1)].column_list); - ;} + } break; case 26: -/* Line 1455 of yacc.c */ -#line 337 "sql.y" +/* Line 1806 of yacc.c */ +#line 322 "sql.y" { (yyval.column_list) = (yyvsp[(1) - (2)].column_list); (yyval.column_list)->type = ((yyvsp[(2) - (2)].column_type) | MSITYPE_VALID); (yyval.column_list)->temporary = (yyvsp[(2) - (2)].column_type) & MSITYPE_TEMPORARY ? TRUE : FALSE; - ;} + } break; case 27: -/* Line 1455 of yacc.c */ -#line 346 "sql.y" +/* Line 1806 of yacc.c */ +#line 331 "sql.y" { (yyval.column_type) = (yyvsp[(1) - (1)].column_type); - ;} + } break; case 28: -/* Line 1455 of yacc.c */ -#line 350 "sql.y" +/* Line 1806 of yacc.c */ +#line 335 "sql.y" { (yyval.column_type) = (yyvsp[(1) - (2)].column_type) | MSITYPE_LOCALIZABLE; - ;} + } break; case 29: -/* Line 1455 of yacc.c */ -#line 354 "sql.y" +/* Line 1806 of yacc.c */ +#line 339 "sql.y" { (yyval.column_type) = (yyvsp[(1) - (2)].column_type) | MSITYPE_TEMPORARY; - ;} + } break; case 30: -/* Line 1455 of yacc.c */ -#line 361 "sql.y" +/* Line 1806 of yacc.c */ +#line 346 "sql.y" { (yyval.column_type) |= MSITYPE_NULLABLE; - ;} + } break; case 31: -/* Line 1455 of yacc.c */ -#line 365 "sql.y" +/* Line 1806 of yacc.c */ +#line 350 "sql.y" { (yyval.column_type) = (yyvsp[(1) - (3)].column_type); - ;} + } break; case 32: -/* Line 1455 of yacc.c */ -#line 372 "sql.y" +/* Line 1806 of yacc.c */ +#line 357 "sql.y" { (yyval.column_type) = MSITYPE_STRING | 1; - ;} + } break; case 33: -/* Line 1455 of yacc.c */ -#line 376 "sql.y" +/* Line 1806 of yacc.c */ +#line 361 "sql.y" { (yyval.column_type) = MSITYPE_STRING | 0x400 | (yyvsp[(3) - (4)].column_type); - ;} + } break; case 34: -/* Line 1455 of yacc.c */ -#line 380 "sql.y" +/* Line 1806 of yacc.c */ +#line 365 "sql.y" { (yyval.column_type) = MSITYPE_STRING | 0x400; - ;} + } break; case 35: -/* Line 1455 of yacc.c */ -#line 384 "sql.y" +/* Line 1806 of yacc.c */ +#line 369 "sql.y" { (yyval.column_type) = 2 | 0x400; - ;} + } break; case 36: -/* Line 1455 of yacc.c */ -#line 388 "sql.y" +/* Line 1806 of yacc.c */ +#line 373 "sql.y" { (yyval.column_type) = 2 | 0x400; - ;} + } break; case 37: -/* Line 1455 of yacc.c */ -#line 392 "sql.y" +/* Line 1806 of yacc.c */ +#line 377 "sql.y" { (yyval.column_type) = 4; - ;} + } break; case 38: -/* Line 1455 of yacc.c */ -#line 396 "sql.y" +/* Line 1806 of yacc.c */ +#line 381 "sql.y" { (yyval.column_type) = MSITYPE_STRING | MSITYPE_VALID; - ;} + } break; case 39: -/* Line 1455 of yacc.c */ -#line 403 "sql.y" +/* Line 1806 of yacc.c */ +#line 388 "sql.y" { if( ( (yyvsp[(1) - (1)].integer) > 255 ) || ( (yyvsp[(1) - (1)].integer) < 0 ) ) YYABORT; (yyval.column_type) = (yyvsp[(1) - (1)].integer); - ;} + } break; case 40: -/* Line 1455 of yacc.c */ -#line 412 "sql.y" +/* Line 1806 of yacc.c */ +#line 397 "sql.y" { (yyval.query) = (yyvsp[(2) - (2)].query); - ;} + } break; case 41: -/* Line 1455 of yacc.c */ -#line 416 "sql.y" +/* Line 1806 of yacc.c */ +#line 401 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW* distinct = NULL; @@ -2027,13 +2047,13 @@ yyreduce: YYABORT; PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), distinct ); - ;} + } break; case 42: -/* Line 1455 of yacc.c */ -#line 431 "sql.y" +/* Line 1806 of yacc.c */ +#line 416 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW* select = NULL; @@ -2049,49 +2069,49 @@ yyreduce: } else (yyval.query) = (yyvsp[(2) - (2)].query); - ;} + } break; case 44: -/* Line 1455 of yacc.c */ -#line 452 "sql.y" +/* Line 1806 of yacc.c */ +#line 437 "sql.y" { (yyvsp[(1) - (3)].column_list)->next = (yyvsp[(3) - (3)].column_list); - ;} + } break; case 45: -/* Line 1455 of yacc.c */ -#line 456 "sql.y" +/* Line 1806 of yacc.c */ +#line 441 "sql.y" { (yyval.column_list) = NULL; - ;} + } break; case 47: -/* Line 1455 of yacc.c */ -#line 464 "sql.y" +/* Line 1806 of yacc.c */ +#line 449 "sql.y" { (yyvsp[(1) - (3)].column_list)->next = (yyvsp[(3) - (3)].column_list); - ;} + } break; case 48: -/* Line 1455 of yacc.c */ -#line 468 "sql.y" +/* Line 1806 of yacc.c */ +#line 453 "sql.y" { (yyval.column_list) = NULL; - ;} + } break; case 49: -/* Line 1455 of yacc.c */ -#line 475 "sql.y" +/* Line 1806 of yacc.c */ +#line 460 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW* table = NULL; @@ -2102,13 +2122,13 @@ yyreduce: YYABORT; PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), table ); - ;} + } break; case 50: -/* Line 1455 of yacc.c */ -#line 487 "sql.y" +/* Line 1806 of yacc.c */ +#line 472 "sql.y" { UINT r; @@ -2120,13 +2140,13 @@ yyreduce: } (yyval.query) = (yyvsp[(1) - (4)].query); - ;} + } break; case 52: -/* Line 1455 of yacc.c */ -#line 504 "sql.y" +/* Line 1806 of yacc.c */ +#line 489 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW* where = NULL; @@ -2137,13 +2157,13 @@ yyreduce: YYABORT; PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), where ); - ;} + } break; case 53: -/* Line 1455 of yacc.c */ -#line 516 "sql.y" +/* Line 1806 of yacc.c */ +#line 501 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW* where = NULL; @@ -2154,349 +2174,360 @@ yyreduce: YYABORT; PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), where ); - ;} + } break; case 54: -/* Line 1455 of yacc.c */ -#line 531 "sql.y" +/* Line 1806 of yacc.c */ +#line 516 "sql.y" { (yyval.string) = (yyvsp[(1) - (1)].string); - ;} + } break; case 55: -/* Line 1455 of yacc.c */ -#line 535 "sql.y" +/* Line 1806 of yacc.c */ +#line 520 "sql.y" { (yyval.string) = parser_add_table( info, (yyvsp[(3) - (3)].string), (yyvsp[(1) - (3)].string) ); if (!(yyval.string)) YYABORT; - ;} + } break; case 56: -/* Line 1455 of yacc.c */ -#line 544 "sql.y" +/* Line 1806 of yacc.c */ +#line 529 "sql.y" { (yyval.expr) = (yyvsp[(2) - (3)].expr); if( !(yyval.expr) ) YYABORT; - ;} + } break; case 57: -/* Line 1455 of yacc.c */ -#line 550 "sql.y" +/* Line 1806 of yacc.c */ +#line 535 "sql.y" { (yyval.expr) = EXPR_complex( info, (yyvsp[(1) - (3)].expr), OP_AND, (yyvsp[(3) - (3)].expr) ); if( !(yyval.expr) ) YYABORT; - ;} + } break; case 58: -/* Line 1455 of yacc.c */ -#line 556 "sql.y" +/* Line 1806 of yacc.c */ +#line 541 "sql.y" { (yyval.expr) = EXPR_complex( info, (yyvsp[(1) - (3)].expr), OP_OR, (yyvsp[(3) - (3)].expr) ); if( !(yyval.expr) ) YYABORT; - ;} + } break; case 59: -/* Line 1455 of yacc.c */ -#line 562 "sql.y" +/* Line 1806 of yacc.c */ +#line 547 "sql.y" { (yyval.expr) = EXPR_complex( info, (yyvsp[(1) - (3)].expr), OP_EQ, (yyvsp[(3) - (3)].expr) ); if( !(yyval.expr) ) YYABORT; - ;} + } break; case 60: -/* Line 1455 of yacc.c */ -#line 568 "sql.y" +/* Line 1806 of yacc.c */ +#line 553 "sql.y" { (yyval.expr) = EXPR_complex( info, (yyvsp[(1) - (3)].expr), OP_GT, (yyvsp[(3) - (3)].expr) ); if( !(yyval.expr) ) YYABORT; - ;} + } break; case 61: -/* Line 1455 of yacc.c */ -#line 574 "sql.y" +/* Line 1806 of yacc.c */ +#line 559 "sql.y" { (yyval.expr) = EXPR_complex( info, (yyvsp[(1) - (3)].expr), OP_LT, (yyvsp[(3) - (3)].expr) ); if( !(yyval.expr) ) YYABORT; - ;} + } break; case 62: -/* Line 1455 of yacc.c */ -#line 580 "sql.y" +/* Line 1806 of yacc.c */ +#line 565 "sql.y" { (yyval.expr) = EXPR_complex( info, (yyvsp[(1) - (3)].expr), OP_LE, (yyvsp[(3) - (3)].expr) ); if( !(yyval.expr) ) YYABORT; - ;} + } break; case 63: -/* Line 1455 of yacc.c */ -#line 586 "sql.y" +/* Line 1806 of yacc.c */ +#line 571 "sql.y" { (yyval.expr) = EXPR_complex( info, (yyvsp[(1) - (3)].expr), OP_GE, (yyvsp[(3) - (3)].expr) ); if( !(yyval.expr) ) YYABORT; - ;} + } break; case 64: -/* Line 1455 of yacc.c */ -#line 592 "sql.y" +/* Line 1806 of yacc.c */ +#line 577 "sql.y" { (yyval.expr) = EXPR_complex( info, (yyvsp[(1) - (3)].expr), OP_NE, (yyvsp[(3) - (3)].expr) ); if( !(yyval.expr) ) YYABORT; - ;} + } break; case 65: -/* Line 1455 of yacc.c */ -#line 598 "sql.y" +/* Line 1806 of yacc.c */ +#line 583 "sql.y" { (yyval.expr) = EXPR_unary( info, (yyvsp[(1) - (3)].expr), OP_ISNULL ); if( !(yyval.expr) ) YYABORT; - ;} + } break; case 66: -/* Line 1455 of yacc.c */ -#line 604 "sql.y" +/* Line 1806 of yacc.c */ +#line 589 "sql.y" { (yyval.expr) = EXPR_unary( info, (yyvsp[(1) - (4)].expr), OP_NOTNULL ); if( !(yyval.expr) ) YYABORT; - ;} + } break; case 69: -/* Line 1455 of yacc.c */ -#line 618 "sql.y" +/* Line 1806 of yacc.c */ +#line 603 "sql.y" { (yyval.column_list) = parser_alloc_column( info, NULL, NULL ); if( !(yyval.column_list) ) YYABORT; (yyval.column_list)->val = (yyvsp[(1) - (1)].expr); - ;} + } break; case 70: -/* Line 1455 of yacc.c */ -#line 625 "sql.y" +/* Line 1806 of yacc.c */ +#line 610 "sql.y" { (yyval.column_list) = parser_alloc_column( info, NULL, NULL ); if( !(yyval.column_list) ) YYABORT; (yyval.column_list)->val = (yyvsp[(1) - (3)].expr); (yyval.column_list)->next = (yyvsp[(3) - (3)].column_list); - ;} + } break; case 72: -/* Line 1455 of yacc.c */ -#line 637 "sql.y" +/* Line 1806 of yacc.c */ +#line 622 "sql.y" { (yyval.column_list) = (yyvsp[(1) - (3)].column_list); (yyval.column_list)->next = (yyvsp[(3) - (3)].column_list); - ;} + } break; case 73: -/* Line 1455 of yacc.c */ -#line 645 "sql.y" +/* Line 1806 of yacc.c */ +#line 630 "sql.y" { (yyval.column_list) = (yyvsp[(1) - (3)].column_list); (yyval.column_list)->val = (yyvsp[(3) - (3)].expr); - ;} + } break; case 74: -/* Line 1455 of yacc.c */ -#line 653 "sql.y" +/* Line 1806 of yacc.c */ +#line 638 "sql.y" { (yyval.expr) = EXPR_ival( info, (yyvsp[(1) - (1)].integer) ); if( !(yyval.expr) ) YYABORT; - ;} + } break; case 75: -/* Line 1455 of yacc.c */ -#line 659 "sql.y" +/* Line 1806 of yacc.c */ +#line 644 "sql.y" { (yyval.expr) = EXPR_ival( info, -(yyvsp[(2) - (2)].integer) ); if( !(yyval.expr) ) YYABORT; - ;} + } break; case 76: -/* Line 1455 of yacc.c */ -#line 665 "sql.y" +/* Line 1806 of yacc.c */ +#line 650 "sql.y" { (yyval.expr) = EXPR_sval( info, &(yyvsp[(1) - (1)].str) ); if( !(yyval.expr) ) YYABORT; - ;} + } break; case 77: -/* Line 1455 of yacc.c */ -#line 671 "sql.y" +/* Line 1806 of yacc.c */ +#line 656 "sql.y" { (yyval.expr) = EXPR_wildcard( info ); if( !(yyval.expr) ) YYABORT; - ;} + } break; case 78: -/* Line 1455 of yacc.c */ -#line 680 "sql.y" +/* Line 1806 of yacc.c */ +#line 665 "sql.y" { (yyval.expr) = EXPR_column( info, (yyvsp[(1) - (1)].column_list) ); if( !(yyval.expr) ) YYABORT; - ;} + } break; case 79: -/* Line 1455 of yacc.c */ +/* Line 1806 of yacc.c */ +#line 674 "sql.y" + { + (yyval.column_list) = parser_alloc_column( info, (yyvsp[(1) - (3)].string), (yyvsp[(3) - (3)].string) ); + if( !(yyval.column_list) ) + YYABORT; + } + break; + + case 80: + +/* Line 1806 of yacc.c */ +#line 680 "sql.y" + { + (yyval.column_list) = parser_alloc_column( info, NULL, (yyvsp[(1) - (1)].string) ); + if( !(yyval.column_list) ) + YYABORT; + } + break; + + case 81: + +/* Line 1806 of yacc.c */ #line 689 "sql.y" { (yyval.column_list) = parser_alloc_column( info, (yyvsp[(1) - (3)].string), (yyvsp[(3) - (3)].string) ); if( !(yyval.column_list) ) YYABORT; - ;} + } break; - case 80: + case 82: -/* Line 1455 of yacc.c */ +/* Line 1806 of yacc.c */ #line 695 "sql.y" { (yyval.column_list) = parser_alloc_column( info, NULL, (yyvsp[(1) - (1)].string) ); if( !(yyval.column_list) ) YYABORT; - ;} - break; - - case 81: - -/* Line 1455 of yacc.c */ -#line 704 "sql.y" - { - (yyval.column_list) = parser_alloc_column( info, (yyvsp[(1) - (3)].string), (yyvsp[(3) - (3)].string) ); - if( !(yyval.column_list) ) - YYABORT; - ;} - break; - - case 82: - -/* Line 1455 of yacc.c */ -#line 710 "sql.y" - { - (yyval.column_list) = parser_alloc_column( info, NULL, (yyvsp[(1) - (1)].string) ); - if( !(yyval.column_list) ) - YYABORT; - ;} + } break; case 83: -/* Line 1455 of yacc.c */ -#line 716 "sql.y" +/* Line 1806 of yacc.c */ +#line 701 "sql.y" { (yyval.column_list) = parser_alloc_column( info, NULL, (yyvsp[(1) - (1)].string) ); if( !(yyval.column_list) ) YYABORT; - ;} + } break; case 84: -/* Line 1455 of yacc.c */ -#line 725 "sql.y" +/* Line 1806 of yacc.c */ +#line 710 "sql.y" { (yyval.string) = (yyvsp[(1) - (1)].string); - ;} + } break; case 85: -/* Line 1455 of yacc.c */ -#line 732 "sql.y" +/* Line 1806 of yacc.c */ +#line 717 "sql.y" { if ( SQL_getstring( info, &(yyvsp[(1) - (1)].str), &(yyval.string) ) != ERROR_SUCCESS || !(yyval.string) ) YYABORT; - ;} + } break; case 86: -/* Line 1455 of yacc.c */ -#line 740 "sql.y" +/* Line 1806 of yacc.c */ +#line 725 "sql.y" { if ( SQL_getstring( info, &(yyvsp[(1) - (1)].str), &(yyval.string) ) != ERROR_SUCCESS || !(yyval.string) ) YYABORT; - ;} + } break; case 87: -/* Line 1455 of yacc.c */ -#line 748 "sql.y" +/* Line 1806 of yacc.c */ +#line 733 "sql.y" { (yyval.integer) = SQL_getint( info ); - ;} + } break; -/* Line 1455 of yacc.c */ -#line 2488 "sql.tab.c" +/* Line 1806 of yacc.c */ +#line 2515 "sql.tab.c" default: break; } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); @@ -2524,44 +2555,47 @@ yyreduce: | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE - yyerror (YY_("syntax error")); + yyerror (info, YY_("syntax error")); #else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) - { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - } - } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (yymsg); - } - else - { - yyerror (YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (info, yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; } +# undef YYSYNTAX_ERROR #endif } @@ -2581,7 +2615,7 @@ yyerrlab: else { yydestruct ("Error: discarding", - yytoken, &yylval); + yytoken, &yylval, info); yychar = YYEMPTY; } } @@ -2620,7 +2654,7 @@ yyerrlab1: for (;;) { yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) + if (!yypact_value_is_default (yyn)) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) @@ -2637,7 +2671,7 @@ yyerrlab1: yydestruct ("Error: popping", - yystos[yystate], yyvsp); + yystos[yystate], yyvsp, info); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); @@ -2672,15 +2706,20 @@ yyabortlab: | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: - yyerror (YY_("memory exhausted")); + yyerror (info, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, info); + } /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); @@ -2688,7 +2727,7 @@ yyreturn: while (yyssp != yyss) { yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp); + yystos[*yyssp], yyvsp, info); YYPOPSTACK (1); } #ifndef yyoverflow @@ -2705,8 +2744,8 @@ yyreturn: -/* Line 1675 of yacc.c */ -#line 753 "sql.y" +/* Line 2067 of yacc.c */ +#line 738 "sql.y" static LPWSTR parser_add_table( void *info, LPCWSTR list, LPCWSTR table ) @@ -2823,7 +2862,7 @@ INT SQL_getint( void *info ) return r; } -static int sql_error( const char *str ) +static int sql_error( SQL_input *info, const char *str ) { return 0; } diff --git a/reactos/dll/win32/msi/sql.tab.h b/reactos/dll/win32/msi/sql.tab.h index 35f67fbf6ae..e34c0cbc2b3 100644 --- a/reactos/dll/win32/msi/sql.tab.h +++ b/reactos/dll/win32/msi/sql.tab.h @@ -1,10 +1,8 @@ +/* A Bison parser, made by GNU Bison 2.5. */ -/* A Bison parser, made by GNU Bison 2.4.1. */ - -/* Skeleton interface for Bison's Yacc-like parsers in C +/* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -109,8 +107,8 @@ typedef union YYSTYPE { -/* Line 1676 of yacc.c */ -#line 83 "sql.y" +/* Line 2068 of yacc.c */ +#line 68 "sql.y" struct sql_str str; LPWSTR string; @@ -122,8 +120,8 @@ typedef union YYSTYPE -/* Line 1676 of yacc.c */ -#line 127 "sql.tab.h" +/* Line 2068 of yacc.c */ +#line 125 "sql.tab.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ diff --git a/reactos/dll/win32/msi/sql.y b/reactos/dll/win32/msi/sql.y index ead7743171d..fa547412c03 100644 --- a/reactos/dll/win32/msi/sql.y +++ b/reactos/dll/win32/msi/sql.y @@ -34,29 +34,12 @@ #include "wine/debug.h" #include "wine/unicode.h" -#define YYLEX_PARAM info -#define YYPARSE_PARAM info - -static int sql_error(const char *str); - WINE_DEFAULT_DEBUG_CHANNEL(msi); -typedef struct tag_SQL_input -{ - MSIDATABASE *db; - LPCWSTR command; - DWORD n, len; - UINT r; - MSIVIEW **view; /* View structure for the resulting query. This value - * tracks the view currently being created so we can free - * this view on syntax error. - */ - struct list *mem; -} SQL_input; - static UINT SQL_getstring( void *info, const struct sql_str *strdata, LPWSTR *str ); static INT SQL_getint( void *info ); static int sql_lex( void *SQL_lval, SQL_input *info ); +static int sql_error( SQL_input *info, const char *str); static LPWSTR parser_add_table( void *info, LPCWSTR list, LPCWSTR table ); static void *parser_alloc( void *info, unsigned int sz ); @@ -77,6 +60,8 @@ static struct expr * EXPR_wildcard( void *info ); %} +%lex-param { SQL_input *info } +%parse-param { SQL_input *info } %pure-parser %union @@ -866,7 +851,7 @@ INT SQL_getint( void *info ) return r; } -static int sql_error( const char *str ) +static int sql_error( SQL_input *info, const char *str ) { return 0; } diff --git a/reactos/dll/win32/msi/table.c b/reactos/dll/win32/msi/table.c index dc53b13d684..75e9a19c4ec 100644 --- a/reactos/dll/win32/msi/table.c +++ b/reactos/dll/win32/msi/table.c @@ -1263,6 +1263,7 @@ static UINT get_table_value_from_record( MSITABLEVIEW *tv, MSIRECORD *rec, UINT { MSICOLUMNINFO columninfo; UINT r; + int ival; if ( (iField <= 0) || (iField > tv->num_cols) || @@ -1289,16 +1290,21 @@ static UINT get_table_value_from_record( MSITABLEVIEW *tv, MSIRECORD *rec, UINT } else if ( bytes_per_column( tv->db, &columninfo, LONG_STR_BYTES ) == 2 ) { - *pvalue = 0x8000 + MSI_RecordGetInteger( rec, iField ); - if ( *pvalue & 0xffff0000 ) + ival = MSI_RecordGetInteger( rec, iField ); + if (ival == 0x80000000) *pvalue = 0x8000; + else { - ERR("field %u value %d out of range\n", iField, *pvalue - 0x8000); - return ERROR_FUNCTION_FAILED; + *pvalue = 0x8000 + MSI_RecordGetInteger( rec, iField ); + if (*pvalue & 0xffff0000) + { + ERR("field %u value %d out of range\n", iField, *pvalue - 0x8000); + return ERROR_FUNCTION_FAILED; + } } } else { - INT ival = MSI_RecordGetInteger( rec, iField ); + ival = MSI_RecordGetInteger( rec, iField ); *pvalue = ival ^ 0x80000000; } diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 94c56666230..e626f01667a 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -116,7 +116,7 @@ reactos/dll/win32/msg711.acm # Synced to Wine-1.7.1 reactos/dll/win32/msgsm32.acm # Synced to Wine-1.7.1 reactos/dll/win32/mshtml # Synced to Wine-1.5.26 reactos/dll/win32/mshtml.tlb # Synced to Wine-1.5.26 -reactos/dll/win32/msi # Synced to Wine-1.5.26 +reactos/dll/win32/msi # Synced to Wine-1.7.1 reactos/dll/win32/msimg32 # Synced to Wine-1.5.19 reactos/dll/win32/msimtf # Synced to Wine-1.5.19 reactos/dll/win32/msisip # Synced to Wine-1.5.19