Author: akhaldi
Date: Mon Mar 9 20:28:19 2015
New Revision: 66632
URL:
http://svn.reactos.org/svn/reactos?rev=66632&view=rev
Log:
[MSI] Sync with Wine Staging 1.7.37. CORE-9246
Modified:
trunk/reactos/dll/win32/msi/action.c
trunk/reactos/dll/win32/msi/assembly.c
trunk/reactos/dll/win32/msi/database.c
trunk/reactos/dll/win32/msi/dialog.c
trunk/reactos/dll/win32/msi/media.c
trunk/reactos/dll/win32/msi/msi.c
trunk/reactos/dll/win32/msi/msi.rc
trunk/reactos/dll/win32/msi/msi.spec
trunk/reactos/dll/win32/msi/msipriv.h
trunk/reactos/dll/win32/msi/msiquery.c
trunk/reactos/dll/win32/msi/package.c
trunk/reactos/dll/win32/msi/patch.c
trunk/reactos/dll/win32/msi/registry.c
trunk/reactos/dll/win32/msi/script.c
trunk/reactos/dll/win32/msi/storages.c
trunk/reactos/dll/win32/msi/streams.c
trunk/reactos/dll/win32/msi/string.c
trunk/reactos/dll/win32/msi/table.c
trunk/reactos/media/doc/README.WINE
Modified: trunk/reactos/dll/win32/msi/action.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/action.c?rev…
==============================================================================
--- trunk/reactos/dll/win32/msi/action.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/action.c [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -2407,7 +2407,6 @@
sprintfW( buf, fmtW, free.QuadPart / 512 );
msi_set_property( package->db, szPrimaryVolumeSpaceAvailable, buf,
-1 );
}
- toupperW( primary_folder[0] );
msi_set_property( package->db, szPrimaryVolumePath, primary_folder, 2
);
}
msi_free( primary_folder );
@@ -2422,9 +2421,9 @@
return MSI_SetFeatureStates(package);
}
-static BYTE *parse_value( MSIPACKAGE *package, const WCHAR *value, DWORD *type, DWORD
*size )
-{
- BYTE *data = NULL;
+static BYTE *parse_value( MSIPACKAGE *package, const WCHAR *value, DWORD len, DWORD
*type, DWORD *size )
+{
+ BYTE *data;
if (!value)
{
@@ -2513,19 +2512,18 @@
else
{
const WCHAR *ptr = value;
- DWORD len;
*type = REG_SZ;
if (value[0] == '#')
{
- ptr++;
+ ptr++; len--;
if (value[1] == '%')
{
- ptr++;
+ ptr++; len--;
*type = REG_EXPAND_SZ;
}
}
- len = deformat_string( package, ptr, (WCHAR **)&data );
+ data = (BYTE *)msi_strdupW( ptr, len );
if (len > strlenW( (const WCHAR *)data )) *type = REG_MULTI_SZ;
*size = (len + 1) * sizeof(WCHAR);
}
@@ -2574,38 +2572,22 @@
return ret;
}
-static WCHAR *get_keypath( MSICOMPONENT *comp, HKEY root, const WCHAR *path )
-{
- static const WCHAR prefixW[] =
{'S','O','F','T','W','A','R','E','\\'};
- static const UINT len = sizeof(prefixW) / sizeof(prefixW[0]);
-
- if ((is_64bit || is_wow64) &&
- !(comp->Attributes & msidbComponentAttributes64bit) &&
- root == HKEY_LOCAL_MACHINE && !strncmpiW( path, prefixW, len ))
- {
- UINT size;
- WCHAR *path_32node;
-
- size = (strlenW( path ) + strlenW( szWow6432Node ) + 2) * sizeof(WCHAR);
- if (!(path_32node = msi_alloc( size ))) return NULL;
-
- memcpy( path_32node, path, len * sizeof(WCHAR) );
- strcpyW( path_32node + len, szWow6432Node );
- strcatW( path_32node, szBackSlash );
- strcatW( path_32node, path + len );
- return path_32node;
- }
- return strdupW( path );
-}
-
-static HKEY open_key( HKEY root, const WCHAR *path, BOOL create )
+static inline REGSAM get_registry_view( const MSICOMPONENT *comp )
+{
+ REGSAM view = 0;
+ if (is_wow64 || is_64bit)
+ view |= (comp->Attributes & msidbComponentAttributes64bit) ?
KEY_WOW64_64KEY : KEY_WOW64_32KEY;
+ return view;
+}
+
+static HKEY open_key( const MSICOMPONENT *comp, HKEY root, const WCHAR *path, BOOL create
)
{
REGSAM access = KEY_ALL_ACCESS;
WCHAR *subkey, *p, *q;
HKEY hkey, ret = NULL;
LONG res;
- if (is_wow64) access |= KEY_WOW64_64KEY;
+ access |= get_registry_view( comp );
if (!(subkey = strdupW( path ))) return NULL;
p = subkey;
@@ -2622,7 +2604,7 @@
}
if (q && q[1])
{
- ret = open_key( hkey, q + 1, create );
+ ret = open_key( comp, hkey, q + 1, create );
RegCloseKey( hkey );
}
else ret = hkey;
@@ -2803,7 +2785,7 @@
BYTE *new_value, *old_value = NULL;
HKEY root_key, hkey;
DWORD type, old_type, new_size, old_size = 0;
- LPWSTR deformated, uikey, keypath;
+ LPWSTR deformated, uikey;
const WCHAR *szRoot, *component, *name, *key, *str;
MSICOMPONENT *comp;
MSIRECORD * uirow;
@@ -2847,23 +2829,19 @@
strcpyW(uikey,szRoot);
strcatW(uikey,deformated);
- keypath = get_keypath( comp, root_key, deformated );
+ if (!(hkey = open_key( comp, root_key, deformated, TRUE )))
+ {
+ ERR("Could not create key %s\n", debugstr_w(deformated));
+ msi_free(uikey);
+ msi_free(deformated);
+ return ERROR_FUNCTION_FAILED;
+ }
msi_free( deformated );
- if (!(hkey = open_key( root_key, keypath, TRUE )))
- {
- ERR("Could not create key %s\n", debugstr_w(keypath));
- msi_free(uikey);
- msi_free(keypath);
- return ERROR_FUNCTION_FAILED;
- }
- str = msi_record_get_string( row, 5, &len );
- if (str && len > strlenW( str ))
- {
- type = REG_MULTI_SZ;
- new_size = (len + 1) * sizeof(WCHAR);
- new_value = (BYTE *)msi_strdupW( str, len );
- }
- else new_value = parse_value( package, str, &type, &new_size );
+ str = msi_record_get_string( row, 5, NULL );
+ len = deformat_string( package, str, &deformated );
+ new_value = parse_value( package, deformated, len, &type, &new_size );
+
+ msi_free( deformated );
deformat_string(package, name, &deformated);
if (!is_special_entry( name ))
@@ -2911,7 +2889,6 @@
msi_free(old_value);
msi_free(deformated);
msi_free(uikey);
- msi_free(keypath);
return ERROR_SUCCESS;
}
@@ -2933,20 +2910,20 @@
return rc;
}
-static void delete_key( HKEY root, const WCHAR *path )
+static void delete_key( const MSICOMPONENT *comp, HKEY root, const WCHAR *path )
{
REGSAM access = 0;
WCHAR *subkey, *p;
HKEY hkey;
LONG res;
- if (is_wow64) access |= KEY_WOW64_64KEY;
+ access |= get_registry_view( comp );
if (!(subkey = strdupW( path ))) return;
for (;;)
{
if ((p = strrchrW( subkey, '\\' ))) *p = 0;
- hkey = open_key( root, subkey, FALSE );
+ hkey = open_key( comp, root, subkey, FALSE );
if (!hkey) break;
if (p && p[1])
res = RegDeleteKeyExW( hkey, p + 1, access, 0 );
@@ -2963,13 +2940,13 @@
msi_free( subkey );
}
-static void delete_value( HKEY root, const WCHAR *path, const WCHAR *value )
+static void delete_value( const MSICOMPONENT *comp, HKEY root, const WCHAR *path, const
WCHAR *value )
{
LONG res;
HKEY hkey;
DWORD num_subkeys, num_values;
- if ((hkey = open_key( root, path, FALSE )))
+ if ((hkey = open_key( comp, root, path, FALSE )))
{
if ((res = RegDeleteValueW( hkey, value )))
TRACE("failed to delete value %s (%d)\n", debugstr_w(value), res);
@@ -2980,20 +2957,20 @@
if (!res && !num_subkeys && !num_values)
{
TRACE("removing empty key %s\n", debugstr_w(path));
- delete_key( root, path );
- }
- }
-}
-
-static void delete_tree( HKEY root, const WCHAR *path )
+ delete_key( comp, root, path );
+ }
+ }
+}
+
+static void delete_tree( const MSICOMPONENT *comp, HKEY root, const WCHAR *path )
{
LONG res;
HKEY hkey;
- if (!(hkey = open_key( root, path, FALSE ))) return;
+ if (!(hkey = open_key( comp, root, path, FALSE ))) return;
res = SHDeleteKeyW( hkey, NULL );
if (res) TRACE("failed to delete subtree of %s (%d)\n", debugstr_w(path),
res);
- delete_key( root, path );
+ delete_key( comp, root, path );
RegCloseKey( hkey );
}
@@ -3001,7 +2978,7 @@
{
MSIPACKAGE *package = param;
LPCWSTR component, name, key_str, root_key_str;
- LPWSTR deformated_key, deformated_name, ui_key_str, keypath;
+ LPWSTR deformated_key, deformated_name, ui_key_str;
MSICOMPONENT *comp;
MSIRECORD *uirow;
BOOL delete_key = FALSE;
@@ -3050,11 +3027,9 @@
deformat_string( package, name, &deformated_name );
- keypath = get_keypath( comp, hkey_root, deformated_key );
+ if (delete_key) delete_tree( comp, hkey_root, deformated_key );
+ else delete_value( comp, hkey_root, deformated_key, deformated_name );
msi_free( deformated_key );
- if (delete_key) delete_tree( hkey_root, keypath );
- else delete_value( hkey_root, keypath, deformated_name );
- msi_free( keypath );
uirow = MSI_CreateRecord( 2 );
MSI_RecordSetStringW( uirow, 1, ui_key_str );
@@ -3071,7 +3046,7 @@
{
MSIPACKAGE *package = param;
LPCWSTR component, name, key_str, root_key_str;
- LPWSTR deformated_key, deformated_name, ui_key_str, keypath;
+ LPWSTR deformated_key, deformated_name, ui_key_str;
MSICOMPONENT *comp;
MSIRECORD *uirow;
BOOL delete_key = FALSE;
@@ -3115,11 +3090,9 @@
deformat_string( package, name, &deformated_name );
- keypath = get_keypath( comp, hkey_root, deformated_key );
+ if (delete_key) delete_tree( comp, hkey_root, deformated_key );
+ else delete_value( comp, hkey_root, deformated_key, deformated_name );
msi_free( deformated_key );
- if (delete_key) delete_tree( hkey_root, keypath );
- else delete_value( hkey_root, keypath, deformated_name );
- msi_free( keypath );
uirow = MSI_CreateRecord( 2 );
MSI_RecordSetStringW( uirow, 1, ui_key_str );
@@ -5300,7 +5273,7 @@
WCHAR *remove;
/* first do the same as an InstallExecute */
- rc = ACTION_InstallExecute(package);
+ rc = execute_script(package, SCRIPT_INSTALL);
if (rc != ERROR_SUCCESS)
return rc;
@@ -5940,23 +5913,20 @@
if (!comp)
return ERROR_SUCCESS;
+ event = MSI_RecordGetInteger( rec, 3 );
+ deformat_string( package, MSI_RecordGetString( rec, 2 ), &name );
+
comp->Action = msi_get_component_action( package, comp );
- if (comp->Action != INSTALLSTATE_LOCAL)
- {
- TRACE("component not scheduled for installation %s\n",
debugstr_w(component));
- return ERROR_SUCCESS;
- }
-
- deformat_string(package, MSI_RecordGetString(rec, 2), &name);
+ if (!(comp->Action == INSTALLSTATE_LOCAL && (event &
msidbServiceControlEventStart)) &&
+ !(comp->Action == INSTALLSTATE_ABSENT && (event &
msidbServiceControlEventUninstallStart)))
+ {
+ TRACE("not starting %s\n", debugstr_w(name));
+ msi_free( name );
+ return ERROR_SUCCESS;
+ }
+
deformat_string(package, MSI_RecordGetString(rec, 4), &args);
- event = MSI_RecordGetInteger(rec, 3);
wait = MSI_RecordGetInteger(rec, 5);
-
- if (!(event & msidbServiceControlEventStart))
- {
- r = ERROR_SUCCESS;
- goto done;
- }
scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
if (!scm)
@@ -6147,23 +6117,24 @@
MSICOMPONENT *comp;
MSIRECORD *uirow;
LPCWSTR component;
- LPWSTR name = NULL, display_name = NULL;
+ WCHAR *name, *display_name = NULL;
DWORD event, len;
SC_HANDLE scm;
-
- event = MSI_RecordGetInteger( rec, 3 );
- if (!(event & msidbServiceControlEventStop))
- return ERROR_SUCCESS;
component = MSI_RecordGetString( rec, 6 );
comp = msi_get_loaded_component( package, component );
if (!comp)
return ERROR_SUCCESS;
+ event = MSI_RecordGetInteger( rec, 3 );
+ deformat_string( package, MSI_RecordGetString( rec, 2 ), &name );
+
comp->Action = msi_get_component_action( package, comp );
- if (comp->Action != INSTALLSTATE_ABSENT)
- {
- TRACE("component not scheduled for removal %s\n",
debugstr_w(component));
+ if (!(comp->Action == INSTALLSTATE_LOCAL && (event &
msidbServiceControlEventStop)) &&
+ !(comp->Action == INSTALLSTATE_ABSENT && (event &
msidbServiceControlEventUninstallStop)))
+ {
+ TRACE("not stopping %s\n", debugstr_w(name));
+ msi_free( name );
return ERROR_SUCCESS;
}
@@ -6183,7 +6154,6 @@
}
CloseServiceHandle( scm );
- deformat_string( package, MSI_RecordGetString( rec, 2 ), &name );
stop_service( name );
done:
@@ -6982,6 +6952,7 @@
data = msi_alloc(size);
if (!data)
{
+ msi_free(deformatted);
RegCloseKey(env);
return ERROR_OUTOFMEMORY;
}
@@ -7801,10 +7772,7 @@
package->full_reinstall = 1;
}
- /* properties may have been added by a transform */
- msi_clone_properties( package );
msi_set_original_database_property( package->db, szPackagePath );
-
msi_parse_command_line( package, szCommandLine, FALSE );
msi_adjust_privilege_properties( package );
msi_set_context( package );
Modified: trunk/reactos/dll/win32/msi/assembly.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/assembly.c?r…
==============================================================================
--- trunk/reactos/dll/win32/msi/assembly.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/assembly.c [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -242,7 +242,7 @@
memset( &info, 0, sizeof(info) );
info.cbAssemblyInfo = sizeof(info);
hr = IAssemblyCache_QueryAssemblyInfo( cache, 0, display_name, &info );
- if (hr == S_OK /* sxs version */ || hr == HRESULT_FROM_WIN32(
ERROR_INSUFFICIENT_BUFFER ))
+ if (hr == S_OK /* sxs version */ || hr == E_NOT_SUFFICIENT_BUFFER)
{
return (info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED);
}
@@ -348,7 +348,7 @@
if (!pGetFileVersion) return CLR_VERSION_V10;
hr = pGetFileVersion( filename, NULL, 0, &len );
- if (hr != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) return CLR_VERSION_V11;
+ if (hr != E_NOT_SUFFICIENT_BUFFER) return CLR_VERSION_V11;
if ((strW = msi_alloc( len * sizeof(WCHAR) )))
{
hr = pGetFileVersion( filename, strW, len, &len );
Modified: trunk/reactos/dll/win32/msi/database.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/database.c?r…
==============================================================================
--- trunk/reactos/dll/win32/msi/database.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/database.c [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -36,179 +36,25 @@
#define IS_INTMSIDBOPEN(x) (((ULONG_PTR)(x) >> 16) == 0)
-typedef struct tagMSITRANSFORM {
- struct list entry;
- IStorage *stg;
-} MSITRANSFORM;
-
-typedef struct tagMSISTREAM {
- struct list entry;
- IStorage *stg;
- IStream *stm;
-} MSISTREAM;
-
-static UINT find_open_stream( MSIDATABASE *db, IStorage *stg, LPCWSTR name, IStream **stm
)
-{
- MSISTREAM *stream;
-
- LIST_FOR_EACH_ENTRY( stream, &db->streams, MSISTREAM, entry )
- {
- HRESULT r;
- STATSTG stat;
-
- if (stream->stg != stg) continue;
-
- r = IStream_Stat( stream->stm, &stat, 0 );
- if( FAILED( r ) )
- {
- WARN("failed to stat stream r = %08x!\n", r);
- continue;
- }
-
- if( !strcmpW( name, stat.pwcsName ) )
- {
- TRACE("found %s\n", debugstr_w(name));
- *stm = stream->stm;
- CoTaskMemFree( stat.pwcsName );
- return ERROR_SUCCESS;
- }
-
- CoTaskMemFree( stat.pwcsName );
- }
-
- return ERROR_FUNCTION_FAILED;
-}
-
-UINT msi_clone_open_stream( MSIDATABASE *db, IStorage *stg, LPCWSTR name, IStream **stm
)
-{
- IStream *stream;
-
- if (find_open_stream( db, stg, name, &stream ) == ERROR_SUCCESS)
- {
- HRESULT r;
- LARGE_INTEGER pos;
-
- r = IStream_Clone( stream, stm );
- if( FAILED( r ) )
- {
- WARN("failed to clone stream r = %08x!\n", r);
- return ERROR_FUNCTION_FAILED;
- }
-
- pos.QuadPart = 0;
- r = IStream_Seek( *stm, pos, STREAM_SEEK_SET, NULL );
- if( FAILED( r ) )
- {
- IStream_Release( *stm );
- return ERROR_FUNCTION_FAILED;
- }
-
- return ERROR_SUCCESS;
- }
-
- return ERROR_FUNCTION_FAILED;
-}
-
-UINT msi_get_raw_stream( MSIDATABASE *db, LPCWSTR stname, IStream **stm )
-{
- HRESULT r;
- IStorage *stg;
- WCHAR decoded[MAX_STREAM_NAME_LEN + 1];
-
- decode_streamname( stname, decoded );
- TRACE("%s -> %s\n", debugstr_w(stname), debugstr_w(decoded));
-
- if (msi_clone_open_stream( db, db->storage, stname, stm ) == ERROR_SUCCESS)
- return ERROR_SUCCESS;
-
- r = IStorage_OpenStream( db->storage, stname, NULL,
- STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm );
- if( FAILED( r ) )
- {
- MSITRANSFORM *transform;
-
- LIST_FOR_EACH_ENTRY( transform, &db->transforms, MSITRANSFORM, entry )
- {
- r = IStorage_OpenStream( transform->stg, stname, NULL,
- STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm );
- if (SUCCEEDED(r))
- {
- stg = transform->stg;
- break;
- }
- }
- }
- else stg = db->storage;
-
- if( SUCCEEDED(r) )
- {
- MSISTREAM *stream;
-
- if (!(stream = msi_alloc( sizeof(MSISTREAM) ))) return ERROR_NOT_ENOUGH_MEMORY;
- stream->stg = stg;
- IStorage_AddRef( stg );
- stream->stm = *stm;
- IStream_AddRef( *stm );
- list_add_tail( &db->streams, &stream->entry );
- }
-
- return SUCCEEDED(r) ? ERROR_SUCCESS : ERROR_FUNCTION_FAILED;
-}
-
static void free_transforms( MSIDATABASE *db )
{
while( !list_empty( &db->transforms ) )
{
- MSITRANSFORM *t = LIST_ENTRY( list_head( &db->transforms ),
- MSITRANSFORM, entry );
+ MSITRANSFORM *t = LIST_ENTRY( list_head( &db->transforms ), MSITRANSFORM,
entry );
list_remove( &t->entry );
IStorage_Release( t->stg );
msi_free( t );
}
}
-void msi_destroy_stream( MSIDATABASE *db, const WCHAR *stname )
-{
- MSISTREAM *stream, *stream2;
-
- LIST_FOR_EACH_ENTRY_SAFE( stream, stream2, &db->streams, MSISTREAM, entry )
- {
- HRESULT r;
- STATSTG stat;
-
- r = IStream_Stat( stream->stm, &stat, 0 );
- if (FAILED(r))
- {
- WARN("failed to stat stream r = %08x\n", r);
- continue;
- }
-
- if (!strcmpW( stname, stat.pwcsName ))
- {
- TRACE("destroying %s\n", debugstr_w(stname));
-
- list_remove( &stream->entry );
- IStream_Release( stream->stm );
- IStorage_Release( stream->stg );
- IStorage_DestroyElement( stream->stg, stname );
- msi_free( stream );
- CoTaskMemFree( stat.pwcsName );
- break;
- }
- CoTaskMemFree( stat.pwcsName );
- }
-}
-
static void free_streams( MSIDATABASE *db )
{
- while( !list_empty( &db->streams ) )
- {
- MSISTREAM *s = LIST_ENTRY(list_head( &db->streams ), MSISTREAM, entry);
- list_remove( &s->entry );
- IStream_Release( s->stm );
- IStorage_Release( s->stg );
- msi_free( s );
- }
+ UINT i;
+ for (i = 0; i < db->num_streams; i++)
+ {
+ if (db->streams[i].stream) IStream_Release( db->streams[i].stream );
+ }
+ msi_free( db->streams );
}
void append_storage_to_db( MSIDATABASE *db, IStorage *stg )
@@ -219,18 +65,15 @@
t->stg = stg;
IStorage_AddRef( stg );
list_add_head( &db->transforms, &t->entry );
-
- /* the transform may add or replace streams */
+}
+
+static VOID MSI_CloseDatabase( MSIOBJECTHDR *arg )
+{
+ MSIDATABASE *db = (MSIDATABASE *) arg;
+
+ msi_free(db->path);
free_streams( db );
-}
-
-static VOID MSI_CloseDatabase( MSIOBJECTHDR *arg )
-{
- MSIDATABASE *db = (MSIDATABASE *) arg;
-
- msi_free(db->path);
free_cached_tables( db );
- free_streams( db );
free_transforms( db );
if (db->strings) msi_destroy_stringtable( db->strings );
IStorage_Release( db->storage );
@@ -413,7 +256,6 @@
db->deletefile = strdupW( szDBPath );
list_init( &db->tables );
list_init( &db->transforms );
- list_init( &db->streams );
db->strings = msi_load_string_table( stg, &db->bytes_per_strref );
if( !db->strings )
Modified: trunk/reactos/dll/win32/msi/dialog.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/dialog.c?rev…
==============================================================================
--- trunk/reactos/dll/win32/msi/dialog.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/dialog.c [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -135,7 +135,6 @@
static const WCHAR szVolumeSelectCombo[] = {
'V','o','l','u','m','e','S','e','l','e','c','t','C','o','m','b','o',0
};
static const WCHAR szSelectionDescription[] =
{'S','e','l','e','c','t','i','o','n','D','e','s','c','r','i','p','t','i','o','n',0};
static const WCHAR szSelectionPath[] =
{'S','e','l','e','c','t','i','o','n','P','a','t','h',0};
-static const WCHAR szProperty[] =
{'P','r','o','p','e','r','t','y',0};
static const WCHAR szHyperLink[] =
{'H','y','p','e','r','L','i','n','k',0};
/* dialog sequencing */
@@ -2152,7 +2151,7 @@
/* FIXME: test when this should fail */
static BOOL msi_dialog_verify_path( LPWSTR path )
{
- if ( !lstrlenW( path ) )
+ if ( !path[0] )
return FALSE;
if ( PathIsRelativeW( path ) )
Modified: trunk/reactos/dll/win32/msi/media.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/media.c?rev=…
==============================================================================
--- trunk/reactos/dll/win32/msi/media.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/media.c [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -216,15 +216,12 @@
WARN("failed to encode stream name\n");
return -1;
}
- if (msi_clone_open_stream( package_disk.package->db, cab->storage, encoded,
&stream ) != ERROR_SUCCESS)
- {
- hr = IStorage_OpenStream( cab->storage, encoded, NULL,
STGM_READ|STGM_SHARE_EXCLUSIVE, 0, &stream );
- if (FAILED(hr))
- {
- WARN("failed to open stream 0x%08x\n", hr);
- msi_free( encoded );
- return -1;
- }
+ hr = IStorage_OpenStream( cab->storage, encoded, NULL,
STGM_READ|STGM_SHARE_EXCLUSIVE, 0, &stream );
+ if (FAILED(hr))
+ {
+ WARN("failed to open stream 0x%08x\n", hr);
+ msi_free( encoded );
+ return -1;
}
msi_free( encoded );
return (INT_PTR)stream;
@@ -286,9 +283,6 @@
mi->disk_prompt = strdupW(MSI_RecordGetString(row, 3));
mi->cabinet = strdupW(MSI_RecordGetString(row, 4));
mi->volume_label = strdupW(MSI_RecordGetString(row, 5));
-
- if (!mi->first_volume)
- mi->first_volume = strdupW(mi->volume_label);
msiobj_release(&row->hdr);
return ERROR_SUCCESS;
@@ -662,7 +656,6 @@
msi_free(mi->disk_prompt);
msi_free(mi->cabinet);
msi_free(mi->volume_label);
- msi_free(mi->first_volume);
msi_free(mi);
}
@@ -707,9 +700,6 @@
msi_free(mi->volume_label);
mi->volume_label = strdupW(MSI_RecordGetString(row, 5));
msiobj_release(&row->hdr);
-
- if (!mi->first_volume)
- mi->first_volume = strdupW(mi->volume_label);
msi_set_sourcedir_props(package, FALSE);
source_dir = msi_dup_property(package->db, szSourceDir);
@@ -880,7 +870,7 @@
}
}
/* check volume matches, change media if not */
- if (mi->volume_label && mi->disk_id > 1 && strcmpW(
mi->first_volume, mi->volume_label ))
+ if (mi->volume_label && mi->disk_id > 1)
{
WCHAR *source = msi_dup_property( package->db, szSourceDir );
BOOL match = source_matches_volume( mi, source );
Modified: trunk/reactos/dll/win32/msi/msi.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/msi.c?rev=66…
==============================================================================
--- trunk/reactos/dll/win32/msi/msi.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/msi.c [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -1737,10 +1737,6 @@
{
datakey = patch;
szProperty = szInstalled;
- }
- else if (!strcmpW( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ))
- {
- datakey = udpatch;
}
else if (!strcmpW( szProperty, INSTALLPROPERTY_UNINSTALLABLEW ) ||
!strcmpW( szProperty, INSTALLPROPERTY_PATCHSTATEW ) ||
@@ -4178,6 +4174,92 @@
return ERROR_SUCCESS;
}
+UINT WINAPI MsiProvideComponentA( LPCSTR product, LPCSTR feature, LPCSTR component, DWORD
mode, LPSTR buf, LPDWORD buflen )
+{
+ WCHAR *productW = NULL, *componentW = NULL, *featureW = NULL, *bufW = NULL;
+ UINT r = ERROR_OUTOFMEMORY;
+ DWORD lenW;
+ int len;
+
+ TRACE("%s, %s, %s, %x, %p, %p\n", debugstr_a(product),
debugstr_a(component), debugstr_a(feature), mode, buf, buflen);
+
+ if (product && !(productW = strdupAtoW( product ))) goto done;
+ if (feature && !(featureW = strdupAtoW( feature ))) goto done;
+ if (component && !(componentW = strdupAtoW( component ))) goto done;
+
+ r = MsiProvideComponentW( productW, featureW, componentW, mode, NULL, &lenW );
+ if (r != ERROR_SUCCESS)
+ goto done;
+
+ if (!(bufW = msi_alloc( ++lenW * sizeof(WCHAR) )))
+ {
+ r = ERROR_OUTOFMEMORY;
+ goto done;
+ }
+
+ r = MsiProvideComponentW( productW, featureW, componentW, mode, bufW, &lenW );
+ if (r != ERROR_SUCCESS)
+ goto done;
+
+ len = WideCharToMultiByte( CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
+ if (buf)
+ {
+ if (len > *buflen)
+ r = ERROR_MORE_DATA;
+ else
+ WideCharToMultiByte( CP_ACP, 0, bufW, -1, buf, *buflen, NULL, NULL );
+ }
+
+ *buflen = len - 1;
+
+done:
+ msi_free( productW );
+ msi_free( featureW );
+ msi_free( componentW );
+ msi_free( bufW );
+ return r;
+}
+
+UINT WINAPI MsiProvideComponentW( LPCWSTR product, LPCWSTR feature, LPCWSTR component,
DWORD mode, LPWSTR buf, LPDWORD buflen )
+{
+ INSTALLSTATE state;
+
+ TRACE("%s, %s, %s, %x, %p, %p\n", debugstr_w(product),
debugstr_w(component), debugstr_w(feature), mode, buf, buflen);
+
+ state = MsiQueryFeatureStateW( product, feature );
+ TRACE("feature state: %d\n", state);
+ switch (mode)
+ {
+ case INSTALLMODE_NODETECTION:
+ break;
+
+ default:
+ FIXME("mode %x not implemented\n", mode);
+ return ERROR_INSTALL_FAILURE;
+ }
+
+ state = MsiGetComponentPathW( product, component, buf, buflen );
+ TRACE("component state: %d\n", state);
+ switch (state)
+ {
+ case INSTALLSTATE_INVALIDARG:
+ return ERROR_INVALID_PARAMETER;
+
+ case INSTALLSTATE_MOREDATA:
+ return ERROR_MORE_DATA;
+
+ case INSTALLSTATE_ADVERTISED:
+ case INSTALLSTATE_LOCAL:
+ case INSTALLSTATE_SOURCE:
+ MsiUseFeatureW( product, feature );
+ return ERROR_SUCCESS;
+
+ default:
+ TRACE("MsiGetComponentPathW returned %d\n", state);
+ return ERROR_INSTALL_FAILURE;
+ }
+}
+
/***********************************************************************
* MsiBeginTransactionA [MSI.@]
*/
@@ -4224,3 +4306,21 @@
FIXME("%p,%p,%p,%08x\n", a, b, c, d);
return ERROR_SUCCESS;
}
+
+/***********************************************************************
+ * MsiRemovePatchesA [MSI.@]
+ */
+UINT WINAPI MsiRemovePatchesA(LPCSTR patchlist, LPCSTR product, INSTALLTYPE type, LPCSTR
propertylist)
+{
+ FIXME("(%s %s %d %s\n", debugstr_a(patchlist), debugstr_a(product), type,
debugstr_a(propertylist));
+ return ERROR_SUCCESS;
+}
+
+/***********************************************************************
+ * MsiRemovePatchesW [MSI.@]
+ */
+UINT WINAPI MsiRemovePatchesW(LPCWSTR patchlist, LPCWSTR product, INSTALLTYPE type,
LPCWSTR propertylist)
+{
+ FIXME("(%s %s %d %s\n", debugstr_w(patchlist), debugstr_w(product), type,
debugstr_w(propertylist));
+ return ERROR_SUCCESS;
+}
Modified: trunk/reactos/dll/win32/msi/msi.rc
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/msi.rc?rev=6…
==============================================================================
--- trunk/reactos/dll/win32/msi/msi.rc [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/msi.rc [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -84,9 +84,9 @@
#define WINE_FILEDESCRIPTION_STR "Wine MSI dll"
#define WINE_FILENAME_STR "msi.dll"
-#define WINE_FILEVERSION 4,5,6001,22299
-#define WINE_FILEVERSION_STR "4.5.6001.22299"
-#define WINE_PRODUCTVERSION 4,5,6001,22299
-#define WINE_PRODUCTVERSION_STR "4.5.6001.22299"
+#define WINE_FILEVERSION 4,5,6001,22308
+#define WINE_FILEVERSION_STR "4.5.6001.22308"
+#define WINE_PRODUCTVERSION 4,5,6001,22308
+#define WINE_PRODUCTVERSION_STR "4.5.6001.22308"
#include <wine/wine_common_ver.rc>
Modified: trunk/reactos/dll/win32/msi/msi.spec
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/msi.spec?rev…
==============================================================================
--- trunk/reactos/dll/win32/msi/msi.spec [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/msi.spec [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -97,10 +97,10 @@
101 stub MsiProcessAdvertiseScriptA
102 stub MsiProcessAdvertiseScriptW
103 stdcall MsiProcessMessage(long long long)
-104 stub MsiProvideComponentA
+104 stdcall MsiProvideComponentA(str str str long ptr ptr)
105 stdcall MsiProvideComponentFromDescriptorA(str ptr ptr ptr)
106 stdcall MsiProvideComponentFromDescriptorW(wstr ptr ptr ptr)
-107 stub MsiProvideComponentW
+107 stdcall MsiProvideComponentW(wstr wstr wstr long ptr ptr)
108 stdcall MsiProvideQualifiedComponentA(str str long ptr ptr)
109 stdcall MsiProvideQualifiedComponentW(wstr wstr long ptr ptr)
110 stdcall MsiQueryFeatureStateA(str str)
@@ -230,8 +230,8 @@
234 stub MsiDeleteUserDataW
235 stub Migrate10CachedPackagesA
236 stdcall Migrate10CachedPackagesW(ptr ptr ptr long)
-237 stub MsiRemovePatchesA
-238 stub MsiRemovePatchesW
+237 stdcall MsiRemovePatchesA(str str long str)
+238 stdcall MsiRemovePatchesW(wstr wstr long wstr)
239 stdcall MsiApplyMultiplePatchesA(str str str)
240 stdcall MsiApplyMultiplePatchesW(wstr wstr wstr)
241 stub MsiExtractPatchXMLDataA
@@ -281,9 +281,16 @@
285 stdcall MsiBeginTransactionW(wstr long ptr ptr)
286 stdcall MsiEndTransaction(long)
287 stub MsiJoinTransaction
-288 stub QueryInstanceCount
+288 stub MsiSetOfflineContextW
+289 stdcall MsiEnumComponentsExA(str long long ptr ptr ptr ptr)
+290 stdcall MsiEnumComponentsExW(wstr long long ptr ptr ptr ptr)
+291 stdcall MsiEnumClientsExA(str str long long ptr ptr ptr ptr)
+292 stdcall MsiEnumClientsExW(wstr wstr long long ptr ptr ptr ptr)
+293 stub MsiGetComponentPathExA
+294 stub MsiGetComponentPathExW
+295 stub QueryInstanceCount
+
@ stdcall -private DllCanUnloadNow()
@ stdcall -private DllGetClassObject(ptr ptr ptr)
@ stdcall -private DllRegisterServer()
@ stdcall -private DllUnregisterServer()
-
Modified: trunk/reactos/dll/win32/msi/msipriv.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/msipriv.h?re…
==============================================================================
--- trunk/reactos/dll/win32/msi/msipriv.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/msipriv.h [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -94,6 +94,18 @@
#define MSI_INITIAL_MEDIA_TRANSFORM_OFFSET 10000
#define MSI_INITIAL_MEDIA_TRANSFORM_DISKID 30000
+typedef struct tagMSISTREAM
+{
+ UINT str_index;
+ IStream *stream;
+} MSISTREAM;
+
+typedef struct tagMSITRANSFORM
+{
+ struct list entry;
+ IStorage *stg;
+} MSITRANSFORM;
+
typedef struct tagMSIDATABASE
{
MSIOBJECTHDR hdr;
@@ -107,7 +119,9 @@
UINT media_transform_disk_id;
struct list tables;
struct list transforms;
- struct list streams;
+ MSISTREAM *streams;
+ UINT num_streams;
+ UINT num_streams_allocated;
} MSIDATABASE;
typedef struct tagMSIVIEW MSIVIEW;
@@ -168,7 +182,6 @@
UINT last_sequence;
LPWSTR disk_prompt;
LPWSTR cabinet;
- LPWSTR first_volume;
LPWSTR volume_label;
BOOL is_continuous;
BOOL is_extracted;
@@ -757,6 +770,7 @@
extern void free_cached_tables( MSIDATABASE *db ) DECLSPEC_HIDDEN;
extern UINT MSI_CommitTables( MSIDATABASE *db ) DECLSPEC_HIDDEN;
+extern UINT msi_commit_streams( MSIDATABASE *db ) DECLSPEC_HIDDEN;
/* string table functions */
@@ -766,7 +780,7 @@
StringNonPersistent = 1
};
-extern BOOL msi_addstringW( string_table *st, const WCHAR *data, int len, USHORT
refcount, enum StringPersistence persistence ) DECLSPEC_HIDDEN;
+extern BOOL msi_add_string( string_table *st, const WCHAR *data, int len, enum
StringPersistence persistence ) DECLSPEC_HIDDEN;
extern UINT msi_string2id( const string_table *st, const WCHAR *data, int len, UINT *id )
DECLSPEC_HIDDEN;
extern VOID msi_destroy_stringtable( string_table *st ) DECLSPEC_HIDDEN;
extern const WCHAR *msi_string_lookup( const string_table *st, UINT id, int *len )
DECLSPEC_HIDDEN;
@@ -844,9 +858,7 @@
extern BOOL decode_streamname(LPCWSTR in, LPWSTR out) DECLSPEC_HIDDEN;
/* database internals */
-extern UINT msi_get_raw_stream( MSIDATABASE *, LPCWSTR, IStream ** ) DECLSPEC_HIDDEN;
-extern UINT msi_clone_open_stream( MSIDATABASE *, IStorage *, const WCHAR *, IStream ** )
DECLSPEC_HIDDEN;
-void msi_destroy_stream( MSIDATABASE *, const WCHAR * ) DECLSPEC_HIDDEN;
+extern UINT msi_get_stream( MSIDATABASE *, const WCHAR *, IStream ** ) DECLSPEC_HIDDEN;
extern UINT MSI_OpenDatabaseW( LPCWSTR, LPCWSTR, MSIDATABASE ** ) DECLSPEC_HIDDEN;
extern UINT MSI_DatabaseOpenViewW(MSIDATABASE *, LPCWSTR, MSIQUERY ** ) DECLSPEC_HIDDEN;
extern UINT MSI_OpenQuery( MSIDATABASE *, MSIQUERY **, LPCWSTR, ... ) DECLSPEC_HIDDEN;
@@ -879,7 +891,7 @@
extern UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename ) DECLSPEC_HIDDEN;
extern UINT msi_package_add_info(MSIPACKAGE *, DWORD, DWORD, LPCWSTR, LPWSTR)
DECLSPEC_HIDDEN;
extern UINT msi_package_add_media_disk(MSIPACKAGE *, DWORD, DWORD, DWORD, LPWSTR, LPWSTR)
DECLSPEC_HIDDEN;
-extern UINT msi_clone_properties(MSIPACKAGE *) DECLSPEC_HIDDEN;
+extern UINT msi_clone_properties(MSIDATABASE *) DECLSPEC_HIDDEN;
extern UINT msi_set_context(MSIPACKAGE *) DECLSPEC_HIDDEN;
extern void msi_adjust_privilege_properties(MSIPACKAGE *) DECLSPEC_HIDDEN;
extern UINT MSI_GetFeatureCost(MSIPACKAGE *, MSIFEATURE *, MSICOSTTREE, INSTALLSTATE,
LPINT) DECLSPEC_HIDDEN;
@@ -955,6 +967,7 @@
extern INT msi_suminfo_get_int32( MSISUMMARYINFO *si, UINT uiProperty ) DECLSPEC_HIDDEN;
extern LPWSTR msi_get_suminfo_product( IStorage *stg ) DECLSPEC_HIDDEN;
extern UINT msi_add_suminfo( MSIDATABASE *db, LPWSTR **records, int num_records, int
num_columns ) DECLSPEC_HIDDEN;
+extern enum platform parse_platform( const WCHAR *str ) DECLSPEC_HIDDEN;
/* undocumented functions */
UINT WINAPI MsiCreateAndVerifyInstallerDirectory( DWORD );
@@ -1173,7 +1186,6 @@
static const WCHAR szAMD64[] =
{'A','M','D','6','4',0};
static const WCHAR szARM[] = {'A','r','m',0};
static const WCHAR szWow6432NodeCLSID[] =
{'W','o','w','6','4','3','2','N','o','d','e','\\','C','L','S','I','D',0};
-static const WCHAR szWow6432Node[] =
{'W','o','w','6','4','3','2','N','o','d','e',0};
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};
static const WCHAR szMsiPublishAssemblies[] =
{'M','s','i','P','u','b','l','i','s','h','A','s','s','e','m','b','l','i','e','s',0};
@@ -1194,6 +1206,7 @@
static const WCHAR szData[] = {'D','a','t','a',0};
static const WCHAR szLangResource[] =
{'\\','V','a','r','F','i','l','e','I','n','f','o','\\','T','r','a','n','s','l','a','t','i','o','n',0};
static const WCHAR szInstallLocation[] =
{'I','n','s','t','a','l','l','L','o','c','a','t','i','o','n',0};
+static const WCHAR szProperty[] =
{'P','r','o','p','e','r','t','y',0};
/* memory allocation macro functions */
static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1);
Modified: trunk/reactos/dll/win32/msi/msiquery.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/msiquery.c?r…
==============================================================================
--- trunk/reactos/dll/win32/msi/msiquery.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/msiquery.c [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -821,8 +821,13 @@
/* FIXME: lock the database */
- r = MSI_CommitTables( db );
- if (r != ERROR_SUCCESS) ERR("Failed to commit tables!\n");
+ r = msi_commit_streams( db );
+ if (r != ERROR_SUCCESS) ERR("Failed to commit streams!\n");
+ else
+ {
+ r = MSI_CommitTables( db );
+ if (r != ERROR_SUCCESS) ERR("Failed to commit tables!\n");
+ }
/* FIXME: unlock the database */
Modified: trunk/reactos/dll/win32/msi/package.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/package.c?re…
==============================================================================
--- trunk/reactos/dll/win32/msi/package.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/package.c [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -361,7 +361,7 @@
return rc;
}
-UINT msi_clone_properties(MSIPACKAGE *package)
+UINT msi_clone_properties( MSIDATABASE *db )
{
static const WCHAR query_select[] = {
'S','E','L','E','C','T','
','*',' ','F','R','O','M','
',
@@ -378,7 +378,7 @@
MSIQUERY *view_select;
UINT rc;
- rc = MSI_DatabaseOpenViewW( package->db, query_select, &view_select );
+ rc = MSI_DatabaseOpenViewW( db, query_select, &view_select );
if (rc != ERROR_SUCCESS)
return rc;
@@ -399,7 +399,7 @@
if (rc != ERROR_SUCCESS)
break;
- rc = MSI_DatabaseOpenViewW( package->db, query_insert, &view_insert );
+ rc = MSI_DatabaseOpenViewW( db, query_insert, &view_insert );
if (rc != ERROR_SUCCESS)
{
msiobj_release( &rec_select->hdr );
@@ -415,7 +415,7 @@
TRACE("insert failed, trying update\n");
- rc = MSI_DatabaseOpenViewW( package->db, query_update, &view_update
);
+ rc = MSI_DatabaseOpenViewW( db, query_update, &view_update );
if (rc != ERROR_SUCCESS)
{
WARN("open view failed %u\n", rc);
@@ -1150,7 +1150,7 @@
package->BaseURL = strdupW( base_url );
create_temp_property_table( package );
- msi_clone_properties( package );
+ msi_clone_properties( package->db );
msi_adjust_privilege_properties( package );
package->ProductCode = msi_dup_property( package->db, szProductCode );
@@ -1246,7 +1246,7 @@
return ERROR_SUCCESS;
}
-static enum platform parse_platform( WCHAR *str )
+enum platform parse_platform( const WCHAR *str )
{
if (!str[0] || !strcmpW( str, szIntel )) return PLATFORM_INTEL;
else if (!strcmpW( str, szIntel64 )) return PLATFORM_INTEL64;
@@ -1652,11 +1652,8 @@
}
index++;
}
- if (index)
- {
- msi_clone_properties( package );
- msi_adjust_privilege_properties( package );
- }
+ if (index) msi_adjust_privilege_properties( package );
+
r = msi_set_original_database_property( package->db, szPackage );
if (r != ERROR_SUCCESS)
{
Modified: trunk/reactos/dll/win32/msi/patch.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/patch.c?rev=…
==============================================================================
--- trunk/reactos/dll/win32/msi/patch.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/patch.c [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -35,57 +35,220 @@
return FALSE;
}
+struct transform_desc
+{
+ WCHAR *product_code_from;
+ WCHAR *product_code_to;
+ WCHAR *version_from;
+ WCHAR *version_to;
+ WCHAR *upgrade_code;
+};
+
+static void free_transform_desc( struct transform_desc *desc )
+{
+ msi_free( desc->product_code_from );
+ msi_free( desc->product_code_to );
+ msi_free( desc->version_from );
+ msi_free( desc->version_to );
+ msi_free( desc->upgrade_code );
+ msi_free( desc );
+}
+
+static struct transform_desc *parse_transform_desc( const WCHAR *str )
+{
+ struct transform_desc *ret;
+ const WCHAR *p = str, *q;
+ UINT len;
+
+ if (!(ret = msi_alloc_zero( sizeof(*ret) ))) return NULL;
+
+ q = strchrW( p, '}' );
+ if (*p != '{' || !q) goto error;
+
+ len = q - p + 1;
+ if (!(ret->product_code_from = msi_alloc( (len + 1) * sizeof(WCHAR) ))) goto
error;
+ memcpy( ret->product_code_from, p, len * sizeof(WCHAR) );
+ ret->product_code_from[len] = 0;
+
+ p = q + 1;
+ if (!(q = strchrW( p, ';' ))) goto error;
+ len = q - p;
+ if (!(ret->version_from = msi_alloc( (len + 1) * sizeof(WCHAR) ))) goto error;
+ memcpy( ret->version_from, p, len * sizeof(WCHAR) );
+ ret->version_from[len] = 0;
+
+ p = q + 1;
+ q = strchrW( p, '}' );
+ if (*p != '{' || !q) goto error;
+
+ len = q - p + 1;
+ if (!(ret->product_code_to = msi_alloc( (len + 1) * sizeof(WCHAR) ))) goto error;
+ memcpy( ret->product_code_to, p, len * sizeof(WCHAR) );
+ ret->product_code_to[len] = 0;
+
+ p = q + 1;
+ if (!(q = strchrW( p, ';' ))) goto error;
+ len = q - p;
+ if (!(ret->version_to = msi_alloc( (len + 1) * sizeof(WCHAR) ))) goto error;
+ memcpy( ret->version_to, p, len * sizeof(WCHAR) );
+ ret->version_to[len] = 0;
+
+ p = q + 1;
+ q = strchrW( p, '}' );
+ if (*p != '{' || !q) goto error;
+
+ len = q - p + 1;
+ if (!(ret->upgrade_code = msi_alloc( (len + 1) * sizeof(WCHAR) ))) goto error;
+ memcpy( ret->upgrade_code, p, len * sizeof(WCHAR) );
+ ret->upgrade_code[len] = 0;
+
+ return ret;
+
+error:
+ free_transform_desc( ret );
+ return NULL;
+}
+
static UINT check_transform_applicable( MSIPACKAGE *package, IStorage *transform )
{
+ static const UINT supported_flags =
+ MSITRANSFORM_VALIDATE_PRODUCT | MSITRANSFORM_VALIDATE_LANGUAGE |
+ MSITRANSFORM_VALIDATE_PLATFORM | MSITRANSFORM_VALIDATE_MAJORVERSION |
+ MSITRANSFORM_VALIDATE_MINORVERSION | MSITRANSFORM_VALIDATE_UPGRADECODE;
MSISUMMARYINFO *si = MSI_GetSummaryInformationW( transform, 0 );
UINT valid_flags = 0, wanted_flags = 0;
-
- if (si) wanted_flags = msi_suminfo_get_int32( si, PID_CHARCOUNT );
- TRACE("validation flags %x\n", wanted_flags);
-
- if (wanted_flags &
~(MSITRANSFORM_VALIDATE_PRODUCT|MSITRANSFORM_VALIDATE_LANGUAGE))
- FIXME("unsupported validation flags %x\n", wanted_flags);
-
+ WCHAR *template, *product, *p;
+ struct transform_desc *desc;
+
+ if (!si)
+ {
+ WARN("no summary information!\n");
+ return ERROR_FUNCTION_FAILED;
+ }
+ wanted_flags = msi_suminfo_get_int32( si, PID_CHARCOUNT );
+ wanted_flags &= 0xffff; /* mask off error condition flags */
+ TRACE("validation flags 0x%04x\n", wanted_flags);
+
+ if (wanted_flags & ~supported_flags)
+ {
+ FIXME("unsupported validation flags 0x%04x\n", wanted_flags);
+ msiobj_release( &si->hdr );
+ return ERROR_FUNCTION_FAILED;
+ }
+ if (!(template = msi_suminfo_dup_string( si, PID_TEMPLATE )))
+ {
+ WARN("no template property!\n");
+ msiobj_release( &si->hdr );
+ return ERROR_FUNCTION_FAILED;
+ }
+ TRACE("template property: %s\n", debugstr_w(template));
+ if (!(product = msi_get_suminfo_product( transform )))
+ {
+ WARN("no product property!\n");
+ msi_free( template );
+ msiobj_release( &si->hdr );
+ return ERROR_FUNCTION_FAILED;
+ }
+ TRACE("product property: %s\n", debugstr_w(product));
+ if (!(desc = parse_transform_desc( product )))
+ {
+ msi_free( template );
+ msiobj_release( &si->hdr );
+ return ERROR_FUNCTION_FAILED;
+ }
+ msi_free( product );
+
+ if (wanted_flags & MSITRANSFORM_VALIDATE_LANGUAGE)
+ {
+ if (!template[0] || ((p = strchrW( template, ';' )) &&
match_language( package, atoiW( p + 1 ) )))
+ {
+ valid_flags |= MSITRANSFORM_VALIDATE_LANGUAGE;
+ }
+ }
if (wanted_flags & MSITRANSFORM_VALIDATE_PRODUCT)
{
- WCHAR *package_product = msi_dup_property( package->db, szProductCode );
- WCHAR *transform_product = msi_get_suminfo_product( transform );
-
- TRACE("package = %s transform = %s\n", debugstr_w(package_product),
debugstr_w(transform_product));
-
- if (!transform_product || strstrW( transform_product, package_product ))
+ WCHAR *product_code_installed = msi_dup_property( package->db, szProductCode
);
+
+ if (!product_code_installed)
+ {
+ msi_free( template );
+ free_transform_desc( desc );
+ msiobj_release( &si->hdr );
+ return ERROR_INSTALL_PACKAGE_INVALID;
+ }
+ if (!strcmpW( desc->product_code_from, product_code_installed ))
{
valid_flags |= MSITRANSFORM_VALIDATE_PRODUCT;
}
- msi_free( transform_product );
- msi_free( package_product );
- }
- if (wanted_flags & MSITRANSFORM_VALIDATE_LANGUAGE)
- {
- WCHAR *template;
- const WCHAR *p;
-
- if (!si)
- {
- ERR("no summary information!\n");
- goto end;
- }
- if (!(template = msi_suminfo_dup_string( si, PID_TEMPLATE )))
- {
- ERR("no template property!\n");
- goto end;
- }
- TRACE("template: %s\n", debugstr_w(template));
- if (!template[0] || ((p = strchrW( template, ';' )) &&
match_language( package, atoiW( p + 1 ) )))
- {
- valid_flags |= MSITRANSFORM_VALIDATE_LANGUAGE;
- }
- msi_free( template );
- }
-
-end:
+ msi_free( product_code_installed );
+ }
+ if (wanted_flags & MSITRANSFORM_VALIDATE_PLATFORM)
+ {
+ if ((p = strchrW( template, ';' )))
+ {
+ *p = 0;
+ if (package->platform == parse_platform( template ))
+ valid_flags |= MSITRANSFORM_VALIDATE_PLATFORM;
+ }
+ }
+ msi_free( template );
+ if (wanted_flags & MSITRANSFORM_VALIDATE_MAJORVERSION)
+ {
+ WCHAR *product_version_installed = msi_dup_property( package->db,
szProductVersion );
+ DWORD major_installed, minor_installed, major, minor;
+
+ if (!product_version_installed)
+ {
+ free_transform_desc( desc );
+ msiobj_release( &si->hdr );
+ return ERROR_INSTALL_PACKAGE_INVALID;
+ }
+ msi_parse_version_string( product_version_installed, &major_installed,
&minor_installed );
+ msi_parse_version_string( desc->version_from, &major, &minor );
+
+ if (major_installed == major)
+ {
+ valid_flags |= MSITRANSFORM_VALIDATE_MAJORVERSION;
+ wanted_flags &= ~MSITRANSFORM_VALIDATE_MINORVERSION;
+ }
+ msi_free( product_version_installed );
+ }
+ else if (wanted_flags & MSITRANSFORM_VALIDATE_MINORVERSION)
+ {
+ WCHAR *product_version_installed = msi_dup_property( package->db,
szProductVersion );
+ DWORD major_installed, minor_installed, major, minor;
+
+ if (!product_version_installed)
+ {
+ free_transform_desc( desc );
+ msiobj_release( &si->hdr );
+ return ERROR_INSTALL_PACKAGE_INVALID;
+ }
+ msi_parse_version_string( product_version_installed, &major_installed,
&minor_installed );
+ msi_parse_version_string( desc->version_from, &major, &minor );
+
+ if (major_installed == major && minor_installed == minor)
+ valid_flags |= MSITRANSFORM_VALIDATE_MINORVERSION;
+ msi_free( product_version_installed );
+ }
+ if (wanted_flags & MSITRANSFORM_VALIDATE_UPGRADECODE)
+ {
+ WCHAR *upgrade_code_installed = msi_dup_property( package->db, szUpgradeCode
);
+
+ if (!upgrade_code_installed)
+ {
+ free_transform_desc( desc );
+ msiobj_release( &si->hdr );
+ return ERROR_INSTALL_PACKAGE_INVALID;
+ }
+ if (!strcmpW( desc->upgrade_code, upgrade_code_installed ))
+ valid_flags |= MSITRANSFORM_VALIDATE_UPGRADECODE;
+ msi_free( upgrade_code_installed );
+ }
+
+ free_transform_desc( desc );
msiobj_release( &si->hdr );
- if (valid_flags & ~wanted_flags) return ERROR_FUNCTION_FAILED;
+ if ((valid_flags & wanted_flags) != wanted_flags) return ERROR_FUNCTION_FAILED;
TRACE("applicable transform\n");
return ERROR_SUCCESS;
}
Modified: trunk/reactos/dll/win32/msi/registry.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/registry.c?r…
==============================================================================
--- trunk/reactos/dll/win32/msi/registry.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/registry.c [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -83,12 +83,6 @@
'%','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_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','\\',
'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
@@ -110,11 +104,6 @@
'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','\\','P','a','t','c','h','e','s',0};
-
-static const WCHAR szInstaller_Components[] = {
-
'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','\\','C','o','m','p','o','n','e','n','t','s',0};
static const WCHAR szInstaller_LocalClassesProducts[] = {
'S','o','f','t','w','a','r','e','\\','C','l','a','s','s','e','s','\\',
@@ -1497,6 +1486,24 @@
return r;
}
+UINT WINAPI MsiEnumClientsExA(LPCSTR component, LPCSTR usersid, DWORD ctx, DWORD index,
+ CHAR installed_product[GUID_SIZE],
+ MSIINSTALLCONTEXT *installed_ctx, LPSTR sid, LPDWORD
sid_len)
+{
+ FIXME("%s, %s, %u, %u, %p, %p, %p, %p\n", debugstr_a(component),
debugstr_a(usersid),
+ ctx, index, installed_product, installed_ctx, sid, sid_len);
+ return ERROR_ACCESS_DENIED;
+}
+
+UINT WINAPI MsiEnumClientsExW(LPCWSTR component, LPCWSTR usersid, DWORD ctx, DWORD
index,
+ WCHAR installed_product[GUID_SIZE],
+ MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid, LPDWORD
sid_len)
+{
+ FIXME("%s, %s, %u, %u, %p, %p, %p, %p\n", debugstr_w(component),
debugstr_w(usersid),
+ ctx, index, installed_product, installed_ctx, sid, sid_len);
+ return ERROR_ACCESS_DENIED;
+}
+
static UINT MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
awstring *lpQualBuf, LPDWORD pcchQual,
awstring *lpAppBuf, LPDWORD pcchAppBuf )
Modified: trunk/reactos/dll/win32/msi/script.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/script.c?rev…
==============================================================================
--- trunk/reactos/dll/win32/msi/script.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/script.c [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -344,7 +344,7 @@
if (FAILED(hr)) goto done;
/* Call a function if necessary through the IDispatch interface */
- if (function != NULL && strlenW(function) > 0) {
+ if (function && function[0]) {
TRACE("Calling function %s\n", debugstr_w(function));
hr = IActiveScript_GetScriptDispatch(pActiveScript, NULL, &pDispatch);
Modified: trunk/reactos/dll/win32/msi/storages.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/storages.c?r…
==============================================================================
--- trunk/reactos/dll/win32/msi/storages.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/storages.c [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -62,7 +62,7 @@
if (!storage)
return NULL;
- storage->str_index = msi_addstringW(sv->db->strings, name, -1, 1,
StringNonPersistent);
+ storage->str_index = msi_add_string(sv->db->strings, name, -1,
StringNonPersistent);
storage->storage = stg;
if (storage->storage)
Modified: trunk/reactos/dll/win32/msi/streams.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/streams.c?re…
==============================================================================
--- trunk/reactos/dll/win32/msi/streams.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/streams.c [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -2,6 +2,7 @@
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2007 James Hawkins
+ * Copyright 2015 Hans Leidekker for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,54 +25,30 @@
#define NUM_STREAMS_COLS 2
-typedef struct tabSTREAM
-{
- UINT str_index;
- IStream *stream;
-} STREAM;
-
typedef struct tagMSISTREAMSVIEW
{
MSIVIEW view;
MSIDATABASE *db;
- STREAM **streams;
- UINT max_streams;
- UINT num_rows;
- UINT row_size;
+ UINT num_cols;
} MSISTREAMSVIEW;
-static BOOL streams_set_table_size(MSISTREAMSVIEW *sv, UINT size)
-{
- if (size >= sv->max_streams)
- {
- sv->max_streams *= 2;
- sv->streams = msi_realloc_zero(sv->streams, sv->max_streams *
sizeof(STREAM *));
- if (!sv->streams)
- return FALSE;
- }
-
+static BOOL streams_resize_table( MSIDATABASE *db, UINT size )
+{
+ if (!db->num_streams_allocated)
+ {
+ if (!(db->streams = msi_alloc_zero( size * sizeof(MSISTREAM) ))) return
FALSE;
+ db->num_streams_allocated = size;
+ return TRUE;
+ }
+ while (size >= db->num_streams_allocated)
+ {
+ MSISTREAM *tmp;
+ UINT new_size = db->num_streams_allocated * 2;
+ if (!(tmp = msi_realloc_zero( db->streams, new_size * sizeof(MSISTREAM) )))
return FALSE;
+ db->streams = tmp;
+ db->num_streams_allocated = new_size;
+ }
return TRUE;
-}
-
-static STREAM *create_stream(MSISTREAMSVIEW *sv, LPCWSTR name, BOOL encoded, IStream
*stm)
-{
- STREAM *stream;
- WCHAR decoded[MAX_STREAM_NAME_LEN + 1];
-
- stream = msi_alloc(sizeof(STREAM));
- if (!stream)
- return NULL;
-
- if (encoded)
- {
- decode_streamname(name, decoded);
- TRACE("stream -> %s %s\n", debugstr_w(name), debugstr_w(decoded));
- name = decoded;
- }
-
- stream->str_index = msi_addstringW(sv->db->strings, name, -1, 1,
StringNonPersistent);
- stream->stream = stm;
- return stream;
}
static UINT STREAMS_fetch_int(struct tagMSIVIEW *view, UINT row, UINT col, UINT *val)
@@ -83,10 +60,10 @@
if (col != 1)
return ERROR_INVALID_PARAMETER;
- if (row >= sv->num_rows)
+ if (row >= sv->db->num_streams)
return ERROR_NO_MORE_ITEMS;
- *val = sv->streams[row]->str_index;
+ *val = sv->db->streams[row].str_index;
return ERROR_SUCCESS;
}
@@ -94,14 +71,21 @@
static UINT STREAMS_fetch_stream(struct tagMSIVIEW *view, UINT row, UINT col, IStream
**stm)
{
MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
+ LARGE_INTEGER pos;
+ HRESULT hr;
TRACE("(%p, %d, %d, %p)\n", view, row, col, stm);
- if (row >= sv->num_rows)
+ if (row >= sv->db->num_streams)
return ERROR_FUNCTION_FAILED;
- IStream_AddRef(sv->streams[row]->stream);
- *stm = sv->streams[row]->stream;
+ pos.QuadPart = 0;
+ hr = IStream_Seek( sv->db->streams[row].stream, pos, STREAM_SEEK_SET, NULL );
+ if (FAILED( hr ))
+ return ERROR_FUNCTION_FAILED;
+
+ *stm = sv->db->streams[row].stream;
+ IStream_AddRef( *stm );
return ERROR_SUCCESS;
}
@@ -118,112 +102,96 @@
static UINT STREAMS_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT
mask)
{
MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
- STREAM *stream;
- IStream *stm;
- STATSTG stat;
- LPWSTR encname = NULL, name = NULL;
- USHORT *data = NULL;
- HRESULT hr;
- ULONG count;
- UINT r = ERROR_FUNCTION_FAILED;
TRACE("(%p, %d, %p, %08x)\n", view, row, rec, mask);
- if (row > sv->num_rows)
- return ERROR_FUNCTION_FAILED;
-
- r = MSI_RecordGetIStream(rec, 2, &stm);
+ if (row > sv->db->num_streams || mask >= (1 << sv->num_cols))
+ return ERROR_INVALID_PARAMETER;
+
+ if (mask & 1)
+ {
+ const WCHAR *name = MSI_RecordGetString( rec, 1 );
+
+ if (!name) return ERROR_INVALID_PARAMETER;
+ sv->db->streams[row].str_index = msi_add_string( sv->db->strings,
name, -1, StringNonPersistent );
+ }
+ if (mask & 2)
+ {
+ IStream *old, *new;
+ HRESULT hr;
+ UINT r;
+
+ r = MSI_RecordGetIStream( rec, 2, &new );
+ if (r != ERROR_SUCCESS)
+ return r;
+
+ old = sv->db->streams[row].stream;
+ hr = IStream_QueryInterface( new, &IID_IStream, (void
**)&sv->db->streams[row].stream );
+ if (FAILED( hr ))
+ {
+ IStream_Release( new );
+ return ERROR_FUNCTION_FAILED;
+ }
+ if (old) IStream_Release( old );
+ }
+
+ return ERROR_SUCCESS;
+}
+
+static UINT streams_find_row( MSISTREAMSVIEW *sv, MSIRECORD *rec, UINT *row )
+{
+ const WCHAR *str;
+ UINT r, i, id, val;
+
+ str = MSI_RecordGetString( rec, 1 );
+ r = msi_string2id( sv->db->strings, str, -1, &id );
if (r != ERROR_SUCCESS)
return r;
- hr = IStream_Stat(stm, &stat, STATFLAG_NONAME);
- if (FAILED(hr))
- {
- WARN("failed to stat stream: %08x\n", hr);
- goto done;
- }
-
- if (stat.cbSize.QuadPart >> 32)
- {
- WARN("stream too large\n");
- goto done;
- }
-
- data = msi_alloc(stat.cbSize.QuadPart);
- if (!data)
- goto done;
-
- hr = IStream_Read(stm, data, stat.cbSize.QuadPart, &count);
- if (FAILED(hr) || count != stat.cbSize.QuadPart)
- {
- WARN("failed to read stream: %08x\n", hr);
- goto done;
- }
-
- name = strdupW(MSI_RecordGetString(rec, 1));
- if (!name)
- {
- WARN("failed to retrieve stream name\n");
- goto done;
- }
-
- encname = encode_streamname(FALSE, name);
- msi_destroy_stream(sv->db, encname);
-
- r = write_stream_data(sv->db->storage, name, data, count, FALSE);
- if (r != ERROR_SUCCESS)
- {
- WARN("failed to write stream data: %d\n", r);
- goto done;
- }
-
- stream = create_stream(sv, name, FALSE, NULL);
- if (!stream)
- goto done;
-
- hr = IStorage_OpenStream(sv->db->storage, encname, 0,
- STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
&stream->stream);
- if (FAILED(hr))
- {
- WARN("failed to open stream: %08x\n", hr);
- msi_free(stream);
- goto done;
- }
-
- sv->streams[row] = stream;
-
-done:
- msi_free(name);
- msi_free(data);
- msi_free(encname);
-
- IStream_Release(stm);
+ for (i = 0; i < sv->db->num_streams; i++)
+ {
+ STREAMS_fetch_int( &sv->view, i, 1, &val );
+
+ if (val == id)
+ {
+ if (row) *row = i;
+ return ERROR_SUCCESS;
+ }
+ }
+
+ return ERROR_FUNCTION_FAILED;
+}
+
+static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL
temporary)
+{
+ MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
+ UINT i, r, num_rows = sv->db->num_streams + 1;
+
+ TRACE("(%p, %p, %d, %d)\n", view, rec, row, temporary);
+
+ r = streams_find_row( sv, rec, NULL );
+ if (r == ERROR_SUCCESS)
+ return ERROR_FUNCTION_FAILED;
+
+ if (!streams_resize_table( sv->db, num_rows ))
+ return ERROR_FUNCTION_FAILED;
+
+ if (row == -1)
+ row = num_rows - 1;
+
+ /* shift the rows to make room for the new row */
+ for (i = num_rows - 1; i > row; i--)
+ {
+ sv->db->streams[i] = sv->db->streams[i - 1];
+ }
+
+ r = STREAMS_set_row( view, row, rec, (1 << sv->num_cols) - 1 );
+ if (r == ERROR_SUCCESS)
+ sv->db->num_streams = num_rows;
return r;
}
-static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL
temporary)
-{
- MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
- UINT i;
-
- TRACE("(%p, %p, %d, %d)\n", view, rec, row, temporary);
-
- if (!streams_set_table_size(sv, ++sv->num_rows))
- return ERROR_FUNCTION_FAILED;
-
- if (row == -1)
- row = sv->num_rows - 1;
-
- /* shift the rows to make room for the new row */
- for (i = sv->num_rows - 1; i > row; i--)
- {
- sv->streams[i] = sv->streams[i - 1];
- }
-
- return STREAMS_set_row(view, row, rec, 0);
-}
-
static UINT STREAMS_delete_row(struct tagMSIVIEW *view, UINT row)
{
FIXME("(%p %d): stub!\n", view, row);
@@ -248,8 +216,8 @@
TRACE("(%p, %p, %p)\n", view, rows, cols);
- if (cols) *cols = NUM_STREAMS_COLS;
- if (rows) *rows = sv->num_rows;
+ if (cols) *cols = sv->num_cols;
+ if (rows) *rows = sv->db->num_streams;
return ERROR_SUCCESS;
}
@@ -257,10 +225,11 @@
static UINT STREAMS_get_column_info( struct tagMSIVIEW *view, UINT n, LPCWSTR *name,
UINT *type, BOOL *temporary, LPCWSTR *table_name )
{
- TRACE("(%p, %d, %p, %p, %p, %p)\n", view, n, name, type, temporary,
- table_name);
-
- if (n == 0 || n > NUM_STREAMS_COLS)
+ MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
+
+ TRACE("(%p, %d, %p, %p, %p, %p)\n", view, n, name, type, temporary,
table_name);
+
+ if (!n || n > sv->num_cols)
return ERROR_INVALID_PARAMETER;
switch (n)
@@ -280,30 +249,6 @@
return ERROR_SUCCESS;
}
-static UINT streams_find_row(MSISTREAMSVIEW *sv, MSIRECORD *rec, UINT *row)
-{
- LPCWSTR str;
- UINT r, i, id, data;
-
- str = MSI_RecordGetString(rec, 1);
- r = msi_string2id(sv->db->strings, str, -1, &id);
- if (r != ERROR_SUCCESS)
- return r;
-
- for (i = 0; i < sv->num_rows; i++)
- {
- STREAMS_fetch_int(&sv->view, i, 1, &data);
-
- if (data == id)
- {
- *row = i;
- return ERROR_SUCCESS;
- }
- }
-
- return ERROR_FUNCTION_FAILED;
-}
-
static UINT streams_modify_update(struct tagMSIVIEW *view, MSIRECORD *rec)
{
MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
@@ -313,15 +258,15 @@
if (r != ERROR_SUCCESS)
return ERROR_FUNCTION_FAILED;
- return STREAMS_set_row(view, row, rec, 0);
+ return STREAMS_set_row( view, row, rec, (1 << sv->num_cols) - 1 );
}
static UINT streams_modify_assign(struct tagMSIVIEW *view, MSIRECORD *rec)
{
MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
- UINT r, row;
-
- r = streams_find_row(sv, rec, &row);
+ UINT r;
+
+ r = streams_find_row( sv, rec, NULL );
if (r == ERROR_SUCCESS)
return streams_modify_update(view, rec);
@@ -371,23 +316,10 @@
static UINT STREAMS_delete(struct tagMSIVIEW *view)
{
MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
- UINT i;
TRACE("(%p)\n", view);
- for (i = 0; i < sv->num_rows; i++)
- {
- if (sv->streams[i])
- {
- if (sv->streams[i]->stream)
- IStream_Release(sv->streams[i]->stream);
- msi_free(sv->streams[i]);
- }
- }
-
- msi_free(sv->streams);
msi_free(sv);
-
return ERROR_SUCCESS;
}
@@ -399,23 +331,22 @@
TRACE("(%p, %d, %d, %p, %p)\n", view, col, val, row, handle);
- if (col == 0 || col > NUM_STREAMS_COLS)
+ if (!col || col > sv->num_cols)
return ERROR_INVALID_PARAMETER;
- while (index < sv->num_rows)
- {
- if (sv->streams[index]->str_index == val)
+ while (index < sv->db->num_streams)
+ {
+ if (sv->db->streams[index].str_index == val)
{
*row = index;
break;
}
-
index++;
}
*handle = UlongToPtr(++index);
- if (index > sv->num_rows)
+ if (index > sv->db->num_streams)
return ERROR_NO_MORE_ITEMS;
return ERROR_SUCCESS;
@@ -444,107 +375,256 @@
NULL,
};
-static INT add_streams_to_table(MSISTREAMSVIEW *sv)
-{
- IEnumSTATSTG *stgenum = NULL;
+static HRESULT open_stream( MSIDATABASE *db, const WCHAR *name, IStream **stream )
+{
+ HRESULT hr;
+
+ hr = IStorage_OpenStream( db->storage, name, NULL, STGM_READ|STGM_SHARE_EXCLUSIVE,
0, stream );
+ if (FAILED( hr ))
+ {
+ MSITRANSFORM *transform;
+
+ LIST_FOR_EACH_ENTRY( transform, &db->transforms, MSITRANSFORM, entry )
+ {
+ hr = IStorage_OpenStream( transform->stg, name, NULL,
STGM_READ|STGM_SHARE_EXCLUSIVE, 0, stream );
+ if (SUCCEEDED( hr ))
+ break;
+ }
+ }
+ return hr;
+}
+
+static MSISTREAM *find_stream( MSIDATABASE *db, const WCHAR *name )
+{
+ UINT r, id, i;
+
+ r = msi_string2id( db->strings, name, -1, &id );
+ if (r != ERROR_SUCCESS)
+ return NULL;
+
+ for (i = 0; i < db->num_streams; i++)
+ {
+ if (db->streams[i].str_index == id) return &db->streams[i];
+ }
+ return NULL;
+}
+
+static UINT append_stream( MSIDATABASE *db, const WCHAR *name, IStream *stream )
+{
+ WCHAR decoded[MAX_STREAM_NAME_LEN + 1];
+ UINT i = db->num_streams;
+
+ if (!streams_resize_table( db, db->num_streams + 1 ))
+ return ERROR_OUTOFMEMORY;
+
+ decode_streamname( name, decoded );
+ db->streams[i].str_index = msi_add_string( db->strings, decoded, -1,
StringNonPersistent );
+ db->streams[i].stream = stream;
+ db->num_streams++;
+
+ TRACE("added %s\n", debugstr_w( decoded ));
+ return ERROR_SUCCESS;
+}
+
+static UINT load_streams( MSIDATABASE *db )
+{
+ IEnumSTATSTG *stgenum;
STATSTG stat;
- STREAM *stream = NULL;
HRESULT hr;
- UINT r, count = 0, size;
- LPWSTR encname;
-
- hr = IStorage_EnumElements(sv->db->storage, 0, NULL, 0, &stgenum);
- if (FAILED(hr))
- return -1;
-
- sv->max_streams = 1;
- sv->streams = msi_alloc_zero(sizeof(STREAM *));
- if (!sv->streams)
- return -1;
-
- while (TRUE)
- {
- size = 0;
- hr = IEnumSTATSTG_Next(stgenum, 1, &stat, &size);
- if (FAILED(hr) || !size)
+ UINT count, r = ERROR_SUCCESS;
+ IStream *stream;
+
+ hr = IStorage_EnumElements( db->storage, 0, NULL, 0, &stgenum );
+ if (FAILED( hr ))
+ return ERROR_FUNCTION_FAILED;
+
+ for (;;)
+ {
+ count = 0;
+ hr = IEnumSTATSTG_Next( stgenum, 1, &stat, &count );
+ if (FAILED( hr ) || !count)
break;
- if (stat.type != STGTY_STREAM)
- {
- CoTaskMemFree(stat.pwcsName);
+ /* table streams are not in the _Streams table */
+ if (stat.type != STGTY_STREAM || *stat.pwcsName == 0x4840 ||
+ find_stream( db, stat.pwcsName ))
+ {
+ CoTaskMemFree( stat.pwcsName );
continue;
}
-
- /* table streams are not in the _Streams table */
- if (*stat.pwcsName == 0x4840)
- {
- CoTaskMemFree(stat.pwcsName);
- continue;
- }
-
- stream = create_stream(sv, stat.pwcsName, TRUE, NULL);
- if (!stream)
- {
- count = -1;
- CoTaskMemFree(stat.pwcsName);
+ TRACE("found new stream %s\n", debugstr_w( stat.pwcsName ));
+
+ hr = open_stream( db, stat.pwcsName, &stream );
+ if (FAILED( hr ))
+ {
+ ERR("unable to open stream %08x\n", hr);
+ CoTaskMemFree( stat.pwcsName );
+ r = ERROR_FUNCTION_FAILED;
break;
}
- /* these streams appear to be unencoded */
- if (*stat.pwcsName == 0x0005)
- {
- r = msi_get_raw_stream(sv->db, stat.pwcsName, &stream->stream);
- }
- else
- {
- encname = encode_streamname(FALSE, stat.pwcsName);
- r = msi_get_raw_stream(sv->db, encname, &stream->stream);
- msi_free(encname);
- }
- CoTaskMemFree(stat.pwcsName);
-
+ r = append_stream( db, stat.pwcsName, stream );
+ CoTaskMemFree( stat.pwcsName );
if (r != ERROR_SUCCESS)
- {
- WARN("unable to get stream %u\n", r);
- count = -1;
break;
- }
-
- if (!streams_set_table_size(sv, ++count))
- {
- count = -1;
- break;
- }
-
- sv->streams[count - 1] = stream;
- }
-
- IEnumSTATSTG_Release(stgenum);
- return count;
+ }
+
+ TRACE("loaded %u streams\n", db->num_streams);
+ IEnumSTATSTG_Release( stgenum );
+ return r;
+}
+
+UINT msi_get_stream( MSIDATABASE *db, const WCHAR *name, IStream **ret )
+{
+ MSISTREAM *stream;
+ WCHAR *encname;
+ HRESULT hr;
+ UINT r;
+
+ if ((stream = find_stream( db, name )))
+ {
+ LARGE_INTEGER pos;
+
+ pos.QuadPart = 0;
+ hr = IStream_Seek( stream->stream, pos, STREAM_SEEK_SET, NULL );
+ if (FAILED( hr ))
+ return ERROR_FUNCTION_FAILED;
+
+ *ret = stream->stream;
+ IStream_AddRef( *ret );
+ return ERROR_SUCCESS;
+ }
+
+ if (!(encname = encode_streamname( FALSE, name )))
+ return ERROR_OUTOFMEMORY;
+
+ hr = open_stream( db, encname, ret );
+ msi_free( encname );
+ if (FAILED( hr ))
+ return ERROR_FUNCTION_FAILED;
+
+ r = append_stream( db, name, *ret );
+ if (r != ERROR_SUCCESS)
+ {
+ IStream_Release( *ret );
+ return r;
+ }
+
+ IStream_AddRef( *ret );
+ return ERROR_SUCCESS;
}
UINT STREAMS_CreateView(MSIDATABASE *db, MSIVIEW **view)
{
MSISTREAMSVIEW *sv;
- INT rows;
+ UINT r;
TRACE("(%p, %p)\n", db, view);
- sv = msi_alloc_zero( sizeof(MSISTREAMSVIEW) );
- if (!sv)
- return ERROR_FUNCTION_FAILED;
+ r = load_streams( db );
+ if (r != ERROR_SUCCESS)
+ return r;
+
+ if (!(sv = msi_alloc_zero( sizeof(MSISTREAMSVIEW) )))
+ return ERROR_OUTOFMEMORY;
sv->view.ops = &streams_ops;
+ sv->num_cols = NUM_STREAMS_COLS;
sv->db = db;
- rows = add_streams_to_table(sv);
- if (rows < 0)
- {
- msi_free( sv );
- return ERROR_FUNCTION_FAILED;
- }
- sv->num_rows = rows;
*view = (MSIVIEW *)sv;
return ERROR_SUCCESS;
}
+
+static HRESULT write_stream( IStream *dst, IStream *src )
+{
+ HRESULT hr;
+ char buf[4096];
+ STATSTG stat;
+ LARGE_INTEGER pos;
+ UINT count, size;
+
+ hr = IStream_Stat( src, &stat, STATFLAG_NONAME );
+ if (FAILED( hr )) return hr;
+
+ hr = IStream_SetSize( dst, stat.cbSize );
+ if (FAILED( hr )) return hr;
+
+ pos.QuadPart = 0;
+ hr = IStream_Seek( dst, pos, STREAM_SEEK_SET, NULL );
+ if (FAILED( hr )) return hr;
+
+ for (;;)
+ {
+ size = min( sizeof(buf), stat.cbSize.QuadPart );
+ hr = IStream_Read( src, buf, size, &count );
+ if (FAILED( hr ) || count != size)
+ {
+ WARN("failed to read stream: %08x\n", hr);
+ return E_INVALIDARG;
+ }
+ stat.cbSize.QuadPart -= count;
+ if (count)
+ {
+ size = count;
+ hr = IStream_Write( dst, buf, size, &count );
+ if (FAILED( hr ) || count != size)
+ {
+ WARN("failed to write stream: %08x\n", hr);
+ return E_INVALIDARG;
+ }
+ }
+ if (!stat.cbSize.QuadPart) break;
+ }
+
+ return S_OK;
+}
+
+UINT msi_commit_streams( MSIDATABASE *db )
+{
+ UINT i;
+ const WCHAR *name;
+ WCHAR *encname;
+ IStream *stream;
+ HRESULT hr;
+
+ TRACE("got %u streams\n", db->num_streams);
+
+ for (i = 0; i < db->num_streams; i++)
+ {
+ name = msi_string_lookup( db->strings, db->streams[i].str_index, NULL );
+ if (!(encname = encode_streamname( FALSE, name ))) return ERROR_OUTOFMEMORY;
+
+ hr = open_stream( db, encname, &stream );
+ if (FAILED( hr )) /* new stream */
+ {
+ hr = IStorage_CreateStream( db->storage, encname,
STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, 0, &stream );
+ if (FAILED( hr ))
+ {
+ ERR("failed to create stream %s (hr = %08x)\n",
debugstr_w(encname), hr);
+ msi_free( encname );
+ return ERROR_FUNCTION_FAILED;
+ }
+ hr = write_stream( stream, db->streams[i].stream );
+ if (FAILED( hr ))
+ {
+ ERR("failed to write stream %s (hr = %08x)\n",
debugstr_w(encname), hr);
+ msi_free( encname );
+ IStream_Release( stream );
+ return ERROR_FUNCTION_FAILED;
+ }
+ }
+ hr = IStream_Commit( stream, 0 );
+ IStream_Release( stream );
+ if (FAILED( hr ))
+ {
+ WARN("failed to commit stream %s (hr = %08x)\n",
debugstr_w(encname), hr);
+ msi_free( encname );
+ return ERROR_FUNCTION_FAILED;
+ }
+ msi_free( encname );
+ }
+
+ return ERROR_SUCCESS;
+}
Modified: trunk/reactos/dll/win32/msi/string.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/string.c?rev…
==============================================================================
--- trunk/reactos/dll/win32/msi/string.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/string.c [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -214,7 +214,7 @@
st->freeslot = n + 1;
}
-static UINT msi_string2idA( const string_table *st, LPCSTR buffer, UINT *id )
+static UINT string2id( const string_table *st, const char *buffer, UINT *id )
{
DWORD sz;
UINT r = ERROR_INVALID_PARAMETER;
@@ -241,7 +241,7 @@
return r;
}
-static int msi_addstring( string_table *st, UINT n, const char *data, UINT len, USHORT
refcount, enum StringPersistence persistence )
+static int add_string( string_table *st, UINT n, const char *data, UINT len, USHORT
refcount, enum StringPersistence persistence )
{
LPWSTR str;
int sz;
@@ -256,7 +256,7 @@
}
else
{
- if( ERROR_SUCCESS == msi_string2idA( st, data, &n ) )
+ if (string2id( st, data, &n ) == ERROR_SUCCESS)
{
if (persistence == StringPersistent)
st->strings[n].persistent_refcount += refcount;
@@ -287,7 +287,7 @@
return n;
}
-int msi_addstringW( string_table *st, const WCHAR *data, int len, USHORT refcount, enum
StringPersistence persistence )
+int msi_add_string( string_table *st, const WCHAR *data, int len, enum StringPersistence
persistence )
{
UINT n;
LPWSTR str;
@@ -303,9 +303,9 @@
if (msi_string2id( st, data, len, &n) == ERROR_SUCCESS )
{
if (persistence == StringPersistent)
- st->strings[n].persistent_refcount += refcount;
+ st->strings[n].persistent_refcount++;
else
- st->strings[n].nonpersistent_refcount += refcount;
+ st->strings[n].nonpersistent_refcount++;
return n;
}
@@ -322,7 +322,7 @@
memcpy( str, data, len*sizeof(WCHAR) );
str[len] = 0;
- set_st_entry( st, n, str, len, refcount, persistence );
+ set_st_entry( st, n, str, len, 1, persistence );
return n;
}
@@ -346,7 +346,7 @@
}
/*
- * msi_id2stringA
+ * id2string
*
* [in] st - pointer to the string table
* [in] id - id of the string to retrieve
@@ -356,7 +356,7 @@
*
* Returned string is not nul terminated.
*/
-static UINT msi_id2stringA( const string_table *st, UINT id, LPSTR buffer, UINT *sz )
+static UINT id2string( const string_table *st, UINT id, char *buffer, UINT *sz )
{
int len, lenW;
const WCHAR *str;
@@ -529,7 +529,7 @@
break;
}
- r = msi_addstring( st, n, data+offset, len, refs, StringPersistent );
+ r = add_string( st, n, data+offset, len, refs, StringPersistent );
if( r != n )
ERR("Failed to add string %d\n", n );
n++;
@@ -599,7 +599,7 @@
}
sz = datasize - used;
- r = msi_id2stringA( st, i, data+used, &sz );
+ r = id2string( st, i, data+used, &sz );
if( r != ERROR_SUCCESS )
{
ERR("failed to fetch string\n");
Modified: trunk/reactos/dll/win32/msi/table.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/table.c?rev=…
==============================================================================
--- trunk/reactos/dll/win32/msi/table.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/table.c [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -88,7 +88,7 @@
return 2;
if( (col->type & 0xff) != 4 )
- ERR("Invalid column size!\n");
+ ERR("Invalid column size %u\n", col->type & 0xff);
return 4;
}
@@ -741,8 +741,8 @@
for( i = 0, col = col_info; col; i++, col = col->next )
{
- UINT table_id = msi_addstringW( db->strings, col->table, -1, 1,
string_persistence );
- UINT col_id = msi_addstringW( db->strings, col->column, -1, 1,
string_persistence );
+ UINT table_id = msi_add_string( db->strings, col->table, -1,
string_persistence );
+ UINT col_id = msi_add_string( db->strings, col->column, -1,
string_persistence );
table->colinfo[ i ].tablename = msi_string_lookup( db->strings, table_id,
NULL );
table->colinfo[ i ].number = i + 1;
@@ -932,7 +932,7 @@
UINT size, offset, old_count;
UINT n;
- table = find_cached_table( db, name );
+ if (!(table = find_cached_table( db, name ))) return;
old_count = table->col_count;
msi_free_colinfo( table->colinfo, table->col_count );
msi_free( table->colinfo );
@@ -1130,25 +1130,23 @@
{
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
UINT r;
- LPWSTR encname, full_name = NULL;
+ WCHAR *name;
if( !view->ops->fetch_int )
return ERROR_INVALID_PARAMETER;
- r = msi_stream_name( tv, row, &full_name );
- if ( r != ERROR_SUCCESS )
- {
- ERR("fetching stream, error = %d\n", r);
+ r = msi_stream_name( tv, row, &name );
+ if (r != ERROR_SUCCESS)
+ {
+ ERR("fetching stream, error = %u\n", r);
return r;
}
- encname = encode_streamname( FALSE, full_name );
- r = msi_get_raw_stream( tv->db, encname, stm );
- if( r )
- ERR("fetching stream %s, error = %d\n",debugstr_w(full_name), r);
-
- msi_free( full_name );
- msi_free( encname );
+ r = msi_get_stream( tv->db, name, stm );
+ if (r != ERROR_SUCCESS)
+ ERR("fetching stream %s, error = %u\n", debugstr_w(name), r);
+
+ msi_free( name );
return r;
}
@@ -1350,8 +1348,8 @@
{
int len;
const WCHAR *sval = msi_record_get_string( rec, i + 1, &len );
- val = msi_addstringW( tv->db->strings, sval, len, 1,
- persistent ? StringPersistent : StringNonPersistent );
+ val = msi_add_string( tv->db->strings, sval, len,
+ persistent ? StringPersistent :
StringNonPersistent );
}
else
{
@@ -2555,6 +2553,12 @@
*/
sz = 2;
num_cols = mask >> 8;
+ if (num_cols > tv->num_cols)
+ {
+ ERR("excess columns in transform: %u > %u\n", num_cols,
tv->num_cols);
+ break;
+ }
+
for (i = 0; i < num_cols; i++)
{
if( (tv->columns[i].type & MSITYPE_STRING) &&
@@ -2612,7 +2616,7 @@
/*
* Native msi seems writes nul into the Number (2nd) column of
- * the _Columns table, only when the columns are from a new table
+ * the _Columns table when there are new columns
*/
if ( number == MSI_NULL_INTEGER )
{
@@ -2663,7 +2667,7 @@
WARN("failed to insert row %u\n", r);
}
- if (number != MSI_NULL_INTEGER && !strcmpW( name, szColumns ))
+ if (!strcmpW( name, szColumns ))
msi_update_table_columns( db, table );
msiobj_release( &rec->hdr );
@@ -2697,6 +2701,7 @@
string_table *strings;
UINT ret = ERROR_FUNCTION_FAILED;
UINT bytes_per_strref;
+ BOOL property_update = FALSE;
TRACE("%p %p\n", db, stg );
@@ -2741,6 +2746,8 @@
tables = transform;
else if (!strcmpW( transform->name, szColumns ) )
columns = transform;
+ else if (!strcmpW( transform->name, szProperty ))
+ property_update = TRUE;
TRACE("transform contains stream %s\n", debugstr_w(name));
@@ -2790,7 +2797,10 @@
}
if ( ret == ERROR_SUCCESS )
+ {
append_storage_to_db( db, stg );
+ if (property_update) msi_clone_properties( db );
+ }
end:
if ( stgenum )
Modified: trunk/reactos/media/doc/README.WINE
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=…
==============================================================================
--- trunk/reactos/media/doc/README.WINE [iso-8859-1] (original)
+++ trunk/reactos/media/doc/README.WINE [iso-8859-1] Mon Mar 9 20:28:19 2015
@@ -123,7 +123,7 @@
reactos/dll/win32/msgsm32.acm # Synced to Wine-1.7.27
reactos/dll/win32/mshtml # Synced to Wine-1.7.27
reactos/dll/win32/mshtml.tlb # Synced to Wine-1.7.27
-reactos/dll/win32/msi # Synced to Wine-1.7.27
+reactos/dll/win32/msi # Synced to WineStaging-1.7.37
reactos/dll/win32/msimg32 # Synced to Wine-1.7.27
reactos/dll/win32/msimtf # Synced to Wine-1.7.27
reactos/dll/win32/msisip # Synced to Wine-1.7.27