sync msi with wine 1.1.21

svn path=/trunk/; revision=41016
This commit is contained in:
Christoph von Wittich 2009-05-20 12:59:23 +00:00
parent e0cba65fdf
commit 7d1a590941
40 changed files with 3155 additions and 1807 deletions

View file

@ -401,9 +401,13 @@ static LPWSTR* msi_split_string( LPCWSTR str, WCHAR sep )
static UINT msi_check_transform_applicable( MSIPACKAGE *package, IStorage *patch )
{
WCHAR szProductCode[] = { 'P','r','o','d','u','c','t','C','o','d','e',0 };
LPWSTR prod_code, patch_product;
UINT ret;
static const WCHAR szProductCode[] =
{ 'P','r','o','d','u','c','t','C','o','d','e',0 };
static const WCHAR szSystemLanguageID[] =
{ 'S','y','s','t','e','m','L','a','n','g','u','a','g','e','I','D',0 };
LPWSTR prod_code, patch_product, langid = NULL, template = NULL;
UINT ret = ERROR_FUNCTION_FAILED;
prod_code = msi_dup_property( package, szProductCode );
patch_product = msi_get_suminfo_product( patch );
@ -411,12 +415,57 @@ static UINT msi_check_transform_applicable( MSIPACKAGE *package, IStorage *patch
TRACE("db = %s patch = %s\n", debugstr_w(prod_code), debugstr_w(patch_product));
if ( strstrW( patch_product, prod_code ) )
ret = ERROR_SUCCESS;
else
ret = ERROR_FUNCTION_FAILED;
{
static const WCHAR zero[] = {'0',0};
MSISUMMARYINFO *si;
const WCHAR *p;
si = MSI_GetSummaryInformationW( patch, 0 );
if (!si)
{
ERR("no summary information!\n");
goto end;
}
template = msi_suminfo_dup_string( si, PID_TEMPLATE );
if (!template)
{
ERR("no template property!\n");
msiobj_release( &si->hdr );
goto end;
}
if (!template[0])
{
ret = ERROR_SUCCESS;
msiobj_release( &si->hdr );
goto end;
}
langid = msi_dup_property( package, szSystemLanguageID );
if (!langid)
{
msiobj_release( &si->hdr );
goto end;
}
p = strchrW( template, ';' );
if (p && (!strcmpW( p + 1, langid ) || !strcmpW( p + 1, zero )))
{
TRACE("applicable transform\n");
ret = ERROR_SUCCESS;
}
/* FIXME: check platform */
msiobj_release( &si->hdr );
}
end:
msi_free( patch_product );
msi_free( prod_code );
msi_free( template );
msi_free( langid );
return ret;
}
@ -1782,6 +1831,7 @@ static BOOL process_state_property(MSIPACKAGE* package, int level,
{
static const WCHAR all[]={'A','L','L',0};
static const WCHAR remove[] = {'R','E','M','O','V','E',0};
static const WCHAR reinstall[] = {'R','E','I','N','S','T','A','L','L',0};
LPWSTR override;
MSIFEATURE *feature;
@ -1795,6 +1845,8 @@ static BOOL process_state_property(MSIPACKAGE* package, int level,
(feature->Level <= 0 || feature->Level > level))
continue;
if (!strcmpW(property, reinstall)) state = feature->Installed;
if (strcmpiW(override,all)==0)
msi_feature_set_state(package, feature, state);
else
@ -1838,6 +1890,8 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
{'R','E','M','O','V','E',0};
static const WCHAR szReinstall[] =
{'R','E','I','N','S','T','A','L','L',0};
static const WCHAR szAdvertise[] =
{'A','D','V','E','R','T','I','S','E',0};
BOOL override = FALSE;
MSICOMPONENT* component;
MSIFEATURE *feature;
@ -1852,12 +1906,13 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
/* ok here is the _real_ rub
* all these activation/deactivation things happen in order and things
* later on the list override things earlier on the list.
* 1) INSTALLLEVEL processing
* 2) ADDLOCAL
* 3) REMOVE
* 4) ADDSOURCE
* 5) ADDDEFAULT
* 6) REINSTALL
* 0) INSTALLLEVEL processing
* 1) ADDLOCAL
* 2) REMOVE
* 3) ADDSOURCE
* 4) ADDDEFAULT
* 5) REINSTALL
* 6) ADVERTISE
* 7) COMPADDLOCAL
* 8) COMPADDSOURCE
* 9) FILEADDLOCAL
@ -1871,7 +1926,8 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
override |= process_state_property(package, level, szAddLocal, INSTALLSTATE_LOCAL);
override |= process_state_property(package, level, szRemove, INSTALLSTATE_ABSENT);
override |= process_state_property(package, level, szAddSource, INSTALLSTATE_SOURCE);
override |= process_state_property(package, level, szReinstall, INSTALLSTATE_LOCAL);
override |= process_state_property(package, level, szReinstall, INSTALLSTATE_UNKNOWN);
override |= process_state_property(package, level, szAdvertise, INSTALLSTATE_ADVERTISED);
if (!override)
{
@ -3503,9 +3559,6 @@ static UINT msi_publish_product_properties(MSIPACKAGE *package, HKEY hkey)
langid = msi_get_property_int(package, szProductLanguage, 0);
msi_reg_set_val_dword(hkey, INSTALLPROPERTY_LANGUAGEW, langid);
ptr = strrchrW(package->PackagePath, '\\' ) + 1;
msi_reg_set_val_str(hkey, INSTALLPROPERTY_PACKAGENAMEW, ptr);
/* FIXME */
msi_reg_set_val_dword(hkey, INSTALLPROPERTY_AUTHORIZED_LUA_APPW, 0);
@ -3668,7 +3721,7 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
if (!msi_check_publish(package))
return ERROR_SUCCESS;
rc = MSIREG_OpenProductKey(package->ProductCode, package->Context,
rc = MSIREG_OpenProductKey(package->ProductCode, NULL, package->Context,
&hukey, TRUE);
if (rc != ERROR_SUCCESS)
goto end;
@ -5876,13 +5929,13 @@ static UINT parse_assembly_name(MSIRECORD *rec, LPVOID param)
static const WCHAR PublicKeyToken[] = {
'P','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
if (!lstrcmpW(name, Name))
if (!strcmpiW(name, Name))
asmname->name = val;
else if (!lstrcmpW(name, Version))
else if (!strcmpiW(name, Version))
asmname->version = val;
else if (!lstrcmpW(name, Culture))
else if (!strcmpiW(name, Culture))
asmname->culture = val;
else if (!lstrcmpW(name, PublicKeyToken))
else if (!strcmpiW(name, PublicKeyToken))
asmname->pubkeytoken = val;
else
msi_free(val);
@ -5974,7 +6027,6 @@ static BOOL check_assembly_installed(MSIDATABASE *db, IAssemblyCache *cache,
found = (asminfo.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED);
done:
msiobj_release(&view->hdr);
msi_free(disp);
msi_free(name.name);
msi_free(name.version);
@ -6015,9 +6067,24 @@ static UINT load_assembly(MSIRECORD *rec, LPVOID param)
assembly->manifest = strdupW(MSI_RecordGetString(rec, 3));
assembly->application = strdupW(MSI_RecordGetString(rec, 4));
assembly->attributes = MSI_RecordGetInteger(rec, 5);
assembly->installed = check_assembly_installed(list->package->db,
list->cache,
assembly->component);
if (assembly->application)
{
WCHAR version[24];
DWORD size = sizeof(version)/sizeof(WCHAR);
/* 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->installed = TRUE;
}
}
else
assembly->installed = check_assembly_installed(list->package->db,
list->cache,
assembly->component);
list_add_head(list->assemblies, &assembly->entry);
return ERROR_SUCCESS;

View file

@ -183,11 +183,11 @@ static UINT ALTER_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *col
}
static UINT ALTER_get_column_info( struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type )
UINT n, LPWSTR *name, UINT *type, BOOL *temporary )
{
MSIALTERVIEW *av = (MSIALTERVIEW*)view;
TRACE("%p %d %p %p\n", av, n, name, type );
TRACE("%p %d %p %p %p\n", av, n, name, type, temporary );
return ERROR_FUNCTION_FAILED;
}

View file

@ -178,7 +178,8 @@ static LPWSTR app_search_file(LPWSTR path, MSISIGNATURE *sig)
}
attr = GetFileAttributesW(path);
if (attr == INVALID_FILE_ATTRIBUTES || attr == FILE_ATTRIBUTE_DIRECTORY)
if (attr == INVALID_FILE_ATTRIBUTES ||
(attr & FILE_ATTRIBUTE_DIRECTORY))
return NULL;
size = GetFileVersionInfoSizeW(path, &handle);
@ -298,7 +299,8 @@ static UINT ACTION_AppSearchComponents(MSIPACKAGE *package, LPWSTR *appValue, MS
lstrcatW(path, MSI_RecordGetString(rec, 2));
attr = GetFileAttributesW(path);
if (attr != INVALID_FILE_ATTRIBUTES && attr != FILE_ATTRIBUTE_DIRECTORY)
if (attr != INVALID_FILE_ATTRIBUTES &&
!(attr & FILE_ATTRIBUTE_DIRECTORY))
*appValue = strdupW(path);
}
@ -901,7 +903,8 @@ static UINT ACTION_SearchDirectory(MSIPACKAGE *package, MSISIGNATURE *sig,
}
attr = GetFileAttributesW(val);
if ((attr & FILE_ATTRIBUTE_DIRECTORY) &&
if (attr != INVALID_FILE_ATTRIBUTES &&
(attr & FILE_ATTRIBUTE_DIRECTORY) &&
val && val[lstrlenW(val) - 1] != '\\')
{
val = msi_realloc(val, (lstrlenW(val) + 2) * sizeof(WCHAR));
@ -933,7 +936,7 @@ static UINT ACTION_AppSearchDr(MSIPACKAGE *package, LPWSTR *appValue, MSISIGNATU
WCHAR expanded[MAX_PATH];
MSIRECORD *row;
int depth;
DWORD sz;
DWORD sz, attr;
UINT rc;
TRACE("%s\n", debugstr_w(sig->Name));
@ -966,11 +969,16 @@ static UINT ACTION_AppSearchDr(MSIPACKAGE *package, LPWSTR *appValue, MSISIGNATU
else
depth = MSI_RecordGetInteger(row,4);
ACTION_ExpandAnyPath(package, path, expanded, MAX_PATH);
if (sz)
ACTION_ExpandAnyPath(package, path, expanded, MAX_PATH);
else
strcpyW(expanded, path);
if (parent)
{
if (!(GetFileAttributesW(parent) & FILE_ATTRIBUTE_DIRECTORY))
attr = GetFileAttributesW(parent);
if (attr != INVALID_FILE_ATTRIBUTES &&
!(attr & FILE_ATTRIBUTE_DIRECTORY))
{
PathRemoveFileSpecW(parent);
PathAddBackslashW(parent);
@ -979,7 +987,7 @@ static UINT ACTION_AppSearchDr(MSIPACKAGE *package, LPWSTR *appValue, MSISIGNATU
strcpyW(path, parent);
strcatW(path, expanded);
}
else
else if (sz)
strcpyW(path, expanded);
PathAddBackslashW(path);

View file

@ -162,7 +162,7 @@ static HRESULT create_automation_object(MSIHANDLE msiHandle, IUnknown *pUnkOuter
AutomationObject *object;
HRESULT hr;
TRACE("(%ld,%p,%p,%s,%p,%p,%ld)\n", (unsigned long)msiHandle, pUnkOuter, ppObj, debugstr_guid(clsid), funcInvoke, funcFree, sizetPrivateData);
TRACE("(%d,%p,%p,%s,%p,%p,%ld)\n", msiHandle, pUnkOuter, ppObj, debugstr_guid(clsid), funcInvoke, funcFree, sizetPrivateData);
if( pUnkOuter )
return CLASS_E_NOAGGREGATION;

File diff suppressed because it is too large Load diff

View file

@ -1,27 +1,37 @@
/* A Bison parser, made by GNU Bison 2.1. */
/* Skeleton parser for Yacc-like parsing with Bison,
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
/* A Bison parser, made by GNU Bison 2.4.1. */
This program is free software; you can redistribute it and/or modify
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* As a special exception, when this file is copied by Bison into a
Bison output file, you may use that output file without restriction.
This special exception was added by the Free Software Foundation
in version 1.24 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
@ -69,64 +79,30 @@
COND_ERROR = 295
};
#endif
/* Tokens. */
#define COND_SPACE 258
#define COND_EOF 259
#define COND_OR 260
#define COND_AND 261
#define COND_NOT 262
#define COND_XOR 263
#define COND_IMP 264
#define COND_EQV 265
#define COND_LT 266
#define COND_GT 267
#define COND_EQ 268
#define COND_NE 269
#define COND_GE 270
#define COND_LE 271
#define COND_ILT 272
#define COND_IGT 273
#define COND_IEQ 274
#define COND_INE 275
#define COND_IGE 276
#define COND_ILE 277
#define COND_LPAR 278
#define COND_RPAR 279
#define COND_TILDA 280
#define COND_SS 281
#define COND_ISS 282
#define COND_ILHS 283
#define COND_IRHS 284
#define COND_LHS 285
#define COND_RHS 286
#define COND_PERCENT 287
#define COND_DOLLARS 288
#define COND_QUESTION 289
#define COND_AMPER 290
#define COND_EXCLAM 291
#define COND_IDENT 292
#define COND_NUMBER 293
#define COND_LITER 294
#define COND_ERROR 295
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
{
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
/* Line 1676 of yacc.c */
#line 111 "cond.y"
typedef union YYSTYPE {
struct cond_str str;
LPWSTR string;
INT value;
/* Line 1676 of yacc.c */
#line 100 "cond.tab.h"
} YYSTYPE;
/* Line 1447 of yacc.c. */
#line 124 "cond.tab.h"
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif

View file

@ -553,14 +553,14 @@ static int COND_GetOperator( COND_input *cond )
const WCHAR str[4];
int id;
} table[] = {
{ {'~','=',0}, COND_IEQ },
{ {'~','<','=',0}, COND_ILE },
{ {'~','>','<',0}, COND_ISS },
{ {'~','>','>',0}, COND_IRHS },
{ {'~','<','>',0}, COND_INE },
{ {'~','<',0}, COND_ILT },
{ {'~','>','=',0}, COND_IGE },
{ {'~','<','<',0}, COND_ILHS },
{ {'~','=',0}, COND_IEQ },
{ {'~','<',0}, COND_ILT },
{ {'~','>',0}, COND_IGT },
{ {'>','=',0}, COND_GE },
{ {'>','<',0}, COND_SS },

View file

@ -44,6 +44,7 @@ typedef struct tagMSICREATEVIEW
MSIDATABASE *db;
LPWSTR name;
BOOL bIsTemp;
BOOL hold;
column_info *col_info;
} MSICREATEVIEW;
@ -60,11 +61,15 @@ static UINT CREATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
{
MSICREATEVIEW *cv = (MSICREATEVIEW*)view;
MSITABLE *table;
BOOL persist = (cv->bIsTemp) ? MSICONDITION_FALSE : MSICONDITION_TRUE;
TRACE("%p Table %s (%s)\n", cv, debugstr_w(cv->name),
TRACE("%p Table %s (%s)\n", cv, debugstr_w(cv->name),
cv->bIsTemp?"temporary":"permanent");
return msi_create_table( cv->db, cv->name, cv->col_info, !cv->bIsTemp, &table);
if (cv->bIsTemp && !cv->hold)
return ERROR_SUCCESS;
return msi_create_table( cv->db, cv->name, cv->col_info, persist, &table);
}
static UINT CREATE_close( struct tagMSIVIEW *view )
@ -86,11 +91,11 @@ static UINT CREATE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *co
}
static UINT CREATE_get_column_info( struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type )
UINT n, LPWSTR *name, UINT *type, BOOL *temporary )
{
MSICREATEVIEW *cv = (MSICREATEVIEW*)view;
TRACE("%p %d %p %p\n", cv, n, name, type );
TRACE("%p %d %p %p %p\n", cv, n, name, type, temporary );
return ERROR_FUNCTION_FAILED;
}
@ -160,6 +165,7 @@ UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
UINT r;
column_info *col;
BOOL temp = TRUE;
BOOL tempprim = FALSE;
TRACE("%p\n", cv );
@ -178,6 +184,14 @@ UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
if( !col->temporary )
temp = FALSE;
else if ( col->type & MSITYPE_KEY )
tempprim = TRUE;
}
if ( !temp && tempprim )
{
msi_free( cv );
return ERROR_FUNCTION_FAILED;
}
/* fill the structure */
@ -187,6 +201,7 @@ UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
cv->name = table;
cv->col_info = col_info;
cv->bIsTemp = temp;
cv->hold = hold;
*view = (MSIVIEW*) cv;
return ERROR_SUCCESS;

View file

@ -695,8 +695,6 @@ static DWORD ACTION_CallDllFunction( const GUID *guid )
TRACE("calling %s\n", debugstr_w( function ) );
handle_msi_break( function );
CoInitialize(NULL);
__TRY
{
r = fn( hPackage );
@ -709,8 +707,6 @@ static DWORD ACTION_CallDllFunction( const GUID *guid )
}
__ENDTRY;
CoUninitialize();
MsiCloseHandle( hPackage );
}
else

View file

@ -610,6 +610,8 @@ static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
LPWSTR **temp_records;
static const WCHAR backslash[] = {'\\',0};
static const WCHAR suminfo[] =
{'_','S','u','m','m','a','r','y','I','n','f','o','r','m','a','t','i','o','n',0};
TRACE("%p %s %s\n", db, debugstr_w(folder), debugstr_w(file) );
@ -660,17 +662,29 @@ static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
records = temp_records;
}
if (!TABLE_Exists(db, labels[0]))
if (!strcmpW(labels[0], suminfo))
{
r = msi_add_table_to_db( db, columns, types, labels, num_labels, num_columns );
r = msi_add_suminfo( db, records, num_records, num_columns );
if (r != ERROR_SUCCESS)
{
r = ERROR_FUNCTION_FAILED;
goto done;
}
}
else
{
if (!TABLE_Exists(db, labels[0]))
{
r = msi_add_table_to_db( db, columns, types, labels, num_labels, num_columns );
if (r != ERROR_SUCCESS)
{
r = ERROR_FUNCTION_FAILED;
goto done;
}
}
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 );
}
done:
msi_free(path);
@ -1349,7 +1363,7 @@ static UINT merge_table(MSIDATABASE *db, MERGETABLE *table)
if (r != ERROR_SUCCESS)
return r;
r = tv->ops->insert_row(tv, row->data, FALSE);
r = tv->ops->insert_row(tv, row->data, -1, FALSE);
tv->ops->delete(tv);
if (r != ERROR_SUCCESS)

View file

@ -127,16 +127,17 @@ static UINT DELETE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *co
}
static UINT DELETE_get_column_info( struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type )
UINT n, LPWSTR *name, UINT *type, BOOL *temporary )
{
MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view;
TRACE("%p %d %p %p\n", dv, n, name, type );
TRACE("%p %d %p %p %p\n", dv, n, name, type, temporary );
if( !dv->table )
return ERROR_FUNCTION_FAILED;
return dv->table->ops->get_column_info( dv->table, n, name, type );
return dv->table->ops->get_column_info( dv->table, n, name,
type, temporary );
}
static UINT DELETE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,

View file

@ -205,16 +205,17 @@ static UINT DISTINCT_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *
}
static UINT DISTINCT_get_column_info( struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type )
UINT n, LPWSTR *name, UINT *type, BOOL *temporary )
{
MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view;
TRACE("%p %d %p %p\n", dv, n, name, type );
TRACE("%p %d %p %p %p\n", dv, n, name, type, temporary );
if( !dv->table )
return ERROR_FUNCTION_FAILED;
return dv->table->ops->get_column_info( dv->table, n, name, type );
return dv->table->ops->get_column_info( dv->table, n, name,
type, temporary );
}
static UINT DISTINCT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,

View file

@ -41,6 +41,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msidb);
typedef struct tagMSIINSERTVIEW
{
MSIVIEW view;
MSIVIEW *table;
MSIDATABASE *db;
BOOL bIsTemp;
MSIVIEW *sv;
@ -102,10 +103,121 @@ err:
return NULL;
}
/* checks to see if the column order specified in the INSERT query
* matches the column order of the table
*/
static BOOL msi_columns_in_order(MSIINSERTVIEW *iv, UINT col_count)
{
LPWSTR a, b = NULL;
UINT i;
int res;
for (i = 1; i <= col_count; i++)
{
iv->sv->ops->get_column_info(iv->sv, i, &a, NULL, NULL);
iv->table->ops->get_column_info(iv->table, i, &b, NULL, NULL);
res = lstrcmpW(a, b);
msi_free(a);
msi_free(b);
if (res != 0)
return FALSE;
}
return TRUE;
}
/* rearranges the data in the record to be inserted based on column order,
* and pads the record for any missing columns in the INSERT query
*/
static UINT msi_arrange_record(MSIINSERTVIEW *iv, MSIRECORD **values)
{
MSIRECORD *padded;
UINT col_count, val_count;
UINT r, i, colidx;
LPWSTR a, b = NULL;
int res;
r = iv->table->ops->get_dimensions(iv->table, NULL, &col_count);
if (r != ERROR_SUCCESS)
return r;
val_count = MSI_RecordGetFieldCount(*values);
/* check to see if the columns are arranged already
* to avoid unnecessary copying
*/
if (col_count == val_count && msi_columns_in_order(iv, col_count))
return ERROR_SUCCESS;
padded = MSI_CreateRecord(col_count);
if (!padded)
return ERROR_OUTOFMEMORY;
for (colidx = 1; colidx <= val_count; colidx++)
{
r = iv->sv->ops->get_column_info(iv->sv, colidx, &a, NULL, NULL);
if (r != ERROR_SUCCESS)
goto err;
for (i = 1; i <= col_count; i++)
{
r = iv->table->ops->get_column_info(iv->table, i, &b, NULL, NULL);
if (r != ERROR_SUCCESS)
goto err;
res = lstrcmpW(a, b);
msi_free(b);
if (res == 0)
{
MSI_RecordCopyField(*values, colidx, padded, i);
break;
}
}
msi_free(a);
}
msiobj_release(&(*values)->hdr);
*values = padded;
return ERROR_SUCCESS;
err:
msiobj_release(&padded->hdr);
return r;
}
static BOOL row_has_null_primary_keys(MSIINSERTVIEW *iv, MSIRECORD *row)
{
UINT r, i, col_count, type;
r = iv->table->ops->get_dimensions( iv->table, NULL, &col_count );
if (r != ERROR_SUCCESS)
return FALSE;
for (i = 1; i <= col_count; i++)
{
r = iv->table->ops->get_column_info(iv->table, i, NULL, &type, NULL);
if (r != ERROR_SUCCESS)
return FALSE;
if (!(type & MSITYPE_KEY))
continue;
if (MSI_RecordIsNull(row, i))
return TRUE;
}
return FALSE;
}
static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
{
MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
UINT r, col_count = 0;
UINT r, row = -1, col_count = 0;
MSIVIEW *sv;
MSIRECORD *values = NULL;
@ -116,7 +228,7 @@ static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
return ERROR_FUNCTION_FAILED;
r = sv->ops->execute( sv, 0 );
TRACE("tv execute returned %x\n", r);
TRACE("sv execute returned %x\n", r);
if( r )
return r;
@ -132,7 +244,15 @@ static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
if( !values )
goto err;
r = sv->ops->insert_row( sv, values, iv->bIsTemp );
r = msi_arrange_record( iv, &values );
if( r != ERROR_SUCCESS )
goto err;
/* rows with NULL primary keys are inserted at the beginning of the table */
if( row_has_null_primary_keys( iv, values ) )
row = 0;
r = iv->table->ops->insert_row( iv->table, values, row, iv->bIsTemp );
err:
if( values )
@ -171,18 +291,18 @@ static UINT INSERT_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *co
}
static UINT INSERT_get_column_info( struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type )
UINT n, LPWSTR *name, UINT *type, BOOL *temporary )
{
MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
MSIVIEW *sv;
TRACE("%p %d %p %p\n", iv, n, name, type );
TRACE("%p %d %p %p %p\n", iv, n, name, type, temporary );
sv = iv->sv;
if( !sv )
return ERROR_FUNCTION_FAILED;
return sv->ops->get_column_info( sv, n, name, type );
return sv->ops->get_column_info( sv, n, name, type, temporary );
}
static UINT INSERT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row)
@ -282,6 +402,7 @@ UINT INSERT_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR table,
/* fill the structure */
iv->view.ops = &insert_ops;
msiobj_addref( &db->hdr );
iv->table = tv;
iv->db = db;
iv->vals = values;
iv->bIsTemp = temp;

View file

@ -194,13 +194,13 @@ static UINT JOIN_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols
}
static UINT JOIN_get_column_info( struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type )
UINT n, LPWSTR *name, UINT *type, BOOL *temporary )
{
MSIJOINVIEW *jv = (MSIJOINVIEW*)view;
JOINTABLE *table;
UINT cols = 0;
TRACE("%p %d %p %p\n", jv, n, name, type );
TRACE("%p %d %p %p %p\n", jv, n, name, type, temporary );
if (n == 0 || n > jv->columns)
return ERROR_FUNCTION_FAILED;
@ -208,7 +208,8 @@ static UINT JOIN_get_column_info( struct tagMSIVIEW *view,
LIST_FOR_EACH_ENTRY(table, &jv->tables, JOINTABLE, entry)
{
if (n <= cols + table->columns)
return table->view->ops->get_column_info(table->view, n - cols, name, type);
return table->view->ops->get_column_info(table->view, n - cols,
name, type, temporary);
cols += table->columns;
}

View file

@ -51,13 +51,14 @@ static UINT msi_locate_product(LPCWSTR szProduct, MSIINSTALLCONTEXT *context)
*context = MSIINSTALLCONTEXT_NONE;
if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
&hkey, FALSE) == ERROR_SUCCESS)
*context = MSIINSTALLCONTEXT_USERMANAGED;
else if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
else if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
&hkey, FALSE) == ERROR_SUCCESS)
*context = MSIINSTALLCONTEXT_MACHINE;
else if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
else if (MSIREG_OpenProductKey(szProduct, NULL,
MSIINSTALLCONTEXT_USERUNMANAGED,
&hkey, FALSE) == ERROR_SUCCESS)
*context = MSIINSTALLCONTEXT_USERUNMANAGED;
@ -230,6 +231,12 @@ UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
TRACE("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
if (!szPackagePath)
return ERROR_INVALID_PARAMETER;
if (!*szPackagePath)
return ERROR_PATH_NOT_FOUND;
r = MSI_OpenPackageW( szPackagePath, &package );
if (r == ERROR_SUCCESS)
{
@ -242,14 +249,26 @@ UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode)
{
FIXME("%s %08x\n", debugstr_a(szProduct), dwReinstallMode);
return ERROR_CALL_NOT_IMPLEMENTED;
LPWSTR wszProduct;
UINT rc;
TRACE("%s %08x\n", debugstr_a(szProduct), dwReinstallMode);
wszProduct = strdupAtoW(szProduct);
rc = MsiReinstallProductW(wszProduct, dwReinstallMode);
msi_free(wszProduct);
return rc;
}
UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode)
{
FIXME("%s %08x\n", debugstr_w(szProduct), dwReinstallMode);
return ERROR_CALL_NOT_IMPLEMENTED;
static const WCHAR szAll[] = {'A','L','L',0};
TRACE("%s %08x\n", debugstr_w(szProduct), dwReinstallMode);
return MsiReinstallFeatureW(szProduct, szAll, dwReinstallMode);
}
UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage,
@ -282,13 +301,13 @@ done:
return r;
}
UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
static UINT MSI_ApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szProductCode, LPCWSTR szCommandLine)
{
MSIHANDLE patch, info;
MSIHANDLE patch = 0, info = 0;
UINT r, type;
DWORD size = 0;
LPCWSTR cmd_ptr = szCommandLine;
LPCWSTR product_code = szProductCode;
LPWSTR beg, end;
LPWSTR cmd = NULL, codes = NULL;
@ -296,42 +315,40 @@ UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
static const WCHAR patcheq[] = {'P','A','T','C','H','=',0};
static WCHAR empty[] = {0};
TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
eInstallType, debugstr_w(szCommandLine));
if (!szPatchPackage || !szPatchPackage[0])
return ERROR_INVALID_PARAMETER;
if (szInstallPackage || eInstallType == INSTALLTYPE_NETWORK_IMAGE ||
eInstallType == INSTALLTYPE_SINGLE_INSTANCE)
if (!szProductCode)
{
FIXME("Only reading target products from patch\n");
return ERROR_CALL_NOT_IMPLEMENTED;
r = MsiOpenDatabaseW(szPatchPackage, MSIDBOPEN_READONLY, &patch);
if (r != ERROR_SUCCESS)
return r;
r = MsiGetSummaryInformationW(patch, NULL, 0, &info);
if (r != ERROR_SUCCESS)
goto done;
r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, empty, &size);
if (r != ERROR_MORE_DATA || !size || type != VT_LPSTR)
{
ERR("Failed to read product codes from patch\n");
goto done;
}
codes = msi_alloc(++size * sizeof(WCHAR));
if (!codes)
{
r = ERROR_OUTOFMEMORY;
goto done;
}
r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, codes, &size);
if (r != ERROR_SUCCESS)
goto done;
product_code = codes;
}
r = MsiOpenDatabaseW(szPatchPackage, MSIDBOPEN_READONLY, &patch);
if (r != ERROR_SUCCESS)
return r;
r = MsiGetSummaryInformationW(patch, NULL, 0, &info);
if (r != ERROR_SUCCESS)
goto done;
r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, empty, &size);
if (r != ERROR_MORE_DATA || !size || type != VT_LPSTR)
{
ERR("Failed to read product codes from patch\n");
goto done;
}
codes = msi_alloc(++size * sizeof(WCHAR));
if (!codes)
{
r = ERROR_OUTOFMEMORY;
goto done;
}
r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, codes, &size);
if (r != ERROR_SUCCESS)
goto done;
if (!szCommandLine)
cmd_ptr = empty;
@ -370,6 +387,99 @@ done:
return r;
}
UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
{
TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
eInstallType, debugstr_w(szCommandLine));
if (szInstallPackage || eInstallType == INSTALLTYPE_NETWORK_IMAGE ||
eInstallType == INSTALLTYPE_SINGLE_INSTANCE)
{
FIXME("Only reading target products from patch\n");
return ERROR_CALL_NOT_IMPLEMENTED;
}
return MSI_ApplyPatchW(szPatchPackage, NULL, szCommandLine);
}
UINT WINAPI MsiApplyMultiplePatchesA(LPCSTR szPatchPackages,
LPCSTR szProductCode, LPCSTR szPropertiesList)
{
LPWSTR patch_packages = NULL;
LPWSTR product_code = NULL;
LPWSTR properties_list = NULL;
UINT r = ERROR_OUTOFMEMORY;
TRACE("%s %s %s\n", debugstr_a(szPatchPackages), debugstr_a(szProductCode),
debugstr_a(szPropertiesList));
if (!szPatchPackages || !szPatchPackages[0])
return ERROR_INVALID_PARAMETER;
if (!(patch_packages = strdupAtoW(szPatchPackages)))
return ERROR_OUTOFMEMORY;
if (szProductCode && !(product_code = strdupAtoW(szProductCode)))
goto done;
if (szPropertiesList && !(properties_list = strdupAtoW(szPropertiesList)))
goto done;
r = MsiApplyMultiplePatchesW(patch_packages, product_code, properties_list);
done:
msi_free(patch_packages);
msi_free(product_code);
msi_free(properties_list);
return r;
}
UINT WINAPI MsiApplyMultiplePatchesW(LPCWSTR szPatchPackages,
LPCWSTR szProductCode, LPCWSTR szPropertiesList)
{
UINT r = ERROR_SUCCESS;
LPCWSTR beg, end;
TRACE("%s %s %s\n", debugstr_w(szPatchPackages), debugstr_w(szProductCode),
debugstr_w(szPropertiesList));
if (!szPatchPackages || !szPatchPackages[0])
return ERROR_INVALID_PARAMETER;
beg = end = szPatchPackages;
while (*beg)
{
DWORD len;
LPWSTR patch;
while (*beg == ' ') beg++;
while (*end && *end != ';') end++;
len = end - beg;
while (len && beg[len - 1] == ' ') len--;
if (!len) return ERROR_INVALID_NAME;
patch = msi_alloc((len + 1) * sizeof(WCHAR));
if (!patch)
return ERROR_OUTOFMEMORY;
memcpy(patch, beg, len * sizeof(WCHAR));
patch[len] = '\0';
r = MSI_ApplyPatchW(patch, szProductCode, szPropertiesList);
msi_free(patch);
if (r != ERROR_SUCCESS)
break;
beg = ++end;
}
return r;
}
UINT WINAPI MsiDetermineApplicablePatchesA(LPCSTR szProductPackagePath,
DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOA pPatchInfo)
{
@ -388,6 +498,24 @@ UINT WINAPI MsiDetermineApplicablePatchesW(LPCWSTR szProductPackagePath,
return ERROR_CALL_NOT_IMPLEMENTED;
}
UINT WINAPI MsiDeterminePatchSequenceA(LPCSTR szProductCode, LPCSTR szUserSid,
MSIINSTALLCONTEXT dwContext, DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOA pPatchInfo)
{
FIXME("(%s, %s, %d, %d, %p): stub!\n", debugstr_a(szProductCode),
debugstr_a(szUserSid), dwContext, cPatchInfo, pPatchInfo);
return ERROR_CALL_NOT_IMPLEMENTED;
}
UINT WINAPI MsiDeterminePatchSequenceW(LPCWSTR szProductCode, LPCWSTR szUserSid,
MSIINSTALLCONTEXT dwContext, DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOW pPatchInfo)
{
FIXME("(%s, %s, %d, %d, %p): stub!\n", debugstr_w(szProductCode),
debugstr_w(szUserSid), dwContext, cPatchInfo, pPatchInfo);
return ERROR_CALL_NOT_IMPLEMENTED;
}
static UINT msi_open_package(LPCWSTR product, MSIINSTALLCONTEXT context,
MSIPACKAGE **package)
{
@ -439,7 +567,7 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
MSIINSTALLCONTEXT context;
UINT r;
DWORD sz;
WCHAR sourcepath[MAX_PATH];
WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
LPWSTR commandline;
static const WCHAR szInstalled[] = {
@ -501,6 +629,16 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
if (context == MSIINSTALLCONTEXT_MACHINE)
lstrcatW(commandline, szMachine);
sz = sizeof(sourcepath);
MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT,
INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
sz = sizeof(filename);
MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT,
INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
strcatW(sourcepath, filename);
r = MSI_InstallPackage( package, sourcepath, commandline );
msi_free(commandline);
@ -639,11 +777,14 @@ UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
sz = GUID_SIZE;
unsquash_guid(squished_prod, szBuffer);
if (MSIREG_OpenProductKey(szBuffer, MSIINSTALLCONTEXT_USERMANAGED,
if (MSIREG_OpenProductKey(szBuffer, NULL,
MSIINSTALLCONTEXT_USERMANAGED,
&prodkey, FALSE) == ERROR_SUCCESS ||
MSIREG_OpenProductKey(szBuffer, MSIINSTALLCONTEXT_USERUNMANAGED,
MSIREG_OpenProductKey(szBuffer, NULL,
MSIINSTALLCONTEXT_USERUNMANAGED,
&prodkey, FALSE) == ERROR_SUCCESS ||
MSIREG_OpenProductKey(szBuffer, MSIINSTALLCONTEXT_MACHINE,
MSIREG_OpenProductKey(szBuffer, NULL,
MSIINSTALLCONTEXT_MACHINE,
&prodkey, FALSE) == ERROR_SUCCESS)
{
RegCloseKey(prodkey);
@ -714,12 +855,15 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
if (!squash_guid(szProduct, squished_pc))
return ERROR_INVALID_PARAMETER;
if ((r = MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
if ((r = MSIREG_OpenProductKey(szProduct, NULL,
MSIINSTALLCONTEXT_USERMANAGED,
&prodkey, FALSE)) != ERROR_SUCCESS &&
(r = MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
(r = MSIREG_OpenProductKey(szProduct, NULL,
MSIINSTALLCONTEXT_USERUNMANAGED,
&prodkey, FALSE)) != ERROR_SUCCESS &&
(r = MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
&prodkey, FALSE)) == ERROR_SUCCESS)
(r = MSIREG_OpenProductKey(szProduct, NULL,
MSIINSTALLCONTEXT_MACHINE,
&prodkey, FALSE)) == ERROR_SUCCESS)
{
context = MSIINSTALLCONTEXT_MACHINE;
}
@ -784,8 +928,15 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW))
{
res = RegOpenKeyW(prodkey, sourcelist, &source);
if (res == ERROR_SUCCESS)
val = msi_reg_get_value(source, szAttribute, &type);
if (res != ERROR_SUCCESS)
{
r = ERROR_UNKNOWN_PRODUCT;
goto done;
}
val = msi_reg_get_value(source, szAttribute, &type);
if (!val)
val = empty;
RegCloseKey(source);
}
@ -1028,9 +1179,9 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
return ERROR_INVALID_PARAMETER;
/* FIXME: dwContext is provided, no need to search for it */
MSIREG_OpenProductKey(szProductCode, MSIINSTALLCONTEXT_USERMANAGED,
MSIREG_OpenProductKey(szProductCode, NULL,MSIINSTALLCONTEXT_USERMANAGED,
&managed, FALSE);
MSIREG_OpenProductKey(szProductCode, MSIINSTALLCONTEXT_USERUNMANAGED,
MSIREG_OpenProductKey(szProductCode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
&prod, FALSE);
MSIREG_OpenInstallProps(szProductCode, dwContext, NULL, &props, FALSE);
@ -1052,7 +1203,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
{
package = INSTALLPROPERTY_LOCALPACKAGEW;
MSIREG_OpenProductKey(szProductCode, dwContext, &classes, FALSE);
MSIREG_OpenProductKey(szProductCode, NULL, dwContext, &classes, FALSE);
if (!props && !classes)
goto done;
@ -1314,7 +1465,7 @@ UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW))
{
if (MSIREG_OpenProductKey(szProductCode, dwContext,
if (MSIREG_OpenProductKey(szProductCode, NULL, dwContext,
&prod, FALSE) != ERROR_SUCCESS)
goto done;
@ -1483,7 +1634,7 @@ static BOOL msi_comp_find_prod_key(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
UINT r;
HKEY hkey;
r = MSIREG_OpenProductKey(prodcode, context, &hkey, FALSE);
r = MSIREG_OpenProductKey(prodcode, NULL, context, &hkey, FALSE);
RegCloseKey(hkey);
return (r == ERROR_SUCCESS);
}
@ -1632,11 +1783,11 @@ INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
if (lstrlenW(szProduct) != GUID_SIZE - 1)
return INSTALLSTATE_INVALIDARG;
if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
&prodkey, FALSE) != ERROR_SUCCESS &&
MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
&prodkey, FALSE) != ERROR_SUCCESS &&
MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
&prodkey, FALSE) == ERROR_SUCCESS)
{
context = MSIINSTALLCONTEXT_MACHINE;
@ -2115,9 +2266,10 @@ static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent,
}
if (state != INSTALLSTATE_LOCAL &&
(MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
(MSIREG_OpenProductKey(szProduct, NULL,
MSIINSTALLCONTEXT_USERUNMANAGED,
&hkey, FALSE) == ERROR_SUCCESS ||
MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
&hkey, FALSE) == ERROR_SUCCESS))
{
RegCloseKey(hkey);
@ -2758,11 +2910,11 @@ static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct,
if (!szProduct || !squash_guid(szProduct, squished_pc))
return USERINFOSTATE_INVALIDARG;
if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
&hkey, FALSE) != ERROR_SUCCESS &&
MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
&hkey, FALSE) != ERROR_SUCCESS &&
MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
&hkey, FALSE) != ERROR_SUCCESS)
{
return USERINFOSTATE_UNKNOWN;
@ -2912,7 +3064,11 @@ UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
if (rc != ERROR_SUCCESS)
return ERROR_INVALID_PARAMETER;
/* MsiCollectUserInfo cannot be called from a custom action. */
package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
if (!package)
return ERROR_CALL_NOT_IMPLEMENTED;
rc = ACTION_PerformUIAction(package, szFirstRun, -1);
msiobj_release( &package->hdr );
@ -2934,7 +3090,11 @@ UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
if (rc != ERROR_SUCCESS)
return ERROR_INVALID_PARAMETER;
/* MsiCollectUserInfo cannot be called from a custom action. */
package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
if (!package)
return ERROR_CALL_NOT_IMPLEMENTED;
rc = ACTION_PerformUIAction(package, szFirstRun, -1);
msiobj_release( &package->hdr );

View file

@ -42,6 +42,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#include "msi_No.rc"
#include "msi_Pl.rc"
#include "msi_Pt.rc"
#include "msi_Ro.rc"
#include "msi_Ru.rc"
#include "msi_Si.rc"
#include "msi_Sv.rc"

View file

@ -60,10 +60,10 @@
64 stdcall MsiGetMode(long long)
65 stdcall MsiGetProductCodeA(str str)
66 stdcall MsiGetProductCodeW(wstr wstr)
67 stdcall MsiGetProductInfoA(str str str long)
67 stdcall MsiGetProductInfoA(str str ptr long)
68 stub MsiGetProductInfoFromScriptA
69 stub MsiGetProductInfoFromScriptW
70 stdcall MsiGetProductInfoW(wstr wstr wstr long)
70 stdcall MsiGetProductInfoW(wstr wstr ptr long)
71 stdcall MsiGetProductPropertyA(long str ptr ptr)
72 stdcall MsiGetProductPropertyW(long wstr ptr ptr)
73 stdcall MsiGetPropertyA(ptr str ptr ptr)
@ -232,8 +232,8 @@
236 stub Migrate10CachedPackagesW
237 stub MsiRemovePatchesA
238 stub MsiRemovePatchesW
239 stub MsiApplyMultiplePatchesA
240 stub MsiApplyMultiplePatchesW
239 stdcall MsiApplyMultiplePatchesA(str str str)
240 stdcall MsiApplyMultiplePatchesW(wstr wstr wstr)
241 stub MsiExtractPatchXMLDataA
242 stub MsiExtractPatchXMLDataW
243 stdcall MsiGetPatchInfoExA(str str str long str ptr ptr)
@ -246,14 +246,14 @@
250 stdcall MsiQueryComponentStateW(wstr wstr long wstr ptr)
251 stub MsiQueryFeatureStateExA
252 stub MsiQueryFeatureStateExW
253 stub MsiDeterminePatchSequenceA
254 stub MsiDeterminePatchSequenceW
253 stdcall MsiDeterminePatchSequenceA(str str long long ptr)
254 stdcall MsiDeterminePatchSequenceW(wstr wstr long long ptr)
255 stdcall MsiSourceListAddSourceExA(str str long long str long)
256 stdcall MsiSourceListAddSourceExW(wstr wstr long long wstr long)
257 stdcall MsiSourceListClearSourceA(str str long long str)
258 stdcall MsiSourceListClearSourceW(wstr wstr long long wstr)
259 stub MsiSourceListClearAllExA
260 stub MsiSourceListClearAllExW
259 stdcall MsiSourceListClearAllExA(str str long long)
260 stdcall MsiSourceListClearAllExW(wstr wstr long long)
261 stub MsiSourceListForceResolutionExA
262 stub MsiSourceListForceResolutionExW
263 stdcall MsiSourceListEnumSourcesA(str str long long long ptr ptr)

View file

@ -20,15 +20,19 @@
LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
#pragma code_page(65001)
STRINGTABLE DISCARDABLE
{
4 "The specified installation package could not be opened. Please check the file path and try again."
4 "Das angegebene Installationspaket konnte nicht geöffnet werden. Bitte überprüfen Sie den Pfadnamen und versuchen Sie es noch einmal."
5 "Der Pfad %s wurde nicht gefunden."
9 "Bitte Disk %s einlegen."
10 "schlechte Parameter"
11 "Geben Sie das Verzeichnis ein, dass %s enthält."
12 "Die Installationsquelle für das Feature fehlt."
13 "Das Netzwerklaufwerk für das Feature fehlt."
10 "Falsche Parameter"
11 "Geben Sie das Verzeichnis ein, dass %s enthält."
12 "Die Installationsquelle für das Feature fehlt."
13 "Das Netzwerklaufwerk für das Feature fehlt."
14 "Feature von:"
15 "Wählen Sie das Verzeichnis aus, dass %s enthält."
15 "Wählen Sie das Verzeichnis aus, dass %s enthält."
}
#pragma code_page(default)

View file

@ -0,0 +1,37 @@
/*
* Copyright 2005 Mike McCormack
* Copyright 2009 Michael Stefaniuc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL
#pragma code_page(65001)
STRINGTABLE DISCARDABLE
{
4 "Pachetul de instalare menționat nu a putut fi deschis. Verificați calea și încercați din nou."
5 "calea %s nu a fost găsită"
9 "inserați discul %s"
10 "parameteri greșiți"
11 "introduceți fișierul care conține %s"
12 "lipsește sursa de instalare pentru această caracteristică"
13 "lipsește unitatea de rețea pentru această caracteristică"
14 "caracteristică de la:"
15 "selectați fișierul care conține %s"
}
#pragma code_page(default)

View file

@ -199,7 +199,7 @@ typedef struct tagMSIVIEWOPS
/*
* Inserts a new row into the database from the records contents
*/
UINT (*insert_row)( struct tagMSIVIEW *view, MSIRECORD *record, BOOL temporary );
UINT (*insert_row)( struct tagMSIVIEW *view, MSIRECORD *record, UINT row, BOOL temporary );
/*
* Deletes a row from the database
@ -231,7 +231,7 @@ typedef struct tagMSIVIEWOPS
* the caller.
* The column information can be queried at any time.
*/
UINT (*get_column_info)( struct tagMSIVIEW *view, UINT n, LPWSTR *name, UINT *type );
UINT (*get_column_info)( struct tagMSIVIEW *view, UINT n, LPWSTR *name, UINT *type, BOOL *temporary );
/*
* modify - not yet implemented properly
@ -760,8 +760,8 @@ extern BOOL encode_base85_guid(GUID *,LPWSTR);
extern BOOL decode_base85_guid(LPCWSTR,GUID*);
extern UINT MSIREG_OpenUninstallKey(LPCWSTR szProduct, HKEY* key, BOOL create);
extern UINT MSIREG_DeleteUninstallKey(LPCWSTR szProduct);
extern UINT MSIREG_OpenProductKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context,
HKEY* key, BOOL create);
extern UINT MSIREG_OpenProductKey(LPCWSTR szProduct, LPCWSTR szUserSid,
MSIINSTALLCONTEXT context, HKEY* key, BOOL create);
extern UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context,
HKEY *key, BOOL create);
extern UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create);
@ -819,6 +819,7 @@ extern UINT msi_spawn_error_dialog( MSIPACKAGE*, LPWSTR, LPWSTR );
extern MSISUMMARYINFO *MSI_GetSummaryInformationW( IStorage *stg, UINT uiUpdateCount );
extern LPWSTR msi_suminfo_dup_string( MSISUMMARYINFO *si, UINT uiProperty );
extern LPWSTR msi_get_suminfo_product( IStorage *stg );
extern UINT msi_add_suminfo( MSIDATABASE *db, LPWSTR **records, int num_records, int num_columns );
/* undocumented functions */
UINT WINAPI MsiCreateAndVerifyInstallerDirectory( DWORD );

View file

@ -70,7 +70,7 @@ UINT VIEW_find_column( MSIVIEW *table, LPCWSTR name, UINT *n )
INT x;
col_name = NULL;
r = table->ops->get_column_info( table, i, &col_name, NULL );
r = table->ops->get_column_info( table, i, &col_name, NULL, NULL );
if( r != ERROR_SUCCESS )
return r;
x = lstrcmpW( name, col_name );
@ -308,7 +308,7 @@ UINT msi_view_get_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD **rec)
for (i = 1; i <= col_count; i++)
{
ret = view->ops->get_column_info(view, i, NULL, &type);
ret = view->ops->get_column_info(view, i, NULL, &type, NULL);
if (ret)
{
ERR("Error getting column type for %d\n", i);
@ -377,7 +377,10 @@ UINT MSI_ViewFetch(MSIQUERY *query, MSIRECORD **prec)
r = msi_view_get_row(query->db, view, query->row, prec);
if (r == ERROR_SUCCESS)
{
query->row ++;
MSI_RecordSetInteger(*prec, 0, (int)query);
}
return r;
}
@ -490,7 +493,8 @@ out:
return ret;
}
static UINT msi_set_record_type_string( MSIRECORD *rec, UINT field, UINT type )
static UINT msi_set_record_type_string( MSIRECORD *rec, UINT field,
UINT type, BOOL temporary )
{
static const WCHAR fmt[] = { '%','d',0 };
WCHAR szType[0x10];
@ -500,9 +504,20 @@ static UINT msi_set_record_type_string( MSIRECORD *rec, UINT field, UINT type )
else if (type & MSITYPE_LOCALIZABLE)
szType[0] = 'l';
else if (type & MSITYPE_STRING)
szType[0] = 's';
{
if (temporary)
szType[0] = 'g';
else
szType[0] = 's';
}
else
szType[0] = 'i';
{
if (temporary)
szType[0] = 'j';
else
szType[0] = 'i';
}
if (type & MSITYPE_NULLABLE)
szType[0] &= ~0x20;
@ -519,6 +534,7 @@ UINT MSI_ViewGetColumnInfo( MSIQUERY *query, MSICOLINFO info, MSIRECORD **prec )
MSIRECORD *rec;
MSIVIEW *view = query->view;
LPWSTR name;
BOOL temporary;
if( !view )
return ERROR_FUNCTION_FAILED;
@ -539,13 +555,13 @@ UINT MSI_ViewGetColumnInfo( MSIQUERY *query, MSICOLINFO info, MSIRECORD **prec )
for( i=0; i<count; i++ )
{
name = NULL;
r = view->ops->get_column_info( view, i+1, &name, &type );
r = view->ops->get_column_info( view, i+1, &name, &type, &temporary );
if( r != ERROR_SUCCESS )
continue;
if (info == MSICOLINFO_NAMES)
MSI_RecordSetStringW( rec, i+1, name );
else
msi_set_record_type_string( rec, i+1, type);
msi_set_record_type_string( rec, i+1, type, temporary );
msi_free( name );
}
@ -597,6 +613,9 @@ UINT MSI_ViewModify( MSIQUERY *query, MSIMODIFY mode, MSIRECORD *rec )
if ( !view || !view->ops->modify)
return ERROR_FUNCTION_FAILED;
if ( mode == MSIMODIFY_UPDATE && MSI_RecordGetInteger( rec, 0 ) != (int)query )
return ERROR_FUNCTION_FAILED;
r = view->ops->modify( view, mode, rec, query->row );
if (mode == MSIMODIFY_DELETE && r == ERROR_SUCCESS)
query->row--;
@ -842,7 +861,7 @@ struct msi_primary_key_record_info
static UINT msi_primary_key_iterator( MSIRECORD *rec, LPVOID param )
{
struct msi_primary_key_record_info *info = param;
LPCWSTR name;
LPCWSTR name, table;
DWORD type;
type = MSI_RecordGetInteger( rec, 4 );
@ -851,6 +870,12 @@ static UINT msi_primary_key_iterator( MSIRECORD *rec, LPVOID param )
info->n++;
if( info->rec )
{
if ( info->n == 1 )
{
table = MSI_RecordGetString( rec, 1 );
MSI_RecordSetStringW( info->rec, 0, table);
}
name = MSI_RecordGetString( rec, 3 );
MSI_RecordSetStringW( info->rec, info->n, name );
}

View file

@ -29,7 +29,6 @@ typedef int INSTALLMESSAGE;
typedef int MSICONDITION;
typedef int MSIRUNMODE;
typedef int INSTALLSTATE;
typedef WORD LANGID;
cpp_quote("#endif")
[

View file

@ -66,14 +66,15 @@ static UINT create_temp_property_table(MSIPACKAGE *package)
UINT rc;
static const WCHAR CreateSql[] = {
'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','_','P','r','o',
'p','e','r','t','y','`',' ','(',' ','`','_','P','r','o','p','e','r','t',
'y','`',' ','C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U',
'L','L',' ','T','E','M','P','O','R','A','R','Y',',',' ','`','V','a','l',
'u','e','`',' ','C','H','A','R','(','9','8',')',' ','N','O','T',' ','N',
'U','L','L',' ','T','E','M','P','O','R','A','R','Y',' ','P','R','I','M',
'A','R','Y',' ','K','E','Y',' ','`','_','P','r','o','p','e','r','t','y',
'`',')',0};
'C','R','E','A','T','E',' ','T','A','B','L','E',' ',
'`','_','P','r','o','p','e','r','t','y','`',' ','(',' ',
'`','_','P','r','o','p','e','r','t','y','`',' ',
'C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U','L','L',' ',
'T','E','M','P','O','R','A','R','Y',',',' ',
'`','V','a','l','u','e','`',' ','C','H','A','R','(','9','8',')',' ',
'N','O','T',' ','N','U','L','L',' ','T','E','M','P','O','R','A','R','Y',
' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ',
'`','_','P','r','o','p','e','r','t','y','`',')',' ','H','O','L','D',0};
rc = MSI_DatabaseOpenViewW(package->db, CreateSql, &view);
if (rc != ERROR_SUCCESS)
@ -219,7 +220,7 @@ static LPWSTR get_fusion_filename(MSIPACKAGE *package)
{
HKEY netsetup;
LONG res;
LPWSTR file;
LPWSTR file = NULL;
DWORD index = 0, size;
WCHAR ver[MAX_PATH];
WCHAR name[MAX_PATH];
@ -242,34 +243,46 @@ static LPWSTR get_fusion_filename(MSIPACKAGE *package)
if (res != ERROR_SUCCESS)
return NULL;
GetWindowsDirectoryW(windir, MAX_PATH);
ver[0] = '\0';
size = MAX_PATH;
while (RegEnumKeyExW(netsetup, index, name, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
{
index++;
/* verify existence of fusion.dll .Net 3.0 does not install a new one */
if (lstrcmpW(ver, name) < 0)
lstrcpyW(ver, name);
{
LPWSTR check;
size = lstrlenW(windir) + lstrlenW(subdir) + lstrlenW(name) +lstrlenW(fusion) + 3;
check = msi_alloc(size * sizeof(WCHAR));
if (!check)
{
msi_free(file);
return NULL;
}
lstrcpyW(check, windir);
lstrcatW(check, backslash);
lstrcatW(check, subdir);
lstrcatW(check, name);
lstrcatW(check, backslash);
lstrcatW(check, fusion);
if(GetFileAttributesW(check) != INVALID_FILE_ATTRIBUTES)
{
msi_free(file);
file = check;
lstrcpyW(ver, name);
}
else
msi_free(check);
}
}
RegCloseKey(netsetup);
if (!index)
return NULL;
GetWindowsDirectoryW(windir, MAX_PATH);
size = lstrlenW(windir) + lstrlenW(subdir) + lstrlenW(ver) +lstrlenW(fusion) + 3;
file = msi_alloc(size * sizeof(WCHAR));
if (!file)
return NULL;
lstrcpyW(file, windir);
lstrcatW(file, backslash);
lstrcatW(file, subdir);
lstrcatW(file, ver);
lstrcatW(file, backslash);
lstrcatW(file, fusion);
return file;
}
@ -439,11 +452,12 @@ static VOID set_installer_properties(MSIPACKAGE *package)
static const WCHAR szDate[] = {'D','a','t','e',0};
static const WCHAR szTime[] = {'T','i','m','e',0};
static const WCHAR szUserLangID[] = {'U','s','e','r','L','a','n','g','u','a','g','e','I','D',0};
static const WCHAR szSystemLangID[] = {'S','y','s','t','e','m','L','a','n','g','u','a','g','e','I','D',0};
/*
* Other things that probably should be set:
*
* SystemLanguageID ComputerName UserLanguageID LogonUser VirtualMemory
* ComputerName LogonUser VirtualMemory
* ShellAdvSupport DefaultUIFont PackagecodeChanging
* ProductState CaptionHeight BorderTop BorderSide TextHeight
* RedirectedDllSupport
@ -639,6 +653,11 @@ static VOID set_installer_properties(MSIPACKAGE *package)
sprintfW(bufstr, szIntFormat, langid);
MSI_SetPropertyW( package, szUserLangID, bufstr );
langid = GetSystemDefaultLangID();
sprintfW(bufstr, szIntFormat, langid);
MSI_SetPropertyW( package, szSystemLangID, bufstr );
}
static UINT msi_load_summary_properties( MSIPACKAGE *package )
@ -1344,7 +1363,8 @@ UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
msiobj_release(&view->hdr);
}
msiobj_release(&row->hdr);
if (row)
msiobj_release(&row->hdr);
if (rc == ERROR_SUCCESS && (!lstrcmpW(szName, cszSourceDir)))
msi_reset_folders(package, TRUE);
@ -1402,16 +1422,36 @@ UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue
static MSIRECORD *MSI_GetPropertyRow( MSIPACKAGE *package, LPCWSTR name )
{
MSIQUERY *view;
MSIRECORD *rec, *row = NULL;
UINT r;
static const WCHAR query[]= {
'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ',
'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
' ','W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
'=','\'','%','s','\'',0};
'=','?',0};
if (!name || !*name)
return NULL;
return MSI_QueryGetRecord( package->db, query, name );
rec = MSI_CreateRecord(1);
if (!rec)
return NULL;
MSI_RecordSetStringW(rec, 1, name);
r = MSI_DatabaseOpenViewW(package->db, query, &view);
if (r == ERROR_SUCCESS)
{
MSI_ViewExecute(view, rec);
MSI_ViewFetch(view, &row);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
}
msiobj_release(&rec->hdr);
return row;
}
/* internal function, not compatible with MsiGetPropertyW */

View file

@ -124,6 +124,6 @@ int sqliteGetToken(const WCHAR *z, int *tokenType);
MSIRECORD *msi_query_merge_record( UINT fields, const column_info *vl, MSIRECORD *rec );
UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
BOOL persistent, MSITABLE **table_ret);
MSICONDITION persistent, MSITABLE **table_ret);
#endif /* __WINE_MSI_QUERY_H */

View file

@ -444,7 +444,6 @@ UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField,
lstrcpynW(szValue, rec->fields[iField].u.szwVal, *pcchValue);
break;
case MSIFIELD_NULL:
len = 1;
if( szValue && *pcchValue > 0 )
szValue[0] = 0;
default:
@ -765,6 +764,12 @@ UINT MSI_RecordReadStream(MSIRECORD *rec, UINT iField, char *buf, LPDWORD sz)
if( iField > rec->count)
return ERROR_INVALID_PARAMETER;
if ( rec->fields[iField].type == MSIFIELD_NULL )
{
*sz = 0;
return ERROR_INVALID_DATA;
}
if( rec->fields[iField].type != MSIFIELD_STREAM )
return ERROR_INVALID_DATATYPE;

View file

@ -103,6 +103,12 @@ static const WCHAR szUninstall_fmt[] = {
'U','n','i','n','s','t','a','l','l','\\',
'%','s',0 };
static const WCHAR szUserProduct[] = {
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
'I','n','s','t','a','l','l','e','r','\\',
'P','r','o','d','u','c','t','s',0};
static const WCHAR szUserProduct_fmt[] = {
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
@ -187,6 +193,12 @@ static const WCHAR szInstallProperties_fmt[] = {
'%','s','\\','P','r','o','d','u','c','t','s','\\','%','s','\\',
'I','n','s','t','a','l','l','P','r','o','p','e','r','t','i','e','s',0};
static const WCHAR szInstaller_LocalClassesProd[] = {
'S','o','f','t','w','a','r','e','\\',
'C','l','a','s','s','e','s','\\',
'I','n','s','t','a','l','l','e','r','\\',
'P','r','o','d','u','c','t','s',0};
static const WCHAR szInstaller_LocalClassesProd_fmt[] = {
'S','o','f','t','w','a','r','e','\\',
'C','l','a','s','s','e','s','\\',
@ -199,6 +211,16 @@ static const WCHAR szInstaller_LocalClassesFeat_fmt[] = {
'I','n','s','t','a','l','l','e','r','\\',
'F','e','a','t','u','r','e','s','\\','%','s',0};
static const WCHAR szInstaller_LocalManaged_fmt[] = {
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s','\\',
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
'I','n','s','t','a','l','l','e','r','\\',
'M','a','n','a','g','e','d','\\','%','s','\\',
'I','n','s','t','a','l','l','e','r','\\',
'P','r','o','d','u','c','t','s',0};
static const WCHAR szInstaller_LocalManagedProd_fmt[] = {
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
@ -504,11 +526,11 @@ UINT MSIREG_DeleteUninstallKey(LPCWSTR szProduct)
return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
}
UINT MSIREG_OpenProductKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context,
HKEY *key, BOOL create)
UINT MSIREG_OpenProductKey(LPCWSTR szProduct, LPCWSTR szUserSid,
MSIINSTALLCONTEXT context, HKEY *key, BOOL create)
{
UINT r;
LPWSTR usersid;
LPWSTR usersid = NULL;
HKEY root = HKEY_LOCAL_MACHINE;
WCHAR squished_pc[GUID_SIZE];
WCHAR keypath[MAX_PATH];
@ -531,14 +553,20 @@ UINT MSIREG_OpenProductKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context,
}
else
{
r = get_user_sid(&usersid);
if (r != ERROR_SUCCESS || !usersid)
if (!szUserSid)
{
ERR("Failed to retrieve user SID: %d\n", r);
return r;
r = get_user_sid(&usersid);
if (r != ERROR_SUCCESS || !usersid)
{
ERR("Failed to retrieve user SID: %d\n", r);
return r;
}
szUserSid = usersid;
}
sprintfW(keypath, szInstaller_LocalManagedProd_fmt, usersid, squished_pc);
sprintfW(keypath, szInstaller_LocalManagedProd_fmt,
szUserSid, squished_pc);
LocalFree(usersid);
}
@ -804,7 +832,7 @@ UINT MSIREG_OpenUserDataProductKey(LPCWSTR szProduct, MSIINSTALLCONTEXT dwContex
if (dwContext == MSIINSTALLCONTEXT_MACHINE)
sprintfW(keypath, szUserDataProd_fmt, szLocalSid, squished_pc);
else if (szUserSid)
sprintfW(keypath, szUserDataProd_fmt, usersid, squished_pc);
sprintfW(keypath, szUserDataProd_fmt, szUserSid, squished_pc);
else
{
rc = get_user_sid(&usersid);
@ -1192,25 +1220,108 @@ UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
{
HKEY hkeyProducts = 0;
DWORD r;
UINT r;
WCHAR szKeyName[SQUISH_GUID_SIZE];
HKEY key;
DWORD machine_count, managed_count, unmanaged_count;
WCHAR keypath[MAX_PATH];
LPWSTR usersid = NULL;
static DWORD last_index;
TRACE("%d %p\n", index, lpguid);
if (NULL == lpguid)
return ERROR_INVALID_PARAMETER;
r = RegCreateKeyW(HKEY_LOCAL_MACHINE, szInstaller_Products, &hkeyProducts);
if (index && index - last_index != 1)
return ERROR_INVALID_PARAMETER;
r = RegCreateKeyW(HKEY_LOCAL_MACHINE, szInstaller_LocalClassesProd, &key);
if( r != ERROR_SUCCESS )
return ERROR_NO_MORE_ITEMS;
r = RegEnumKeyW(hkeyProducts, index, szKeyName, SQUISH_GUID_SIZE);
if( r == ERROR_SUCCESS )
unsquash_guid(szKeyName, lpguid);
RegCloseKey(hkeyProducts);
r = RegQueryInfoKeyW(key, NULL, NULL, NULL, &machine_count, NULL, NULL,
NULL, NULL, NULL, NULL, NULL);
if( r != ERROR_SUCCESS )
{
RegCloseKey(key);
return ERROR_NO_MORE_ITEMS;
}
return r;
if (machine_count && index <= machine_count)
{
r = RegEnumKeyW(key, index, szKeyName, SQUISH_GUID_SIZE);
if( r == ERROR_SUCCESS )
{
unsquash_guid(szKeyName, lpguid);
last_index = index;
RegCloseKey(key);
return ERROR_SUCCESS;
}
}
RegCloseKey(key);
r = get_user_sid(&usersid);
if (r != ERROR_SUCCESS || !usersid)
{
ERR("Failed to retrieve user SID: %d\n", r);
return r;
}
sprintfW(keypath, szInstaller_LocalManaged_fmt, usersid);
LocalFree(usersid);
r = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, &key);
if( r != ERROR_SUCCESS )
return ERROR_NO_MORE_ITEMS;
r = RegQueryInfoKeyW(key, NULL, NULL, NULL, &managed_count, NULL, NULL,
NULL, NULL, NULL, NULL, NULL);
if( r != ERROR_SUCCESS )
{
RegCloseKey(key);
return ERROR_NO_MORE_ITEMS;
}
if (managed_count && index <= machine_count + managed_count)
{
r = RegEnumKeyW(key, index - machine_count, szKeyName, SQUISH_GUID_SIZE);
if( r == ERROR_SUCCESS )
{
unsquash_guid(szKeyName, lpguid);
last_index = index;
RegCloseKey(key);
return ERROR_SUCCESS;
}
}
RegCloseKey(key);
r = RegCreateKeyW(HKEY_CURRENT_USER, szUserProduct, &key);
if( r != ERROR_SUCCESS )
return ERROR_NO_MORE_ITEMS;
r = RegQueryInfoKeyW(key, NULL, NULL, NULL, &unmanaged_count, NULL, NULL,
NULL, NULL, NULL, NULL, NULL);
if( r != ERROR_SUCCESS )
{
RegCloseKey(key);
return ERROR_NO_MORE_ITEMS;
}
if (unmanaged_count && index <= machine_count + managed_count + unmanaged_count)
{
r = RegEnumKeyW(key, index - machine_count - managed_count, szKeyName, SQUISH_GUID_SIZE);
if( r == ERROR_SUCCESS )
{
unsquash_guid(szKeyName, lpguid);
last_index = index;
RegCloseKey(key);
return ERROR_SUCCESS;
}
}
RegCloseKey(key);
return ERROR_NO_MORE_ITEMS;
}
UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index,
@ -1659,6 +1770,7 @@ done:
}
static UINT msi_get_patch_state(LPCWSTR prodcode, LPCWSTR usersid,
MSIINSTALLCONTEXT context,
LPWSTR patch, MSIPATCHSTATE *state)
{
DWORD type, val, size;
@ -1672,9 +1784,8 @@ static UINT msi_get_patch_state(LPCWSTR prodcode, LPCWSTR usersid,
*state = MSIPATCHSTATE_INVALID;
/* FIXME: usersid might not be current user */
r = MSIREG_OpenUserDataProductKey(prodcode, MSIINSTALLCONTEXT_USERUNMANAGED,
NULL, &prod, FALSE);
r = MSIREG_OpenUserDataProductKey(prodcode, context,
usersid, &prod, FALSE);
if (r != ERROR_SUCCESS)
return ERROR_NO_MORE_ITEMS;
@ -1723,7 +1834,8 @@ static UINT msi_check_product_patches(LPCWSTR prodcode, LPCWSTR usersid,
static const WCHAR szState[] = {'S','t','a','t','e',0};
static const WCHAR szEmpty[] = {0};
if (MSIREG_OpenProductKey(prodcode, context, &prod, FALSE) != ERROR_SUCCESS)
if (MSIREG_OpenProductKey(prodcode, usersid, context,
&prod, FALSE) != ERROR_SUCCESS)
return ERROR_NO_MORE_ITEMS;
size = 0;
@ -1784,7 +1896,8 @@ static UINT msi_check_product_patches(LPCWSTR prodcode, LPCWSTR usersid,
{
if (!(filter & MSIPATCHSTATE_APPLIED))
{
temp = msi_get_patch_state(prodcode, usersid, ptr, &state);
temp = msi_get_patch_state(prodcode, usersid, context,
ptr, &state);
if (temp == ERROR_BAD_CONFIGURATION)
{
r = ERROR_BAD_CONFIGURATION;
@ -1799,7 +1912,8 @@ static UINT msi_check_product_patches(LPCWSTR prodcode, LPCWSTR usersid,
{
if (!(filter & MSIPATCHSTATE_APPLIED))
{
temp = msi_get_patch_state(prodcode, usersid, ptr, &state);
temp = msi_get_patch_state(prodcode, usersid, context,
ptr, &state);
if (temp == ERROR_BAD_CONFIGURATION)
{
r = ERROR_BAD_CONFIGURATION;
@ -1883,8 +1997,15 @@ static UINT msi_enum_patches(LPCWSTR szProductCode, LPCWSTR szUserSid,
MSIINSTALLCONTEXT *pdwTargetProductContext, LPWSTR szTargetUserSid,
LPDWORD pcchTargetUserSid, LPWSTR *szTransforms)
{
LPWSTR usersid = NULL;
UINT r = ERROR_INVALID_PARAMETER;
if (!szUserSid)
{
get_user_sid(&usersid);
szUserSid = usersid;
}
if (dwContext & MSIINSTALLCONTEXT_USERMANAGED)
{
r = msi_check_product_patches(szProductCode, szUserSid,
@ -1922,6 +2043,7 @@ static UINT msi_enum_patches(LPCWSTR szProductCode, LPCWSTR szUserSid,
}
done:
LocalFree(usersid);
return r;
}
@ -1983,7 +2105,7 @@ UINT WINAPI MsiEnumPatchesExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
UINT WINAPI MsiEnumPatchesA(LPCSTR szProduct, DWORD iPatchIndex,
LPSTR lpPatchBuf, LPSTR lpTransformsBuf, LPDWORD pcchTransformsBuf)
{
LPWSTR product, transforms = NULL;
LPWSTR product, transforms;
WCHAR patch[GUID_SIZE];
DWORD len;
UINT r;
@ -1998,12 +2120,8 @@ UINT WINAPI MsiEnumPatchesA(LPCSTR szProduct, DWORD iPatchIndex,
if (!product)
return ERROR_OUTOFMEMORY;
len = 0;
r = MsiEnumPatchesW(product, iPatchIndex, patch, patch, &len);
if (r != ERROR_MORE_DATA)
goto done;
transforms = msi_alloc(len);
len = *pcchTransformsBuf;
transforms = msi_alloc( len * sizeof(WCHAR) );
if (!transforms)
{
r = ERROR_OUTOFMEMORY;
@ -2011,24 +2129,23 @@ UINT WINAPI MsiEnumPatchesA(LPCSTR szProduct, DWORD iPatchIndex,
}
r = MsiEnumPatchesW(product, iPatchIndex, patch, transforms, &len);
if (r != ERROR_SUCCESS)
if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
goto done;
WideCharToMultiByte(CP_ACP, 0, patch, -1, lpPatchBuf,
GUID_SIZE, NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, transforms, -1, lpTransformsBuf,
*pcchTransformsBuf - 1, NULL, NULL);
len = lstrlenW(transforms);
if (*pcchTransformsBuf < len + 1)
{
if (!WideCharToMultiByte(CP_ACP, 0, transforms, -1, lpTransformsBuf,
*pcchTransformsBuf, NULL, NULL))
r = ERROR_MORE_DATA;
if (r == ERROR_MORE_DATA)
{
lpTransformsBuf[*pcchTransformsBuf - 1] = '\0';
*pcchTransformsBuf = len * sizeof(WCHAR);
*pcchTransformsBuf = len * 2;
}
else
*pcchTransformsBuf = len;
*pcchTransformsBuf = strlen( lpTransformsBuf );
done:
msi_free(transforms);
@ -2058,11 +2175,11 @@ UINT WINAPI MsiEnumPatchesW(LPCWSTR szProduct, DWORD iPatchIndex,
if (!lpPatchBuf || !lpTransformsBuf || !pcchTransformsBuf)
return ERROR_INVALID_PARAMETER;
if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
&prod, FALSE) != ERROR_SUCCESS &&
MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
&prod, FALSE) != ERROR_SUCCESS &&
MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
&prod, FALSE) != ERROR_SUCCESS)
return ERROR_UNKNOWN_PRODUCT;
@ -2078,7 +2195,7 @@ UINT WINAPI MsiEnumPatchesW(LPCWSTR szProduct, DWORD iPatchIndex,
if (*pcchTransformsBuf <= lstrlenW(transforms))
{
r = ERROR_MORE_DATA;
*pcchTransformsBuf = lstrlenW(transforms) * sizeof(WCHAR);
*pcchTransformsBuf = lstrlenW(transforms);
}
else
*pcchTransformsBuf = lstrlenW(transforms);

View file

@ -136,7 +136,7 @@ static UINT SELECT_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, U
return r;
}
static UINT SELECT_insert_row( struct tagMSIVIEW *view, MSIRECORD *record, BOOL temporary )
static UINT SELECT_insert_row( struct tagMSIVIEW *view, MSIRECORD *record, UINT row, BOOL temporary )
{
MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
UINT i, table_cols, r;
@ -161,7 +161,7 @@ static UINT SELECT_insert_row( struct tagMSIVIEW *view, MSIRECORD *record, BOOL
goto fail;
}
r = sv->table->ops->insert_row( sv->table, outrec, temporary );
r = sv->table->ops->insert_row( sv->table, outrec, row, temporary );
fail:
msiobj_release( &outrec->hdr );
@ -209,11 +209,11 @@ static UINT SELECT_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *co
}
static UINT SELECT_get_column_info( struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type )
UINT n, LPWSTR *name, UINT *type, BOOL *temporary )
{
MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
TRACE("%p %d %p %p\n", sv, n, name, type );
TRACE("%p %d %p %p %p\n", sv, n, name, type, temporary );
if( !sv->table )
return ERROR_FUNCTION_FAILED;
@ -223,7 +223,8 @@ static UINT SELECT_get_column_info( struct tagMSIVIEW *view,
n = sv->cols[ n - 1 ];
return sv->table->ops->get_column_info( sv->table, n, name, type );
return sv->table->ops->get_column_info( sv->table, n, name,
type, temporary );
}
static UINT msi_select_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
@ -246,7 +247,7 @@ static UINT msi_select_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
{
col = sv->cols[i];
r = SELECT_get_column_info(view, i + 1, &name, &type);
r = SELECT_get_column_info(view, i + 1, &name, &type, NULL);
msi_free(name);
if (r != ERROR_SUCCESS)
{

View file

@ -64,21 +64,24 @@ static UINT OpenSourceKey(LPCWSTR szProduct, HKEY* key, DWORD dwOptions,
if (dwOptions & MSICODE_PATCH)
rc = MSIREG_OpenUserPatchesKey(szProduct, &rootkey, create);
else
rc = MSIREG_OpenProductKey(szProduct, context, &rootkey, create);
rc = MSIREG_OpenProductKey(szProduct, NULL, context,
&rootkey, create);
}
else if (context == MSIINSTALLCONTEXT_USERMANAGED)
{
if (dwOptions & MSICODE_PATCH)
rc = MSIREG_OpenUserPatchesKey(szProduct, &rootkey, create);
else
rc = MSIREG_OpenProductKey(szProduct, context, &rootkey, create);
rc = MSIREG_OpenProductKey(szProduct, NULL, context,
&rootkey, create);
}
else if (context == MSIINSTALLCONTEXT_MACHINE)
{
if (dwOptions & MSICODE_PATCH)
rc = MSIREG_OpenPatchesKey(szProduct, &rootkey, create);
else
rc = MSIREG_OpenProductKey(szProduct, context, &rootkey, create);
rc = MSIREG_OpenProductKey(szProduct, NULL, context,
&rootkey, create);
}
if (rc != ERROR_SUCCESS)
@ -903,13 +906,14 @@ UINT WINAPI MsiSourceListAddSourceW( LPCWSTR szProduct, LPCWSTR szUserName,
msi_free(psid);
}
r = MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
&hkey, FALSE);
r = MSIREG_OpenProductKey(szProduct, NULL,
MSIINSTALLCONTEXT_USERMANAGED, &hkey, FALSE);
if (r == ERROR_SUCCESS)
context = MSIINSTALLCONTEXT_USERMANAGED;
else
{
r = MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
r = MSIREG_OpenProductKey(szProduct, NULL,
MSIINSTALLCONTEXT_USERUNMANAGED,
&hkey, FALSE);
if (r != ERROR_SUCCESS)
return ERROR_UNKNOWN_PRODUCT;
@ -1315,6 +1319,28 @@ UINT WINAPI MsiSourceListClearAllW( LPCWSTR szProduct, LPCWSTR szUserName, DWORD
return ERROR_SUCCESS;
}
/******************************************************************
* MsiSourceListClearAllExA (MSI.@)
*/
UINT WINAPI MsiSourceListClearAllExA( LPCSTR szProduct, LPCSTR szUserSid,
MSIINSTALLCONTEXT dwContext, DWORD dwOptions )
{
FIXME("(%s %s %d %08x)\n", debugstr_a(szProduct), debugstr_a(szUserSid),
dwContext, dwOptions);
return ERROR_SUCCESS;
}
/******************************************************************
* MsiSourceListClearAllExW (MSI.@)
*/
UINT WINAPI MsiSourceListClearAllExW( LPCWSTR szProduct, LPCWSTR szUserSid,
MSIINSTALLCONTEXT dwContext, DWORD dwOptions )
{
FIXME("(%s %s %d %08x)\n", debugstr_w(szProduct), debugstr_w(szUserSid),
dwContext, dwOptions);
return ERROR_SUCCESS;
}
/******************************************************************
* MsiSourceListClearSourceA (MSI.@)
*/

File diff suppressed because it is too large Load diff

View file

@ -1,27 +1,37 @@
/* A Bison parser, made by GNU Bison 2.1. */
/* Skeleton parser for Yacc-like parsing with Bison,
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
/* A Bison parser, made by GNU Bison 2.4.1. */
This program is free software; you can redistribute it and/or modify
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* As a special exception, when this file is copied by Bison into a
Bison output file, you may use that output file without restriction.
This special exception was added by the Free Software Foundation
in version 1.24 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
@ -92,75 +102,16 @@
TK_NEGATION = 319
};
#endif
/* Tokens. */
#define TK_ALTER 258
#define TK_AND 259
#define TK_BY 260
#define TK_CHAR 261
#define TK_COMMA 262
#define TK_CREATE 263
#define TK_DELETE 264
#define TK_DROP 265
#define TK_DISTINCT 266
#define TK_DOT 267
#define TK_EQ 268
#define TK_FREE 269
#define TK_FROM 270
#define TK_GE 271
#define TK_GT 272
#define TK_HOLD 273
#define TK_ADD 274
#define TK_ID 275
#define TK_ILLEGAL 276
#define TK_INSERT 277
#define TK_INT 278
#define TK_INTEGER 279
#define TK_INTO 280
#define TK_IS 281
#define TK_KEY 282
#define TK_LE 283
#define TK_LONG 284
#define TK_LONGCHAR 285
#define TK_LP 286
#define TK_LT 287
#define TK_LOCALIZABLE 288
#define TK_MINUS 289
#define TK_NE 290
#define TK_NOT 291
#define TK_NULL 292
#define TK_OBJECT 293
#define TK_OR 294
#define TK_ORDER 295
#define TK_PRIMARY 296
#define TK_RP 297
#define TK_SELECT 298
#define TK_SET 299
#define TK_SHORT 300
#define TK_SPACE 301
#define TK_STAR 302
#define TK_STRING 303
#define TK_TABLE 304
#define TK_TEMPORARY 305
#define TK_UPDATE 306
#define TK_VALUES 307
#define TK_WHERE 308
#define TK_WILDCARD 309
#define COLUMN 311
#define FUNCTION 312
#define COMMENT 313
#define UNCLOSED_STRING 314
#define SPACE 315
#define ILLEGAL 316
#define END_OF_FILE 317
#define TK_LIKE 318
#define TK_NEGATION 319
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
{
/* Line 1676 of yacc.c */
#line 75 "sql.y"
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
#line 74 "sql.y"
typedef union YYSTYPE {
struct sql_str str;
LPWSTR string;
column_info *column_list;
@ -168,15 +119,17 @@ typedef union YYSTYPE {
struct expr *expr;
USHORT column_type;
int integer;
/* Line 1676 of yacc.c */
#line 127 "sql.tab.h"
} YYSTYPE;
/* Line 1447 of yacc.c. */
#line 174 "sql.tab.h"
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif

View file

@ -45,11 +45,12 @@ typedef struct tag_SQL_input
MSIDATABASE *db;
LPCWSTR command;
DWORD n, len;
UINT r;
MSIVIEW **view; /* view structure for the resulting query */
struct list *mem;
} SQL_input;
static LPWSTR SQL_getstring( void *info, const struct sql_str *str );
static UINT SQL_getstring( void *info, const struct sql_str *strdata, LPWSTR *str );
static INT SQL_getint( void *info );
static int sql_lex( void *SQL_lval, SQL_input *info );
@ -57,7 +58,7 @@ static LPWSTR parser_add_table( LPWSTR list, LPWSTR table );
static void *parser_alloc( void *info, unsigned int sz );
static column_info *parser_alloc_column( void *info, LPCWSTR table, LPCWSTR column );
static BOOL SQL_MarkPrimaryKeys( column_info *cols, column_info *keys);
static BOOL SQL_MarkPrimaryKeys( column_info **cols, column_info *keys);
static struct expr * EXPR_complex( void *info, struct expr *l, UINT op, struct expr *r );
static struct expr * EXPR_unary( void *info, struct expr *l, UINT op );
@ -166,12 +167,16 @@ onecreate:
{
SQL_input* sql = (SQL_input*) info;
MSIVIEW *create = NULL;
UINT r;
if( !$5 )
YYABORT;
CREATE_CreateView( sql->db, &create, $3, $5, FALSE );
r = CREATE_CreateView( sql->db, &create, $3, $5, FALSE );
if( !create )
{
sql->r = r;
YYABORT;
}
$$ = create;
}
| TK_CREATE TK_TABLE table TK_LP table_def TK_RP TK_HOLD
@ -284,7 +289,7 @@ onedrop:
table_def:
column_def TK_PRIMARY TK_KEY selcollist
{
if( SQL_MarkPrimaryKeys( $1, $4 ) )
if( SQL_MarkPrimaryKeys( &$1, $4 ) )
$$ = $1;
else
$$ = NULL;
@ -354,15 +359,15 @@ data_type:
}
| TK_LONGCHAR
{
$$ = 2;
$$ = MSITYPE_STRING | 0x400;
}
| TK_SHORT
{
$$ = 2;
$$ = 2 | 0x400;
}
| TK_INT
{
$$ = 2;
$$ = 2 | 0x400;
}
| TK_LONG
{
@ -677,8 +682,7 @@ table:
id:
TK_ID
{
$$ = SQL_getstring( info, &$1 );
if( !$$ )
if ( SQL_getstring( info, &$1, &$$ ) != ERROR_SUCCESS || !$$ )
YYABORT;
}
;
@ -757,11 +761,15 @@ static int sql_lex( void *SQL_lval, SQL_input *sql )
return token;
}
LPWSTR SQL_getstring( void *info, const struct sql_str *strdata )
UINT SQL_getstring( void *info, const struct sql_str *strdata, LPWSTR *str )
{
LPCWSTR p = strdata->data;
UINT len = strdata->len;
LPWSTR str;
/* match quotes */
if( ( (p[0]=='`') && (p[len-1]!='`') ) ||
( (p[0]=='\'') && (p[len-1]!='\'') ) )
return ERROR_FUNCTION_FAILED;
/* if there's quotes, remove them */
if( ( (p[0]=='`') && (p[len-1]=='`') ) ||
@ -770,13 +778,13 @@ LPWSTR SQL_getstring( void *info, const struct sql_str *strdata )
p++;
len -= 2;
}
str = parser_alloc( info, (len + 1)*sizeof(WCHAR) );
if( !str )
return str;
memcpy( str, p, len*sizeof(WCHAR) );
str[len]=0;
*str = parser_alloc( info, (len + 1)*sizeof(WCHAR) );
if( !*str )
return ERROR_OUTOFMEMORY;
memcpy( *str, p, len*sizeof(WCHAR) );
(*str)[len]=0;
return str;
return ERROR_SUCCESS;
}
INT SQL_getint( void *info )
@ -867,28 +875,62 @@ static struct expr * EXPR_sval( void *info, const struct sql_str *str )
if( e )
{
e->type = EXPR_SVAL;
e->u.sval = SQL_getstring( info, str );
if( SQL_getstring( info, str, (LPWSTR *)&e->u.sval ) != ERROR_SUCCESS )
return NULL; /* e will be freed by query destructor */
}
return e;
}
static BOOL SQL_MarkPrimaryKeys( column_info *cols,
static void swap_columns( column_info **cols, column_info *A, int idx )
{
column_info *preA = NULL, *preB = NULL, *B, *ptr;
int i = 0;
B = NULL;
ptr = *cols;
while( ptr )
{
if( i++ == idx )
B = ptr;
else if( !B )
preB = ptr;
if( ptr->next == A )
preA = ptr;
ptr = ptr->next;
}
if( preB ) preB->next = A;
if( preA ) preA->next = B;
ptr = A->next;
A->next = B->next;
B->next = ptr;
if( idx == 0 )
*cols = A;
}
static BOOL SQL_MarkPrimaryKeys( column_info **cols,
column_info *keys )
{
column_info *k;
BOOL found = TRUE;
int count;
for( k = keys; k && found; k = k->next )
for( k = keys, count = 0; k && found; k = k->next, count++ )
{
column_info *c;
int idx;
found = FALSE;
for( c = cols; c && !found; c = c->next )
for( c = *cols, idx = 0; c && !found; c = c->next, idx++ )
{
if( lstrcmpW( k->column, c->column ) )
continue;
c->type |= MSITYPE_KEY;
found = TRUE;
if( lstrcmpW( k->column, c->column ) )
continue;
c->type |= MSITYPE_KEY;
found = TRUE;
if (idx != count)
swap_columns( cols, c, count );
}
}
@ -907,6 +949,7 @@ UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview,
sql.command = command;
sql.n = 0;
sql.len = 0;
sql.r = ERROR_BAD_QUERY_SYNTAX;
sql.view = phview;
sql.mem = mem;
@ -915,8 +958,12 @@ UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview,
TRACE("Parse returned %d\n", r);
if( r )
{
*sql.view = NULL;
return ERROR_BAD_QUERY_SYNTAX;
if (*sql.view)
{
(*sql.view)->ops->delete(*sql.view);
*sql.view = NULL;
}
return sql.r;
}
return ERROR_SUCCESS;

View file

@ -243,14 +243,19 @@ done:
return r;
}
static UINT STORAGES_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, BOOL temporary)
static UINT STORAGES_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary)
{
MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
if (!storages_set_table_size(sv, ++sv->num_rows))
return ERROR_FUNCTION_FAILED;
return STORAGES_set_row(view, sv->num_rows - 1, rec, 0);
if (row == -1)
row = sv->num_rows - 1;
/* FIXME have to readjust rows */
return STORAGES_set_row(view, row, rec, 0);
}
static UINT STORAGES_delete_row(struct tagMSIVIEW *view, UINT row)
@ -283,15 +288,15 @@ static UINT STORAGES_get_dimensions(struct tagMSIVIEW *view, UINT *rows, UINT *c
return ERROR_SUCCESS;
}
static UINT STORAGES_get_column_info(struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type)
static UINT STORAGES_get_column_info(struct tagMSIVIEW *view, UINT n,
LPWSTR *name, UINT *type, BOOL *temporary)
{
LPCWSTR name_ptr = NULL;
static const WCHAR Name[] = {'N','a','m','e',0};
static const WCHAR Data[] = {'D','a','t','a',0};
TRACE("(%p, %d, %p, %p)\n", view, n, name, type);
TRACE("(%p, %d, %p, %p, %p)\n", view, n, name, type, temporary);
if (n == 0 || n > NUM_STORAGES_COLS)
return ERROR_INVALID_PARAMETER;
@ -315,6 +320,9 @@ static UINT STORAGES_get_column_info(struct tagMSIVIEW *view,
if (!*name) return ERROR_FUNCTION_FAILED;
}
if (temporary)
*temporary = FALSE;
return ERROR_SUCCESS;
}
@ -361,7 +369,7 @@ static UINT storages_modify_assign(struct tagMSIVIEW *view, MSIRECORD *rec)
if (r == ERROR_SUCCESS)
return storages_modify_update(view, rec);
return STORAGES_insert_row(view, rec, FALSE);
return STORAGES_insert_row(view, rec, -1, FALSE);
}
static UINT STORAGES_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row)
@ -377,7 +385,7 @@ static UINT STORAGES_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIR
break;
case MSIMODIFY_INSERT:
r = STORAGES_insert_row(view, rec, FALSE);
r = STORAGES_insert_row(view, rec, -1, FALSE);
break;
case MSIMODIFY_UPDATE:

View file

@ -209,14 +209,19 @@ done:
return r;
}
static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, BOOL temporary)
static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary)
{
MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
if (!streams_set_table_size(sv, ++sv->num_rows))
return ERROR_FUNCTION_FAILED;
return STREAMS_set_row(view, sv->num_rows - 1, rec, 0);
if (row == -1)
row = sv->num_rows - 1;
/* FIXME have to readjust rows */
return STREAMS_set_row(view, row, rec, 0);
}
static UINT STREAMS_delete_row(struct tagMSIVIEW *view, UINT row)
@ -249,15 +254,15 @@ static UINT STREAMS_get_dimensions(struct tagMSIVIEW *view, UINT *rows, UINT *co
return ERROR_SUCCESS;
}
static UINT STREAMS_get_column_info(struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type)
static UINT STREAMS_get_column_info(struct tagMSIVIEW *view, UINT n,
LPWSTR *name, UINT *type, BOOL *temporary)
{
LPCWSTR name_ptr = NULL;
static const WCHAR Name[] = {'N','a','m','e',0};
static const WCHAR Data[] = {'D','a','t','a',0};
TRACE("(%p, %d, %p, %p)\n", view, n, name, type);
TRACE("(%p, %d, %p, %p, %p)\n", view, n, name, type, temporary);
if (n == 0 || n > NUM_STREAMS_COLS)
return ERROR_INVALID_PARAMETER;
@ -281,6 +286,9 @@ static UINT STREAMS_get_column_info(struct tagMSIVIEW *view,
if (!*name) return ERROR_FUNCTION_FAILED;
}
if (temporary)
*temporary = FALSE;
return ERROR_SUCCESS;
}
@ -327,7 +335,7 @@ static UINT streams_modify_assign(struct tagMSIVIEW *view, MSIRECORD *rec)
if (r == ERROR_SUCCESS)
return streams_modify_update(view, rec);
return STREAMS_insert_row(view, rec, FALSE);
return STREAMS_insert_row(view, rec, -1, FALSE);
}
static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row)
@ -343,7 +351,7 @@ static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRE
break;
case MSIMODIFY_INSERT:
r = STREAMS_insert_row(view, rec, FALSE);
r = STREAMS_insert_row(view, rec, -1, FALSE);
break;
case MSIMODIFY_UPDATE:

View file

@ -29,6 +29,7 @@
#include "winnls.h"
#include "shlwapi.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "msi.h"
#include "msiquery.h"
#include "msidefs.h"
@ -694,43 +695,26 @@ UINT WINAPI MsiSummaryInfoGetPropertyW(
pftValue, &str, pcchValueBuf );
}
static UINT set_prop( MSIHANDLE handle, UINT uiProperty, UINT uiDataType,
static UINT set_prop( MSISUMMARYINFO *si, UINT uiProperty, UINT type,
INT iValue, FILETIME* pftValue, awcstring *str )
{
MSISUMMARYINFO *si;
PROPVARIANT *prop;
UINT type, len, ret = ERROR_SUCCESS;
UINT len;
TRACE("%d %u %u %i %p %p\n", handle, uiProperty, uiDataType,
iValue, pftValue, str );
type = get_type( uiProperty );
if( type == VT_EMPTY || type != uiDataType )
return ERROR_DATATYPE_MISMATCH;
if( uiDataType == VT_LPSTR && !str->str.w )
return ERROR_INVALID_PARAMETER;
if( uiDataType == VT_FILETIME && !pftValue )
return ERROR_INVALID_PARAMETER;
si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO );
if( !si )
return ERROR_INVALID_HANDLE;
TRACE("%p %u %u %i %p %p\n", si, uiProperty, type, iValue,
pftValue, str );
prop = &si->property[uiProperty];
if( prop->vt == VT_EMPTY )
{
if( !si->update_count )
{
ret = ERROR_FUNCTION_FAILED;
goto end;
}
return ERROR_FUNCTION_FAILED;
si->update_count--;
}
else if( prop->vt != type )
goto end;
return ERROR_SUCCESS;
free_prop( prop );
prop->vt = type;
@ -763,51 +747,80 @@ static UINT set_prop( MSIHANDLE handle, UINT uiProperty, UINT uiDataType,
break;
}
end:
msiobj_release( &si->hdr );
return ret;
return ERROR_SUCCESS;
}
UINT WINAPI MsiSummaryInfoSetPropertyW( MSIHANDLE handle, UINT uiProperty,
UINT uiDataType, INT iValue, FILETIME* pftValue, LPCWSTR szValue )
{
awcstring str;
MSISUMMARYINFO *si;
UINT type, ret;
TRACE("%d %u %u %i %p %s\n", handle, uiProperty, uiDataType,
iValue, pftValue, debugstr_w(szValue) );
type = get_type( uiProperty );
if( type == VT_EMPTY || type != uiDataType )
return ERROR_DATATYPE_MISMATCH;
if( uiDataType == VT_LPSTR && !szValue )
return ERROR_INVALID_PARAMETER;
if( uiDataType == VT_FILETIME && !pftValue )
return ERROR_INVALID_PARAMETER;
si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO );
if( !si )
return ERROR_INVALID_HANDLE;
str.unicode = TRUE;
str.str.w = szValue;
return set_prop( handle, uiProperty, uiDataType, iValue, pftValue, &str );
ret = set_prop( si, uiProperty, type, iValue, pftValue, &str );
msiobj_release( &si->hdr );
return ret;
}
UINT WINAPI MsiSummaryInfoSetPropertyA( MSIHANDLE handle, UINT uiProperty,
UINT uiDataType, INT iValue, FILETIME* pftValue, LPCSTR szValue )
{
awcstring str;
MSISUMMARYINFO *si;
UINT type, ret;
TRACE("%d %u %u %i %p %s\n", handle, uiProperty, uiDataType,
iValue, pftValue, debugstr_a(szValue) );
str.unicode = FALSE;
str.str.a = szValue;
return set_prop( handle, uiProperty, uiDataType, iValue, pftValue, &str );
}
type = get_type( uiProperty );
if( type == VT_EMPTY || type != uiDataType )
return ERROR_DATATYPE_MISMATCH;
UINT WINAPI MsiSummaryInfoPersist( MSIHANDLE handle )
{
IStream *stm = NULL;
MSISUMMARYINFO *si;
DWORD grfMode;
HRESULT r;
UINT ret = ERROR_FUNCTION_FAILED;
if( uiDataType == VT_LPSTR && !szValue )
return ERROR_INVALID_PARAMETER;
TRACE("%d\n", handle );
if( uiDataType == VT_FILETIME && !pftValue )
return ERROR_INVALID_PARAMETER;
si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO );
if( !si )
return ERROR_INVALID_HANDLE;
str.unicode = FALSE;
str.str.a = szValue;
ret = set_prop( si, uiProperty, uiDataType, iValue, pftValue, &str );
msiobj_release( &si->hdr );
return ret;
}
static UINT suminfo_persist( MSISUMMARYINFO *si )
{
UINT ret = ERROR_FUNCTION_FAILED;
IStream *stm = NULL;
DWORD grfMode;
HRESULT r;
grfMode = STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
r = IStorage_CreateStream( si->storage, szSumInfo, grfMode, 0, 0, &stm );
if( SUCCEEDED(r) )
@ -815,7 +828,143 @@ UINT WINAPI MsiSummaryInfoPersist( MSIHANDLE handle )
ret = save_summary_info( si, stm );
IStream_Release( stm );
}
msiobj_release( &si->hdr );
return ret;
}
static void parse_filetime( LPCWSTR str, FILETIME *ft )
{
SYSTEMTIME lt, utc;
const WCHAR *p = str;
WCHAR *end;
memset( &lt, 0, sizeof(lt) );
/* YYYY/MM/DD hh:mm:ss */
while (isspaceW( *p )) p++;
lt.wYear = strtolW( p, &end, 10 );
if (*end != '/') return;
p = end + 1;
lt.wMonth = strtolW( p, &end, 10 );
if (*end != '/') return;
p = end + 1;
lt.wDay = strtolW( p, &end, 10 );
if (*end != ' ') return;
p = end + 1;
while (isspaceW( *p )) p++;
lt.wHour = strtolW( p, &end, 10 );
if (*end != ':') return;
p = end + 1;
lt.wMinute = strtolW( p, &end, 10 );
if (*end != ':') return;
p = end + 1;
lt.wSecond = strtolW( p, &end, 10 );
TzSpecificLocalTimeToSystemTime( NULL, &lt, &utc );
SystemTimeToFileTime( &utc, ft );
}
static UINT parse_prop( LPCWSTR prop, LPCWSTR value, UINT *pid, INT *int_value,
FILETIME *ft_value, awcstring *str_value )
{
*pid = atoiW( prop );
switch (*pid)
{
case PID_CODEPAGE:
case PID_WORDCOUNT:
case PID_CHARCOUNT:
case PID_SECURITY:
case PID_PAGECOUNT:
*int_value = atoiW( value );
break;
case PID_LASTPRINTED:
case PID_CREATE_DTM:
case PID_LASTSAVE_DTM:
parse_filetime( value, ft_value );
break;
case PID_SUBJECT:
case PID_AUTHOR:
case PID_KEYWORDS:
case PID_COMMENTS:
case PID_TEMPLATE:
case PID_LASTAUTHOR:
case PID_REVNUMBER:
case PID_APPNAME:
case PID_TITLE:
str_value->str.w = value;
str_value->unicode = TRUE;
break;
default:
WARN("unhandled prop id %u\n", *pid);
return ERROR_FUNCTION_FAILED;
}
return ERROR_SUCCESS;
}
UINT msi_add_suminfo( MSIDATABASE *db, LPWSTR **records, int num_records, int num_columns )
{
UINT r = ERROR_FUNCTION_FAILED;
DWORD i, j;
MSISUMMARYINFO *si;
si = MSI_GetSummaryInformationW( db->storage, num_records * (num_columns / 2) );
if (!si)
{
ERR("no summary information!\n");
return ERROR_FUNCTION_FAILED;
}
for (i = 0; i < num_records; i++)
{
for (j = 0; j < num_columns; j += 2)
{
UINT pid;
INT int_value = 0;
FILETIME ft_value;
awcstring str_value;
r = parse_prop( records[i][j], records[i][j + 1], &pid, &int_value, &ft_value, &str_value );
if (r != ERROR_SUCCESS)
goto end;
r = set_prop( si, pid, get_type(pid), int_value, &ft_value, &str_value );
if (r != ERROR_SUCCESS)
goto end;
}
}
end:
if (r == ERROR_SUCCESS)
r = suminfo_persist( si );
msiobj_release( &si->hdr );
return r;
}
UINT WINAPI MsiSummaryInfoPersist( MSIHANDLE handle )
{
MSISUMMARYINFO *si;
UINT ret;
TRACE("%d\n", handle );
si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO );
if( !si )
return ERROR_INVALID_HANDLE;
ret = suminfo_persist( si );
msiobj_release( &si->hdr );
return ret;
}

View file

@ -59,6 +59,7 @@ typedef struct tagMSICOLUMNINFO
UINT type;
UINT offset;
INT ref_count;
BOOL temporary;
MSICOLUMNHASHENTRY **hash_table;
} MSICOLUMNINFO;
@ -78,7 +79,7 @@ struct tagMSITABLE
struct list entry;
MSICOLUMNINFO *colinfo;
UINT col_count;
BOOL persistent;
MSICONDITION persistent;
INT ref_count;
WCHAR name[1];
};
@ -102,14 +103,14 @@ static WCHAR szNumber[] = { 'N','u','m','b','e','r',0 };
static WCHAR szType[] = { 'T','y','p','e',0 };
static const MSICOLUMNINFO _Columns_cols[4] = {
{ szColumns, 1, szTable, MSITYPE_VALID | MSITYPE_STRING | MSITYPE_KEY | 64, 0, 0, NULL },
{ szColumns, 2, szNumber, MSITYPE_VALID | MSITYPE_KEY | 2, 2, 0, NULL },
{ szColumns, 3, szName, MSITYPE_VALID | MSITYPE_STRING | 64, 4, 0, NULL },
{ szColumns, 4, szType, MSITYPE_VALID | 2, 6, 0, NULL },
{ szColumns, 1, szTable, MSITYPE_VALID | MSITYPE_STRING | MSITYPE_KEY | 64, 0, 0, 0, NULL },
{ szColumns, 2, szNumber, MSITYPE_VALID | MSITYPE_KEY | 2, 2, 0, 0, NULL },
{ szColumns, 3, szName, MSITYPE_VALID | MSITYPE_STRING | 64, 4, 0, 0, NULL },
{ szColumns, 4, szType, MSITYPE_VALID | 2, 6, 0, 0, NULL },
};
static const MSICOLUMNINFO _Tables_cols[1] = {
{ szTables, 1, szName, MSITYPE_VALID | MSITYPE_STRING | MSITYPE_KEY | 64, 0, 0, NULL },
{ szTables, 1, szName, MSITYPE_VALID | MSITYPE_STRING | MSITYPE_KEY | 64, 0, 0, 0, NULL },
};
#define MAX_STREAM_NAME 0x1f
@ -610,7 +611,7 @@ static UINT table_get_column_info( MSIDATABASE *db, LPCWSTR name, MSICOLUMNINFO
}
UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
BOOL persistent, MSITABLE **table_ret)
MSICONDITION persistent, MSITABLE **table_ret)
{
UINT r, nField;
MSIVIEW *tv = NULL;
@ -659,6 +660,7 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
table->colinfo[ i ].offset = 0;
table->colinfo[ i ].ref_count = 0;
table->colinfo[ i ].hash_table = NULL;
table->colinfo[ i ].temporary = col->temporary;
}
table_calc_column_offsets( db, table->colinfo, table->col_count);
@ -683,7 +685,7 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
if( r )
goto err;
r = tv->ops->insert_row( tv, rec, !persistent );
r = tv->ops->insert_row( tv, rec, -1, persistent == MSICONDITION_FALSE );
TRACE("insert_row returned %x\n", r);
if( r )
goto err;
@ -694,7 +696,7 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
msiobj_release( &rec->hdr );
rec = NULL;
if( persistent )
if( persistent != MSICONDITION_FALSE )
{
/* add each column to the _Columns table */
r = TABLE_CreateView( db, szColumns, &tv );
@ -733,7 +735,7 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
if( r )
goto err;
r = tv->ops->insert_row( tv, rec, FALSE );
r = tv->ops->insert_row( tv, rec, -1, FALSE );
if( r )
goto err;
@ -785,9 +787,12 @@ static UINT get_table( MSIDATABASE *db, LPCWSTR name, MSITABLE **table_ret )
table->nonpersistent_data = NULL;
table->colinfo = NULL;
table->col_count = 0;
table->persistent = TRUE;
table->persistent = MSICONDITION_TRUE;
lstrcpyW( table->name, name );
if ( !lstrcmpW(name, szTables) || !lstrcmpW(name, szColumns) )
table->persistent = MSICONDITION_NONE;
r = table_get_column_info( db, name, &table->colinfo, &table->col_count);
if (r != ERROR_SUCCESS)
{
@ -813,7 +818,7 @@ static UINT save_table( MSIDATABASE *db, const MSITABLE *t )
UINT rawsize, r, i, j, row_size;
/* Nothing to do for non-persistent tables */
if( !t->persistent )
if( t->persistent == MSICONDITION_FALSE )
return ERROR_SUCCESS;
TRACE("Saving %s\n", debugstr_w( t->name ) );
@ -1033,8 +1038,9 @@ static void msi_update_table_columns( MSIDATABASE *db, LPCWSTR name )
table = find_cached_table( db, name );
old_count = table->col_count;
msi_free( table->colinfo );
table_get_column_info( db, name, &table->colinfo, &table->col_count );
table->colinfo = NULL;
table_get_column_info( db, name, &table->colinfo, &table->col_count );
if (!table->col_count)
return;
@ -1055,9 +1061,11 @@ BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name )
UINT r, table_id = 0, i, count;
MSITABLE *table = NULL;
if( !lstrcmpW( name, szTables ) )
return TRUE;
if( !lstrcmpW( name, szColumns ) )
static const WCHAR szStreams[] = {'_','S','t','r','e','a','m','s',0};
static const WCHAR szStorages[] = {'_','S','t','o','r','a','g','e','s',0};
if( !lstrcmpW( name, szTables ) || !lstrcmpW( name, szColumns ) ||
!lstrcmpW( name, szStreams ) || !lstrcmpW( name, szStorages ) )
return TRUE;
r = msi_string2idW( db->strings, name, &table_id );
@ -1298,7 +1306,8 @@ static UINT TABLE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UI
continue;
/* if row >= tv->table->row_count then it is a non-persistent row */
persistent = tv->table->persistent && (row < tv->table->row_count);
persistent = (tv->table->persistent != MSICONDITION_FALSE) &&
(row < tv->table->row_count);
/* FIXME: should we allow updating keys? */
val = 0;
@ -1368,13 +1377,15 @@ static UINT table_create_new_row( struct tagMSIVIEW *view, UINT *num, BOOL tempo
{
row_count = &tv->table->nonpersistent_row_count;
data_ptr = &tv->table->nonpersistent_data;
*num = tv->table->row_count + tv->table->nonpersistent_row_count;
if (*num == -1)
*num = tv->table->row_count + tv->table->nonpersistent_row_count;
}
else
{
row_count = &tv->table->row_count;
data_ptr = &tv->table->data;
*num = tv->table->row_count;
if (*num == -1)
*num = tv->table->row_count;
}
sz = (*row_count + 1) * sizeof (BYTE*);
@ -1432,7 +1443,7 @@ static UINT TABLE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *col
}
static UINT TABLE_get_column_info( struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type )
UINT n, LPWSTR *name, UINT *type, BOOL *temporary )
{
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
@ -1447,9 +1458,13 @@ static UINT TABLE_get_column_info( struct tagMSIVIEW *view,
if( !*name )
return ERROR_FUNCTION_FAILED;
}
if( type )
*type = tv->columns[n-1].type;
if( temporary )
*temporary = tv->columns[n-1].temporary;
return ERROR_SUCCESS;
}
@ -1493,10 +1508,11 @@ static UINT table_validate_new( MSITABLEVIEW *tv, MSIRECORD *rec )
return ERROR_SUCCESS;
}
static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec, BOOL temporary )
static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary )
{
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
UINT r, row = -1;
UINT i, r, idx, size;
BYTE **data;
TRACE("%p %p %s\n", tv, rec, temporary ? "TRUE" : "FALSE" );
@ -1510,6 +1526,27 @@ static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec, BOOL temp
if( r != ERROR_SUCCESS )
return r;
idx = row;
if( temporary )
{
data = tv->table->nonpersistent_data;
size = tv->table->nonpersistent_row_count;
idx -= tv->table->row_count;
}
else
{
data = tv->table->data;
size = tv->table->row_count;
}
/* shift the rows to make room for the new row */
if( idx != size - 1 )
{
for (i = 1; i < size - idx; i++)
memmove(&(data[size - i][0]),
&(data[size - i - 1][0]), tv->row_size);
}
return TABLE_set_row( view, row, rec, (1<<tv->num_cols) - 1 );
}
@ -1637,14 +1674,14 @@ static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
r = table_validate_new( tv, rec );
if (r != ERROR_SUCCESS)
break;
r = TABLE_insert_row( view, rec, FALSE );
r = TABLE_insert_row( view, rec, -1, FALSE );
break;
case MSIMODIFY_INSERT_TEMPORARY:
r = table_validate_new( tv, rec );
if (r != ERROR_SUCCESS)
break;
r = TABLE_insert_row( view, rec, TRUE );
r = TABLE_insert_row( view, rec, -1, TRUE );
break;
case MSIMODIFY_REFRESH:
@ -1876,7 +1913,7 @@ static UINT TABLE_add_column(struct tagMSIVIEW *view, LPCWSTR table, UINT number
MSI_RecordSetStringW(rec, 3, column);
MSI_RecordSetInteger(rec, 4, type);
r = TABLE_insert_row(&tv->view, rec, FALSE);
r = TABLE_insert_row(&tv->view, rec, -1, FALSE);
if (r != ERROR_SUCCESS)
goto done;
@ -2214,10 +2251,7 @@ MSICONDITION MSI_DatabaseIsTablePersistent( MSIDATABASE *db, LPCWSTR table )
if (r != ERROR_SUCCESS)
return MSICONDITION_NONE;
if (t->persistent)
return MSICONDITION_TRUE;
else
return MSICONDITION_FALSE;
return t->persistent;
}
static UINT read_raw_int(const BYTE *data, UINT col, UINT bytes)
@ -2353,7 +2387,10 @@ static UINT* msi_record_to_row( const MSITABLEVIEW *tv, MSIRECORD *rec )
else
{
data[i] = MSI_RecordGetInteger( rec, i+1 );
if ((tv->columns[i].type&0xff) == 2)
if (data[i] == MSI_NULL_INTEGER)
data[i] = 0;
else if ((tv->columns[i].type&0xff) == 2)
data[i] += 0x8000;
else
data[i] += 0x80000000;
@ -2547,7 +2584,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
}
}
r = TABLE_insert_row( &tv->view, rec, FALSE );
r = TABLE_insert_row( &tv->view, rec, -1, FALSE );
if (r != ERROR_SUCCESS)
ERR("insert row failed\n");

View file

@ -193,8 +193,8 @@ static const char isIdChar[] = {
int sqliteGetToken(const WCHAR *z, int *tokenType){
int i;
switch( *z ){
case ' ': case '\t': case '\n': case '\f': case '\r': {
for(i=1; isspace(z[i]); i++){}
case ' ': case '\t': case '\n': case '\f': {
for(i=1; isspace(z[i]) && z[i] != '\r'; i++){}
*tokenType = TK_SPACE;
return i;
}
@ -254,13 +254,8 @@ int sqliteGetToken(const WCHAR *z, int *tokenType){
case '`': case '\'': {
int delim = z[0];
for(i=1; z[i]; i++){
if( z[i]==delim ){
if( z[i+1]==delim ){
i++;
}else{
break;
}
}
if( z[i]==delim )
break;
}
if( z[i] ) i++;
if( delim == '`' )

View file

@ -155,18 +155,18 @@ static UINT UPDATE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *co
}
static UINT UPDATE_get_column_info( struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type )
UINT n, LPWSTR *name, UINT *type, BOOL *temporary )
{
MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
MSIVIEW *wv;
TRACE("%p %d %p %p\n", uv, n, name, type );
TRACE("%p %d %p %p %p\n", uv, n, name, type, temporary );
wv = uv->wv;
if( !wv )
return ERROR_FUNCTION_FAILED;
return wv->ops->get_column_info( wv, n, name, type );
return wv->ops->get_column_info( wv, n, name, type, temporary );
}
static UINT UPDATE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,

View file

@ -119,7 +119,7 @@ static UINT ITERATE_FindRelatedProducts(MSIRECORD *rec, LPVOID param)
uirow = MSI_CreateRecord(1);
attributes = MSI_RecordGetInteger(rec,5);
while (rc == ERROR_SUCCESS)
{
rc = RegEnumValueW(hkey, index, product, &sz, NULL, NULL, NULL, NULL);
@ -137,7 +137,7 @@ static UINT ITERATE_FindRelatedProducts(MSIRECORD *rec, LPVOID param)
INT r;
unsquash_guid(product, productid);
rc = MSIREG_OpenProductKey(productid, package->Context,
rc = MSIREG_OpenProductKey(productid, NULL, package->Context,
&hukey, FALSE);
if (rc != ERROR_SUCCESS)
{

View file

@ -490,16 +490,17 @@ static UINT WHERE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *col
}
static UINT WHERE_get_column_info( struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type )
UINT n, LPWSTR *name, UINT *type, BOOL *temporary )
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
TRACE("%p %d %p %p\n", wv, n, name, type );
TRACE("%p %d %p %p %p\n", wv, n, name, type, temporary );
if( !wv->table )
return ERROR_FUNCTION_FAILED;
return wv->table->ops->get_column_info( wv->table, n, name, type );
return wv->table->ops->get_column_info( wv->table, n, name,
type, temporary );
}
static UINT WHERE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
@ -600,7 +601,7 @@ static UINT WHERE_VerifyCondition( MSIDATABASE *db, MSIVIEW *table, struct expr
if( r == ERROR_SUCCESS )
{
UINT type = 0;
r = table->ops->get_column_info( table, val, NULL, &type );
r = table->ops->get_column_info( table, val, NULL, &type, NULL );
if( r == ERROR_SUCCESS )
{
if (type&MSITYPE_STRING)

View file

@ -649,6 +649,10 @@ UINT WINAPI MsiDetermineApplicablePatchesA(LPCSTR, DWORD, PMSIPATCHSEQUENCEINFOA
UINT WINAPI MsiDetermineApplicablePatchesW(LPCWSTR, DWORD, PMSIPATCHSEQUENCEINFOW);
#define MsiDetermineApplicablePatches WINELIB_NAME_AW(MsiDetermineApplicablePatches)
UINT WINAPI MsiApplyMultiplePatchesA(LPCSTR, LPCSTR, LPCSTR);
UINT WINAPI MsiApplyMultiplePatchesW(LPCWSTR, LPCWSTR, LPCWSTR);
#define MsiApplyMultiplePatches WINELIB_NAME_AW(MsiApplyMultiplePatches)
/* Non Unicode */
UINT WINAPI MsiCloseHandle(MSIHANDLE);
UINT WINAPI MsiCloseAllHandles(void);