mirror of
https://github.com/reactos/reactos.git
synced 2024-12-30 19:14:31 +00:00
sync msi with wine 1.1.21
svn path=/trunk/; revision=41016
This commit is contained in:
parent
e0cba65fdf
commit
7d1a590941
40 changed files with 3155 additions and 1807 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
37
reactos/dll/win32/msi/msi_Ro.rc
Normal file
37
reactos/dll/win32/msi/msi_Ro.rc
Normal 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)
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ typedef int INSTALLMESSAGE;
|
|||
typedef int MSICONDITION;
|
||||
typedef int MSIRUNMODE;
|
||||
typedef int INSTALLSTATE;
|
||||
typedef WORD LANGID;
|
||||
cpp_quote("#endif")
|
||||
|
||||
[
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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( <, 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, <, &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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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 == '`' )
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue