4 * Implementation of the Microsoft Installer (msi.dll)
6 * Copyright 2003 Mike McCormack for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
38 #define YYLEX_PARAM info
39 #define YYPARSE_PARAM info
41 static int COND_error
(const char *str
);
43 WINE_DEFAULT_DEBUG_CHANNEL
(msi
);
45 typedef
struct tag_yyinput
58 static LPWSTR COND_GetString
( struct cond_str
*str
);
59 static LPWSTR COND_GetLiteral
( struct cond_str
*str
);
60 static int COND_lex
( void *COND_lval
, COND_input
*info
);
62 typedef INT
(*comp_int
)(INT a
, INT b
);
63 typedef INT
(*comp_str
)(LPWSTR a
, LPWSTR b
, BOOL caseless
);
64 typedef INT
(*comp_m1
)(LPWSTR a
,int b
);
65 typedef INT
(*comp_m2
)(int a
,LPWSTR b
);
67 static INT comp_lt_i
(INT a
, INT b
);
68 static INT comp_gt_i
(INT a
, INT b
);
69 static INT comp_le_i
(INT a
, INT b
);
70 static INT comp_ge_i
(INT a
, INT b
);
71 static INT comp_eq_i
(INT a
, INT b
);
72 static INT comp_ne_i
(INT a
, INT b
);
73 static INT comp_bitand
(INT a
, INT b
);
74 static INT comp_highcomp
(INT a
, INT b
);
75 static INT comp_lowcomp
(INT a
, INT b
);
77 static INT comp_eq_s
(LPWSTR a
, LPWSTR b
, BOOL casless
);
78 static INT comp_ne_s
(LPWSTR a
, LPWSTR b
, BOOL casless
);
79 static INT comp_lt_s
(LPWSTR a
, LPWSTR b
, BOOL casless
);
80 static INT comp_gt_s
(LPWSTR a
, LPWSTR b
, BOOL casless
);
81 static INT comp_le_s
(LPWSTR a
, LPWSTR b
, BOOL casless
);
82 static INT comp_ge_s
(LPWSTR a
, LPWSTR b
, BOOL casless
);
83 static INT comp_substring
(LPWSTR a
, LPWSTR b
, BOOL casless
);
84 static INT comp_start
(LPWSTR a
, LPWSTR b
, BOOL casless
);
85 static INT comp_end
(LPWSTR a
, LPWSTR b
, BOOL casless
);
87 static INT comp_eq_m1
(LPWSTR a
, INT b
);
88 static INT comp_ne_m1
(LPWSTR a
, INT b
);
89 static INT comp_lt_m1
(LPWSTR a
, INT b
);
90 static INT comp_gt_m1
(LPWSTR a
, INT b
);
91 static INT comp_le_m1
(LPWSTR a
, INT b
);
92 static INT comp_ge_m1
(LPWSTR a
, INT b
);
94 static INT comp_eq_m2
(INT a
, LPWSTR b
);
95 static INT comp_ne_m2
(INT a
, LPWSTR b
);
96 static INT comp_lt_m2
(INT a
, LPWSTR b
);
97 static INT comp_gt_m2
(INT a
, LPWSTR b
);
98 static INT comp_le_m2
(INT a
, LPWSTR b
);
99 static INT comp_ge_m2
(INT a
, LPWSTR b
);
110 comp_int fn_comp_int
;
111 comp_str fn_comp_str
;
116 %token COND_SPACE COND_EOF COND_SPACE
117 %token COND_OR COND_AND COND_NOT
118 %token COND_LT COND_GT COND_EQ
119 %token COND_LPAR COND_RPAR COND_TILDA
120 %token COND_PERCENT COND_DOLLARS COND_QUESTION COND_AMPER COND_EXCLAM
121 %token
<str
> COND_IDENT
<str
> COND_NUMBER
<str
> COND_LITER
123 %nonassoc COND_EOF COND_ERROR
125 %type
<value
> expression boolean_term boolean_factor
126 %type
<value
> term value_i symbol_i integer
127 %type
<string> identifier value_s symbol_s literal
128 %type
<fn_comp_int
> comp_op_i
129 %type
<fn_comp_str
> comp_op_s
130 %type
<fn_comp_m1
> comp_op_m1
131 %type
<fn_comp_m2
> comp_op_m2
138 COND_input
* cond
= (COND_input
*) info
;
148 | boolean_term COND_OR expression
159 | boolean_term COND_AND boolean_factor
184 $$
= ($1 && $1[0]) ? MSICONDITION_TRUE
: MSICONDITION_FALSE
;
186 | value_i comp_op_i value_i
190 | value_s comp_op_s value_s
192 $$
= $2( $1, $3, FALSE
);
194 | value_s COND_TILDA comp_op_s value_s
196 $$
= $3( $1, $4, TRUE
);
198 | value_s comp_op_m1 value_i
202 | value_i comp_op_m2 value_s
206 | COND_LPAR expression COND_RPAR
213 /* common functions */
254 /* common functions */
295 /* common functions */
320 /*Not valid for mixed compares*/
336 /* common functions */
361 /*Not valid for mixed compares*/
401 $$
= COND_GetLiteral
(&$1);
408 COND_DOLLARS identifier
410 COND_input
* cond
= (COND_input
*) info
;
411 INSTALLSTATE install
= INSTALLSTATE_UNKNOWN
, action
= INSTALLSTATE_UNKNOWN
;
413 MSI_GetComponentStateW
(cond
->package
, $2, &install
, &action
);
415 HeapFree
( GetProcessHeap
(), 0, $2 );
417 | COND_QUESTION identifier
419 COND_input
* cond
= (COND_input
*) info
;
420 INSTALLSTATE install
= INSTALLSTATE_UNKNOWN
, action
= INSTALLSTATE_UNKNOWN
;
422 MSI_GetComponentStateW
(cond
->package
, $2, &install
, &action
);
424 HeapFree
( GetProcessHeap
(), 0, $2 );
426 | COND_AMPER identifier
428 COND_input
* cond
= (COND_input
*) info
;
429 INSTALLSTATE install
= INSTALLSTATE_UNKNOWN
, action
= INSTALLSTATE_UNKNOWN
;
431 MSI_GetFeatureStateW
(cond
->package
, $2, &install
, &action
);
433 HeapFree
( GetProcessHeap
(), 0, $2 );
435 | COND_EXCLAM identifier
437 COND_input
* cond
= (COND_input
*) info
;
438 INSTALLSTATE install
= INSTALLSTATE_UNKNOWN
, action
= INSTALLSTATE_UNKNOWN
;
440 MSI_GetFeatureStateW
(cond
->package
, $2, &install
, &action
);
442 HeapFree
( GetProcessHeap
(), 0, $2 );
450 COND_input
* cond
= (COND_input
*) info
;
453 MSI_GetPropertyW
(cond
->package
, $1, NULL
, &sz
);
456 $$
= HeapAlloc
( GetProcessHeap
(), 0 ,sizeof
(WCHAR
));
462 $$
= HeapAlloc
( GetProcessHeap
(), 0, sz
*sizeof
(WCHAR
) );
464 /* Lookup the identifier */
466 MSI_GetPropertyW
(cond
->package
,$1,$$
,&sz
);
468 HeapFree
( GetProcessHeap
(), 0, $1 );
470 | COND_PERCENT identifier
472 UINT len
= GetEnvironmentVariableW
( $2, NULL
, 0 );
475 $$
= HeapAlloc
( GetProcessHeap
(), 0, len
*sizeof
(WCHAR
) );
477 GetEnvironmentVariableW
( $2, $$
, len
);
479 HeapFree
( GetProcessHeap
(), 0, $2 );
486 $$
= COND_GetString
(&$1);
495 LPWSTR szNum
= COND_GetString
(&$1);
499 HeapFree
( GetProcessHeap
(), 0, szNum
);
506 static int COND_IsAlpha
( WCHAR x
)
508 return
( ( ( x
>= 'A' ) && ( x
<= 'Z' ) ) ||
509 ( ( x
>= 'a' ) && ( x
<= 'z' ) ) ||
513 static int COND_IsNumber
( WCHAR x
)
515 return
( (( x
>= '0' ) && ( x
<= '9' )) ||
(x
=='-') ||
(x
=='.') );
519 /* the mess of comparison functions */
521 static INT comp_lt_i
(INT a
, INT b
)
523 static INT comp_gt_i
(INT a
, INT b
)
525 static INT comp_le_i
(INT a
, INT b
)
527 static INT comp_ge_i
(INT a
, INT b
)
529 static INT comp_eq_i
(INT a
, INT b
)
531 static INT comp_ne_i
(INT a
, INT b
)
533 static INT comp_bitand
(INT a
, INT b
)
535 static INT comp_highcomp
(INT a
, INT b
)
536 { return HIWORD
(a
)==b
; }
537 static INT comp_lowcomp
(INT a
, INT b
)
538 { return LOWORD
(a
)==b
; }
540 static INT comp_eq_s
(LPWSTR a
, LPWSTR b
, BOOL casless
)
541 { if
(casless
) return
!strcmpiW
(a
,b
); else return
!strcmpW
(a
,b
);}
542 static INT comp_ne_s
(LPWSTR a
, LPWSTR b
, BOOL casless
)
543 { if
(casless
) return strcmpiW
(a
,b
); else return strcmpW
(a
,b
);}
544 static INT comp_lt_s
(LPWSTR a
, LPWSTR b
, BOOL casless
)
545 { if
(casless
) return strcmpiW
(a
,b
)<0; else return strcmpW
(a
,b
)<0;}
546 static INT comp_gt_s
(LPWSTR a
, LPWSTR b
, BOOL casless
)
547 { if
(casless
) return strcmpiW
(a
,b
)>0; else return strcmpW
(a
,b
)>0;}
548 static INT comp_le_s
(LPWSTR a
, LPWSTR b
, BOOL casless
)
549 { if
(casless
) return strcmpiW
(a
,b
)<=0; else return strcmpW
(a
,b
)<=0;}
550 static INT comp_ge_s
(LPWSTR a
, LPWSTR b
, BOOL casless
)
551 { if
(casless
) return strcmpiW
(a
,b
)>=0; else return strcmpW
(a
,b
)>=0;}
552 static INT comp_substring
(LPWSTR a
, LPWSTR b
, BOOL casless
)
553 /* ERROR NOT WORKING REWRITE */
554 { if
(casless
) return strstrW
(a
,b
)!=NULL
; else return strstrW
(a
,b
)!=NULL
;}
555 static INT comp_start
(LPWSTR a
, LPWSTR b
, BOOL casless
)
556 { if
(casless
) return strncmpiW
(a
,b
,strlenW
(b
))==0;
557 else return strncmpW
(a
,b
,strlenW
(b
))==0;}
558 static INT comp_end
(LPWSTR a
, LPWSTR b
, BOOL casless
)
564 if
(casless
) return
(!strcmpiW
(&a
[i
-j
-1],b
));
565 else return
(!strcmpW
(&a
[i
-j
-1],b
));
569 static INT comp_eq_m1
(LPWSTR a
, INT b
)
570 { if
(COND_IsNumber
(a
[0])) return atoiW
(a
)==b
; else return
0;}
571 static INT comp_ne_m1
(LPWSTR a
, INT b
)
572 { if
(COND_IsNumber
(a
[0])) return atoiW
(a
)!=b
; else return
1;}
573 static INT comp_lt_m1
(LPWSTR a
, INT b
)
574 { if
(COND_IsNumber
(a
[0])) return atoiW
(a
)<b
; else return
0;}
575 static INT comp_gt_m1
(LPWSTR a
, INT b
)
576 { if
(COND_IsNumber
(a
[0])) return atoiW
(a
)>b
; else return
0;}
577 static INT comp_le_m1
(LPWSTR a
, INT b
)
578 { if
(COND_IsNumber
(a
[0])) return atoiW
(a
)<=b
; else return
0;}
579 static INT comp_ge_m1
(LPWSTR a
, INT b
)
580 { if
(COND_IsNumber
(a
[0])) return atoiW
(a
)>=b
; else return
0;}
582 static INT comp_eq_m2
(INT a
, LPWSTR b
)
583 { if
(COND_IsNumber
(b
[0])) return a
== atoiW
(b
); else return
0;}
584 static INT comp_ne_m2
(INT a
, LPWSTR b
)
585 { if
(COND_IsNumber
(b
[0])) return a
!= atoiW
(b
); else return
1;}
586 static INT comp_lt_m2
(INT a
, LPWSTR b
)
587 { if
(COND_IsNumber
(b
[0])) return a
< atoiW
(b
); else return
0;}
588 static INT comp_gt_m2
(INT a
, LPWSTR b
)
589 { if
(COND_IsNumber
(b
[0])) return a
> atoiW
(b
); else return
0;}
590 static INT comp_le_m2
(INT a
, LPWSTR b
)
591 { if
(COND_IsNumber
(b
[0])) return a
<= atoiW
(b
); else return
0;}
592 static INT comp_ge_m2
(INT a
, LPWSTR b
)
593 { if
(COND_IsNumber
(b
[0])) return a
>= atoiW
(b
); else return
0;}
597 static int COND_IsIdent
( WCHAR x
)
599 return
( COND_IsAlpha
( x
) || COND_IsNumber
( x
) ||
( x
== '_' )
600 ||
( x
== '#' ) ||
(x
== '.') );
603 static int COND_GetOne
( struct cond_str
*str
, COND_input
*cond
)
605 static const WCHAR szNot
[] = {'N','O','T',0};
606 static const WCHAR szAnd
[] = {'A','N','D',0};
607 static const WCHAR szOr
[] = {'O','R',0};
611 str
->data
= &cond
->str
[cond
->n
];
617 case
'(': rc
= COND_LPAR
; break
;
618 case
')': rc
= COND_RPAR
; break
;
619 case
'&': rc
= COND_AMPER
; break
;
620 case
'!': rc
= COND_EXCLAM
; break
;
621 case
'$': rc
= COND_DOLLARS
; break
;
622 case
'?': rc
= COND_QUESTION
; break
;
623 case
'%': rc
= COND_PERCENT
; break
;
624 case
' ': rc
= COND_SPACE
; break
;
625 case
'=': rc
= COND_EQ
; break
;
626 case
'~': rc
= COND_TILDA
; break
;
627 case
'<': rc
= COND_LT
; break
;
628 case
'>': rc
= COND_GT
; break
;
631 const WCHAR
*ch2
= str
->data
+ 1;
634 while
( *ch2
&& *ch2
!= '"' )
638 len
= ch2
- str
->data
+ 1;
643 ERR
("Unterminated string\n");
647 if
( COND_IsAlpha
( ch
) )
649 while
( COND_IsIdent
( str
->data
[len
] ) )
655 if
( COND_IsNumber
( ch
) )
657 while
( COND_IsNumber
( str
->data
[len
] ) )
663 ERR
("Got unknown character %c(%x)\n",ch
,ch
);
668 /* keyword identifiers */
669 if
( rc
== COND_IDENT
)
671 if
( (len
==3) && (strncmpiW
(str
->data
,szNot
,len
)==0) )
673 else if
( (len
==3) && (strncmpiW
(str
->data
,szAnd
,len
)==0) )
675 else if
( (len
==2) && (strncmpiW
(str
->data
,szOr
,len
)==0) )
685 static int COND_lex
( void *COND_lval
, COND_input
*cond
)
688 struct cond_str
*str
= COND_lval
;
691 rc
= COND_GetOne
( str
, cond
);
692 } while
(rc
== COND_SPACE
);
697 static LPWSTR COND_GetString
( struct cond_str
*str
)
701 ret
= HeapAlloc
( GetProcessHeap
(), 0, (str
->len
+1) * sizeof
(WCHAR
) );
704 memcpy
( ret
, str
->data
, str
->len
* sizeof
(WCHAR
));
707 TRACE
("Got identifier %s\n",debugstr_w
(ret
));
711 static LPWSTR COND_GetLiteral
( struct cond_str
*str
)
715 ret
= HeapAlloc
( GetProcessHeap
(), 0, (str
->len
-1) * sizeof
(WCHAR
) );
718 memcpy
( ret
, str
->data
+1, (str
->len
-2) * sizeof
(WCHAR
) );
721 TRACE
("Got literal %s\n",debugstr_w
(ret
));
725 static int COND_error
(const char *str
)
730 MSICONDITION MSI_EvaluateConditionW
( MSIPACKAGE
*package
, LPCWSTR szCondition
)
735 cond.package
= package
;
736 cond.str
= szCondition
;
740 TRACE
("Evaluating %s\n",debugstr_w
(szCondition
));
742 if
( szCondition
== NULL || szCondition
[0] == 0)
743 r
= MSICONDITION_NONE
;
744 else if
( !COND_parse
( &cond
) )
747 r
= MSICONDITION_ERROR
;
749 TRACE
("Evaluates to %i\n",r
);
753 MSICONDITION WINAPI MsiEvaluateConditionW
( MSIHANDLE hInstall
, LPCWSTR szCondition
)
758 package
= msihandle2msiinfo
( hInstall
, MSIHANDLETYPE_PACKAGE
);
760 return ERROR_INVALID_HANDLE
;
761 ret
= MSI_EvaluateConditionW
( package
, szCondition
);
762 msiobj_release
( &package
->hdr
);
766 MSICONDITION WINAPI MsiEvaluateConditionA
( MSIHANDLE hInstall
, LPCSTR szCondition
)
768 LPWSTR szwCond
= NULL
;
773 UINT len
= MultiByteToWideChar
( CP_ACP
, 0, szCondition
, -1, NULL
, 0 );
774 szwCond
= HeapAlloc
( GetProcessHeap
(), 0, len
* sizeof
(WCHAR
) );
775 MultiByteToWideChar
( CP_ACP
, 0, szCondition
, -1, szwCond
, len
);
778 r
= MsiEvaluateConditionW
( hInstall
, szwCond
);
780 HeapFree
( GetProcessHeap
(), 0, szwCond
);