From cb11ae87884863eb55f4e30672e181b17cb8a456 Mon Sep 17 00:00:00 2001 From: Christoph von Wittich Date: Sat, 6 Jun 2009 15:59:47 +0000 Subject: [PATCH] sync cabinet, jscript, msi and msxml3 with wine 1.1.23 svn path=/trunk/; revision=41310 --- reactos/dll/win32/cabinet/fdi.c | 2 +- reactos/dll/win32/jscript/date.c | 50 +++- reactos/dll/win32/jscript/global.c | 4 +- reactos/dll/win32/jscript/jscript.h | 7 + reactos/dll/win32/jscript/lex.c | 64 ++++- reactos/dll/win32/jscript/math.c | 184 +++++++++++-- reactos/dll/win32/jscript/regexp.c | 2 +- reactos/dll/win32/jscript/string.c | 4 +- reactos/dll/win32/msi/action.c | 2 +- reactos/dll/win32/msi/alter.c | 5 +- reactos/dll/win32/msi/create.c | 10 +- reactos/dll/win32/msi/database.c | 391 +++++++++++++++++++++++----- reactos/dll/win32/msi/drop.c | 5 +- reactos/dll/win32/msi/format.c | 2 +- reactos/dll/win32/msi/join.c | 5 +- reactos/dll/win32/msi/msipriv.h | 2 + reactos/dll/win32/msi/query.h | 2 +- reactos/dll/win32/msi/record.c | 5 +- reactos/dll/win32/msi/registry.c | 2 +- reactos/dll/win32/msi/sql.tab.c | 127 ++++----- reactos/dll/win32/msi/sql.tab.h | 2 +- reactos/dll/win32/msi/sql.y | 27 +- reactos/dll/win32/msi/storages.c | 4 +- reactos/dll/win32/msi/streams.c | 3 + reactos/dll/win32/msi/table.c | 285 ++++++++++++++++---- reactos/dll/win32/msi/update.c | 3 + reactos/dll/win32/msxml3/node.c | 4 +- 27 files changed, 941 insertions(+), 262 deletions(-) diff --git a/reactos/dll/win32/cabinet/fdi.c b/reactos/dll/win32/cabinet/fdi.c index c7749eb66a3..81328183ac8 100644 --- a/reactos/dll/win32/cabinet/fdi.c +++ b/reactos/dll/win32/cabinet/fdi.c @@ -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) { diff --git a/reactos/dll/win32/jscript/date.c b/reactos/dll/win32/jscript/date.c index 0dac085abcc..e17ad268f56 100644 --- a/reactos/dll/win32/jscript/date.c +++ b/reactos/dll/win32/jscript/date.c @@ -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; diff --git a/reactos/dll/win32/jscript/global.c b/reactos/dll/win32/jscript/global.c index 01d9eb245a2..a714f8ef4e4 100644 --- a/reactos/dll/win32/jscript/global.c +++ b/reactos/dll/win32/jscript/global.c @@ -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) { diff --git a/reactos/dll/win32/jscript/jscript.h b/reactos/dll/win32/jscript/jscript.h index 4862b28f55f..6cf3535c92f 100644 --- a/reactos/dll/win32/jscript/jscript.h +++ b/reactos/dll/win32/jscript/jscript.h @@ -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; diff --git a/reactos/dll/win32/jscript/lex.c b/reactos/dll/win32/jscript/lex.c index 68bfef82a84..5b7e7a4249b 100644 --- a/reactos/dll/win32/jscript/lex.c +++ b/reactos/dll/win32/jscript/lex.c @@ -17,6 +17,7 @@ */ #include +#include #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"); diff --git a/reactos/dll/win32/jscript/math.c b/reactos/dll/win32/jscript/math.c index ac487d133b9..9d609e5d8c0 100644 --- a/reactos/dll/win32/jscript/math.c +++ b/reactos/dll/win32/jscript/math.c @@ -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[] = { diff --git a/reactos/dll/win32/jscript/regexp.c b/reactos/dll/win32/jscript/regexp.c index e79fee45aab..fe552b10778 100644 --- a/reactos/dll/win32/jscript/regexp.c +++ b/reactos/dll/win32/jscript/regexp.c @@ -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) diff --git a/reactos/dll/win32/jscript/string.c b/reactos/dll/win32/jscript/string.c index eeceb1f6932..82c1043490e 100644 --- a/reactos/dll/win32/jscript/string.c +++ b/reactos/dll/win32/jscript/string.c @@ -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); diff --git a/reactos/dll/win32/msi/action.c b/reactos/dll/win32/msi/action.c index 948cf4a6ba9..c8249045943 100644 --- a/reactos/dll/win32/msi/action.c +++ b/reactos/dll/win32/msi/action.c @@ -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; } diff --git a/reactos/dll/win32/msi/alter.c b/reactos/dll/win32/msi/alter.c index c31aae1fdcf..0f750d0166e 100644 --- a/reactos/dll/win32/msi/alter.c +++ b/reactos/dll/win32/msi/alter.c @@ -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; diff --git a/reactos/dll/win32/msi/create.c b/reactos/dll/win32/msi/create.c index 05c40cf2318..63cd373dbdc 100644 --- a/reactos/dll/win32/msi/create.c +++ b/reactos/dll/win32/msi/create.c @@ -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; diff --git a/reactos/dll/win32/msi/database.c b/reactos/dll/win32/msi/database.c index 70bcd90b49e..bc9319e33db 100644 --- a/reactos/dll/win32/msi/database.c +++ b/reactos/dll/win32/msi/database.c @@ -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) diff --git a/reactos/dll/win32/msi/drop.c b/reactos/dll/win32/msi/drop.c index 20ab4417b52..a385633d442 100644 --- a/reactos/dll/win32/msi/drop.c +++ b/reactos/dll/win32/msi/drop.c @@ -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; diff --git a/reactos/dll/win32/msi/format.c b/reactos/dll/win32/msi/format.c index de531bf1e13..f59024abf86 100644 --- a/reactos/dll/win32/msi/format.c +++ b/reactos/dll/win32/msi/format.c @@ -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) diff --git a/reactos/dll/win32/msi/join.c b/reactos/dll/win32/msi/join.c index 572e84bb0f2..35db2fef160 100644 --- a/reactos/dll/win32/msi/join.c +++ b/reactos/dll/win32/msi/join.c @@ -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 ) diff --git a/reactos/dll/win32/msi/msipriv.h b/reactos/dll/win32/msi/msipriv.h index ccfd6e3d5a8..8c4bd3a4515 100644 --- a/reactos/dll/win32/msi/msipriv.h +++ b/reactos/dll/win32/msi/msipriv.h @@ -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 * ); diff --git a/reactos/dll/win32/msi/query.h b/reactos/dll/win32/msi/query.h index 93b13fd6a7b..eb11a1c0321 100644 --- a/reactos/dll/win32/msi/query.h +++ b/reactos/dll/win32/msi/query.h @@ -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, diff --git a/reactos/dll/win32/msi/record.c b/reactos/dll/win32/msi/record.c index db54cdc3e0b..68eab694370 100644 --- a/reactos/dll/win32/msi/record.c +++ b/reactos/dll/win32/msi/record.c @@ -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 { diff --git a/reactos/dll/win32/msi/registry.c b/reactos/dll/win32/msi/registry.c index 3ba34d12072..f22c01fb680 100644 --- a/reactos/dll/win32/msi/registry.c +++ b/reactos/dll/win32/msi/registry.c @@ -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; diff --git a/reactos/dll/win32/msi/sql.tab.c b/reactos/dll/win32/msi/sql.tab.c index ec872e1011e..31eb33853b5 100644 --- a/reactos/dll/win32/msi/sql.tab.c +++ b/reactos/dll/win32/msi/sql.tab.c @@ -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 ) diff --git a/reactos/dll/win32/msi/sql.tab.h b/reactos/dll/win32/msi/sql.tab.h index 7d9ed248b7c..d19f0fd7a26 100644 --- a/reactos/dll/win32/msi/sql.tab.h +++ b/reactos/dll/win32/msi/sql.tab.h @@ -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; diff --git a/reactos/dll/win32/msi/sql.y b/reactos/dll/win32/msi/sql.y index 8f241b155d2..969c92cc817 100644 --- a/reactos/dll/win32/msi/sql.y +++ b/reactos/dll/win32/msi/sql.y @@ -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 ) diff --git a/reactos/dll/win32/msi/storages.c b/reactos/dll/win32/msi/storages.c index 3a548226040..16b323c872e 100644 --- a/reactos/dll/win32/msi/storages.c +++ b/reactos/dll/win32/msi/storages.c @@ -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; diff --git a/reactos/dll/win32/msi/streams.c b/reactos/dll/win32/msi/streams.c index 065f8ed1f66..2d869cc0d29 100644 --- a/reactos/dll/win32/msi/streams.c +++ b/reactos/dll/win32/msi/streams.c @@ -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; diff --git a/reactos/dll/win32/msi/table.c b/reactos/dll/win32/msi/table.c index e7e2e68c38f..885c0ddf796 100644 --- a/reactos/dll/win32/msi/table.c +++ b/reactos/dll/win32/msi/table.c @@ -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<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 ) diff --git a/reactos/dll/win32/msi/update.c b/reactos/dll/win32/msi/update.c index 31e5e252a8a..56d2391a731 100644 --- a/reactos/dll/win32/msi/update.c +++ b/reactos/dll/win32/msi/update.c @@ -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; diff --git a/reactos/dll/win32/msxml3/node.c b/reactos/dll/win32/msxml3/node.c index f33f6f8e6e4..19fa4c592ce 100644 --- a/reactos/dll/win32/msxml3/node.c +++ b/reactos/dll/win32/msxml3/node.c @@ -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;