diff --git a/dlls/msi/.cvsignore b/dlls/msi/.cvsignore index d96b95b4550..df022caee6d 100644 --- a/dlls/msi/.cvsignore +++ b/dlls/msi/.cvsignore @@ -1,6 +1,8 @@ Makefile +cond.tab.c +cond.tab.h msi.dll.dbg.c msi.spec.c msi.spec.def -y.tab.c -y.tab.h +sql.tab.c +sql.tab.h diff --git a/dlls/msi/Makefile.in b/dlls/msi/Makefile.in index 242d87df448..34dce1beb5f 100644 --- a/dlls/msi/Makefile.in +++ b/dlls/msi/Makefile.in @@ -21,18 +21,23 @@ C_SRCS = \ #RC_SRCS= msi_rc.rc -EXTRA_SRCS = sql.y -EXTRA_OBJS = y.tab.o +EXTRA_SRCS = sql.y cond.y +EXTRA_OBJS = sql.tab.o cond.tab.o @MAKE_DLL_RULES@ -y.tab.c y.tab.h: sql.y - $(YACC) -d -t $(SRCDIR)/sql.y +sql.tab.c sql.tab.h: sql.y + $(BISON) -p SQL_ -d $(SRCDIR)/sql.y + +cond.tab.c cond.tab.h: cond.y + $(BISON) -p COND_ -d $(SRCDIR)/cond.y # hack to allow parallel make -y.tab.h: y.tab.c -y.tab.o: y.tab.h +sql.tab.h: sql.tab.c +sql.tab.o: sql.tab.h +cond.tab.h: cond.tab.c +cond.tab.o: cond.tab.h -tokenize.o: y.tab.h +tokenize.o: sql.tab.h ### Dependencies: diff --git a/dlls/msi/cond.y b/dlls/msi/cond.y new file mode 100644 index 00000000000..8e7013636c9 --- /dev/null +++ b/dlls/msi/cond.y @@ -0,0 +1,397 @@ +%{ + +/* + * Implementation of the Microsoft Installer (msi.dll) + * + * Copyright 2003 Mike McCormack 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "wine/debug.h" +#include "wine/unicode.h" + +#include "msi.h" +#include "msiquery.h" + +#define YYLEX_PARAM info +#define YYPARSE_PARAM info + +static int COND_error(char *str); + +WINE_DEFAULT_DEBUG_CHANNEL(msi); + +typedef struct tag_yyinput +{ + MSIHANDLE hInstall; + LPCWSTR str; + INT n; + INT start; + MSICONDITION result; +} COND_input; + +static LPWSTR COND_GetString( COND_input *info ); +static int COND_lex( void *COND_lval, COND_input *info); + +typedef INT (*comp_int)(INT a, INT b); + +static INT comp_lt(INT a, INT b); +static INT comp_gt(INT a, INT b); +static INT comp_le(INT a, INT b); +static INT comp_ge(INT a, INT b); +static INT comp_eq(INT a, INT b); +static INT comp_ne(INT a, INT b); + +%} + +%pure-parser + +%union +{ + LPWSTR string; + INT value; + comp_int fn_comp_int; +} + +%token COND_SPACE COND_EOF COND_SPACE +%token COND_OR COND_AND COND_NOT +%token COND_LT COND_GT COND_LE COND_GE COND_EQ COND_NE +%token COND_LPAR COND_RPAR +%token COND_PERCENT COND_DOLLARS COND_QUESTION COND_AMPER COND_EXCLAM +%token COND_IDENT COND_NUMBER + +%nonassoc COND_EOF COND_ERROR + +%type expression boolean_term boolean_factor term value symbol integer +%type identifier +%type comparison_op + +%% + +condition: + expression + { + COND_input* cond = (COND_input*) info; + cond->result = $1; + } + ; + +expression: + boolean_term + { + $$ = $1; + } + | boolean_term COND_OR expression + { + $$ = $1 || $3; + } + ; + +boolean_term: + boolean_factor + { + $$ = $1; + } + | boolean_factor COND_AND term + { + $$ = $1 && $3; + } + ; + +boolean_factor: + term + { + $$ = $1; + } + | COND_NOT term + { + $$ = ! $2; + } + ; + +term: + value + { + $$ = $1; + } + | value comparison_op value + { + $$ = $2( $1, $3 ); + } + | COND_LPAR expression COND_RPAR + { + $$ = $2; + } + ; + +comparison_op: + COND_LT + { + $$ = comp_lt; + } + | COND_GT + { + $$ = comp_gt; + } + | COND_LE + { + $$ = comp_le; + } + | COND_GE + { + $$ = comp_ge; + } + | COND_EQ + { + $$ = comp_eq; + } + | COND_NE + { + $$ = comp_ne; + } + ; + +value: + symbol + { + $$ = $1; + } + | integer + { + $$ = $1; + } + ; + +symbol: + COND_DOLLARS identifier + { + COND_input* cond = (COND_input*) info; + INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN; + + MsiGetComponentStateW(cond->hInstall, $2, &install, &action ); + $$ = action; + } + | COND_QUESTION identifier + { + COND_input* cond = (COND_input*) info; + INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN; + + MsiGetComponentStateW(cond->hInstall, $2, &install, &action ); + $$ = install; + } + | COND_AMPER identifier + { + COND_input* cond = (COND_input*) info; + INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN; + + MsiGetFeatureStateW(cond->hInstall, $2, &install, &action ); + $$ = action; + } + | COND_EXCLAM identifier + { + COND_input* cond = (COND_input*) info; + INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN; + + MsiGetFeatureStateW(cond->hInstall, $2, &install, &action ); + $$ = install; + } + ; + +identifier: + COND_IDENT + { + COND_input* cond = (COND_input*) info; + $$ = COND_GetString(cond); + if( !$$ ) + YYABORT; + } + | COND_PERCENT identifier + { + UINT len = GetEnvironmentVariableW( $2, NULL, 0 ); + if( len++ ) + { + $$ = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) ); + if( $$ ) + GetEnvironmentVariableW( $2, $$, len ); + } + HeapFree( GetProcessHeap(), 0, $2 ); + } + ; + +integer: + COND_NUMBER + { + COND_input* cond = (COND_input*) info; + LPWSTR szNum = COND_GetString(cond); + if( !szNum ) + YYABORT; + $$ = atoiW( szNum ); + HeapFree( GetProcessHeap(), 0, szNum ); + } + ; + +%% + +static INT comp_lt(INT a, INT b) +{ + return (a < b); +} + +static INT comp_gt(INT a, INT b) +{ + return (a > b); +} + +static INT comp_le(INT a, INT b) +{ + return (a <= b); +} + +static INT comp_ge(INT a, INT b) +{ + return (a >= b); +} + +static INT comp_eq(INT a, INT b) +{ + return (a == b); +} + +static INT comp_ne(INT a, INT b) +{ + return (a != b); +} + + +static int COND_IsAlpha( WCHAR x ) +{ + return( ( ( x >= 'A' ) && ( x <= 'Z' ) ) || + ( ( x >= 'a' ) && ( x <= 'z' ) ) ); +} + +static int COND_IsNumber( WCHAR x ) +{ + return( ( x >= '0' ) && ( x <= '9' ) ); +} + +static int COND_IsIdent( WCHAR x ) +{ + return( COND_IsAlpha( x ) || COND_IsNumber( x ) || ( x == '_' ) ); +} + +static int COND_lex( void *COND_lval, COND_input *cond ) +{ + WCHAR ch; + + cond->start = cond->n; + ch = cond->str[cond->n]; + if( !ch ) + return COND_EOF; + cond->n++; + + switch( ch ) + { + case '(': return COND_LPAR; + case ')': return COND_RPAR; + case '&': return COND_AMPER; + case '!': return COND_EXCLAM; + case '$': return COND_DOLLARS; + case '?': return COND_QUESTION; + case '%': return COND_PERCENT; + case ' ': return COND_SPACE; + } + + if( COND_IsAlpha( ch ) ) + { + ch = cond->str[cond->n]; + while( COND_IsIdent( ch ) ) + ch = cond->str[cond->n++]; + return COND_IDENT; + } + + if( COND_IsNumber( ch ) ) + { + ch = cond->str[cond->n]; + while( COND_IsNumber( ch ) ) + ch = cond->str[cond->n++]; + return COND_NUMBER; + } + + return COND_ERROR; +} + +static LPWSTR COND_GetString( COND_input *cond ) +{ + int len; + LPWSTR str; + + len = cond->n - cond->start; + str = HeapAlloc( GetProcessHeap(), 0, (len+1) * sizeof (WCHAR) ); + if( str ) + strncpyW( str, &cond->str[cond->start], len ); + return str; +} + +static int COND_error(char *str) +{ + return 0; +} + +MSICONDITION WINAPI MsiEvaluateConditionW( MSIHANDLE hInstall, LPCWSTR szCondition ) +{ + COND_input cond; + MSICONDITION r; + + cond.hInstall = hInstall; + cond.str = szCondition; + cond.n = 0; + cond.start = 0; + cond.result = MSICONDITION_ERROR; + + if( !COND_parse( &cond ) ) + r = cond.result; + else + r = MSICONDITION_ERROR; + + return r; +} + +MSICONDITION WINAPI MsiEvaluateConditionA( MSIHANDLE hInstall, LPCSTR szCondition ) +{ + LPWSTR szwCond = NULL; + MSICONDITION r; + + if( szCondition ) + { + UINT len = MultiByteToWideChar( CP_ACP, 0, szCondition, -1, NULL, 0 ); + szwCond = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, szCondition, -1, szwCond, len ); + } + + r = MsiEvaluateConditionW( hInstall, szwCond ); + + if( szwCond ) + HeapFree( GetProcessHeap(), 0, szwCond ); + + return r; +} diff --git a/dlls/msi/msi.spec b/dlls/msi/msi.spec index 483eb4cad52..778be1d3901 100644 --- a/dlls/msi/msi.spec +++ b/dlls/msi/msi.spec @@ -43,8 +43,8 @@ 43 stdcall MsiEnumFeaturesW(wstr long ptr ptr) 44 stdcall MsiEnumProductsA(long ptr) 45 stdcall MsiEnumProductsW(long ptr) -46 stub MsiEvaluateConditionA -47 stub MsiEvaluateConditionW +46 stdcall MsiEvaluateConditionA(long str) +47 stdcall MsiEvaluateConditionW(long wstr) 48 stub MsiGetLastErrorRecord 49 stub MsiGetActiveDatabase 50 stdcall MsiGetComponentStateA(long str ptr ptr) diff --git a/dlls/msi/sql.y b/dlls/msi/sql.y index 9ed5249ad21..1528c51e696 100644 --- a/dlls/msi/sql.y +++ b/dlls/msi/sql.y @@ -36,17 +36,17 @@ #define YYLEX_PARAM info #define YYPARSE_PARAM info -extern int yyerror(const char *str); +extern int SQL_error(const char *str); WINE_DEFAULT_DEBUG_CHANNEL(msi); -typedef struct tag_yyinput +typedef struct tag_SQL_input { MSIDATABASE *db; LPCWSTR command; DWORD n, len; MSIVIEW **view; /* view structure for the resulting query */ -} yyinput; +} SQL_input; struct string_list { @@ -54,9 +54,9 @@ struct string_list struct string_list *next; }; -static LPWSTR yygetstring( yyinput *info ); -static INT yygetint( yyinput *sql ); -static int yylex( void *yylval, yyinput *info); +static LPWSTR SQL_getstring( SQL_input *info ); +static INT SQL_getint( SQL_input *sql ); +static int SQL_lex( void *SQL_lval, SQL_input *info); static MSIVIEW *do_one_select( MSIDATABASE *db, MSIVIEW *in, struct string_list *columns ); @@ -131,7 +131,7 @@ static struct expr * EXPR_sval( LPWSTR string ); oneselect: unorderedsel TK_ORDER TK_BY selcollist { - yyinput* sql = (yyinput*) info; + SQL_input* sql = (SQL_input*) info; if( !$1 ) YYABORT; @@ -142,7 +142,7 @@ oneselect: } | unorderedsel { - yyinput* sql = (yyinput*) info; + SQL_input* sql = (SQL_input*) info; *sql->view = $1; } @@ -151,7 +151,7 @@ oneselect: unorderedsel: TK_SELECT selcollist from { - yyinput* sql = (yyinput*) info; + SQL_input* sql = (SQL_input*) info; if( !$3 ) YYABORT; if( $2 ) @@ -161,7 +161,7 @@ unorderedsel: } | TK_SELECT TK_DISTINCT selcollist from { - yyinput* sql = (yyinput*) info; + SQL_input* sql = (SQL_input*) info; MSIVIEW *view = $4; if( !view ) @@ -208,7 +208,7 @@ selcollist: from: TK_FROM table { - yyinput* sql = (yyinput*) info; + SQL_input* sql = (SQL_input*) info; $$ = NULL; TRACE("From table: %s\n",debugstr_w($2)); @@ -216,7 +216,7 @@ from: } | TK_FROM table TK_WHERE expr { - yyinput* sql = (yyinput*) info; + SQL_input* sql = (SQL_input*) info; MSIVIEW *view = NULL; UINT r; @@ -293,8 +293,8 @@ val: } | TK_INTEGER { - yyinput* sql = (yyinput*) info; - $$ = EXPR_ival( yygetint(sql) ); + SQL_input* sql = (SQL_input*) info; + $$ = EXPR_ival( SQL_getint(sql) ); } | TK_STRING { @@ -330,19 +330,19 @@ table: string_or_id: TK_ID { - yyinput* sql = (yyinput*) info; - $$ = yygetstring(sql); + SQL_input* sql = (SQL_input*) info; + $$ = SQL_getstring(sql); } | TK_STRING { - yyinput* sql = (yyinput*) info; - $$ = yygetstring(sql); + SQL_input* sql = (SQL_input*) info; + $$ = SQL_getstring(sql); } ; %% -int yylex( void *yylval, yyinput *sql) +int SQL_lex( void *SQL_lval, SQL_input *sql) { int token; @@ -364,7 +364,7 @@ int yylex( void *yylval, yyinput *sql) return token; } -LPWSTR yygetstring( yyinput *sql ) +LPWSTR SQL_getstring( SQL_input *sql ) { LPCWSTR p = &sql->command[sql->n]; LPWSTR str; @@ -385,14 +385,14 @@ LPWSTR yygetstring( yyinput *sql ) return str; } -INT yygetint( yyinput *sql ) +INT SQL_getint( SQL_input *sql ) { LPCWSTR p = &sql->command[sql->n]; return atoiW( p ); } -int yyerror(const char *str) +int SQL_error(const char *str) { return 0; } @@ -493,7 +493,7 @@ static struct expr * EXPR_sval( LPWSTR string ) UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview ) { - yyinput sql; + SQL_input sql; int r; *phview = NULL; @@ -504,7 +504,7 @@ UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview ) sql.len = 0; sql.view = phview; - r = yyparse(&sql); + r = SQL_parse(&sql); TRACE("Parse returned %d\n", r); if( r ) diff --git a/dlls/msi/tokenize.c b/dlls/msi/tokenize.c index dc940485eab..99163925ad3 100644 --- a/dlls/msi/tokenize.c +++ b/dlls/msi/tokenize.c @@ -25,7 +25,7 @@ #include "wine/debug.h" #include "winnls.h" #include "query.h" -#include "y.tab.h" +#include "sql.tab.h" WINE_DEFAULT_DEBUG_CHANNEL(msi);