* Sync to Wine 1.5.4.

svn path=/trunk/; revision=56588
This commit is contained in:
Amine Khaldi 2012-05-14 21:41:31 +00:00
parent 87fa6c0693
commit 1ead8de25d
22 changed files with 1390 additions and 790 deletions

View file

@ -7,7 +7,6 @@ add_definitions(-D__WINESRC__ -DMSIRUNMODE=MSIRUNMODE_T)
remove_definitions(-D_WIN32_WINNT=0x502)
add_definitions(-D_WIN32_WINNT=0x600)
set_rc_compiler()
spec2def(msi.dll msi.spec ADD_IMPORTLIB)
generate_idl_iids(msiserver.idl)
@ -98,5 +97,3 @@ add_pch(msi msipriv.h)
add_cd_file(TARGET msi DESTINATION reactos/system32 FOR all)
endif(NOT MSVC)

View file

@ -222,7 +222,6 @@ static int parse_prop( const WCHAR *str, WCHAR *value, int *quotes )
switch (*p)
{
case ' ':
if (!count) goto done;
in_quotes = 1;
ignore = 1;
len++;
@ -234,8 +233,7 @@ static int parse_prop( const WCHAR *str, WCHAR *value, int *quotes )
break;
default:
state = state_token;
if (!count) in_quotes = 0;
else in_quotes = 1;
in_quotes = 1;
len++;
break;
}
@ -482,8 +480,7 @@ UINT msi_set_sourcedir_props(MSIPACKAGE *package, BOOL replace)
static BOOL needs_ui_sequence(MSIPACKAGE *package)
{
INT level = msi_get_property_int(package->db, szUILevel, 0);
return (level & INSTALLUILEVEL_MASK) >= INSTALLUILEVEL_REDUCED;
return (package->ui_level & INSTALLUILEVEL_MASK) >= INSTALLUILEVEL_REDUCED;
}
UINT msi_set_context(MSIPACKAGE *package)
@ -539,6 +536,12 @@ static UINT ITERATE_Actions(MSIRECORD *row, LPVOID param)
if (rc != ERROR_SUCCESS)
ERR("Execution halted, action %s returned %i\n", debugstr_w(action), rc);
if (package->need_reboot_now)
{
TRACE("action %s asked for immediate reboot, suspending installation\n",
debugstr_w(action));
rc = ACTION_ForceReboot( package );
}
return rc;
}
@ -881,6 +884,20 @@ static UINT ACTION_CreateFolders(MSIPACKAGE *package)
return rc;
}
static void remove_persistent_folder( MSIFOLDER *folder )
{
FolderList *fl;
LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry )
{
remove_persistent_folder( fl->folder );
}
if (folder->persistent && folder->State != FOLDER_STATE_REMOVED)
{
if (RemoveDirectoryW( folder->ResolvedTarget )) folder->State = FOLDER_STATE_REMOVED;
}
}
static UINT ITERATE_RemoveFolders( MSIRECORD *row, LPVOID param )
{
MSIPACKAGE *package = param;
@ -924,9 +941,8 @@ static UINT ITERATE_RemoveFolders( MSIRECORD *row, LPVOID param )
msi_ui_actiondata( package, szRemoveFolders, uirow );
msiobj_release( &uirow->hdr );
RemoveDirectoryW( full_path );
folder = msi_get_loaded_folder( package, dir );
folder->State = FOLDER_STATE_REMOVED;
remove_persistent_folder( folder );
return ERROR_SUCCESS;
}
@ -1617,16 +1633,19 @@ static void ACTION_GetComponentInstallStates(MSIPACKAGE *package)
r = MsiQueryComponentStateW( package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERMANAGED, comp->ComponentId,
&comp->Installed );
if (r != ERROR_SUCCESS)
r = MsiQueryComponentStateW( package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERUNMANAGED, comp->ComponentId,
&comp->Installed );
if (r != ERROR_SUCCESS)
r = MsiQueryComponentStateW( package->ProductCode, NULL,
MSIINSTALLCONTEXT_MACHINE, comp->ComponentId,
&comp->Installed );
if (r != ERROR_SUCCESS)
comp->Installed = INSTALLSTATE_ABSENT;
if (r == ERROR_SUCCESS) continue;
r = MsiQueryComponentStateW( package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERUNMANAGED, comp->ComponentId,
&comp->Installed );
if (r == ERROR_SUCCESS) continue;
r = MsiQueryComponentStateW( package->ProductCode, NULL,
MSIINSTALLCONTEXT_MACHINE, comp->ComponentId,
&comp->Installed );
if (r == ERROR_SUCCESS) continue;
comp->Installed = INSTALLSTATE_ABSENT;
}
}
@ -1795,6 +1814,9 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
}
else if (fl->feature->Attributes & msidbFeatureAttributesFollowParent)
{
TRACE("feature %s (level %d request %d) follows parent %s (level %d request %d)\n",
debugstr_w(fl->feature->Feature), fl->feature->Level, fl->feature->ActionRequest,
debugstr_w(feature->Feature), feature->Level, feature->ActionRequest);
fl->feature->Action = feature->Action;
fl->feature->ActionRequest = feature->ActionRequest;
}
@ -1825,12 +1847,14 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
{
FeatureList *fl;
if (!is_feature_selected( feature, level )) continue;
LIST_FOR_EACH_ENTRY( fl, &feature->Children, FeatureList, entry )
{
if (fl->feature->Attributes & msidbFeatureAttributesFollowParent)
if (fl->feature->Attributes & msidbFeatureAttributesFollowParent &&
(!(feature->Attributes & msidbFeatureAttributesFavorAdvertise)))
{
TRACE("feature %s (level %d request %d) follows parent %s (level %d request %d)\n",
debugstr_w(fl->feature->Feature), fl->feature->Level, fl->feature->ActionRequest,
debugstr_w(feature->Feature), feature->Level, feature->ActionRequest);
fl->feature->Action = feature->Action;
fl->feature->ActionRequest = feature->ActionRequest;
}
@ -1843,7 +1867,7 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
{
ComponentList *cl;
TRACE("Examining Feature %s (Level %d Installed %d Request %d Action %d)\n",
TRACE("examining feature %s (level %d installed %d request %d action %d)\n",
debugstr_w(feature->Feature), feature->Level, feature->Installed,
feature->ActionRequest, feature->Action);
@ -1958,7 +1982,7 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
component->ActionRequest = INSTALLSTATE_UNKNOWN;
}
TRACE("Result: Component %s (Installed %d Request %d Action %d)\n",
TRACE("component %s (installed %d request %d action %d)\n",
debugstr_w(component->Component), component->Installed, component->ActionRequest, component->Action);
}
@ -2214,11 +2238,15 @@ static UINT calculate_file_cost( MSIPACKAGE *package )
return ERROR_SUCCESS;
}
void msi_clean_path( WCHAR *p )
WCHAR *msi_normalize_path( const WCHAR *in )
{
WCHAR *q = p;
int n, len = 0;
const WCHAR *p = in;
WCHAR *q, *ret;
int n, len = strlenW( in ) + 2;
if (!(q = ret = msi_alloc( len * sizeof(WCHAR) ))) return NULL;
len = 0;
while (1)
{
/* copy until the end of the string or a space */
@ -2245,32 +2273,20 @@ void msi_clean_path( WCHAR *p )
else /* copy n spaces */
while (n && (*q++ = *p++)) n--;
}
}
static WCHAR *get_target_dir_property( MSIDATABASE *db )
{
int len;
WCHAR *path, *target_dir = msi_dup_property( db, szTargetDir );
if (!target_dir) return NULL;
len = strlenW( target_dir );
if (target_dir[len - 1] == '\\') return target_dir;
if ((path = msi_alloc( (len + 2) * sizeof(WCHAR) )))
while (q - ret > 0 && q[-1] == ' ') q--;
if (q - ret > 0 && q[-1] != '\\')
{
strcpyW( path, target_dir );
path[len] = '\\';
path[len + 1] = 0;
q[0] = '\\';
q[1] = 0;
}
msi_free( target_dir );
return path;
return ret;
}
void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL load_prop )
{
FolderList *fl;
MSIFOLDER *folder, *parent, *child;
WCHAR *path;
WCHAR *path, *normalized_path;
TRACE("resolving %s\n", debugstr_w(name));
@ -2278,7 +2294,7 @@ void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL loa
if (!strcmpW( folder->Directory, szTargetDir )) /* special resolving for target root dir */
{
if (!load_prop || !(path = get_target_dir_property( package->db )))
if (!load_prop || !(path = msi_dup_property( package->db, szTargetDir )))
{
path = msi_dup_property( package->db, szRootDrive );
}
@ -2293,16 +2309,17 @@ void msi_resolve_target_folder( MSIPACKAGE *package, const WCHAR *name, BOOL loa
else
path = msi_build_directory_name( 2, folder->TargetDefault, NULL );
}
msi_clean_path( path );
if (folder->ResolvedTarget && !strcmpiW( path, folder->ResolvedTarget ))
normalized_path = msi_normalize_path( path );
msi_free( path );
if (folder->ResolvedTarget && !strcmpiW( normalized_path, folder->ResolvedTarget ))
{
TRACE("%s already resolved to %s\n", debugstr_w(name), debugstr_w(folder->ResolvedTarget));
msi_free( path );
msi_free( normalized_path );
return;
}
msi_set_property( package->db, folder->Directory, path );
msi_set_property( package->db, folder->Directory, normalized_path );
msi_free( folder->ResolvedTarget );
folder->ResolvedTarget = path;
folder->ResolvedTarget = normalized_path;
LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry )
{
@ -2953,7 +2970,7 @@ static UINT ITERATE_LaunchConditions(MSIRECORD *row, LPVOID param)
r = MSI_EvaluateConditionW(package,cond);
if (r == MSICONDITION_FALSE)
{
if ((gUILevel & INSTALLUILEVEL_MASK) != INSTALLUILEVEL_NONE)
if ((package->ui_level & INSTALLUILEVEL_MASK) != INSTALLUILEVEL_NONE)
{
LPWSTR deformated;
message = MSI_RecordGetString(row,2);
@ -3608,25 +3625,9 @@ static UINT ITERATE_CreateShortcuts(MSIRECORD *row, LPVOID param)
target = MSI_RecordGetString(row, 5);
if (strchrW(target, '['))
{
int len;
WCHAR *format_string, *p;
if (!(p = strchrW( target, ']' ))) goto err;
len = p - target + 1;
format_string = msi_alloc( (len + 1) * sizeof(WCHAR) );
memcpy( format_string, target, len * sizeof(WCHAR) );
format_string[len] = 0;
deformat_string( package, format_string, &deformated );
msi_free( format_string );
path = msi_alloc( (strlenW( deformated ) + strlenW( p + 1 ) + 2) * sizeof(WCHAR) );
strcpyW( path, deformated );
PathAddBackslashW( path );
strcatW( path, p + 1 );
deformat_string( package, target, &path );
TRACE("target path is %s\n", debugstr_w(path));
IShellLinkW_SetPath( sl, path );
msi_free( deformated );
msi_free( path );
}
else
@ -4479,7 +4480,7 @@ static UINT ITERATE_SelfRegModules(MSIRECORD *row, LPVOID param)
MSIFILE *file;
MSIRECORD *uirow;
filename = MSI_RecordGetString(row,1);
filename = MSI_RecordGetString( row, 1 );
file = msi_get_loaded_file( package, filename );
if (!file)
{
@ -4497,7 +4498,7 @@ static UINT ITERATE_SelfRegModules(MSIRECORD *row, LPVOID param)
register_dll( file->TargetPath, FALSE );
uirow = MSI_CreateRecord( 2 );
MSI_RecordSetStringW( uirow, 1, filename );
MSI_RecordSetStringW( uirow, 1, file->File );
MSI_RecordSetStringW( uirow, 2, file->Component->Directory );
msi_ui_actiondata( package, szSelfRegModules, uirow );
msiobj_release( &uirow->hdr );
@ -4547,7 +4548,7 @@ static UINT ITERATE_SelfUnregModules( MSIRECORD *row, LPVOID param )
register_dll( file->TargetPath, TRUE );
uirow = MSI_CreateRecord( 2 );
MSI_RecordSetStringW( uirow, 1, filename );
MSI_RecordSetStringW( uirow, 1, file->File );
MSI_RecordSetStringW( uirow, 2, file->Component->Directory );
msi_ui_actiondata( package, szSelfUnregModules, uirow );
msiobj_release( &uirow->hdr );
@ -5933,28 +5934,25 @@ static UINT ITERATE_DeleteService( MSIRECORD *rec, LPVOID param )
MSIPACKAGE *package = param;
MSICOMPONENT *comp;
MSIRECORD *uirow;
LPCWSTR component;
LPWSTR name = NULL, display_name = NULL;
DWORD event, len;
SC_HANDLE scm = NULL, service = NULL;
event = MSI_RecordGetInteger( rec, 3 );
if (!(event & msidbServiceControlEventDelete))
return ERROR_SUCCESS;
component = MSI_RecordGetString(rec, 6);
comp = msi_get_loaded_component(package, component);
comp = msi_get_loaded_component( package, MSI_RecordGetString(rec, 6) );
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)
if (!(comp->Action == INSTALLSTATE_LOCAL && (event & msidbServiceControlEventDelete)) &&
!(comp->Action == INSTALLSTATE_ABSENT && (event & msidbServiceControlEventUninstallDelete)))
{
TRACE("component not scheduled for removal %s\n", debugstr_w(component));
TRACE("service %s not scheduled for removal\n", debugstr_w(name));
msi_free( name );
return ERROR_SUCCESS;
}
deformat_string( package, MSI_RecordGetString(rec, 2), &name );
stop_service( name );
scm = OpenSCManagerW( NULL, NULL, SC_MANAGER_ALL_ACCESS );
@ -6084,6 +6082,11 @@ static UINT ITERATE_InstallODBCDriver( MSIRECORD *rec, LPVOID param )
ptr += lstrlenW(ptr) + 1;
*ptr = '\0';
if (!driver_file->TargetPath)
{
const WCHAR *dir = msi_get_target_folder( package, driver_file->Component->Directory );
driver_file->TargetPath = msi_build_directory_name( 2, dir, driver_file->FileName );
}
driver_path = strdupW(driver_file->TargetPath);
ptr = strrchrW(driver_path, '\\');
if (ptr) *ptr = '\0';
@ -6907,7 +6910,7 @@ static UINT ACTION_ValidateProductID( MSIPACKAGE *package )
static UINT ACTION_ScheduleReboot( MSIPACKAGE *package )
{
TRACE("\n");
package->need_reboot = 1;
package->need_reboot_at_end = 1;
return ERROR_SUCCESS;
}
@ -7532,7 +7535,7 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
}
msi_free( reinstall );
if (rc == ERROR_SUCCESS && package->need_reboot)
if (rc == ERROR_SUCCESS && package->need_reboot_at_end)
return ERROR_SUCCESS_REBOOT_REQUIRED;
return rc;

View file

@ -608,6 +608,65 @@ static void ACTION_ExpandAnyPath(MSIPACKAGE *package, WCHAR *src, WCHAR *dst,
msi_free(deformatted);
}
static LANGID *parse_languages( const WCHAR *languages, DWORD *num_ids )
{
UINT i, count = 1;
WCHAR *str = strdupW( languages ), *p, *q;
LANGID *ret;
if (!str) return NULL;
for (p = q = str; (q = strchrW( q, ',' )); q++) count++;
if (!(ret = msi_alloc( count * sizeof(LANGID) )))
{
msi_free( str );
return NULL;
}
i = 0;
while (*p)
{
q = strchrW( p, ',' );
if (q) *q = 0;
ret[i] = atoiW( p );
if (!q) break;
p = q + 1;
i++;
}
msi_free( str );
*num_ids = count;
return ret;
}
static BOOL match_languages( const void *version, const WCHAR *languages )
{
struct lang
{
USHORT id;
USHORT codepage;
} *lang;
DWORD len, num_ids, i, j;
BOOL found = FALSE;
LANGID *ids;
if (!languages || !languages[0]) return TRUE;
if (!VerQueryValueW( version, szLangResource, (void **)&lang, &len )) return FALSE;
if (!(ids = parse_languages( languages, &num_ids ))) return FALSE;
for (i = 0; i < num_ids; i++)
{
found = FALSE;
for (j = 0; j < len / sizeof(struct lang); j++)
{
if (!ids[i] || ids[i] == lang[j].id) found = TRUE;
}
if (!found) goto done;
}
done:
msi_free( ids );
return found;
}
/* Sets *matches to whether the file (whose path is filePath) matches the
* versions set in sig.
* Return ERROR_SUCCESS in case of success (whether or not the file matches),
@ -616,69 +675,55 @@ static void ACTION_ExpandAnyPath(MSIPACKAGE *package, WCHAR *src, WCHAR *dst,
static UINT ACTION_FileVersionMatches(const MSISIGNATURE *sig, LPCWSTR filePath,
BOOL *matches)
{
UINT rc = ERROR_SUCCESS;
UINT len;
void *version;
VS_FIXEDFILEINFO *info = NULL;
DWORD zero, size = GetFileVersionInfoSizeW( filePath, &zero );
*matches = FALSE;
if (sig->Languages)
{
FIXME(": need to check version for languages %s\n",
debugstr_w(sig->Languages));
}
else
{
DWORD zero, size = GetFileVersionInfoSizeW(filePath, &zero);
if (size)
if (!size) return ERROR_SUCCESS;
if (!(version = msi_alloc( size ))) return ERROR_OUTOFMEMORY;
if (GetFileVersionInfoW( filePath, 0, size, version ))
VerQueryValueW( version, szBackSlash, (void **)&info, &len );
if (info)
{
TRACE("comparing file version %d.%d.%d.%d:\n",
HIWORD(info->dwFileVersionMS),
LOWORD(info->dwFileVersionMS),
HIWORD(info->dwFileVersionLS),
LOWORD(info->dwFileVersionLS));
if (info->dwFileVersionMS < sig->MinVersionMS
|| (info->dwFileVersionMS == sig->MinVersionMS &&
info->dwFileVersionLS < sig->MinVersionLS))
{
LPVOID buf = msi_alloc( size);
if (buf)
{
UINT versionLen;
LPVOID subBlock = NULL;
if (GetFileVersionInfoW(filePath, 0, size, buf))
VerQueryValueW(buf, szBackSlash, &subBlock, &versionLen);
if (subBlock)
{
VS_FIXEDFILEINFO *info = subBlock;
TRACE("Comparing file version %d.%d.%d.%d:\n",
HIWORD(info->dwFileVersionMS),
LOWORD(info->dwFileVersionMS),
HIWORD(info->dwFileVersionLS),
LOWORD(info->dwFileVersionLS));
if (info->dwFileVersionMS < sig->MinVersionMS
|| (info->dwFileVersionMS == sig->MinVersionMS &&
info->dwFileVersionLS < sig->MinVersionLS))
{
TRACE("Less than minimum version %d.%d.%d.%d\n",
HIWORD(sig->MinVersionMS),
LOWORD(sig->MinVersionMS),
HIWORD(sig->MinVersionLS),
LOWORD(sig->MinVersionLS));
}
else if ((sig->MaxVersionMS || sig->MaxVersionLS) &&
(info->dwFileVersionMS > sig->MaxVersionMS ||
(info->dwFileVersionMS == sig->MaxVersionMS &&
info->dwFileVersionLS > sig->MaxVersionLS)))
{
TRACE("Greater than maximum version %d.%d.%d.%d\n",
HIWORD(sig->MaxVersionMS),
LOWORD(sig->MaxVersionMS),
HIWORD(sig->MaxVersionLS),
LOWORD(sig->MaxVersionLS));
}
else
*matches = TRUE;
}
msi_free( buf);
}
else
rc = ERROR_OUTOFMEMORY;
TRACE("less than minimum version %d.%d.%d.%d\n",
HIWORD(sig->MinVersionMS),
LOWORD(sig->MinVersionMS),
HIWORD(sig->MinVersionLS),
LOWORD(sig->MinVersionLS));
}
else if ((sig->MaxVersionMS || sig->MaxVersionLS) &&
(info->dwFileVersionMS > sig->MaxVersionMS ||
(info->dwFileVersionMS == sig->MaxVersionMS &&
info->dwFileVersionLS > sig->MaxVersionLS)))
{
TRACE("greater than maximum version %d.%d.%d.%d\n",
HIWORD(sig->MaxVersionMS),
LOWORD(sig->MaxVersionMS),
HIWORD(sig->MaxVersionLS),
LOWORD(sig->MaxVersionLS));
}
else if (!match_languages( version, sig->Languages ))
{
TRACE("languages %s not supported\n", debugstr_w( sig->Languages ));
}
else *matches = TRUE;
}
return rc;
msi_free( version );
return ERROR_SUCCESS;
}
/* Sets *matches to whether the file in findData matches that in sig.

View file

@ -262,13 +262,13 @@ static BOOL is_assembly_installed( IAssemblyCache *cache, const WCHAR *display_n
memset( &info, 0, sizeof(info) );
info.cbAssemblyInfo = sizeof(info);
hr = IAssemblyCache_QueryAssemblyInfo( cache, QUERYASMINFO_FLAG_GETSIZE, display_name, &info );
if (hr != HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ))
hr = IAssemblyCache_QueryAssemblyInfo( cache, 0, display_name, &info );
if (hr == S_OK /* sxs version */ || hr == HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ))
{
TRACE("QueryAssemblyInfo returned 0x%08x\n", hr);
return FALSE;
return (info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED);
}
return (info.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED);
TRACE("QueryAssemblyInfo returned 0x%08x\n", hr);
return FALSE;
}
static const WCHAR clr_version_v10[] = {'v','1','.','0','.','3','7','0','5',0};
@ -425,6 +425,45 @@ UINT msi_install_assembly( MSIPACKAGE *package, MSICOMPONENT *comp )
return ERROR_SUCCESS;
}
UINT msi_uninstall_assembly( MSIPACKAGE *package, MSICOMPONENT *comp )
{
HRESULT hr;
IAssemblyCache *cache;
MSIASSEMBLY *assembly = comp->assembly;
MSIFEATURE *feature = NULL;
if (comp->assembly->feature)
feature = msi_get_loaded_feature( package, comp->assembly->feature );
if (assembly->application)
{
if (feature) feature->Action = INSTALLSTATE_ABSENT;
return ERROR_SUCCESS;
}
TRACE("removing %s\n", debugstr_w(assembly->display_name));
if (assembly->attributes == msidbAssemblyAttributesWin32)
{
cache = package->cache_sxs;
hr = IAssemblyCache_UninstallAssembly( cache, 0, assembly->display_name, NULL, NULL );
if (FAILED( hr )) WARN("failed to uninstall assembly 0x%08x\n", hr);
}
else
{
unsigned int i;
for (i = 0; i < CLR_VERSION_MAX; i++)
{
if (!assembly->clr_version[i]) continue;
cache = package->cache_net[i];
hr = IAssemblyCache_UninstallAssembly( cache, 0, assembly->display_name, NULL, NULL );
if (FAILED( hr )) WARN("failed to uninstall assembly 0x%08x\n", hr);
}
}
if (feature) feature->Action = INSTALLSTATE_ABSENT;
assembly->installed = FALSE;
return ERROR_SUCCESS;
}
static WCHAR *build_local_assembly_path( const WCHAR *filename )
{
UINT i;

File diff suppressed because it is too large Load diff

View file

@ -903,11 +903,11 @@ static UINT HANDLE_CustomType19(MSIPACKAGE *package, LPCWSTR source,
if( row )
{
LPCWSTR error = MSI_RecordGetString( row, 1 );
if ((gUILevel & INSTALLUILEVEL_MASK) != INSTALLUILEVEL_NONE)
if ((package->ui_level & INSTALLUILEVEL_MASK) != INSTALLUILEVEL_NONE)
MessageBoxW( NULL, error, NULL, MB_OK );
msiobj_release( &row->hdr );
}
else if ((gUILevel & INSTALLUILEVEL_MASK) != INSTALLUILEVEL_NONE)
else if ((package->ui_level & INSTALLUILEVEL_MASK) != INSTALLUILEVEL_NONE)
MessageBoxW( NULL, deformated, NULL, MB_OK );
msi_free( deformated );

View file

@ -3978,8 +3978,7 @@ UINT msi_spawn_error_dialog( MSIPACKAGE *package, LPWSTR error_dialog, LPWSTR er
'M','S','I','E','r','r','o','r','D','i','a','l','o','g','R','e','s','u','l','t',0
};
if ( (msi_get_property_int( package->db, szUILevel, 0 ) & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE )
return ERROR_SUCCESS;
if ((package->ui_level & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE) return ERROR_SUCCESS;
if ( !error_dialog )
{

View file

@ -215,7 +215,7 @@ static UINT copy_install_file(MSIPACKAGE *package, MSIFILE *file, LPWSTR source)
MoveFileExW(tmpfileW, file->TargetPath, MOVEFILE_DELAY_UNTIL_REBOOT))
{
file->state = msifs_installed;
package->need_reboot = 1;
package->need_reboot_at_end = 1;
gle = ERROR_SUCCESS;
}
else
@ -247,6 +247,17 @@ static UINT msi_create_directory( MSIPACKAGE *package, const WCHAR *dir )
return ERROR_SUCCESS;
}
static MSIFILE *find_file( MSIPACKAGE *package, const WCHAR *filename )
{
MSIFILE *file;
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
{
if (file->state != msifs_installed && !strcmpiW( filename, file->File )) return file;
}
return NULL;
}
static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
LPWSTR *path, DWORD *attrs, PVOID user)
{
@ -255,8 +266,7 @@ static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
if (action == MSICABEXTRACT_BEGINEXTRACT)
{
f = msi_get_loaded_file(package, file);
if (!f)
if (!(f = find_file( package, file )))
{
TRACE("unknown file in cabinet (%s)\n", debugstr_w(file));
return FALSE;
@ -1298,22 +1308,26 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package )
msi_ui_actiondata( package, szRemoveFiles, uirow );
msiobj_release( &uirow->hdr );
}
msi_init_assembly_caches( package );
LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
{
MSIFOLDER *folder;
comp->Action = msi_get_component_action( package, comp );
if (comp->Action != INSTALLSTATE_ABSENT) continue;
if (comp->assembly && !comp->assembly->application) continue;
if (comp->Attributes & msidbComponentAttributesPermanent)
{
TRACE("permanent component, not removing directory\n");
continue;
}
folder = msi_get_loaded_folder( package, comp->Directory );
remove_folder( folder );
if (comp->assembly && !comp->assembly->application)
msi_uninstall_assembly( package, comp );
else
{
MSIFOLDER *folder = msi_get_loaded_folder( package, comp->Directory );
remove_folder( folder );
}
}
msi_destroy_assembly_caches( package );
return ERROR_SUCCESS;
}

View file

@ -347,16 +347,10 @@ UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder,
return MSI_GetTargetPath( hInstall, szFolder, &path, pcchPathBuf );
}
static WCHAR *get_source_root( MSIDATABASE *db )
static WCHAR *get_source_root( MSIPACKAGE *package )
{
WCHAR *path, *p;
if ((path = msi_dup_property( db, szSourceDir ))) return path;
if ((path = msi_dup_property( db, szDatabase )))
{
if ((p = strrchrW( path, '\\' ))) p[1] = 0;
}
return path;
msi_set_sourcedir_props( package, FALSE );
return msi_dup_property( package->db, szSourceDir );
}
WCHAR *msi_resolve_source_folder( MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder )
@ -372,7 +366,7 @@ WCHAR *msi_resolve_source_folder( MSIPACKAGE *package, const WCHAR *name, MSIFOL
/* special resolving for root dir */
if (!strcmpW( name, szTargetDir ) && !f->ResolvedSource)
{
f->ResolvedSource = get_source_root( package->db );
f->ResolvedSource = get_source_root( package );
}
if (folder) *folder = f;
if (f->ResolvedSource)
@ -388,7 +382,7 @@ WCHAR *msi_resolve_source_folder( MSIPACKAGE *package, const WCHAR *name, MSIFOL
p = msi_resolve_source_folder( package, parent, NULL );
if (package->WordCount & msidbSumInfoSourceTypeCompressed)
path = get_source_root( package->db );
path = get_source_root( package );
else if (package->WordCount & msidbSumInfoSourceTypeSFN)
path = msi_build_directory_name( 3, p, f->SourceShortPath, NULL );
else
@ -559,8 +553,7 @@ static void set_target_path( MSIPACKAGE *package, MSIFOLDER *folder, const WCHAR
MSIFOLDER *child;
WCHAR *target_path;
if (!(target_path = strdupW( path ))) return;
msi_clean_path( target_path );
if (!(target_path = msi_normalize_path( path ))) return;
if (strcmpW( target_path, folder->ResolvedTarget ))
{
msi_free( folder->ResolvedTarget );
@ -578,7 +571,7 @@ static void set_target_path( MSIPACKAGE *package, MSIFOLDER *folder, const WCHAR
UINT MSI_SetTargetPathW( MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolderPath )
{
DWORD attrib, len;
DWORD attrib;
MSIFOLDER *folder;
MSIFILE *file;
@ -593,17 +586,7 @@ UINT MSI_SetTargetPathW( MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolder
}
if (!(folder = msi_get_loaded_folder( package, szFolder ))) return ERROR_DIRECTORY;
len = strlenW( szFolderPath );
if (len && szFolderPath[len - 1] != '\\')
{
WCHAR *path = msi_alloc( (len + 2) * sizeof(WCHAR) );
memcpy( path, szFolderPath, len * sizeof(WCHAR) );
path[len] = '\\';
path[len + 1] = 0;
set_target_path( package, folder, path );
msi_free( path );
}
else set_target_path( package, folder, szFolderPath );
set_target_path( package, folder, szFolderPath );
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
{
@ -778,7 +761,11 @@ BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
break;
case MSIRUNMODE_REBOOTATEND:
r = package->need_reboot;
r = package->need_reboot_at_end;
break;
case MSIRUNMODE_REBOOTNOW:
r = package->need_reboot_now;
break;
case MSIRUNMODE_LOGENABLED:
@ -831,13 +818,13 @@ UINT WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState)
switch (iRunMode)
{
case MSIRUNMODE_REBOOTATEND:
package->need_reboot = 1;
package->need_reboot_at_end = (fState != 0);
r = ERROR_SUCCESS;
break;
case MSIRUNMODE_REBOOTNOW:
FIXME("unimplemented run mode: %d\n", iRunMode);
r = ERROR_FUNCTION_FAILED;
package->need_reboot_now = (fState != 0);
r = ERROR_SUCCESS;
break;
default:

View file

@ -77,9 +77,8 @@ static UINT msi_change_media(MSIPACKAGE *package, MSIMEDIAINFO *mi)
static const WCHAR error_prop[] = {'E','r','r','o','r','D','i','a','l','o','g',0};
if ((msi_get_property_int(package->db, szUILevel, 0) & INSTALLUILEVEL_MASK) ==
INSTALLUILEVEL_NONE && !gUIHandlerA && !gUIHandlerW && !gUIHandlerRecord)
return ERROR_SUCCESS;
if ((package->ui_level & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE &&
!gUIHandlerA && !gUIHandlerW && !gUIHandlerRecord) return ERROR_SUCCESS;
error = msi_build_error_string(package, 1302, 1, mi->disk_prompt);
error_dialog = msi_dup_property(package->db, error_prop);
@ -428,7 +427,7 @@ static INT_PTR cabinet_copy_file(FDINOTIFICATIONTYPE fdint,
goto done;
}
TRACE("extracting %s\n", debugstr_w(path));
TRACE("extracting %s -> %s\n", debugstr_w(data->curfile), debugstr_w(path));
attrs = attrs & (FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
if (!attrs) attrs = FILE_ATTRIBUTE_NORMAL;
@ -478,7 +477,7 @@ static INT_PTR cabinet_copy_file(FDINOTIFICATIONTYPE fdint,
MoveFileExW(path, NULL, MOVEFILE_DELAY_UNTIL_REBOOT) &&
MoveFileExW(tmpfileW, path, MOVEFILE_DELAY_UNTIL_REBOOT))
{
data->package->need_reboot = 1;
data->package->need_reboot_at_end = 1;
}
else
{

View file

@ -42,6 +42,9 @@
#include "wintrust.h"
#include "softpub.h"
#include "initguid.h"
#include "msxml2.h"
#include "wine/debug.h"
#include "wine/unicode.h"
@ -304,7 +307,6 @@ done:
return r;
}
static UINT get_patch_product_codes( LPCWSTR szPatchPackage, WCHAR ***product_codes )
{
MSIHANDLE patch, info = 0;
@ -580,17 +582,66 @@ static UINT MSI_ApplicablePatchW( MSIPACKAGE *package, LPCWSTR patch )
return r;
}
/* IXMLDOMDocument should be set to XPath mode already */
static UINT MSI_ApplicablePatchXML( MSIPACKAGE *package, IXMLDOMDocument *desc )
{
static const WCHAR queryW[] = {'M','s','i','P','a','t','c','h','/',
'T','a','r','g','e','t','P','r','o','d','u','c','t','/',
'T','a','r','g','e','t','P','r','o','d','u','c','t','C','o','d','e',0};
UINT r = ERROR_FUNCTION_FAILED;
IXMLDOMNodeList *list;
LPWSTR product_code;
IXMLDOMNode *node;
HRESULT hr;
BSTR s;
product_code = msi_dup_property( package->db, szProductCode );
if (!product_code)
{
/* FIXME: the property ProductCode should be written into the DB somewhere */
ERR("no product code to check\n");
return ERROR_SUCCESS;
}
s = SysAllocString(queryW);
hr = IXMLDOMDocument_selectNodes( desc, s, &list );
SysFreeString(s);
if (hr != S_OK)
return ERROR_INVALID_PATCH_XML;
while (IXMLDOMNodeList_nextNode( list, &node ) == S_OK && r != ERROR_SUCCESS)
{
hr = IXMLDOMNode_get_text( node, &s );
IXMLDOMNode_Release( node );
if (hr == S_OK)
{
if (!strcmpW( s, product_code )) r = ERROR_SUCCESS;
SysFreeString( s );
}
}
IXMLDOMNodeList_Release( list );
if (r != ERROR_SUCCESS)
TRACE("patch not applicable\n");
msi_free( product_code );
return r;
}
static UINT determine_patch_sequence( MSIPACKAGE *package, DWORD count, MSIPATCHSEQUENCEINFOW *info )
{
IXMLDOMDocument *desc = NULL;
DWORD i;
if (count > 1)
FIXME("patch ordering not supported\n");
for (i = 0; i < count; i++)
{
switch (info[i].ePatchDataType)
{
case MSIPATCH_DATATYPE_PATCHFILE:
{
FIXME("patch ordering not supported\n");
if (MSI_ApplicablePatchW( package, info[i].szPatchData ) != ERROR_SUCCESS)
{
info[i].dwOrder = ~0u;
@ -603,19 +654,72 @@ static UINT determine_patch_sequence( MSIPACKAGE *package, DWORD count, MSIPATCH
}
break;
}
case MSIPATCH_DATATYPE_XMLPATH:
case MSIPATCH_DATATYPE_XMLBLOB:
{
VARIANT_BOOL b;
HRESULT hr;
BSTR s;
if (!desc)
{
hr = CoCreateInstance( &CLSID_DOMDocument30, NULL, CLSCTX_INPROC_SERVER,
&IID_IXMLDOMDocument, (void**)&desc );
if (hr != S_OK)
{
ERR("failed to create DOMDocument30 instance, 0x%08x\n", hr);
return ERROR_FUNCTION_FAILED;
}
}
s = SysAllocString( info[i].szPatchData );
if (info[i].ePatchDataType == MSIPATCH_DATATYPE_XMLPATH)
{
VARIANT src;
V_VT(&src) = VT_BSTR;
V_BSTR(&src) = s;
hr = IXMLDOMDocument_load( desc, src, &b );
}
else
hr = IXMLDOMDocument_loadXML( desc, s, &b );
SysFreeString( s );
if ( hr != S_OK )
{
ERR("failed to parse patch description\n");
IXMLDOMDocument_Release( desc );
break;
}
if (MSI_ApplicablePatchXML( package, desc ) != ERROR_SUCCESS)
{
info[i].dwOrder = ~0u;
info[i].uStatus = ERROR_PATCH_TARGET_NOT_FOUND;
}
else
{
info[i].dwOrder = i;
info[i].uStatus = ERROR_SUCCESS;
}
break;
}
default:
{
FIXME("patch data type %u not supported\n", info[i].ePatchDataType);
FIXME("unknown patch data type %u\n", info[i].ePatchDataType);
info[i].dwOrder = i;
info[i].uStatus = ERROR_SUCCESS;
break;
}
}
TRACE("szPatchData: %s\n", debugstr_w(info[i].szPatchData));
TRACE("ePatchDataType: %u\n", info[i].ePatchDataType);
TRACE("dwOrder: %u\n", info[i].dwOrder);
TRACE("uStatus: %u\n", info[i].uStatus);
}
if (desc) IXMLDOMDocument_Release( desc );
return ERROR_SUCCESS;
}
@ -2008,7 +2112,7 @@ UINT WINAPI MsiQueryComponentStateA(LPCSTR szProductCode,
static BOOL msi_comp_find_prod_key(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
{
UINT r;
HKEY hkey;
HKEY hkey = NULL;
r = MSIREG_OpenProductKey(prodcode, NULL, context, &hkey, FALSE);
RegCloseKey(hkey);
@ -2044,7 +2148,7 @@ static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
return (res == ERROR_SUCCESS);
}
static BOOL msi_comp_find_prodcode(LPWSTR squished_pc,
static UINT msi_comp_find_prodcode(LPWSTR squished_pc,
MSIINSTALLCONTEXT context,
LPCWSTR comp, LPWSTR val, DWORD *sz)
{
@ -2058,14 +2162,14 @@ static BOOL msi_comp_find_prodcode(LPWSTR squished_pc,
r = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE);
if (r != ERROR_SUCCESS)
return FALSE;
return r;
res = RegQueryValueExW(hkey, squished_pc, NULL, NULL, (BYTE *)val, sz);
if (res != ERROR_SUCCESS)
return FALSE;
return res;
RegCloseKey(hkey);
return TRUE;
return res;
}
UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
@ -2073,7 +2177,6 @@ UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
LPCWSTR szComponent, INSTALLSTATE *pdwState)
{
WCHAR squished_pc[GUID_SIZE];
WCHAR val[MAX_PATH];
BOOL found;
DWORD sz;
@ -2104,21 +2207,29 @@ UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
*pdwState = INSTALLSTATE_UNKNOWN;
sz = MAX_PATH;
if (!msi_comp_find_prodcode(squished_pc, dwContext, szComponent, val, &sz))
sz = 0;
if (msi_comp_find_prodcode(squished_pc, dwContext, szComponent, NULL, &sz))
return ERROR_UNKNOWN_COMPONENT;
if (sz == 0)
*pdwState = INSTALLSTATE_NOTUSED;
else
{
WCHAR *val;
UINT r;
if (!(val = msi_alloc( sz ))) return ERROR_OUTOFMEMORY;
if ((r = msi_comp_find_prodcode(squished_pc, dwContext, szComponent, val, &sz)))
return r;
if (lstrlenW(val) > 2 &&
val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9')
val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9' && val[2] != ':')
{
*pdwState = INSTALLSTATE_SOURCE;
}
else
*pdwState = INSTALLSTATE_LOCAL;
msi_free( val );
}
TRACE("-> %d\n", *pdwState);
@ -2476,6 +2587,7 @@ HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR path, DWORD flags, PCCER
data.dwProvFlags = 0;
data.dwUIContext = WTD_UICONTEXT_INSTALL;
hr = WinVerifyTrustEx( INVALID_HANDLE_VALUE, &generic_verify_v2, &data );
*cert = NULL;
if (FAILED(hr)) goto done;
if (!(signer = WTHelperGetProvSignerFromChain( data.hWVTStateData, 0, FALSE, 0 )))
@ -3021,11 +3133,7 @@ static UINT get_file_version( const WCHAR *path, WCHAR *verbuf, DWORD *verlen,
WCHAR *langbuf, DWORD *langlen )
{
static const WCHAR szVersionResource[] = {'\\',0};
static const WCHAR szVersionFormat[] = {
'%','d','.','%','d','.','%','d','.','%','d',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 szVersionFormat[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
static const WCHAR szLangFormat[] = {'%','d',0};
UINT ret = ERROR_SUCCESS;
DWORD len, error;
@ -3100,18 +3208,18 @@ UINT WINAPI MsiGetFileVersionW( LPCWSTR path, LPWSTR verbuf, LPDWORD verlen,
return ERROR_INVALID_PARAMETER;
ret = get_file_version( path, verbuf, verlen, langbuf, langlen );
if (ret == ERROR_RESOURCE_DATA_NOT_FOUND)
if (ret == ERROR_RESOURCE_DATA_NOT_FOUND && verlen)
{
int len;
WCHAR *version = msi_font_version_from_file( path );
if (!version) return ERROR_FILE_INVALID;
len = strlenW( version );
if (*verlen > len)
if (len >= *verlen) ret = ERROR_MORE_DATA;
else if (verbuf)
{
strcpyW( verbuf, version );
ret = ERROR_SUCCESS;
}
else ret = ERROR_MORE_DATA;
*verlen = len;
msi_free( version );
}
@ -3909,24 +4017,34 @@ UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions,
}
length = GetFileSize( handle, NULL );
mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL );
if (mapping)
if (length)
{
p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length );
if (p)
mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL );
if (mapping)
{
MD5_CTX ctx;
p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length );
if (p)
{
MD5_CTX ctx;
MD5Init( &ctx );
MD5Update( &ctx, p, length );
MD5Final( &ctx );
UnmapViewOfFile( p );
MD5Init( &ctx );
MD5Update( &ctx, p, length );
MD5Final( &ctx );
UnmapViewOfFile( p );
memcpy( pHash->dwData, ctx.digest, sizeof pHash->dwData );
r = ERROR_SUCCESS;
memcpy( pHash->dwData, ctx.digest, sizeof pHash->dwData );
r = ERROR_SUCCESS;
}
CloseHandle( mapping );
}
CloseHandle( mapping );
}
else
{
/* Empty file -> set hash to 0 */
memset( pHash->dwData, 0, sizeof pHash->dwData );
r = ERROR_SUCCESS;
}
CloseHandle( handle );
return r;

View file

@ -24,7 +24,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
STRINGTABLE
{
4 "The specified installation package could not be opened. Please check the file path and try again."
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "path %s not found"
9 "insert disk %s"
10 "Windows Installer %s\n\n\
@ -44,12 +44,12 @@ Advertise a product:\n\
Apply a patch:\n\
\t/p patch_package [property]\n\
\t/p patch_package /a package [property]\n\
Log and UI Modifiers for above commands:\n\
\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n\
Log and user interface modifiers for the above commands:\n\
\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] log_file\n\
\t/q{|n|b|r|f|n+|b+|b-}\n\
Register MSI Service:\n\
Register the MSI Service:\n\
\t/y\n\
Unregister MSI Service:\n\
Unregister the MSI Service:\n\
\t/z\n\
Display this help:\n\
\t/help\n\
@ -82,9 +82,9 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#define WINE_FILEDESCRIPTION_STR "Wine MSI dll"
#define WINE_FILENAME_STR "msi.dll"
#define WINE_FILEVERSION 4,5,6001,22159
#define WINE_FILEVERSION_STR "4.5.6001.22159"
#define WINE_PRODUCTVERSION 4,5,6001,22159
#define WINE_PRODUCTVERSION_STR "4.5.6001.22159"
#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"
#include "wine/wine_common_ver.rc"

View file

@ -80,7 +80,7 @@ HKCR
{
CLSID = s '{000C101D-0000-0000-C000-000000000046}'
}
NoRemove Typelib
{
NoRemove '{000C1092-0000-0000-C000-000000000046}'

View file

@ -282,8 +282,8 @@
286 stdcall MsiEndTransaction(long)
287 stub MsiJoinTransaction
288 stub MsiSetOfflineContextW
289 stub MsiEnumComponentsExA
290 stub MsiEnumComponentsExW
289 stdcall MsiEnumComponentsExA(str long long ptr ptr ptr ptr)
290 stdcall MsiEnumComponentsExW(wstr long long ptr ptr ptr ptr)
291 stub MsiEnumClientsExA
292 stub MsiEnumClientsExW
293 stub MsiGetComponentPathExA

View file

@ -338,7 +338,8 @@ enum platform
{
PLATFORM_INTEL,
PLATFORM_INTEL64,
PLATFORM_X64
PLATFORM_X64,
PLATFORM_ARM
};
enum clr_version
@ -388,6 +389,7 @@ typedef struct tagMSIPACKAGE
LPWSTR localfile;
BOOL delete_on_close;
INSTALLUILEVEL ui_level;
UINT CurrentInstallState;
msi_dialog *dialog;
LPWSTR next_dialog;
@ -405,7 +407,8 @@ typedef struct tagMSIPACKAGE
unsigned char scheduled_action_running : 1;
unsigned char commit_action_running : 1;
unsigned char rollback_action_running : 1;
unsigned char need_reboot : 1;
unsigned char need_reboot_at_end : 1;
unsigned char need_reboot_now : 1;
unsigned char need_rollback : 1;
} MSIPACKAGE;
@ -998,7 +1001,7 @@ extern UINT msi_get_property( MSIDATABASE *, LPCWSTR, LPWSTR, LPDWORD ) DECLSPEC
extern int msi_get_property_int( MSIDATABASE *package, LPCWSTR prop, int def ) DECLSPEC_HIDDEN;
extern WCHAR *msi_resolve_source_folder(MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder) DECLSPEC_HIDDEN;
extern void msi_resolve_target_folder(MSIPACKAGE *package, const WCHAR *name, BOOL load_prop) DECLSPEC_HIDDEN;
extern void msi_clean_path( WCHAR *p ) DECLSPEC_HIDDEN;
extern WCHAR *msi_normalize_path(const WCHAR *) DECLSPEC_HIDDEN;
extern WCHAR *msi_resolve_file_source(MSIPACKAGE *package, MSIFILE *file) DECLSPEC_HIDDEN;
extern const WCHAR *msi_get_target_folder(MSIPACKAGE *package, const WCHAR *name) DECLSPEC_HIDDEN;
extern void msi_reset_folders( MSIPACKAGE *package, BOOL source ) DECLSPEC_HIDDEN;
@ -1024,6 +1027,7 @@ extern UINT msi_create_empty_local_file(LPWSTR path, LPCWSTR suffix) DECLSPEC_HI
extern UINT msi_set_sourcedir_props(MSIPACKAGE *package, BOOL replace) DECLSPEC_HIDDEN;
extern MSIASSEMBLY *msi_load_assembly(MSIPACKAGE *, MSICOMPONENT *) DECLSPEC_HIDDEN;
extern UINT msi_install_assembly(MSIPACKAGE *, MSICOMPONENT *) DECLSPEC_HIDDEN;
extern UINT msi_uninstall_assembly(MSIPACKAGE *, MSICOMPONENT *) DECLSPEC_HIDDEN;
extern BOOL msi_init_assembly_caches(MSIPACKAGE *) DECLSPEC_HIDDEN;
extern void msi_destroy_assembly_caches(MSIPACKAGE *) DECLSPEC_HIDDEN;
extern WCHAR *msi_font_version_from_file(const WCHAR *) DECLSPEC_HIDDEN;
@ -1077,6 +1081,7 @@ static const WCHAR szSOURCEDIR[] = {'S','O','U','R','C','E','D','I','R',0};
static const WCHAR szRootDrive[] = {'R','O','O','T','D','R','I','V','E',0};
static const WCHAR szTargetDir[] = {'T','A','R','G','E','T','D','I','R',0};
static const WCHAR szLocalSid[] = {'S','-','1','-','5','-','1','8',0};
static const WCHAR szAllSid[] = {'S','-','1','-','1','-','0',0};
static const WCHAR szEmpty[] = {0};
static const WCHAR szAll[] = {'A','L','L',0};
static const WCHAR szOne[] = {'1',0};
@ -1147,6 +1152,7 @@ static const WCHAR szIntel[] = {'I','n','t','e','l',0};
static const WCHAR szIntel64[] = {'I','n','t','e','l','6','4',0};
static const WCHAR szX64[] = {'x','6','4',0};
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};
@ -1167,6 +1173,7 @@ static const WCHAR szAppDataFolder[] = {'A','p','p','D','a','t','a','F','o','l',
static const WCHAR szRollbackDisabled[] = {'R','o','l','l','b','a','c','k','D','i','s','a','b','l','e','d',0};
static const WCHAR szName[] = {'N','a','m','e',0};
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};
/* memory allocation macro functions */
static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1);

View file

@ -884,10 +884,9 @@ static VOID set_installer_properties(MSIPACKAGE *package)
GetNativeSystemInfo( &sys_info );
sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel );
msi_set_property( package->db, szIntel, bufstr );
if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
{
msi_set_property( package->db, szIntel, bufstr );
GetSystemDirectoryW( pth, MAX_PATH );
PathAddBackslashW( pth );
msi_set_property( package->db, szSystemFolder, pth );
@ -1154,9 +1153,9 @@ void msi_adjust_privilege_properties( MSIPACKAGE *package )
MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
{
static const WCHAR szpi[] = {'%','i',0};
static const WCHAR fmtW[] = {'%','u',0};
MSIPACKAGE *package;
WCHAR uilevel[10];
WCHAR uilevel[11];
UINT r;
TRACE("%p\n", db);
@ -1181,7 +1180,8 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
set_installed_prop( package );
set_installer_properties( package );
sprintfW(uilevel,szpi,gUILevel);
package->ui_level = gUILevel;
sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK );
msi_set_property(package->db, szUILevel, uilevel);
r = msi_load_summary_properties( package );
@ -1297,6 +1297,8 @@ static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package )
package->platform = PLATFORM_INTEL64;
else if (!strcmpW( template, szX64 ) || !strcmpW( template, szAMD64 ))
package->platform = PLATFORM_X64;
else if (!strcmpW( template, szARM ))
package->platform = PLATFORM_ARM;
else
{
WARN("unknown platform %s\n", debugstr_w(template));
@ -1341,9 +1343,11 @@ static UINT validate_package( MSIPACKAGE *package )
UINT i;
if (package->platform == PLATFORM_INTEL64)
{
return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
}
#ifndef __arm__
if (package->platform == PLATFORM_ARM)
return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
#endif
IsWow64Process( GetCurrentProcess(), &is_wow64 );
if (package->platform == PLATFORM_X64)
{
@ -1451,6 +1455,9 @@ static UINT get_registered_local_package( const WCHAR *product, const WCHAR *pac
if (!strcmpiW( package, unsquashed ))
{
WCHAR *filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW );
if (!filename)
goto done;
strcpyW( localfile, filename );
msi_free( filename );
r = ERROR_SUCCESS;
@ -1749,13 +1756,11 @@ MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record )
{
static const WCHAR szActionData[] =
{'A','c','t','i','o','n','D','a','t','a',0};
static const WCHAR szSetProgress[] =
{'S','e','t','P','r','o','g','r','e','s','s',0};
static const WCHAR szActionText[] =
{'A','c','t','i','o','n','T','e','x','t',0};
LPWSTR message;
static const WCHAR szActionData[] = {'A','c','t','i','o','n','D','a','t','a',0};
static const WCHAR szSetProgress[] = {'S','e','t','P','r','o','g','r','e','s','s',0};
static const WCHAR szActionText[] = {'A','c','t','i','o','n','T','e','x','t',0};
MSIRECORD *uirow;
LPWSTR deformated, message;
DWORD i, len, total_len, log_type = 0;
INT rc = 0;
char *msg;
@ -1894,27 +1899,27 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC
switch (eMessageType & 0xff000000)
{
case INSTALLMESSAGE_ACTIONDATA:
/* FIXME: format record here instead of in ui_actiondata to get the
* correct action data for external scripts */
ControlEvent_FireSubscribedEvent(package, szActionData, record);
break;
case INSTALLMESSAGE_ACTIONSTART:
{
MSIRECORD *uirow;
LPWSTR deformated;
LPCWSTR action_text = MSI_RecordGetString(record, 2);
deformat_string(package, action_text, &deformated);
deformat_string(package, MSI_RecordGetString(record, 2), &deformated);
uirow = MSI_CreateRecord(1);
MSI_RecordSetStringW(uirow, 1, deformated);
msi_free(deformated);
ControlEvent_FireSubscribedEvent(package, szActionData, uirow);
msiobj_release(&uirow->hdr);
break;
case INSTALLMESSAGE_ACTIONSTART:
deformat_string(package, MSI_RecordGetString(record, 2), &deformated);
uirow = MSI_CreateRecord(1);
MSI_RecordSetStringW(uirow, 1, deformated);
TRACE("INSTALLMESSAGE_ACTIONSTART: %s\n", debugstr_w(deformated));
msi_free(deformated);
ControlEvent_FireSubscribedEvent(package, szActionText, uirow);
msiobj_release(&uirow->hdr);
break;
}
case INSTALLMESSAGE_PROGRESS:
ControlEvent_FireSubscribedEvent(package, szSetProgress, record);
break;

View file

@ -1139,101 +1139,13 @@ UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
{
static const WCHAR pathW[] = {
'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};
UINT r;
WCHAR szKeyName[SQUISH_GUID_SIZE];
HKEY key;
REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
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;
if (index && index - last_index != 1)
return ERROR_INVALID_PARAMETER;
key = 0;
r = RegCreateKeyExW(HKEY_LOCAL_MACHINE, szInstaller_LocalClassesProducts, 0, NULL, 0, access, NULL, &key, NULL);
if( r != ERROR_SUCCESS ) goto failed;
r = RegQueryInfoKeyW(key, NULL, NULL, NULL, &machine_count, NULL, NULL,
NULL, NULL, NULL, NULL, NULL);
if( r != ERROR_SUCCESS ) goto failed;
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);
key = 0;
if (!(usersid = get_user_sid()))
{
ERR("Failed to retrieve user SID\n");
last_index = 0;
return ERROR_FUNCTION_FAILED;
}
sprintfW(keypath, szInstaller_LocalManaged_fmt, usersid);
LocalFree(usersid);
r = RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &key, NULL);
if( r != ERROR_SUCCESS ) goto failed;
r = RegQueryInfoKeyW(key, NULL, NULL, NULL, &managed_count, NULL, NULL,
NULL, NULL, NULL, NULL, NULL);
if( r != ERROR_SUCCESS ) goto failed;
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);
key = 0;
r = RegCreateKeyW(HKEY_CURRENT_USER, pathW, &key);
if( r != ERROR_SUCCESS ) goto failed;
r = RegQueryInfoKeyW(key, NULL, NULL, NULL, &unmanaged_count, NULL, NULL,
NULL, NULL, NULL, NULL, NULL);
if( r != ERROR_SUCCESS ) goto failed;
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;
}
}
failed:
RegCloseKey(key);
last_index = 0;
return ERROR_NO_MORE_ITEMS;
return MsiEnumProductsExW( NULL, szAllSid, MSIINSTALLCONTEXT_ALL, index, lpguid,
NULL, NULL, NULL );
}
UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index,
@ -1293,7 +1205,9 @@ UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
DWORD r;
WCHAR szwGuid[GUID_SIZE];
TRACE("%d %p\n", index, lpguid);
TRACE("%u, %p\n", index, lpguid);
if (!lpguid) return ERROR_INVALID_PARAMETER;
r = MsiEnumComponentsW(index, szwGuid);
if( r == ERROR_SUCCESS )
@ -1304,22 +1218,222 @@ UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid)
{
HKEY hkey;
REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
WCHAR szKeyName[SQUISH_GUID_SIZE];
DWORD r;
TRACE("%u, %p\n", index, lpguid);
TRACE("%d %p\n", index, lpguid);
if (!lpguid) return ERROR_INVALID_PARAMETER;
r = RegCreateKeyExW(HKEY_LOCAL_MACHINE, szInstaller_Components, 0, NULL, 0, access, NULL, &hkey, NULL);
if( r != ERROR_SUCCESS )
return MsiEnumComponentsExW( szAllSid, MSIINSTALLCONTEXT_ALL, index, lpguid, NULL, NULL, NULL );
}
UINT WINAPI MsiEnumComponentsExA( LPCSTR user_sid, DWORD ctx, DWORD index, CHAR guid[39],
MSIINSTALLCONTEXT *installed_ctx, LPSTR sid, LPDWORD sid_len )
{
UINT r;
WCHAR *user_sidW = NULL, *sidW = NULL, guidW[GUID_SIZE];
TRACE("%s, %u, %u, %p, %p, %p, %p\n", debugstr_a(user_sid), ctx, index, guid, installed_ctx,
sid, sid_len);
if (sid && !sid_len) return ERROR_INVALID_PARAMETER;
if (user_sid && !(user_sidW = strdupAtoW( user_sid ))) return ERROR_OUTOFMEMORY;
if (sid && !(sidW = msi_alloc( *sid_len * sizeof(WCHAR) )))
{
msi_free( user_sidW );
return ERROR_OUTOFMEMORY;
}
r = MsiEnumComponentsExW( user_sidW, ctx, index, guidW, installed_ctx, sidW, sid_len );
if (r == ERROR_SUCCESS)
{
if (guid) WideCharToMultiByte( CP_ACP, 0, guidW, GUID_SIZE, guid, GUID_SIZE, NULL, NULL );
if (sid) WideCharToMultiByte( CP_ACP, 0, sidW, *sid_len + 1, sid, *sid_len + 1, NULL, NULL );
}
msi_free( user_sidW );
msi_free( sidW );
return r;
}
static UINT fetch_machine_component( DWORD ctx, DWORD index, DWORD *idx, WCHAR guid[39],
MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid, LPDWORD sid_len )
{
static const WCHAR componentsW[] =
{'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','\\','U','s','e','r','D','a','t','a','\\',
'S','-','1','-','5','-','1','8','\\','C','o','m','p','o','n','e','n','t','s',0};
UINT r = ERROR_SUCCESS;
WCHAR component[GUID_SIZE];
DWORD i = 0, len_component;
REGSAM access = KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY;
HKEY key_components;
if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, componentsW, 0, access, &key_components ))
return ERROR_NO_MORE_ITEMS;
r = RegEnumKeyW(hkey, index, szKeyName, SQUISH_GUID_SIZE);
if( r == ERROR_SUCCESS )
unsquash_guid(szKeyName, lpguid);
len_component = sizeof(component)/sizeof(component[0]);
while (!RegEnumKeyExW( key_components, i, component, &len_component, NULL, NULL, NULL, NULL ))
{
if (*idx == index) goto found;
(*idx)++;
len_component = sizeof(component)/sizeof(component[0]);
i++;
}
RegCloseKey( key_components );
return ERROR_NO_MORE_ITEMS;
found:
if (sid_len)
{
if (*sid_len < 1)
{
*sid_len = 1;
r = ERROR_MORE_DATA;
}
else if (sid)
{
*sid_len = 0;
sid[0] = 0;
}
}
if (guid) unsquash_guid( component, guid );
if (installed_ctx) *installed_ctx = MSIINSTALLCONTEXT_MACHINE;
RegCloseKey( key_components );
return r;
}
static UINT fetch_user_component( const WCHAR *usersid, DWORD ctx, DWORD index, DWORD *idx,
WCHAR guid[39], MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid,
LPDWORD sid_len )
{
static const WCHAR userdataW[] =
{'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','\\','U','s','e','r','D','a','t','a',0};
static const WCHAR componentsW[] = {'\\','C','o','m','p','o','n','e','n','t','s',0};
UINT r = ERROR_SUCCESS;
WCHAR path[MAX_PATH], component[GUID_SIZE], user[128];
DWORD i = 0, j = 0, len_component, len_user;
REGSAM access = KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY;
HKEY key_users, key_components;
if (ctx == MSIINSTALLCONTEXT_USERMANAGED) /* FIXME: were to find these? */
return ERROR_NO_MORE_ITEMS;
if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, userdataW, 0, access, &key_users ))
return ERROR_NO_MORE_ITEMS;
len_user = sizeof(user)/sizeof(user[0]);
while (!RegEnumKeyExW( key_users, i, user, &len_user, NULL, NULL, NULL, NULL ))
{
if ((strcmpW( usersid, szAllSid ) && strcmpW( usersid, user )) ||
!strcmpW( szLocalSid, user ))
{
i++;
len_user = sizeof(user)/sizeof(user[0]);
continue;
}
strcpyW( path, user );
strcatW( path, componentsW );
if (RegOpenKeyExW( key_users, path, 0, access, &key_components ))
{
i++;
len_user = sizeof(user)/sizeof(user[0]);
continue;
}
len_component = sizeof(component)/sizeof(component[0]);
while (!RegEnumKeyExW( key_components, j, component, &len_component, NULL, NULL, NULL, NULL ))
{
if (*idx == index) goto found;
(*idx)++;
len_component = sizeof(component)/sizeof(component[0]);
j++;
}
RegCloseKey( key_components );
len_user = sizeof(user)/sizeof(user[0]);
i++;
}
RegCloseKey( key_users );
return ERROR_NO_MORE_ITEMS;
found:
if (sid_len)
{
if (*sid_len < len_user + 1)
{
*sid_len = len_user + 1;
r = ERROR_MORE_DATA;
}
else if (sid)
{
*sid_len = len_user;
strcpyW( sid, user );
}
}
if (guid) unsquash_guid( component, guid );
if (installed_ctx) *installed_ctx = ctx;
RegCloseKey( key_components );
RegCloseKey( key_users );
return r;
}
static UINT enum_components( const WCHAR *usersid, DWORD ctx, DWORD index, DWORD *idx, WCHAR guid[39],
MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid, LPDWORD sid_len )
{
UINT r = ERROR_NO_MORE_ITEMS;
WCHAR *user = NULL;
if (!usersid)
{
usersid = user = get_user_sid();
if (!user) return ERROR_FUNCTION_FAILED;
}
if (ctx & MSIINSTALLCONTEXT_USERMANAGED)
{
r = fetch_user_component( usersid, MSIINSTALLCONTEXT_USERMANAGED, index, idx, guid,
installed_ctx, sid, sid_len );
if (r != ERROR_NO_MORE_ITEMS) goto done;
}
if (ctx & MSIINSTALLCONTEXT_USERUNMANAGED)
{
r = fetch_user_component( usersid, MSIINSTALLCONTEXT_USERUNMANAGED, index, idx, guid,
installed_ctx, sid, sid_len );
if (r != ERROR_NO_MORE_ITEMS) goto done;
}
if (ctx & MSIINSTALLCONTEXT_MACHINE)
{
r = fetch_machine_component( MSIINSTALLCONTEXT_MACHINE, index, idx, guid, installed_ctx,
sid, sid_len );
if (r != ERROR_NO_MORE_ITEMS) goto done;
}
done:
LocalFree( user );
return r;
}
UINT WINAPI MsiEnumComponentsExW( LPCWSTR user_sid, DWORD ctx, DWORD index, WCHAR guid[39],
MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid, LPDWORD sid_len )
{
UINT r;
DWORD idx = 0;
static DWORD last_index;
TRACE("%s, %u, %u, %p, %p, %p, %p\n", debugstr_w(user_sid), ctx, index, guid, installed_ctx,
sid, sid_len);
if ((sid && !sid_len) || !ctx || (user_sid && ctx == MSIINSTALLCONTEXT_MACHINE))
return ERROR_INVALID_PARAMETER;
if (index && index - last_index != 1)
return ERROR_INVALID_PARAMETER;
if (!index) last_index = 0;
r = enum_components( user_sid, ctx, index, &idx, guid, installed_ctx, sid, sid_len );
if (r == ERROR_SUCCESS)
last_index = index;
else
last_index = 0;
RegCloseKey(hkey);
return r;
}
@ -2113,22 +2227,252 @@ done:
return r;
}
UINT WINAPI MsiEnumProductsExA( LPCSTR szProductCode, LPCSTR szUserSid,
DWORD dwContext, DWORD dwIndex, CHAR szInstalledProductCode[39],
MSIINSTALLCONTEXT* pdwInstalledContext, LPSTR szSid, LPDWORD pcchSid)
UINT WINAPI MsiEnumProductsExA( LPCSTR product, LPCSTR usersid, DWORD ctx, DWORD index,
CHAR installed_product[GUID_SIZE],
MSIINSTALLCONTEXT *installed_ctx, LPSTR sid, LPDWORD sid_len )
{
FIXME("%s %s %d %d %p %p %p %p\n", debugstr_a(szProductCode), debugstr_a(szUserSid),
dwContext, dwIndex, szInstalledProductCode, pdwInstalledContext,
szSid, pcchSid);
return ERROR_NO_MORE_ITEMS;
UINT r;
WCHAR installed_productW[GUID_SIZE], *productW = NULL, *usersidW = NULL, *sidW = NULL;
TRACE("%s, %s, %u, %u, %p, %p, %p, %p\n", debugstr_a(product), debugstr_a(usersid),
ctx, index, installed_product, installed_ctx, sid, sid_len);
if (sid && !sid_len) return ERROR_INVALID_PARAMETER;
if (product && !(productW = strdupAtoW( product ))) return ERROR_OUTOFMEMORY;
if (usersid && !(usersidW = strdupAtoW( usersid )))
{
msi_free( productW );
return ERROR_OUTOFMEMORY;
}
if (sid && !(sidW = msi_alloc( *sid_len * sizeof(WCHAR) )))
{
msi_free( usersidW );
msi_free( productW );
return ERROR_OUTOFMEMORY;
}
r = MsiEnumProductsExW( productW, usersidW, ctx, index, installed_productW,
installed_ctx, sidW, sid_len );
if (r == ERROR_SUCCESS)
{
if (installed_product) WideCharToMultiByte( CP_ACP, 0, installed_productW, GUID_SIZE,
installed_product, GUID_SIZE, NULL, NULL );
if (sid) WideCharToMultiByte( CP_ACP, 0, sidW, *sid_len + 1, sid, *sid_len + 1, NULL, NULL );
}
msi_free( productW );
msi_free( usersidW );
msi_free( sidW );
return r;
}
UINT WINAPI MsiEnumProductsExW( LPCWSTR szProductCode, LPCWSTR szUserSid,
DWORD dwContext, DWORD dwIndex, WCHAR szInstalledProductCode[39],
MSIINSTALLCONTEXT* pdwInstalledContext, LPWSTR szSid, LPDWORD pcchSid)
static UINT fetch_machine_product( const WCHAR *match, DWORD index, DWORD *idx,
WCHAR installed_product[GUID_SIZE],
MSIINSTALLCONTEXT *installed_ctx, WCHAR *sid, DWORD *sid_len )
{
FIXME("%s %s %d %d %p %p %p %p\n", debugstr_w(szProductCode), debugstr_w(szUserSid),
dwContext, dwIndex, szInstalledProductCode, pdwInstalledContext,
szSid, pcchSid);
static const WCHAR productsW[] =
{'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};
UINT r;
WCHAR product[GUID_SIZE];
DWORD i = 0, len;
REGSAM access = KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY;
HKEY key;
if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, productsW, 0, access, &key ))
return ERROR_NO_MORE_ITEMS;
len = sizeof(product)/sizeof(product[0]);
while (!RegEnumKeyExW( key, i, product, &len, NULL, NULL, NULL, NULL ))
{
if (match && strcmpW( match, product ))
{
i++;
len = sizeof(product)/sizeof(product[0]);
continue;
}
if (*idx == index) goto found;
(*idx)++;
len = sizeof(product)/sizeof(product[0]);
i++;
}
RegCloseKey( key );
return ERROR_NO_MORE_ITEMS;
found:
if (sid_len && *sid_len < 1)
{
*sid_len = 1;
r = ERROR_MORE_DATA;
}
else
{
if (installed_product) unsquash_guid( product, installed_product );
if (installed_ctx) *installed_ctx = MSIINSTALLCONTEXT_MACHINE;
if (sid)
{
sid[0] = 0;
*sid_len = 0;
}
r = ERROR_SUCCESS;
}
RegCloseKey( key );
return r;
}
static UINT fetch_user_product( const WCHAR *match, const WCHAR *usersid, DWORD ctx, DWORD index,
DWORD *idx, WCHAR installed_product[GUID_SIZE],
MSIINSTALLCONTEXT *installed_ctx, WCHAR *sid, DWORD *sid_len )
{
static const WCHAR managedW[] =
{'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',0};
static const WCHAR managed_productsW[] =
{'\\','I','n','s','t','a','l','l','e','r','\\','P','r','o','d','u','c','t','s',0};
static const WCHAR unmanaged_productsW[] =
{'\\','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};
UINT r;
const WCHAR *subkey;
WCHAR path[MAX_PATH], product[GUID_SIZE], user[128];
DWORD i = 0, j = 0, len_product, len_user;
REGSAM access = KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY;
HKEY key_users, key_products;
if (ctx == MSIINSTALLCONTEXT_USERMANAGED)
{
subkey = managed_productsW;
if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, managedW, 0, access, &key_users ))
return ERROR_NO_MORE_ITEMS;
}
else if (ctx == MSIINSTALLCONTEXT_USERUNMANAGED)
{
subkey = unmanaged_productsW;
if (RegOpenKeyExW( HKEY_USERS, NULL, 0, access, &key_users ))
return ERROR_NO_MORE_ITEMS;
}
else return ERROR_INVALID_PARAMETER;
len_user = sizeof(user)/sizeof(user[0]);
while (!RegEnumKeyExW( key_users, i, user, &len_user, NULL, NULL, NULL, NULL ))
{
if (strcmpW( usersid, user ) && strcmpW( usersid, szAllSid ))
{
i++;
len_user = sizeof(user)/sizeof(user[0]);
continue;
}
strcpyW( path, user );
strcatW( path, subkey );
if (RegOpenKeyExW( key_users, path, 0, access, &key_products ))
{
i++;
len_user = sizeof(user)/sizeof(user[0]);
continue;
}
len_product = sizeof(product)/sizeof(product[0]);
while (!RegEnumKeyExW( key_products, j, product, &len_product, NULL, NULL, NULL, NULL ))
{
if (match && strcmpW( match, product ))
{
j++;
len_product = sizeof(product)/sizeof(product[0]);
continue;
}
if (*idx == index) goto found;
(*idx)++;
len_product = sizeof(product)/sizeof(product[0]);
j++;
}
RegCloseKey( key_products );
len_user = sizeof(user)/sizeof(user[0]);
i++;
}
RegCloseKey( key_users );
return ERROR_NO_MORE_ITEMS;
found:
if (sid_len && *sid_len <= len_user)
{
*sid_len = len_user;
r = ERROR_MORE_DATA;
}
else
{
if (installed_product) unsquash_guid( product, installed_product );
if (installed_ctx) *installed_ctx = ctx;
if (sid)
{
strcpyW( sid, user );
*sid_len = len_user;
}
r = ERROR_SUCCESS;
}
RegCloseKey( key_products );
RegCloseKey( key_users );
return r;
}
static UINT enum_products( const WCHAR *product, const WCHAR *usersid, DWORD ctx, DWORD index,
DWORD *idx, WCHAR installed_product[GUID_SIZE],
MSIINSTALLCONTEXT *installed_ctx, WCHAR *sid, DWORD *sid_len )
{
UINT r = ERROR_NO_MORE_ITEMS;
WCHAR *user = NULL;
if (!usersid)
{
usersid = user = get_user_sid();
if (!user) return ERROR_FUNCTION_FAILED;
}
if (ctx & MSIINSTALLCONTEXT_MACHINE)
{
r = fetch_machine_product( product, index, idx, installed_product, installed_ctx,
sid, sid_len );
if (r != ERROR_NO_MORE_ITEMS) goto done;
}
if (ctx & MSIINSTALLCONTEXT_USERUNMANAGED)
{
r = fetch_user_product( product, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, index,
idx, installed_product, installed_ctx, sid, sid_len );
if (r != ERROR_NO_MORE_ITEMS) goto done;
}
if (ctx & MSIINSTALLCONTEXT_USERMANAGED)
{
r = fetch_user_product( product, usersid, MSIINSTALLCONTEXT_USERMANAGED, index,
idx, installed_product, installed_ctx, sid, sid_len );
if (r != ERROR_NO_MORE_ITEMS) goto done;
}
done:
LocalFree( user );
return r;
}
UINT WINAPI MsiEnumProductsExW( LPCWSTR product, LPCWSTR usersid, DWORD ctx, DWORD index,
WCHAR installed_product[GUID_SIZE],
MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid, LPDWORD sid_len )
{
UINT r;
DWORD idx = 0;
static DWORD last_index;
TRACE("%s, %s, %u, %u, %p, %p, %p, %p\n", debugstr_w(product), debugstr_w(usersid),
ctx, index, installed_product, installed_ctx, sid, sid_len);
if ((sid && !sid_len) || !ctx || (usersid && ctx == MSIINSTALLCONTEXT_MACHINE))
return ERROR_INVALID_PARAMETER;
if (index && index - last_index != 1)
return ERROR_INVALID_PARAMETER;
if (!index) last_index = 0;
r = enum_products( product, usersid, ctx, index, &idx, installed_product, installed_ctx,
sid, sid_len );
if (r == ERROR_SUCCESS)
last_index = index;
else
last_index = 0;
return r;
}

View file

@ -88,10 +88,7 @@ DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function
DISPID dispid;
CLSID clsid;
VARIANT var;
/* Return success by default (if Windows Script not installed) - not native behavior. This
* should be here until we implement wine scripting. */
DWORD ret = ERROR_SUCCESS;
DWORD ret = ERROR_INSTALL_FAILURE;
CoInitialize(NULL);
@ -126,9 +123,6 @@ DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function
goto done;
}
/* If we got this far, Windows Script is installed, so don't return success by default anymore */
ret = ERROR_INSTALL_FAILURE;
/* Get the IActiveScriptParse engine interface */
hr = IActiveScript_QueryInterface(pActiveScript, &IID_IActiveScriptParse, (void **)&pActiveScriptParse);
if (FAILED(hr)) goto done;
@ -142,7 +136,7 @@ DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function
if (FAILED(hr)) goto done;
/* Add the session object */
hr = IActiveScript_AddNamedItem(pActiveScript, szSession, SCRIPTITEM_ISVISIBLE);
hr = IActiveScript_AddNamedItem(pActiveScript, szSession, SCRIPTITEM_GLOBALMEMBERS);
if (FAILED(hr)) goto done;
/* Pass the script to the engine */

View file

@ -156,7 +156,7 @@ static struct expr * EXPR_wildcard( void *info );
/* Line 189 of yacc.c */
#line 153 "sql.tab.c"
#line 161 "sql.tab.c"
/* Enabling traces. */
#ifndef YYDEBUG
@ -267,7 +267,7 @@ typedef union YYSTYPE
/* Line 214 of yacc.c */
#line 264 "sql.tab.c"
#line 272 "sql.tab.c"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */

View file

@ -1766,7 +1766,7 @@ static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
MSIRECORD *rec, UINT row)
{
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
UINT r, column;
UINT r, frow, column;
TRACE("%p %d %p\n", view, eModifyMode, rec );
@ -1811,8 +1811,18 @@ static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
r = msi_table_assign( view, rec );
break;
case MSIMODIFY_REPLACE:
case MSIMODIFY_MERGE:
/* check row that matches this record */
r = msi_table_find_row( tv, rec, &frow, &column );
if (r != ERROR_SUCCESS)
{
r = table_validate_new( tv, rec, NULL );
if (r == ERROR_SUCCESS)
r = TABLE_insert_row( view, rec, -1, FALSE );
}
break;
case MSIMODIFY_REPLACE:
case MSIMODIFY_VALIDATE:
case MSIMODIFY_VALIDATE_FIELD:
case MSIMODIFY_VALIDATE_DELETE:
@ -2185,9 +2195,6 @@ UINT MSI_CommitTables( MSIDATABASE *db )
}
}
/* force everything to reload next time */
free_cached_tables( db );
hr = IStorage_Commit( db->storage, 0 );
if (FAILED( hr ))
{
@ -2501,14 +2508,12 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
string_table *st, TRANSFORMDATA *transform,
UINT bytes_per_strref )
{
UINT rawsize = 0;
BYTE *rawdata = NULL;
MSITABLEVIEW *tv = NULL;
UINT r, n, sz, i, mask;
UINT r, n, sz, i, mask, num_cols, colcol = 0, rawsize = 0;
MSIRECORD *rec = NULL;
UINT colcol = 0;
WCHAR coltable[32];
LPWSTR name;
const WCHAR *name;
if (!transform)
return ERROR_SUCCESS;
@ -2539,18 +2544,18 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
debugstr_w(name), tv->num_cols, tv->row_size, rawsize );
/* interpret the data */
for( n=0; n < rawsize; )
for (n = 0; n < rawsize;)
{
mask = rawdata[n] | (rawdata[n+1] << 8);
if (mask&1)
mask = rawdata[n] | (rawdata[n + 1] << 8);
if (mask & 1)
{
/*
* if the low bit is set, columns are continuous and
* the number of columns is specified in the high byte
*/
sz = 2;
for( i=0; i<tv->num_cols; i++ )
num_cols = mask >> 8;
for (i = 0; i < num_cols; i++)
{
if( (tv->columns[i].type & MSITYPE_STRING) &&
! MSITYPE_IS_BINARY(tv->columns[i].type) )
@ -2570,12 +2575,13 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
* and it means that this row should be deleted.
*/
sz = 2;
for( i=0; i<tv->num_cols; i++ )
num_cols = tv->num_cols;
for (i = 0; i < num_cols; i++)
{
if( (tv->columns[i].type & MSITYPE_KEY) || ((1<<i)&mask))
if ((tv->columns[i].type & MSITYPE_KEY) || ((1 << i) & mask))
{
if( (tv->columns[i].type & MSITYPE_STRING) &&
! MSITYPE_IS_BINARY(tv->columns[i].type) )
if ((tv->columns[i].type & MSITYPE_STRING) &&
!MSITYPE_IS_BINARY(tv->columns[i].type))
sz += bytes_per_strref;
else
sz += bytes_per_column( tv->db, &tv->columns[i], bytes_per_strref );
@ -2584,7 +2590,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
}
/* check we didn't run of the end of the table */
if ( (n+sz) > rawsize )
if (n + sz > rawsize)
{
ERR("borked.\n");
dump_table( st, (USHORT *)rawdata, rawsize );

View file

@ -453,6 +453,12 @@ UINT WINAPI MsiEnumComponentsA(DWORD, LPSTR);
UINT WINAPI MsiEnumComponentsW(DWORD, LPWSTR);
#define MsiEnumComponents WINELIB_NAME_AW(MsiEnumComponents)
UINT WINAPI MsiEnumComponentsExA(LPCSTR, DWORD, DWORD, CHAR[39],
MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
UINT WINAPI MsiEnumComponentsExW(LPCWSTR, DWORD, DWORD, WCHAR[39],
MSIINSTALLCONTEXT *, LPWSTR, LPDWORD);
#define MsiEnumComponentsEx WINELIB_NAME_AW(MsiEnumComponentsEx)
UINT WINAPI MsiEnumClientsA(LPCSTR, DWORD, LPSTR);
UINT WINAPI MsiEnumClientsW(LPCWSTR, DWORD, LPWSTR);
#define MsiEnumClients WINELIB_NAME_AW(MsiEnumClients)

View file

@ -102,7 +102,7 @@ reactos/dll/win32/msg711.acm # Synced to Wine-1.3.37
reactos/dll/win32/msgsm32.acm # Synced to Wine-1.3.37
reactos/dll/win32/mshtml # Autosync
reactos/dll/win32/mshtml.tlb # Autosync
reactos/dll/win32/msi # Synced to Wine-1.3.37
reactos/dll/win32/msi # Synced to Wine-1.5.4
reactos/dll/win32/msimg32 # Synced to Wine-1.3.37
reactos/dll/win32/msimtf # Synced to Wine-1.3.37
reactos/dll/win32/msisip # Synced to Wine-1.3.37