%{ /* * 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; }