mirror of
https://github.com/reactos/reactos.git
synced 2024-12-30 19:14:31 +00:00
[MSI]
* Sync to Wine 1.5.4. svn path=/trunk/; revision=56588
This commit is contained in:
parent
87fa6c0693
commit
1ead8de25d
22 changed files with 1390 additions and 790 deletions
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
@ -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 );
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -80,7 +80,7 @@ HKCR
|
|||
{
|
||||
CLSID = s '{000C101D-0000-0000-C000-000000000046}'
|
||||
}
|
||||
|
||||
|
||||
NoRemove Typelib
|
||||
{
|
||||
NoRemove '{000C1092-0000-0000-C000-000000000046}'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue