[MSI]
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 22 Sep 2013 16:30:18 +0000 (16:30 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 22 Sep 2013 16:30:18 +0000 (16:30 +0000)
* Sync with Wine 1.7.1.
CORE-7469

svn path=/trunk/; revision=60307

21 files changed:
reactos/dll/win32/msi/CMakeLists.txt
reactos/dll/win32/msi/action.c
reactos/dll/win32/msi/cond.tab.c
reactos/dll/win32/msi/cond.y
reactos/dll/win32/msi/custom.c
reactos/dll/win32/msi/database.c
reactos/dll/win32/msi/dialog.c
reactos/dll/win32/msi/events.c [deleted file]
reactos/dll/win32/msi/files.c
reactos/dll/win32/msi/media.c
reactos/dll/win32/msi/msi_main.c
reactos/dll/win32/msi/msipriv.h
reactos/dll/win32/msi/package.c
reactos/dll/win32/msi/patch.c
reactos/dll/win32/msi/query.h
reactos/dll/win32/msi/script.c
reactos/dll/win32/msi/sql.tab.c
reactos/dll/win32/msi/sql.tab.h
reactos/dll/win32/msi/sql.y
reactos/dll/win32/msi/table.c
reactos/media/doc/README.WINE

index b8ba0f3..0a6098d 100644 (file)
@@ -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)
index 740fb5d..6c291ba 100644 (file)
@@ -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;
index 3a0b533..d4676a8 100644 (file)
@@ -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"
 
 
 #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
@@ -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 <libintl.h> /* 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 <stdlib.h> /* 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 <stdlib.h> /* 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
 
-\f
 
 #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)
-{
-  int yyn = yypact[yystate];
+/* 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.
 
-  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
-    return 0;
-  else
-    {
-      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;
-
-# 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;
-         }
+   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)
+{
+  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;
+
+  /* There are many possibilities here to consider:
+     - Assume YYFAIL is not used.  It's too flawed to consider.  See
+       <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
+       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 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;
+
+          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;
+              }
+        }
+    }
 
-      yyf = YY_(yyformat);
-      yysize1 = yysize + yystrlen (yyf);
-      yysize_overflow |= (yysize1 < yysize);
-      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_
+    }
 
-      if (yysize_overflow)
-       return YYSIZE_MAXIMUM;
+  yysize1 = yysize + yystrlen (yyformat);
+  if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+    return 2;
+  yysize = yysize1;
 
-      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;
+  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 */
-\f
 
 /*-----------------------------------------------.
 | 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;
index 97bb002..fa55825 100644 (file)
 #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;
index 9944f54..ecc3b53 100644 (file)
@@ -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;
index 731427d..f10889d 100644 (file)
@@ -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++)
index bb84b37..403a097 100644 (file)
@@ -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 <winreg.h>
 #include <shlwapi.h>
 #include <msiserver.h>
+#include <shellapi.h>
 
 #include <wine/debug.h>
 #include <wine/unicode.h>
@@ -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 )
+static void dialog_do_preview( msi_dialog *dialog )
 {
-    DWORD style;
-    HWND hwnd;
+    TRACE("\n");
+    dialog->attributes |= msidbDialogAttributesVisible;
+    dialog->attributes &= ~msidbDialogAttributesModal;
+    dialog_run_message_loop( dialog );
+}
 
-    if( uiThreadId != GetCurrentThreadId() )
-        return SendMessageW( hMsiHiddenWindow, WM_MSI_DIALOG_CREATE, 0, (LPARAM) dialog );
+static void free_subscriber( struct subscriber *sub )
+{
+    msi_free( sub->event );
+    msi_free( sub->control );
+    msi_free( sub->attribute );
+    msi_free( sub );
+}
 
-    /* create the dialog window, don't show it yet */
-    style = WS_OVERLAPPED;
-    if( dialog->attributes & msidbDialogAttributesVisible )
-        style |= WS_VISIBLE;
+static void event_cleanup_subscriptions( MSIPACKAGE *package, const WCHAR *dialog )
+{
+    struct list *item, *next;
 
-    hwnd = CreateWindowW( szMsiDialogClass, dialog->name, style,
-                     CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
-                     NULL, NULL, NULL, dialog );
-    if( !hwnd )
+    LIST_FOR_EACH_SAFE( item, next, &package->subscriptions )
     {
-        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 */
+        struct subscriber *sub = LIST_ENTRY( item, struct subscriber, entry );
 
-    if( dialog->attributes & msidbDialogAttributesModal )
-    {
-        while( !dialog->finished )
-        {
-            MsgWaitForMultipleObjects( 0, NULL, 0, INFINITE, QS_ALLINPUT );
-            msi_process_pending_messages( dialog->hwnd );
-        }
+        if (strcmpW( sub->dialog->name, dialog )) continue;
+        list_remove( &sub->entry );
+        free_subscriber( sub );
     }
-    else
-        return ERROR_IO_PENDING;
-
-    return ERROR_SUCCESS;
-}
-
-static void msi_dialog_do_preview( msi_dialog *dialog )
-{
-    TRACE("\n");
-    dialog->attributes |= msidbDialogAttributesVisible;
-    dialog->attributes &= ~msidbDialogAttributesModal;
-    msi_dialog_run_message_loop( dialog );
 }
 
 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 (file)
index b5b69d0..0000000
+++ /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 <stdarg.h>
-//#include <stdio.h>
-
-//#include <windef.h>
-//#include "winbase.h"
-//#include "winerror.h"
-//#include "winreg.h"
-//#include "msi.h"
-#include "msipriv.h"
-
-#include <wine/debug.h>
-#include <wine/unicode.h>
-
-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;
-}
index d29cbab..075fe25 100644 (file)
@@ -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;
         }
index 0473bb8..1dc3a96 100644 (file)
@@ -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)))
index 42d8600..c0d3fde 100644 (file)
@@ -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 );
index 28dc4a4..cbb23dc 100644 (file)
@@ -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 {
index e6d5b6a..bfa6ed8 100644 (file)
@@ -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;
     }
 
index 1026362..7735589 100644 (file)
@@ -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 );
index c0de82b..c154b6c 100644 (file)
@@ -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;
 
index 7a4642a..7f61d91 100644 (file)
@@ -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 {
index f64d8cc..27213d2 100644 (file)
@@ -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"
 #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"
 
 
 #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 );
@@ -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 <libintl.h> /* 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 <stdlib.h> /* 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 <stdlib.h> /* 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
 
-\f
 
 #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)
-{
-  int yyn = yypact[yystate];
+/* 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.
 
-  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
-    return 0;
-  else
-    {
-      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;
-
-# 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;
-         }
+   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)
+{
+  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;
+
+  /* There are many possibilities here to consider:
+     - Assume YYFAIL is not used.  It's too flawed to consider.  See
+       <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
+       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 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;
+
+          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;
+              }
+        }
+    }
 
-      yyf = YY_(yyformat);
-      yysize1 = yysize + yystrlen (yyf);
-      yysize_overflow |= (yysize1 < yysize);
-      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_
+    }
 
-      if (yysize_overflow)
-       return YYSIZE_MAXIMUM;
+  yysize1 = yysize + yystrlen (yyformat);
+  if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+    return 2;
+  yysize = yysize1;
 
-      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;
+  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 */
-\f
 
 /*-----------------------------------------------.
 | 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 689 "sql.y"
+/* 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 1455 of yacc.c  */
-#line 695 "sql.y"
+/* 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 1455 of yacc.c  */
-#line 704 "sql.y"
+/* 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 82:
 
-/* Line 1455 of yacc.c  */
-#line 710 "sql.y"
+/* 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 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;
 }
index 35f67fb..e34c0cb 100644 (file)
@@ -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
 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 */
index ead7743..fa54741 100644 (file)
 #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;
 }
index dc53b13..75e9a19 100644 (file)
@@ -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;
     }
 
index 94c5666..e626f01 100644 (file)
@@ -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