mirror of
https://github.com/reactos/reactos.git
synced 2025-05-31 06:58:10 +00:00
sync cabinet, jscript, msi and msxml3 with wine 1.1.23
svn path=/trunk/; revision=41310
This commit is contained in:
parent
2f98b5a4c4
commit
cb11ae8788
27 changed files with 941 additions and 262 deletions
|
@ -2260,7 +2260,7 @@ static int fdi_decomp(const struct fdi_file *fi, int savemode, fdi_decomp_state
|
|||
return DECR_OK;
|
||||
}
|
||||
|
||||
static void free_decompression_temps(HFDI hfdi, struct fdi_folder *fol,
|
||||
static void free_decompression_temps(HFDI hfdi, const struct fdi_folder *fol,
|
||||
fdi_decomp_state *decomp_state)
|
||||
{
|
||||
switch (fol->comp_type & cffoldCOMPTYPE_MASK) {
|
||||
|
|
|
@ -25,11 +25,16 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
|
||||
|
||||
/* 1601 to 1970 is 369 years plus 89 leap days */
|
||||
#define TIME_EPOCH ((ULONGLONG)(369 * 365 + 89) * 86400 * 1000)
|
||||
|
||||
typedef struct {
|
||||
DispatchEx dispex;
|
||||
|
||||
/* ECMA-262 3rd Edition 15.9.1.1 */
|
||||
DOUBLE time;
|
||||
|
||||
LONG bias;
|
||||
} DateInstance;
|
||||
|
||||
static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
|
||||
|
@ -81,11 +86,8 @@ static const WCHAR setUTCFullYearW[] = {'s','e','t','U','T','C','F','u','l','l',
|
|||
/* ECMA-262 3rd Edition 15.9.1.14 */
|
||||
static inline DOUBLE time_clip(DOUBLE time)
|
||||
{
|
||||
/* FIXME: Handle inf */
|
||||
|
||||
if(8.64e15 < time || time < -8.64e15) {
|
||||
FIXME("return NaN\n");
|
||||
return 0.0;
|
||||
return ret_nan();
|
||||
}
|
||||
|
||||
return floor(time);
|
||||
|
@ -308,8 +310,33 @@ static HRESULT Date_getTimezoneOffset(DispatchEx *dispex, LCID lcid, WORD flags,
|
|||
static HRESULT Date_setTime(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
|
||||
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
VARIANT v;
|
||||
HRESULT hres;
|
||||
DateInstance *date;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
if(!is_class(dispex, JSCLASS_DATE)) {
|
||||
FIXME("throw TypeError\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if(!arg_cnt(dp)) {
|
||||
if(retv) num_set_nan(retv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
date = (DateInstance*)dispex;
|
||||
date->time = time_clip(num_val(&v));
|
||||
|
||||
if(retv)
|
||||
num_set_val(retv, date->time);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT Date_setMiliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
|
||||
|
@ -477,6 +504,9 @@ static HRESULT create_date(script_ctx_t *ctx, BOOL use_constr, DOUBLE time, Disp
|
|||
{
|
||||
DateInstance *date;
|
||||
HRESULT hres;
|
||||
TIME_ZONE_INFORMATION tzi;
|
||||
|
||||
GetTimeZoneInformation(&tzi);
|
||||
|
||||
date = heap_alloc_zero(sizeof(DateInstance));
|
||||
if(!date)
|
||||
|
@ -492,6 +522,7 @@ static HRESULT create_date(script_ctx_t *ctx, BOOL use_constr, DOUBLE time, Disp
|
|||
}
|
||||
|
||||
date->time = time;
|
||||
date->bias = tzi.Bias;
|
||||
|
||||
*ret = &date->dispex;
|
||||
return S_OK;
|
||||
|
@ -511,12 +542,13 @@ static HRESULT DateConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPP
|
|||
/* ECMA-262 3rd Edition 15.9.3.3 */
|
||||
case 0: {
|
||||
FILETIME time;
|
||||
LONGLONG lltime;
|
||||
|
||||
GetSystemTimeAsFileTime(&time);
|
||||
lltime = ((LONGLONG)time.dwHighDateTime<<32)
|
||||
+ time.dwLowDateTime;
|
||||
|
||||
hres = create_date(dispex->ctx, TRUE,
|
||||
floor((DOUBLE)(time.dwLowDateTime/1e6) + (DOUBLE)time.dwHighDateTime*((DOUBLE)UINT_MAX+1.0)/1.e6),
|
||||
&date);
|
||||
hres = create_date(dispex->ctx, TRUE, lltime/10000-TIME_EPOCH, &date);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
break;
|
||||
|
|
|
@ -351,8 +351,8 @@ static HRESULT JSGlobal_parseInt(DispatchEx *dispex, LCID lcid, WORD flags, DISP
|
|||
HRESULT hres;
|
||||
|
||||
if(!arg_cnt(dp)) {
|
||||
FIXME("NAN\n");
|
||||
return E_NOTIMPL;
|
||||
if(retv) num_set_nan(retv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if(arg_cnt(dp) >= 2) {
|
||||
|
|
|
@ -255,6 +255,13 @@ static inline void num_set_nan(VARIANT *v)
|
|||
#endif
|
||||
}
|
||||
|
||||
static inline DOUBLE ret_nan()
|
||||
{
|
||||
VARIANT v;
|
||||
num_set_nan(&v);
|
||||
return V_R8(&v);
|
||||
}
|
||||
|
||||
static inline void num_set_inf(VARIANT *v, BOOL positive)
|
||||
{
|
||||
V_VT(v) = VT_R8;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "jscript.h"
|
||||
#include "activscp.h"
|
||||
|
@ -30,6 +31,8 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
|
||||
|
||||
#define LONGLONG_MAX (((LONGLONG)0x7fffffff<<32)|0xffffffff)
|
||||
|
||||
static const WCHAR breakW[] = {'b','r','e','a','k',0};
|
||||
static const WCHAR caseW[] = {'c','a','s','e',0};
|
||||
static const WCHAR catchW[] = {'c','a','t','c','h',0};
|
||||
|
@ -372,16 +375,42 @@ static literal_t *alloc_int_literal(parser_ctx_t *ctx, LONG l)
|
|||
|
||||
static int parse_double_literal(parser_ctx_t *ctx, LONG int_part, literal_t **literal)
|
||||
{
|
||||
double d, tmp = 1.0;
|
||||
LONGLONG d, hlp;
|
||||
int exp = 0;
|
||||
|
||||
if(ctx->ptr == ctx->end || !isdigitW(*ctx->ptr)) {
|
||||
ERR("No digit after point\n");
|
||||
if(ctx->ptr == ctx->end || (!isdigitW(*ctx->ptr) &&
|
||||
*ctx->ptr!='.' && *ctx->ptr!='e' && *ctx->ptr!='E')) {
|
||||
ERR("Illegal character\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
d = int_part;
|
||||
while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
|
||||
hlp = d*10 + *(ctx->ptr++) - '0';
|
||||
if(d>LONGLONG_MAX/10 || hlp<0) {
|
||||
exp++;
|
||||
break;
|
||||
}
|
||||
else
|
||||
d = hlp;
|
||||
}
|
||||
while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
|
||||
exp++;
|
||||
ctx->ptr++;
|
||||
}
|
||||
|
||||
if(*ctx->ptr == '.') ctx->ptr++;
|
||||
|
||||
while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
|
||||
hlp = d*10 + *(ctx->ptr++) - '0';
|
||||
if(d>LONGLONG_MAX/10 || hlp<0)
|
||||
break;
|
||||
|
||||
d = hlp;
|
||||
exp--;
|
||||
}
|
||||
while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr))
|
||||
d += (tmp /= 10.0)*(*ctx->ptr++ - '0');
|
||||
ctx->ptr++;
|
||||
|
||||
if(ctx->ptr < ctx->end && (*ctx->ptr == 'e' || *ctx->ptr == 'E')) {
|
||||
int sign = 1, e = 0;
|
||||
|
@ -404,16 +433,20 @@ static int parse_double_literal(parser_ctx_t *ctx, LONG int_part, literal_t **li
|
|||
return lex_error(ctx, E_FAIL);
|
||||
}
|
||||
|
||||
while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr))
|
||||
e = e*10 + *ctx->ptr++ - '0';
|
||||
while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
|
||||
if(e > INT_MAX/10 || (e = e*10 + *ctx->ptr++ - '0')<0)
|
||||
e = INT_MAX;
|
||||
}
|
||||
e *= sign;
|
||||
|
||||
d *= pow(10, e);
|
||||
if(exp<0 && e<0 && e+exp>0) exp = INT_MIN;
|
||||
else if(exp>0 && e>0 && e+exp<0) exp = INT_MAX;
|
||||
else exp += e;
|
||||
}
|
||||
|
||||
*literal = parser_alloc(ctx, sizeof(literal_t));
|
||||
(*literal)->vt = VT_R8;
|
||||
(*literal)->u.dval = d;
|
||||
(*literal)->u.dval = (double)d*pow(10, exp);
|
||||
|
||||
return tNumericLiteral;
|
||||
}
|
||||
|
@ -458,13 +491,20 @@ static int parse_numeric_literal(parser_ctx_t *ctx, literal_t **literal)
|
|||
}
|
||||
|
||||
while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr))
|
||||
l = l*10 + *(ctx->ptr++)-'0';
|
||||
{
|
||||
d = l*10 + *(ctx->ptr)-'0';
|
||||
|
||||
/* Check for integer overflow */
|
||||
if (l > INT_MAX/10 || d < 0)
|
||||
return parse_double_literal(ctx, l, literal);
|
||||
|
||||
l = d;
|
||||
ctx->ptr++;
|
||||
}
|
||||
|
||||
if(ctx->ptr < ctx->end) {
|
||||
if(*ctx->ptr == '.') {
|
||||
ctx->ptr++;
|
||||
if(*ctx->ptr == '.' || *ctx->ptr == 'e' || *ctx->ptr == 'E')
|
||||
return parse_double_literal(ctx, l, literal);
|
||||
}
|
||||
|
||||
if(is_identifier_char(*ctx->ptr)) {
|
||||
WARN("unexpected identifier char\n");
|
||||
|
|
|
@ -105,8 +105,8 @@ static HRESULT Math_LN2(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *d
|
|||
static HRESULT Math_LN10(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
|
||||
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
TRACE("\n");
|
||||
return math_constant(M_LN10, flags, retv);
|
||||
}
|
||||
|
||||
/* ECMA-262 3rd Edition 15.8.1.6 */
|
||||
|
@ -120,15 +120,15 @@ static HRESULT Math_PI(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp
|
|||
static HRESULT Math_SQRT2(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
|
||||
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
TRACE("\n");
|
||||
return math_constant(M_SQRT2, flags, retv);
|
||||
}
|
||||
|
||||
static HRESULT Math_SQRT1_2(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
|
||||
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
TRACE("\n");
|
||||
return math_constant(M_SQRT1_2, flags, retv);
|
||||
}
|
||||
|
||||
/* ECMA-262 3rd Edition 15.8.2.12 */
|
||||
|
@ -160,29 +160,89 @@ static HRESULT Math_abs(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *d
|
|||
static HRESULT Math_acos(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
|
||||
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
VARIANT v;
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
if(!arg_cnt(dp)) {
|
||||
if(retv) num_set_nan(retv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
if(retv) num_set_val(retv, acos(num_val(&v)));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT Math_asin(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
|
||||
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
VARIANT v;
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
if(!arg_cnt(dp)) {
|
||||
if(retv) num_set_nan(retv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
if(retv) num_set_val(retv, asin(num_val(&v)));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT Math_atan(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
|
||||
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
VARIANT v;
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
if(!arg_cnt(dp)) {
|
||||
if(retv) num_set_nan(retv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
if(retv) num_set_val(retv, atan(num_val(&v)));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT Math_atan2(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
|
||||
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
VARIANT v1, v2;
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
if(arg_cnt(dp)<2) {
|
||||
if(retv) num_set_nan(retv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v1);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
hres = to_number(dispex->ctx, get_arg(dp, 1), ei, &v2);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
if(retv) num_set_val(retv, atan2(num_val(&v1), num_val(&v2)));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* ECMA-262 3rd Edition 15.8.2.6 */
|
||||
|
@ -233,8 +293,22 @@ static HRESULT Math_cos(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *d
|
|||
static HRESULT Math_exp(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
|
||||
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
VARIANT v;
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
if(!arg_cnt(dp)) {
|
||||
if(retv) num_set_nan(retv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
if(retv) num_set_val(retv, exp(num_val(&v)));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT Math_floor(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
|
||||
|
@ -263,8 +337,24 @@ static HRESULT Math_floor(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS
|
|||
static HRESULT Math_log(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
|
||||
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
VARIANT v;
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
if(!arg_cnt(dp)) {
|
||||
if(retv)
|
||||
num_set_nan(retv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
if(retv)
|
||||
num_set_val(retv, log(num_val(&v)));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* ECMA-262 3rd Edition 15.8.2.11 */
|
||||
|
@ -351,8 +441,8 @@ static HRESULT Math_pow(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *d
|
|||
TRACE("\n");
|
||||
|
||||
if(arg_cnt(dp) < 2) {
|
||||
FIXME("unimplemented arg_cnt %d\n", arg_cnt(dp));
|
||||
return E_NOTIMPL;
|
||||
if(retv) num_set_nan(retv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &x);
|
||||
|
@ -411,22 +501,64 @@ static HRESULT Math_round(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS
|
|||
static HRESULT Math_sin(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
|
||||
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
VARIANT v;
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
if(!arg_cnt(dp)) {
|
||||
if(retv) num_set_nan(retv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
if(retv) num_set_val(retv, sin(num_val(&v)));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT Math_sqrt(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
|
||||
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
VARIANT v;
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
if(!arg_cnt(dp)) {
|
||||
if(retv) num_set_nan(retv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
if(retv) num_set_val(retv, sqrt(num_val(&v)));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT Math_tan(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
|
||||
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
VARIANT v;
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
if(!arg_cnt(dp)) {
|
||||
if(retv) num_set_nan(retv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
if(retv) num_set_val(retv, tan(num_val(&v)));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const builtin_prop_t Math_props[] = {
|
||||
|
|
|
@ -3396,7 +3396,7 @@ HRESULT regexp_match(DispatchEx *dispex, const WCHAR *str, DWORD len, BOOL gflag
|
|||
}
|
||||
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
break;
|
||||
|
||||
if(ret_size == i) {
|
||||
if(ret)
|
||||
|
|
|
@ -254,8 +254,8 @@ static HRESULT String_charCodeAt(DispatchEx *dispex, LCID lcid, WORD flags, DISP
|
|||
return hres;
|
||||
|
||||
if(V_VT(&v) != VT_I4 || V_I4(&v) < 0 || V_I4(&v) >= length) {
|
||||
FIXME("NAN\n");
|
||||
return E_FAIL;
|
||||
if(retv) num_set_nan(&v);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
idx = V_I4(&v);
|
||||
|
|
|
@ -6076,7 +6076,7 @@ static UINT load_assembly(MSIRECORD *rec, LPVOID param)
|
|||
/* FIXME: we should probably check the manifest file here */
|
||||
|
||||
if (!MsiGetFileVersionW(assembly->file->TargetPath, version, &size, NULL, NULL) &&
|
||||
strcmpW(version, assembly->file->Version) >= 0)
|
||||
(!assembly->file->Version || strcmpW(version, assembly->file->Version) >= 0))
|
||||
{
|
||||
assembly->installed = TRUE;
|
||||
}
|
||||
|
|
|
@ -257,8 +257,11 @@ UINT ALTER_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR name, column_inf
|
|||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
r = TABLE_CreateView( db, name, &av->table );
|
||||
if (r != ERROR_SUCCESS || !av->table)
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
msi_free( av );
|
||||
return r;
|
||||
}
|
||||
|
||||
if (colinfo)
|
||||
colinfo->table = name;
|
||||
|
|
|
@ -42,7 +42,7 @@ typedef struct tagMSICREATEVIEW
|
|||
{
|
||||
MSIVIEW view;
|
||||
MSIDATABASE *db;
|
||||
LPWSTR name;
|
||||
LPCWSTR name;
|
||||
BOOL bIsTemp;
|
||||
BOOL hold;
|
||||
column_info *col_info;
|
||||
|
@ -145,9 +145,9 @@ static const MSIVIEWOPS create_ops =
|
|||
NULL,
|
||||
};
|
||||
|
||||
static UINT check_columns( column_info *col_info )
|
||||
static UINT check_columns( const column_info *col_info )
|
||||
{
|
||||
column_info *c1, *c2;
|
||||
const column_info *c1, *c2;
|
||||
|
||||
/* check for two columns with the same name */
|
||||
for( c1 = col_info; c1; c1 = c1->next )
|
||||
|
@ -158,7 +158,7 @@ static UINT check_columns( column_info *col_info )
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
|
||||
UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR table,
|
||||
column_info *col_info, BOOL hold )
|
||||
{
|
||||
MSICREATEVIEW *cv = NULL;
|
||||
|
@ -180,7 +180,7 @@ UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
|
|||
for( col = col_info; col; col = col->next )
|
||||
{
|
||||
if (!col->table)
|
||||
col->table = strdupW(table);
|
||||
col->table = table;
|
||||
|
||||
if( !col->temporary )
|
||||
temp = FALSE;
|
||||
|
|
|
@ -377,6 +377,7 @@ static LPWSTR msi_build_createsql_columns(LPWSTR *columns_data, LPWSTR *types, D
|
|||
static const WCHAR type_char[] = {'C','H','A','R',0};
|
||||
static const WCHAR type_int[] = {'I','N','T',0};
|
||||
static const WCHAR type_long[] = {'L','O','N','G',0};
|
||||
static const WCHAR type_object[] = {'O','B','J','E','C','T',0};
|
||||
static const WCHAR type_notnull[] = {' ','N','O','T',' ','N','U','L','L',0};
|
||||
static const WCHAR localizable[] = {' ','L','O','C','A','L','I','Z','A','B','L','E',0};
|
||||
|
||||
|
@ -421,6 +422,11 @@ static LPWSTR msi_build_createsql_columns(LPWSTR *columns_data, LPWSTR *types, D
|
|||
else
|
||||
type = type_long;
|
||||
break;
|
||||
case 'v':
|
||||
lstrcpyW(extra, type_notnull);
|
||||
case 'V':
|
||||
type = type_object;
|
||||
break;
|
||||
default:
|
||||
ERR("Unknown type: %c\n", types[i][0]);
|
||||
msi_free(columns);
|
||||
|
@ -522,8 +528,32 @@ static UINT msi_add_table_to_db(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types,
|
|||
return r;
|
||||
}
|
||||
|
||||
static LPWSTR msi_import_stream_filename(LPCWSTR path, LPCWSTR name)
|
||||
{
|
||||
DWORD len;
|
||||
LPWSTR fullname, ptr;
|
||||
|
||||
len = lstrlenW(path) + lstrlenW(name) + 1;
|
||||
fullname = msi_alloc(len*sizeof(WCHAR));
|
||||
if (!fullname)
|
||||
return NULL;
|
||||
|
||||
lstrcpyW( fullname, path );
|
||||
|
||||
/* chop off extension from path */
|
||||
ptr = strrchrW(fullname, '.');
|
||||
if (!ptr)
|
||||
{
|
||||
msi_free (fullname);
|
||||
return NULL;
|
||||
}
|
||||
*ptr++ = '\\';
|
||||
lstrcpyW( ptr, name );
|
||||
return fullname;
|
||||
}
|
||||
|
||||
static UINT construct_record(DWORD num_columns, LPWSTR *types,
|
||||
LPWSTR *data, MSIRECORD **rec)
|
||||
LPWSTR *data, LPWSTR path, MSIRECORD **rec)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
|
@ -542,6 +572,20 @@ static UINT construct_record(DWORD num_columns, LPWSTR *types,
|
|||
if (*data[i])
|
||||
MSI_RecordSetInteger(*rec, i + 1, atoiW(data[i]));
|
||||
break;
|
||||
case 'V': case 'v':
|
||||
if (*data[i])
|
||||
{
|
||||
UINT r;
|
||||
LPWSTR file = msi_import_stream_filename(path, data[i]);
|
||||
if (!file)
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
r = MSI_RecordSetStreamFromFileW(*rec, i + 1, file);
|
||||
msi_free (file);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERR("Unhandled column type: %c\n", types[i][0]);
|
||||
msiobj_release(&(*rec)->hdr);
|
||||
|
@ -554,7 +598,8 @@ static UINT construct_record(DWORD num_columns, LPWSTR *types,
|
|||
|
||||
static UINT msi_add_records_to_table(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types,
|
||||
LPWSTR *labels, LPWSTR **records,
|
||||
int num_columns, int num_records)
|
||||
int num_columns, int num_records,
|
||||
LPWSTR path)
|
||||
{
|
||||
UINT r;
|
||||
int i;
|
||||
|
@ -579,7 +624,7 @@ static UINT msi_add_records_to_table(MSIDATABASE *db, LPWSTR *columns, LPWSTR *t
|
|||
|
||||
for (i = 0; i < num_records; i++)
|
||||
{
|
||||
r = construct_record(num_columns, types, records[i], &rec);
|
||||
r = construct_record(num_columns, types, records[i], path, &rec);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
|
@ -683,7 +728,7 @@ static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
|||
}
|
||||
}
|
||||
|
||||
r = msi_add_records_to_table( db, columns, types, labels, records, num_columns, num_records );
|
||||
r = msi_add_records_to_table( db, columns, types, labels, records, num_columns, num_records, path );
|
||||
}
|
||||
|
||||
done:
|
||||
|
@ -1011,6 +1056,12 @@ typedef struct _tagMERGETABLE
|
|||
struct list rows;
|
||||
LPWSTR name;
|
||||
DWORD numconflicts;
|
||||
LPWSTR *columns;
|
||||
DWORD numcolumns;
|
||||
LPWSTR *types;
|
||||
DWORD numtypes;
|
||||
LPWSTR *labels;
|
||||
DWORD numlabels;
|
||||
} MERGETABLE;
|
||||
|
||||
typedef struct _tagMERGEROW
|
||||
|
@ -1129,8 +1180,8 @@ done:
|
|||
static LPWSTR get_key_value(MSIQUERY *view, LPCWSTR key, MSIRECORD *rec)
|
||||
{
|
||||
MSIRECORD *colnames;
|
||||
LPWSTR str;
|
||||
UINT r, i = 0;
|
||||
LPWSTR str, val;
|
||||
UINT r, i = 0, sz = 0;
|
||||
int cmp;
|
||||
|
||||
r = MSI_ViewGetColumnInfo(view, MSICOLINFO_NAMES, &colnames);
|
||||
|
@ -1145,7 +1196,43 @@ static LPWSTR get_key_value(MSIQUERY *view, LPCWSTR key, MSIRECORD *rec)
|
|||
} while (cmp);
|
||||
|
||||
msiobj_release(&colnames->hdr);
|
||||
return msi_dup_record_field(rec, i);
|
||||
|
||||
r = MSI_RecordGetStringW(rec, i, NULL, &sz);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return NULL;
|
||||
sz++;
|
||||
|
||||
if (MSI_RecordGetString(rec, i)) /* check record field is a string */
|
||||
{
|
||||
/* quote string record fields */
|
||||
const WCHAR szQuote[] = {'\'', 0};
|
||||
sz += 2;
|
||||
val = msi_alloc(sz*sizeof(WCHAR));
|
||||
if (!val)
|
||||
return NULL;
|
||||
|
||||
lstrcpyW(val, szQuote);
|
||||
r = MSI_RecordGetStringW(rec, i, val+1, &sz);
|
||||
lstrcpyW(val+1+sz, szQuote);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* do not quote integer record fields */
|
||||
val = msi_alloc(sz*sizeof(WCHAR));
|
||||
if (!val)
|
||||
return NULL;
|
||||
|
||||
r = MSI_RecordGetStringW(rec, i, val, &sz);
|
||||
}
|
||||
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
ERR("failed to get string!\n");
|
||||
msi_free(val);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static LPWSTR create_diff_row_query(MSIDATABASE *merge, MSIQUERY *view,
|
||||
|
@ -1219,31 +1306,34 @@ static UINT merge_diff_row(MSIRECORD *rec, LPVOID param)
|
|||
MERGEDATA *data = param;
|
||||
MERGETABLE *table = data->curtable;
|
||||
MERGEROW *mergerow;
|
||||
MSIQUERY *dbview;
|
||||
MSIQUERY *dbview = NULL;
|
||||
MSIRECORD *row = NULL;
|
||||
LPWSTR query;
|
||||
UINT r;
|
||||
LPWSTR query = NULL;
|
||||
UINT r = ERROR_SUCCESS;
|
||||
|
||||
query = create_diff_row_query(data->merge, data->curview, table->name, rec);
|
||||
if (!query)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
||||
r = MSI_DatabaseOpenViewW(data->db, query, &dbview);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
r = MSI_ViewExecute(dbview, NULL);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
r = MSI_ViewFetch(dbview, &row);
|
||||
if (r == ERROR_SUCCESS && !MSI_RecordsAreEqual(rec, row))
|
||||
if (TABLE_Exists(data->db, table->name))
|
||||
{
|
||||
table->numconflicts++;
|
||||
goto done;
|
||||
query = create_diff_row_query(data->merge, data->curview, table->name, rec);
|
||||
if (!query)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
||||
r = MSI_DatabaseOpenViewW(data->db, query, &dbview);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
r = MSI_ViewExecute(dbview, NULL);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
r = MSI_ViewFetch(dbview, &row);
|
||||
if (r == ERROR_SUCCESS && !MSI_RecordsAreEqual(rec, row))
|
||||
{
|
||||
table->numconflicts++;
|
||||
goto done;
|
||||
}
|
||||
else if (r != ERROR_NO_MORE_ITEMS)
|
||||
goto done;
|
||||
}
|
||||
else if (r != ERROR_NO_MORE_ITEMS)
|
||||
goto done;
|
||||
|
||||
mergerow = msi_alloc(sizeof(MERGEROW));
|
||||
if (!mergerow)
|
||||
|
@ -1269,11 +1359,188 @@ done:
|
|||
return r;
|
||||
}
|
||||
|
||||
static UINT msi_get_table_labels(MSIDATABASE *db, LPCWSTR table, LPWSTR **labels, DWORD *numlabels)
|
||||
{
|
||||
UINT r, i, count;
|
||||
MSIRECORD *prec = NULL;
|
||||
|
||||
r = MSI_DatabaseGetPrimaryKeys(db, table, &prec);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
count = MSI_RecordGetFieldCount(prec);
|
||||
*numlabels = count + 1;
|
||||
*labels = msi_alloc((*numlabels)*sizeof(LPWSTR));
|
||||
if (!*labels)
|
||||
{
|
||||
r = ERROR_OUTOFMEMORY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
(*labels)[0] = strdupW(table);
|
||||
for (i=1; i<=count; i++ )
|
||||
{
|
||||
(*labels)[i] = strdupW(MSI_RecordGetString(prec, i));
|
||||
}
|
||||
|
||||
end:
|
||||
msiobj_release( &prec->hdr );
|
||||
return r;
|
||||
}
|
||||
|
||||
static UINT msi_get_query_columns(MSIQUERY *query, LPWSTR **columns, DWORD *numcolumns)
|
||||
{
|
||||
UINT r, i, count;
|
||||
MSIRECORD *prec = NULL;
|
||||
|
||||
r = MSI_ViewGetColumnInfo(query, MSICOLINFO_NAMES, &prec);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
count = MSI_RecordGetFieldCount(prec);
|
||||
*columns = msi_alloc(count*sizeof(LPWSTR));
|
||||
if (!*columns)
|
||||
{
|
||||
r = ERROR_OUTOFMEMORY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (i=1; i<=count; i++ )
|
||||
{
|
||||
(*columns)[i-1] = strdupW(MSI_RecordGetString(prec, i));
|
||||
}
|
||||
|
||||
*numcolumns = count;
|
||||
|
||||
end:
|
||||
msiobj_release( &prec->hdr );
|
||||
return r;
|
||||
}
|
||||
|
||||
static UINT msi_get_query_types(MSIQUERY *query, LPWSTR **types, DWORD *numtypes)
|
||||
{
|
||||
UINT r, i, count;
|
||||
MSIRECORD *prec = NULL;
|
||||
|
||||
r = MSI_ViewGetColumnInfo(query, MSICOLINFO_TYPES, &prec);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
count = MSI_RecordGetFieldCount(prec);
|
||||
*types = msi_alloc(count*sizeof(LPWSTR));
|
||||
if (!*types)
|
||||
{
|
||||
r = ERROR_OUTOFMEMORY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (i=1; i<=count; i++ )
|
||||
{
|
||||
(*types)[i-1] = strdupW(MSI_RecordGetString(prec, i));
|
||||
}
|
||||
|
||||
end:
|
||||
msiobj_release( &prec->hdr );
|
||||
return r;
|
||||
}
|
||||
|
||||
static void merge_free_rows(MERGETABLE *table)
|
||||
{
|
||||
struct list *item, *cursor;
|
||||
|
||||
LIST_FOR_EACH_SAFE(item, cursor, &table->rows)
|
||||
{
|
||||
MERGEROW *row = LIST_ENTRY(item, MERGEROW, entry);
|
||||
|
||||
list_remove(&row->entry);
|
||||
msiobj_release(&row->data->hdr);
|
||||
msi_free(row);
|
||||
}
|
||||
}
|
||||
|
||||
static void free_merge_table(MERGETABLE *table)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
if (table->labels != NULL)
|
||||
{
|
||||
for (i = 0; i < table->numlabels; i++)
|
||||
msi_free(table->labels[i]);
|
||||
msi_free(table->labels);
|
||||
}
|
||||
|
||||
if (table->columns != NULL)
|
||||
{
|
||||
for (i = 0; i < table->numcolumns; i++)
|
||||
msi_free(table->columns[i]);
|
||||
msi_free(table->columns);
|
||||
}
|
||||
|
||||
if (table->types != NULL)
|
||||
{
|
||||
for (i = 0; i < table->numtypes; i++)
|
||||
msi_free(table->types[i]);
|
||||
msi_free(table->types);
|
||||
}
|
||||
msi_free(table->name);
|
||||
merge_free_rows(table);
|
||||
|
||||
msi_free(table);
|
||||
}
|
||||
|
||||
static UINT msi_get_merge_table (MSIDATABASE *db, LPCWSTR name, MERGETABLE **ptable)
|
||||
{
|
||||
UINT r;
|
||||
MERGETABLE *table;
|
||||
MSIQUERY *mergeview = NULL;
|
||||
|
||||
static const WCHAR query[] = {'S','E','L','E','C','T',' ','*',' ',
|
||||
'F','R','O','M',' ','`','%','s','`',0};
|
||||
|
||||
table = msi_alloc_zero(sizeof(MERGETABLE));
|
||||
if (!table)
|
||||
{
|
||||
*ptable = NULL;
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
r = msi_get_table_labels(db, name, &table->labels, &table->numlabels);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto err;
|
||||
|
||||
r = MSI_OpenQuery(db, &mergeview, query, name);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto err;
|
||||
|
||||
r = msi_get_query_columns(mergeview, &table->columns, &table->numcolumns);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto err;
|
||||
|
||||
r = msi_get_query_types(mergeview, &table->types, &table->numtypes);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto err;
|
||||
|
||||
list_init(&table->rows);
|
||||
|
||||
table->name = strdupW(name);
|
||||
table->numconflicts = 0;
|
||||
|
||||
msiobj_release(&mergeview->hdr);
|
||||
*ptable = table;
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
err:
|
||||
msiobj_release(&mergeview->hdr);
|
||||
free_merge_table(table);
|
||||
*ptable = NULL;
|
||||
return r;
|
||||
}
|
||||
|
||||
static UINT merge_diff_tables(MSIRECORD *rec, LPVOID param)
|
||||
{
|
||||
MERGEDATA *data = param;
|
||||
MERGETABLE *table;
|
||||
MSIQUERY *dbview;
|
||||
MSIQUERY *dbview = NULL;
|
||||
MSIQUERY *mergeview = NULL;
|
||||
LPCWSTR name;
|
||||
UINT r;
|
||||
|
@ -1283,40 +1550,35 @@ static UINT merge_diff_tables(MSIRECORD *rec, LPVOID param)
|
|||
|
||||
name = MSI_RecordGetString(rec, 1);
|
||||
|
||||
r = MSI_OpenQuery(data->db, &dbview, query, name);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
r = MSI_OpenQuery(data->merge, &mergeview, query, name);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
r = merge_verify_colnames(dbview, mergeview);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
r = merge_verify_primary_keys(data->db, data->merge, name);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
table = msi_alloc(sizeof(MERGETABLE));
|
||||
if (!table)
|
||||
if (TABLE_Exists(data->db, name))
|
||||
{
|
||||
r = ERROR_OUTOFMEMORY;
|
||||
goto done;
|
||||
r = MSI_OpenQuery(data->db, &dbview, query, name);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
r = merge_verify_colnames(dbview, mergeview);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
r = merge_verify_primary_keys(data->db, data->merge, name);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
}
|
||||
|
||||
list_init(&table->rows);
|
||||
table->name = strdupW(name);
|
||||
table->numconflicts = 0;
|
||||
r = msi_get_merge_table(data->merge, name, &table);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
data->curtable = table;
|
||||
data->curview = mergeview;
|
||||
|
||||
r = MSI_IterateRecords(mergeview, NULL, merge_diff_row, data);
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
msi_free(table->name);
|
||||
msi_free(table);
|
||||
free_merge_table(table);
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
@ -1357,6 +1619,14 @@ static UINT merge_table(MSIDATABASE *db, MERGETABLE *table)
|
|||
MERGEROW *row;
|
||||
MSIVIEW *tv;
|
||||
|
||||
if (!TABLE_Exists(db, table->name))
|
||||
{
|
||||
r = msi_add_table_to_db(db, table->columns, table->types,
|
||||
table->labels, table->numlabels, table->numcolumns);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
LIST_FOR_EACH_ENTRY(row, &table->rows, MERGEROW, entry)
|
||||
{
|
||||
r = TABLE_CreateView(db, table->name, &tv);
|
||||
|
@ -1415,21 +1685,6 @@ static UINT update_merge_errors(MSIDATABASE *db, LPCWSTR error,
|
|||
return r;
|
||||
}
|
||||
|
||||
static void merge_free_rows(MERGETABLE *table)
|
||||
{
|
||||
struct list *item, *cursor;
|
||||
|
||||
LIST_FOR_EACH_SAFE(item, cursor, &table->rows)
|
||||
{
|
||||
MERGEROW *row = LIST_ENTRY(item, MERGEROW, entry);
|
||||
|
||||
list_remove(&row->entry);
|
||||
merge_free_rows(table);
|
||||
msiobj_release(&row->data->hdr);
|
||||
msi_free(row);
|
||||
}
|
||||
}
|
||||
|
||||
UINT WINAPI MsiDatabaseMergeW(MSIHANDLE hDatabase, MSIHANDLE hDatabaseMerge,
|
||||
LPCWSTR szTableName)
|
||||
{
|
||||
|
@ -1483,9 +1738,7 @@ UINT WINAPI MsiDatabaseMergeW(MSIHANDLE hDatabase, MSIHANDLE hDatabaseMerge,
|
|||
MERGETABLE *table = LIST_ENTRY(item, MERGETABLE, entry);
|
||||
|
||||
list_remove(&table->entry);
|
||||
merge_free_rows(table);
|
||||
msi_free(table->name);
|
||||
msi_free(table);
|
||||
free_merge_table(table);
|
||||
}
|
||||
|
||||
if (conflicts)
|
||||
|
|
|
@ -113,8 +113,11 @@ UINT DROP_CreateView(MSIDATABASE *db, MSIVIEW **view, LPCWSTR name)
|
|||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
r = TABLE_CreateView(db, name, &dv->table);
|
||||
if (r != ERROR_SUCCESS || !dv->table)
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
msi_free( dv );
|
||||
return r;
|
||||
}
|
||||
|
||||
dv->view.ops = &drop_ops;
|
||||
dv->db = db;
|
||||
|
|
|
@ -869,7 +869,7 @@ UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer,
|
|||
DWORD len;
|
||||
UINT rc = ERROR_INVALID_PARAMETER;
|
||||
|
||||
TRACE("%p %p %p %i\n", package, record ,buffer, *size);
|
||||
TRACE("%p %p %p %p\n", package, record, buffer, size);
|
||||
|
||||
rec = msi_dup_record_field(record,0);
|
||||
if (!rec)
|
||||
|
|
|
@ -338,7 +338,10 @@ UINT JOIN_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR tables )
|
|||
|
||||
table = msi_alloc(sizeof(JOINTABLE));
|
||||
if (!table)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
{
|
||||
r = ERROR_OUTOFMEMORY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
r = TABLE_CreateView( db, tables, &table->view );
|
||||
if( r != ERROR_SUCCESS )
|
||||
|
|
|
@ -701,8 +701,10 @@ extern UINT MSI_RecordGetStringW( MSIRECORD * , UINT, LPWSTR, LPDWORD);
|
|||
extern UINT MSI_RecordGetStringA( MSIRECORD *, UINT, LPSTR, LPDWORD);
|
||||
extern int MSI_RecordGetInteger( MSIRECORD *, UINT );
|
||||
extern UINT MSI_RecordReadStream( MSIRECORD *, UINT, char *, LPDWORD);
|
||||
extern UINT MSI_RecordSetStream(MSIRECORD *, UINT, IStream *);
|
||||
extern UINT MSI_RecordGetFieldCount( const MSIRECORD *rec );
|
||||
extern UINT MSI_RecordStreamToFile( MSIRECORD *, UINT, LPCWSTR );
|
||||
extern UINT MSI_RecordSetStreamFromFileW( MSIRECORD *, UINT, LPCWSTR );
|
||||
extern UINT MSI_RecordCopyField( MSIRECORD *, UINT, MSIRECORD *, UINT );
|
||||
extern MSIRECORD *MSI_CloneRecord( MSIRECORD * );
|
||||
extern BOOL MSI_RecordsAreEqual( MSIRECORD *, MSIRECORD * );
|
||||
|
|
|
@ -98,7 +98,7 @@ UINT ORDER_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table,
|
|||
UINT WHERE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table,
|
||||
struct expr *cond );
|
||||
|
||||
UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
|
||||
UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR table,
|
||||
column_info *col_info, BOOL hold );
|
||||
|
||||
UINT INSERT_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR table,
|
||||
|
|
|
@ -661,7 +661,7 @@ static UINT RECORD_StreamFromFile(LPCWSTR szFile, IStream **pstm)
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT MSI_RecordSetStream(MSIRECORD *rec, UINT iField, IStream *stream)
|
||||
UINT MSI_RecordSetStream(MSIRECORD *rec, UINT iField, IStream *stream)
|
||||
{
|
||||
if ( (iField == 0) || (iField > rec->count) )
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
@ -673,7 +673,7 @@ static UINT MSI_RecordSetStream(MSIRECORD *rec, UINT iField, IStream *stream)
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT MSI_RecordSetStreamFromFileW(MSIRECORD *rec, UINT iField, LPCWSTR szFilename)
|
||||
UINT MSI_RecordSetStreamFromFileW(MSIRECORD *rec, UINT iField, LPCWSTR szFilename)
|
||||
{
|
||||
IStream *stm = NULL;
|
||||
HRESULT r;
|
||||
|
@ -930,6 +930,7 @@ MSIRECORD *MSI_CloneRecord(MSIRECORD *rec)
|
|||
msiobj_release(&clone->hdr);
|
||||
return NULL;
|
||||
}
|
||||
clone->fields[i].type = MSIFIELD_STREAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1822,7 +1822,7 @@ static UINT msi_check_product_patches(LPCWSTR prodcode, LPCWSTR usersid,
|
|||
LPWSTR patch, LPWSTR targetprod, MSIINSTALLCONTEXT *targetctx,
|
||||
LPWSTR targetsid, DWORD *sidsize, LPWSTR *transforms)
|
||||
{
|
||||
MSIPATCHSTATE state;
|
||||
MSIPATCHSTATE state = MSIPATCHSTATE_INVALID;
|
||||
LPWSTR ptr, patches = NULL;
|
||||
HKEY prod, patchkey = 0;
|
||||
HKEY localprod = 0, localpatch = 0;
|
||||
|
|
|
@ -111,6 +111,7 @@
|
|||
#include "query.h"
|
||||
#include "wine/list.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
|
||||
#define YYLEX_PARAM info
|
||||
#define YYPARSE_PARAM info
|
||||
|
@ -133,7 +134,7 @@ static UINT SQL_getstring( void *info, const struct sql_str *strdata, LPWSTR *st
|
|||
static INT SQL_getint( void *info );
|
||||
static int sql_lex( void *SQL_lval, SQL_input *info );
|
||||
|
||||
static LPWSTR parser_add_table( LPWSTR list, LPWSTR table );
|
||||
static LPWSTR parser_add_table( void *info, LPCWSTR list, LPCWSTR table );
|
||||
static void *parser_alloc( void *info, unsigned int sz );
|
||||
static column_info *parser_alloc_column( void *info, LPCWSTR table, LPCWSTR column );
|
||||
|
||||
|
@ -149,7 +150,7 @@ static struct expr * EXPR_wildcard( void *info );
|
|||
|
||||
|
||||
/* Line 189 of yacc.c */
|
||||
#line 153 "sql.tab.c"
|
||||
#line 154 "sql.tab.c"
|
||||
|
||||
/* Enabling traces. */
|
||||
#ifndef YYDEBUG
|
||||
|
@ -247,7 +248,7 @@ typedef union YYSTYPE
|
|||
{
|
||||
|
||||
/* Line 214 of yacc.c */
|
||||
#line 75 "sql.y"
|
||||
#line 76 "sql.y"
|
||||
|
||||
struct sql_str str;
|
||||
LPWSTR string;
|
||||
|
@ -260,7 +261,7 @@ typedef union YYSTYPE
|
|||
|
||||
|
||||
/* Line 214 of yacc.c */
|
||||
#line 264 "sql.tab.c"
|
||||
#line 265 "sql.tab.c"
|
||||
} YYSTYPE;
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
|
@ -272,7 +273,7 @@ typedef union YYSTYPE
|
|||
|
||||
|
||||
/* Line 264 of yacc.c */
|
||||
#line 276 "sql.tab.c"
|
||||
#line 277 "sql.tab.c"
|
||||
|
||||
#ifdef short
|
||||
# undef short
|
||||
|
@ -594,12 +595,12 @@ static const yytype_int8 yyrhs[] =
|
|||
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
|
||||
static const yytype_uint16 yyrline[] =
|
||||
{
|
||||
0, 125, 125, 133, 134, 135, 136, 137, 138, 139,
|
||||
143, 153, 166, 182, 197, 207, 220, 233, 243, 253,
|
||||
266, 270, 277, 290, 300, 310, 317, 326, 330, 334,
|
||||
341, 345, 352, 356, 360, 364, 368, 372, 376, 383,
|
||||
392, 405, 409, 413, 429, 450, 451, 455, 462, 463,
|
||||
479, 489, 502, 507, 516, 522, 528, 534, 540, 546,
|
||||
0, 126, 126, 134, 135, 136, 137, 138, 139, 140,
|
||||
144, 154, 167, 183, 198, 208, 221, 234, 244, 254,
|
||||
267, 271, 278, 291, 301, 311, 318, 327, 331, 335,
|
||||
342, 346, 353, 357, 361, 365, 369, 373, 377, 384,
|
||||
393, 406, 410, 414, 430, 451, 452, 456, 463, 464,
|
||||
480, 490, 502, 507, 516, 522, 528, 534, 540, 546,
|
||||
552, 558, 564, 570, 576, 585, 586, 590, 597, 608,
|
||||
609, 617, 625, 631, 637, 643, 652, 661, 667, 676,
|
||||
683, 691
|
||||
|
@ -1611,7 +1612,7 @@ yyreduce:
|
|||
case 2:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 126 "sql.y"
|
||||
#line 127 "sql.y"
|
||||
{
|
||||
SQL_input* sql = (SQL_input*) info;
|
||||
*sql->view = (yyvsp[(1) - (1)].query);
|
||||
|
@ -1621,7 +1622,7 @@ yyreduce:
|
|||
case 10:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 144 "sql.y"
|
||||
#line 145 "sql.y"
|
||||
{
|
||||
SQL_input *sql = (SQL_input*) info;
|
||||
MSIVIEW *insert = NULL;
|
||||
|
@ -1636,7 +1637,7 @@ yyreduce:
|
|||
case 11:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 154 "sql.y"
|
||||
#line 155 "sql.y"
|
||||
{
|
||||
SQL_input *sql = (SQL_input*) info;
|
||||
MSIVIEW *insert = NULL;
|
||||
|
@ -1651,7 +1652,7 @@ yyreduce:
|
|||
case 12:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 167 "sql.y"
|
||||
#line 168 "sql.y"
|
||||
{
|
||||
SQL_input* sql = (SQL_input*) info;
|
||||
MSIVIEW *create = NULL;
|
||||
|
@ -1672,7 +1673,7 @@ yyreduce:
|
|||
case 13:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 183 "sql.y"
|
||||
#line 184 "sql.y"
|
||||
{
|
||||
SQL_input* sql = (SQL_input*) info;
|
||||
MSIVIEW *create = NULL;
|
||||
|
@ -1689,7 +1690,7 @@ yyreduce:
|
|||
case 14:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 198 "sql.y"
|
||||
#line 199 "sql.y"
|
||||
{
|
||||
SQL_input* sql = (SQL_input*) info;
|
||||
MSIVIEW *update = NULL;
|
||||
|
@ -1704,7 +1705,7 @@ yyreduce:
|
|||
case 15:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 208 "sql.y"
|
||||
#line 209 "sql.y"
|
||||
{
|
||||
SQL_input* sql = (SQL_input*) info;
|
||||
MSIVIEW *update = NULL;
|
||||
|
@ -1719,7 +1720,7 @@ yyreduce:
|
|||
case 16:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 221 "sql.y"
|
||||
#line 222 "sql.y"
|
||||
{
|
||||
SQL_input* sql = (SQL_input*) info;
|
||||
MSIVIEW *delete = NULL;
|
||||
|
@ -1734,7 +1735,7 @@ yyreduce:
|
|||
case 17:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 234 "sql.y"
|
||||
#line 235 "sql.y"
|
||||
{
|
||||
SQL_input* sql = (SQL_input*) info;
|
||||
MSIVIEW *alter = NULL;
|
||||
|
@ -1749,7 +1750,7 @@ yyreduce:
|
|||
case 18:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 244 "sql.y"
|
||||
#line 245 "sql.y"
|
||||
{
|
||||
SQL_input *sql = (SQL_input *)info;
|
||||
MSIVIEW *alter = NULL;
|
||||
|
@ -1764,7 +1765,7 @@ yyreduce:
|
|||
case 19:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 254 "sql.y"
|
||||
#line 255 "sql.y"
|
||||
{
|
||||
SQL_input *sql = (SQL_input *)info;
|
||||
MSIVIEW *alter = NULL;
|
||||
|
@ -1779,7 +1780,7 @@ yyreduce:
|
|||
case 20:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 267 "sql.y"
|
||||
#line 268 "sql.y"
|
||||
{
|
||||
(yyval.integer) = 1;
|
||||
;}
|
||||
|
@ -1788,7 +1789,7 @@ yyreduce:
|
|||
case 21:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 271 "sql.y"
|
||||
#line 272 "sql.y"
|
||||
{
|
||||
(yyval.integer) = -1;
|
||||
;}
|
||||
|
@ -1797,7 +1798,7 @@ yyreduce:
|
|||
case 22:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 278 "sql.y"
|
||||
#line 279 "sql.y"
|
||||
{
|
||||
SQL_input* sql = (SQL_input*) info;
|
||||
UINT r;
|
||||
|
@ -1812,7 +1813,7 @@ yyreduce:
|
|||
case 23:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 291 "sql.y"
|
||||
#line 292 "sql.y"
|
||||
{
|
||||
if( SQL_MarkPrimaryKeys( &(yyvsp[(1) - (4)].column_list), (yyvsp[(4) - (4)].column_list) ) )
|
||||
(yyval.column_list) = (yyvsp[(1) - (4)].column_list);
|
||||
|
@ -1824,7 +1825,7 @@ yyreduce:
|
|||
case 24:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 301 "sql.y"
|
||||
#line 302 "sql.y"
|
||||
{
|
||||
column_info *ci;
|
||||
|
||||
|
@ -1839,7 +1840,7 @@ yyreduce:
|
|||
case 25:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 311 "sql.y"
|
||||
#line 312 "sql.y"
|
||||
{
|
||||
(yyval.column_list) = (yyvsp[(1) - (1)].column_list);
|
||||
;}
|
||||
|
@ -1848,7 +1849,7 @@ yyreduce:
|
|||
case 26:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 318 "sql.y"
|
||||
#line 319 "sql.y"
|
||||
{
|
||||
(yyval.column_list) = (yyvsp[(1) - (2)].column_list);
|
||||
(yyval.column_list)->type = ((yyvsp[(2) - (2)].column_type) | MSITYPE_VALID);
|
||||
|
@ -1859,7 +1860,7 @@ yyreduce:
|
|||
case 27:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 327 "sql.y"
|
||||
#line 328 "sql.y"
|
||||
{
|
||||
(yyval.column_type) = (yyvsp[(1) - (1)].column_type);
|
||||
;}
|
||||
|
@ -1868,7 +1869,7 @@ yyreduce:
|
|||
case 28:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 331 "sql.y"
|
||||
#line 332 "sql.y"
|
||||
{
|
||||
(yyval.column_type) = (yyvsp[(1) - (2)].column_type) | MSITYPE_LOCALIZABLE;
|
||||
;}
|
||||
|
@ -1877,7 +1878,7 @@ yyreduce:
|
|||
case 29:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 335 "sql.y"
|
||||
#line 336 "sql.y"
|
||||
{
|
||||
(yyval.column_type) = (yyvsp[(1) - (2)].column_type) | MSITYPE_TEMPORARY;
|
||||
;}
|
||||
|
@ -1886,7 +1887,7 @@ yyreduce:
|
|||
case 30:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 342 "sql.y"
|
||||
#line 343 "sql.y"
|
||||
{
|
||||
(yyval.column_type) |= MSITYPE_NULLABLE;
|
||||
;}
|
||||
|
@ -1895,7 +1896,7 @@ yyreduce:
|
|||
case 31:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 346 "sql.y"
|
||||
#line 347 "sql.y"
|
||||
{
|
||||
(yyval.column_type) = (yyvsp[(1) - (3)].column_type);
|
||||
;}
|
||||
|
@ -1904,7 +1905,7 @@ yyreduce:
|
|||
case 32:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 353 "sql.y"
|
||||
#line 354 "sql.y"
|
||||
{
|
||||
(yyval.column_type) = MSITYPE_STRING | 1;
|
||||
;}
|
||||
|
@ -1913,7 +1914,7 @@ yyreduce:
|
|||
case 33:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 357 "sql.y"
|
||||
#line 358 "sql.y"
|
||||
{
|
||||
(yyval.column_type) = MSITYPE_STRING | 0x400 | (yyvsp[(3) - (4)].column_type);
|
||||
;}
|
||||
|
@ -1922,7 +1923,7 @@ yyreduce:
|
|||
case 34:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 361 "sql.y"
|
||||
#line 362 "sql.y"
|
||||
{
|
||||
(yyval.column_type) = MSITYPE_STRING | 0x400;
|
||||
;}
|
||||
|
@ -1931,7 +1932,7 @@ yyreduce:
|
|||
case 35:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 365 "sql.y"
|
||||
#line 366 "sql.y"
|
||||
{
|
||||
(yyval.column_type) = 2 | 0x400;
|
||||
;}
|
||||
|
@ -1940,7 +1941,7 @@ yyreduce:
|
|||
case 36:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 369 "sql.y"
|
||||
#line 370 "sql.y"
|
||||
{
|
||||
(yyval.column_type) = 2 | 0x400;
|
||||
;}
|
||||
|
@ -1949,7 +1950,7 @@ yyreduce:
|
|||
case 37:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 373 "sql.y"
|
||||
#line 374 "sql.y"
|
||||
{
|
||||
(yyval.column_type) = 4;
|
||||
;}
|
||||
|
@ -1958,7 +1959,7 @@ yyreduce:
|
|||
case 38:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 377 "sql.y"
|
||||
#line 378 "sql.y"
|
||||
{
|
||||
(yyval.column_type) = MSITYPE_STRING | MSITYPE_VALID;
|
||||
;}
|
||||
|
@ -1967,7 +1968,7 @@ yyreduce:
|
|||
case 39:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 384 "sql.y"
|
||||
#line 385 "sql.y"
|
||||
{
|
||||
if( ( (yyvsp[(1) - (1)].integer) > 255 ) || ( (yyvsp[(1) - (1)].integer) < 0 ) )
|
||||
YYABORT;
|
||||
|
@ -1978,7 +1979,7 @@ yyreduce:
|
|||
case 40:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 393 "sql.y"
|
||||
#line 394 "sql.y"
|
||||
{
|
||||
UINT r;
|
||||
|
||||
|
@ -1996,7 +1997,7 @@ yyreduce:
|
|||
case 42:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 410 "sql.y"
|
||||
#line 411 "sql.y"
|
||||
{
|
||||
(yyval.query) = (yyvsp[(2) - (2)].query);
|
||||
;}
|
||||
|
@ -2005,7 +2006,7 @@ yyreduce:
|
|||
case 43:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 414 "sql.y"
|
||||
#line 415 "sql.y"
|
||||
{
|
||||
SQL_input* sql = (SQL_input*) info;
|
||||
UINT r;
|
||||
|
@ -2023,7 +2024,7 @@ yyreduce:
|
|||
case 44:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 430 "sql.y"
|
||||
#line 431 "sql.y"
|
||||
{
|
||||
SQL_input* sql = (SQL_input*) info;
|
||||
UINT r;
|
||||
|
@ -2046,7 +2047,7 @@ yyreduce:
|
|||
case 46:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 452 "sql.y"
|
||||
#line 453 "sql.y"
|
||||
{
|
||||
(yyvsp[(1) - (3)].column_list)->next = (yyvsp[(3) - (3)].column_list);
|
||||
;}
|
||||
|
@ -2055,7 +2056,7 @@ yyreduce:
|
|||
case 47:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 456 "sql.y"
|
||||
#line 457 "sql.y"
|
||||
{
|
||||
(yyval.column_list) = NULL;
|
||||
;}
|
||||
|
@ -2064,7 +2065,7 @@ yyreduce:
|
|||
case 49:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 464 "sql.y"
|
||||
#line 465 "sql.y"
|
||||
{
|
||||
SQL_input* sql = (SQL_input*) info;
|
||||
UINT r;
|
||||
|
@ -2082,7 +2083,7 @@ yyreduce:
|
|||
case 50:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 480 "sql.y"
|
||||
#line 481 "sql.y"
|
||||
{
|
||||
SQL_input* sql = (SQL_input*) info;
|
||||
UINT r;
|
||||
|
@ -2097,13 +2098,12 @@ yyreduce:
|
|||
case 51:
|
||||
|
||||
/* Line 1455 of yacc.c */
|
||||
#line 490 "sql.y"
|
||||
#line 491 "sql.y"
|
||||
{
|
||||
SQL_input* sql = (SQL_input*) info;
|
||||
UINT r;
|
||||
|
||||
r = JOIN_CreateView( sql->db, &(yyval.query), (yyvsp[(2) - (2)].string) );
|
||||
msi_free( (yyvsp[(2) - (2)].string) );
|
||||
if( r != ERROR_SUCCESS )
|
||||
YYABORT;
|
||||
;}
|
||||
|
@ -2114,7 +2114,7 @@ yyreduce:
|
|||
/* Line 1455 of yacc.c */
|
||||
#line 503 "sql.y"
|
||||
{
|
||||
(yyval.string) = strdupW((yyvsp[(1) - (1)].string));
|
||||
(yyval.string) = (yyvsp[(1) - (1)].string);
|
||||
;}
|
||||
break;
|
||||
|
||||
|
@ -2123,7 +2123,7 @@ yyreduce:
|
|||
/* Line 1455 of yacc.c */
|
||||
#line 508 "sql.y"
|
||||
{
|
||||
(yyval.string) = parser_add_table((yyvsp[(3) - (3)].string), (yyvsp[(1) - (3)].string));
|
||||
(yyval.string) = parser_add_table( info, (yyvsp[(3) - (3)].string), (yyvsp[(1) - (3)].string) );
|
||||
if (!(yyval.string))
|
||||
YYABORT;
|
||||
;}
|
||||
|
@ -2618,17 +2618,20 @@ yyreturn:
|
|||
#line 697 "sql.y"
|
||||
|
||||
|
||||
static LPWSTR parser_add_table(LPWSTR list, LPWSTR table)
|
||||
static LPWSTR parser_add_table( void *info, LPCWSTR list, LPCWSTR table )
|
||||
{
|
||||
DWORD size = lstrlenW(list) + lstrlenW(table) + 2;
|
||||
static const WCHAR space[] = {' ',0};
|
||||
DWORD len = strlenW( list ) + strlenW( table ) + 2;
|
||||
LPWSTR ret;
|
||||
|
||||
list = msi_realloc(list, size * sizeof(WCHAR));
|
||||
if (!list) return NULL;
|
||||
|
||||
lstrcatW(list, space);
|
||||
lstrcatW(list, table);
|
||||
return list;
|
||||
ret = parser_alloc( info, len * sizeof(WCHAR) );
|
||||
if( ret )
|
||||
{
|
||||
strcpyW( ret, list );
|
||||
strcatW( ret, space );
|
||||
strcatW( ret, table );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *parser_alloc( void *info, unsigned int sz )
|
||||
|
|
|
@ -110,7 +110,7 @@ typedef union YYSTYPE
|
|||
{
|
||||
|
||||
/* Line 1676 of yacc.c */
|
||||
#line 75 "sql.y"
|
||||
#line 76 "sql.y"
|
||||
|
||||
struct sql_str str;
|
||||
LPWSTR string;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "query.h"
|
||||
#include "wine/list.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
|
||||
#define YYLEX_PARAM info
|
||||
#define YYPARSE_PARAM info
|
||||
|
@ -54,7 +55,7 @@ static UINT SQL_getstring( void *info, const struct sql_str *strdata, LPWSTR *st
|
|||
static INT SQL_getint( void *info );
|
||||
static int sql_lex( void *SQL_lval, SQL_input *info );
|
||||
|
||||
static LPWSTR parser_add_table( LPWSTR list, LPWSTR table );
|
||||
static LPWSTR parser_add_table( void *info, LPCWSTR list, LPCWSTR table );
|
||||
static void *parser_alloc( void *info, unsigned int sz );
|
||||
static column_info *parser_alloc_column( void *info, LPCWSTR table, LPCWSTR column );
|
||||
|
||||
|
@ -492,7 +493,6 @@ fromtable:
|
|||
UINT r;
|
||||
|
||||
r = JOIN_CreateView( sql->db, &$$, $2 );
|
||||
msi_free( $2 );
|
||||
if( r != ERROR_SUCCESS )
|
||||
YYABORT;
|
||||
}
|
||||
|
@ -501,12 +501,12 @@ fromtable:
|
|||
tablelist:
|
||||
table
|
||||
{
|
||||
$$ = strdupW($1);
|
||||
$$ = $1;
|
||||
}
|
||||
|
|
||||
table TK_COMMA tablelist
|
||||
{
|
||||
$$ = parser_add_table($3, $1);
|
||||
$$ = parser_add_table( info, $3, $1 );
|
||||
if (!$$)
|
||||
YYABORT;
|
||||
}
|
||||
|
@ -696,17 +696,20 @@ number:
|
|||
|
||||
%%
|
||||
|
||||
static LPWSTR parser_add_table(LPWSTR list, LPWSTR table)
|
||||
static LPWSTR parser_add_table( void *info, LPCWSTR list, LPCWSTR table )
|
||||
{
|
||||
DWORD size = lstrlenW(list) + lstrlenW(table) + 2;
|
||||
static const WCHAR space[] = {' ',0};
|
||||
DWORD len = strlenW( list ) + strlenW( table ) + 2;
|
||||
LPWSTR ret;
|
||||
|
||||
list = msi_realloc(list, size * sizeof(WCHAR));
|
||||
if (!list) return NULL;
|
||||
|
||||
lstrcatW(list, space);
|
||||
lstrcatW(list, table);
|
||||
return list;
|
||||
ret = parser_alloc( info, len * sizeof(WCHAR) );
|
||||
if( ret )
|
||||
{
|
||||
strcpyW( ret, list );
|
||||
strcatW( ret, space );
|
||||
strcatW( ret, table );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *parser_alloc( void *info, unsigned int sz )
|
||||
|
|
|
@ -559,8 +559,10 @@ UINT STORAGES_CreateView(MSIDATABASE *db, MSIVIEW **view)
|
|||
|
||||
rows = add_storages_to_table(sv);
|
||||
if (rows < 0)
|
||||
{
|
||||
msi_free( sv );
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
}
|
||||
sv->num_rows = rows;
|
||||
|
||||
*view = (MSIVIEW *)sv;
|
||||
|
|
|
@ -523,7 +523,10 @@ UINT STREAMS_CreateView(MSIDATABASE *db, MSIVIEW **view)
|
|||
sv->db = db;
|
||||
rows = add_streams_to_table(sv);
|
||||
if (rows < 0)
|
||||
{
|
||||
msi_free( sv );
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
sv->num_rows = rows;
|
||||
|
||||
*view = (MSIVIEW *)sv;
|
||||
|
|
|
@ -1158,6 +1158,93 @@ static UINT TABLE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT msi_stream_name( const MSITABLEVIEW *tv, UINT row, LPWSTR *pstname )
|
||||
{
|
||||
LPWSTR p, stname = NULL;
|
||||
UINT i, r, type, ival;
|
||||
DWORD len;
|
||||
LPCWSTR sval;
|
||||
MSIVIEW *view = (MSIVIEW *) tv;
|
||||
|
||||
TRACE("%p %d\n", tv, row);
|
||||
|
||||
len = lstrlenW( tv->name ) + 1;
|
||||
stname = msi_alloc( len*sizeof(WCHAR) );
|
||||
if ( !stname )
|
||||
{
|
||||
r = ERROR_OUTOFMEMORY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
lstrcpyW( stname, tv->name );
|
||||
|
||||
for ( i = 0; i < tv->num_cols; i++ )
|
||||
{
|
||||
type = tv->columns[i].type;
|
||||
if ( type & MSITYPE_KEY )
|
||||
{
|
||||
static const WCHAR szDot[] = { '.', 0 };
|
||||
|
||||
r = TABLE_fetch_int( view, row, i+1, &ival );
|
||||
if ( r != ERROR_SUCCESS )
|
||||
goto err;
|
||||
|
||||
if ( tv->columns[i].type & MSITYPE_STRING )
|
||||
{
|
||||
sval = msi_string_lookup_id( tv->db->strings, ival );
|
||||
if ( !sval )
|
||||
{
|
||||
r = ERROR_INVALID_PARAMETER;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static const WCHAR fmt[] = { '%','d',0 };
|
||||
WCHAR number[0x20];
|
||||
UINT n = bytes_per_column( tv->db, &tv->columns[i] );
|
||||
|
||||
switch( n )
|
||||
{
|
||||
case 2:
|
||||
sprintfW( number, fmt, ival^0x8000 );
|
||||
break;
|
||||
case 4:
|
||||
sprintfW( number, fmt, ival^0x80000000 );
|
||||
break;
|
||||
default:
|
||||
ERR( "oops - unknown column width %d\n", n );
|
||||
r = ERROR_FUNCTION_FAILED;
|
||||
goto err;
|
||||
}
|
||||
sval = number;
|
||||
}
|
||||
|
||||
len += lstrlenW( szDot ) + lstrlenW( sval );
|
||||
p = msi_realloc ( stname, len*sizeof(WCHAR) );
|
||||
if ( !p )
|
||||
{
|
||||
r = ERROR_OUTOFMEMORY;
|
||||
goto err;
|
||||
}
|
||||
stname = p;
|
||||
|
||||
lstrcatW( stname, szDot );
|
||||
lstrcatW( stname, sval );
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
*pstname = stname;
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
err:
|
||||
msi_free( stname );
|
||||
*pstname = NULL;
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* We need a special case for streams, as we need to reference column with
|
||||
* the name of the stream in the same table, and the table name
|
||||
|
@ -1166,58 +1253,19 @@ static UINT TABLE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *
|
|||
static UINT TABLE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm )
|
||||
{
|
||||
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
||||
UINT ival = 0, refcol = 0, r;
|
||||
LPCWSTR sval;
|
||||
LPWSTR full_name;
|
||||
DWORD len;
|
||||
static const WCHAR szDot[] = { '.', 0 };
|
||||
WCHAR number[0x20];
|
||||
UINT r;
|
||||
LPWSTR full_name = NULL;
|
||||
|
||||
if( !view->ops->fetch_int )
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
/*
|
||||
* The column marked with the type stream data seems to have a single number
|
||||
* which references the column containing the name of the stream data
|
||||
*
|
||||
* Fetch the column to reference first.
|
||||
*/
|
||||
r = view->ops->fetch_int( view, row, col, &ival );
|
||||
if( r != ERROR_SUCCESS )
|
||||
r = msi_stream_name( tv, row, &full_name );
|
||||
if ( r != ERROR_SUCCESS )
|
||||
{
|
||||
ERR("fetching stream, error = %d\n", r);
|
||||
return r;
|
||||
|
||||
/* check the column value is in range */
|
||||
if (ival > tv->num_cols || ival == col)
|
||||
{
|
||||
ERR("bad column ref (%u) for stream\n", ival);
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
if ( tv->columns[ival - 1].type & MSITYPE_STRING )
|
||||
{
|
||||
/* now get the column with the name of the stream */
|
||||
r = view->ops->fetch_int( view, row, ival, &refcol );
|
||||
if ( r != ERROR_SUCCESS )
|
||||
return r;
|
||||
|
||||
/* lookup the string value from the string table */
|
||||
sval = msi_string_lookup_id( tv->db->strings, refcol );
|
||||
if ( !sval )
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
else
|
||||
{
|
||||
static const WCHAR fmt[] = { '%','d',0 };
|
||||
sprintfW( number, fmt, ival );
|
||||
sval = number;
|
||||
}
|
||||
|
||||
len = lstrlenW( tv->name ) + 2 + lstrlenW( sval );
|
||||
full_name = msi_alloc( len*sizeof(WCHAR) );
|
||||
lstrcpyW( full_name, tv->name );
|
||||
lstrcatW( full_name, szDot );
|
||||
lstrcatW( full_name, sval );
|
||||
|
||||
r = db_get_raw_stream( tv->db, full_name, stm );
|
||||
if( r )
|
||||
ERR("fetching stream %s, error = %d\n",debugstr_w(full_name), r);
|
||||
|
@ -1285,6 +1333,46 @@ static UINT TABLE_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec )
|
|||
return msi_view_get_row(tv->db, view, row, rec);
|
||||
}
|
||||
|
||||
static UINT msi_addstreamW( MSIDATABASE *db, LPCWSTR name, IStream *data )
|
||||
{
|
||||
UINT r;
|
||||
MSIQUERY *query = NULL;
|
||||
MSIRECORD *rec = NULL;
|
||||
|
||||
static const WCHAR insert[] = {
|
||||
'I','N','S','E','R','T',' ','I','N','T','O',' ',
|
||||
'`','_','S','t','r','e','a','m','s','`',' ',
|
||||
'(','`','N','a','m','e','`',',',
|
||||
'`','D','a','t','a','`',')',' ',
|
||||
'V','A','L','U','E','S',' ','(','?',',','?',')',0};
|
||||
|
||||
TRACE("%p %s %p\n", db, debugstr_w(name), data);
|
||||
|
||||
rec = MSI_CreateRecord( 2 );
|
||||
if ( !rec )
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
||||
r = MSI_RecordSetStringW( rec, 1, name );
|
||||
if ( r != ERROR_SUCCESS )
|
||||
goto err;
|
||||
|
||||
r = MSI_RecordSetIStream( rec, 2, data );
|
||||
if ( r != ERROR_SUCCESS )
|
||||
goto err;
|
||||
|
||||
r = MSI_DatabaseOpenViewW( db, insert, &query );
|
||||
if ( r != ERROR_SUCCESS )
|
||||
goto err;
|
||||
|
||||
r = MSI_ViewExecute( query, rec );
|
||||
|
||||
err:
|
||||
msiobj_release( &query->hdr );
|
||||
msiobj_release( &rec->hdr );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static UINT TABLE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask )
|
||||
{
|
||||
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
||||
|
@ -1315,6 +1403,27 @@ static UINT TABLE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UI
|
|||
{
|
||||
if ( MSITYPE_IS_BINARY(tv->columns[ i ].type) )
|
||||
{
|
||||
IStream *stm;
|
||||
LPWSTR stname;
|
||||
|
||||
r = MSI_RecordGetIStream( rec, i + 1, &stm );
|
||||
if ( r != ERROR_SUCCESS )
|
||||
return r;
|
||||
|
||||
r = msi_stream_name( tv, row, &stname );
|
||||
if ( r != ERROR_SUCCESS )
|
||||
{
|
||||
IStream_Release( stm );
|
||||
return r;
|
||||
}
|
||||
|
||||
r = msi_addstreamW( tv->db, stname, stm );
|
||||
IStream_Release( stm );
|
||||
msi_free ( stname );
|
||||
|
||||
if ( r != ERROR_SUCCESS )
|
||||
return r;
|
||||
|
||||
val = 1; /* refers to the first key column */
|
||||
}
|
||||
else if ( tv->columns[i].type & MSITYPE_STRING )
|
||||
|
@ -2264,7 +2373,67 @@ static UINT read_raw_int(const BYTE *data, UINT col, UINT bytes)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static UINT msi_record_encoded_stream_name( const MSITABLEVIEW *tv, MSIRECORD *rec, LPWSTR *pstname )
|
||||
{
|
||||
static const WCHAR szDot[] = { '.', 0 };
|
||||
LPWSTR stname = NULL, sval, p;
|
||||
DWORD len;
|
||||
UINT i, r;
|
||||
|
||||
TRACE("%p %p\n", tv, rec);
|
||||
|
||||
len = lstrlenW( tv->name ) + 1;
|
||||
stname = msi_alloc( len*sizeof(WCHAR) );
|
||||
if ( !stname )
|
||||
{
|
||||
r = ERROR_OUTOFMEMORY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
lstrcpyW( stname, tv->name );
|
||||
|
||||
for ( i = 0; i < tv->num_cols; i++ )
|
||||
{
|
||||
if ( tv->columns[i].type & MSITYPE_KEY )
|
||||
{
|
||||
sval = msi_dup_record_field( rec, i + 1 );
|
||||
if ( !sval )
|
||||
{
|
||||
r = ERROR_OUTOFMEMORY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
len += lstrlenW( szDot ) + lstrlenW ( sval );
|
||||
p = msi_realloc ( stname, len*sizeof(WCHAR) );
|
||||
if ( !p )
|
||||
{
|
||||
r = ERROR_OUTOFMEMORY;
|
||||
goto err;
|
||||
}
|
||||
stname = p;
|
||||
|
||||
lstrcatW( stname, szDot );
|
||||
lstrcatW( stname, sval );
|
||||
|
||||
msi_free( sval );
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
*pstname = encode_streamname( FALSE, stname );
|
||||
msi_free( stname );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
err:
|
||||
msi_free ( stname );
|
||||
*pstname = NULL;
|
||||
return r;
|
||||
}
|
||||
|
||||
static MSIRECORD *msi_get_transform_record( const MSITABLEVIEW *tv, const string_table *st,
|
||||
IStorage *stg,
|
||||
const BYTE *rawdata, UINT bytes_per_strref )
|
||||
{
|
||||
UINT i, val, ofs = 0;
|
||||
|
@ -2288,8 +2457,28 @@ static MSIRECORD *msi_get_transform_record( const MSITABLEVIEW *tv, const string
|
|||
if ( (~mask&1) && (~columns[i].type & MSITYPE_KEY) && ((1<<i) & ~mask) )
|
||||
continue;
|
||||
|
||||
if( (columns[i].type & MSITYPE_STRING) &&
|
||||
! MSITYPE_IS_BINARY(tv->columns[i].type) )
|
||||
if( MSITYPE_IS_BINARY(tv->columns[i].type) )
|
||||
{
|
||||
LPWSTR encname;
|
||||
IStream *stm = NULL;
|
||||
UINT r;
|
||||
|
||||
ofs += bytes_per_column( tv->db, &columns[i] );
|
||||
|
||||
r = msi_record_encoded_stream_name( tv, rec, &encname );
|
||||
if ( r != ERROR_SUCCESS )
|
||||
return NULL;
|
||||
|
||||
r = IStorage_OpenStream( stg, encname, NULL,
|
||||
STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm );
|
||||
msi_free( encname );
|
||||
if ( r != ERROR_SUCCESS )
|
||||
return NULL;
|
||||
|
||||
MSI_RecordSetStream( rec, i+1, stm );
|
||||
TRACE(" field %d [%s]\n", i+1, debugstr_w(encname));
|
||||
}
|
||||
else if( columns[i].type & MSITYPE_STRING )
|
||||
{
|
||||
LPCWSTR sval;
|
||||
|
||||
|
@ -2550,7 +2739,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
|
|||
break;
|
||||
}
|
||||
|
||||
rec = msi_get_transform_record( tv, st, &rawdata[n], bytes_per_strref );
|
||||
rec = msi_get_transform_record( tv, st, stg, &rawdata[n], bytes_per_strref );
|
||||
if (rec)
|
||||
{
|
||||
if ( mask & 1 )
|
||||
|
|
|
@ -261,7 +261,10 @@ UINT UPDATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR table,
|
|||
|
||||
uv = msi_alloc_zero( sizeof *uv );
|
||||
if( !uv )
|
||||
{
|
||||
wv->ops->delete( wv );
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
/* fill the structure */
|
||||
uv->view.ops = &update_ops;
|
||||
|
|
|
@ -369,8 +369,8 @@ static HRESULT WINAPI xmlnode_get_nodeType(
|
|||
|
||||
TRACE("%p %p\n", This, type);
|
||||
|
||||
assert( NODE_ELEMENT == XML_ELEMENT_NODE );
|
||||
assert( NODE_NOTATION == XML_NOTATION_NODE );
|
||||
assert( (int)NODE_ELEMENT == (int)XML_ELEMENT_NODE );
|
||||
assert( (int)NODE_NOTATION == (int)XML_NOTATION_NODE );
|
||||
|
||||
*type = This->node->type;
|
||||
|
||||
|
|
Loading…
Reference in a new issue