msi: Resolve file source paths dynamically, as the source directory can be changed.
This commit is contained in:
parent
15c8206118
commit
d15fddf6f5
|
@ -1495,25 +1495,6 @@ static UINT load_file(MSIRECORD *row, LPVOID param)
|
|||
file->IsCompressed = package->WordCount & msidbSumInfoSourceTypeCompressed;
|
||||
}
|
||||
|
||||
if (!file->IsCompressed)
|
||||
{
|
||||
LPWSTR p, path;
|
||||
|
||||
p = resolve_folder(package, file->Component->Directory,
|
||||
TRUE, FALSE, TRUE, NULL);
|
||||
path = build_directory_name(2, p, file->ShortName);
|
||||
|
||||
if (file->LongName &&
|
||||
GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
msi_free(path);
|
||||
path = build_directory_name(2, p, file->LongName);
|
||||
}
|
||||
|
||||
file->SourcePath = path;
|
||||
msi_free(p);
|
||||
}
|
||||
|
||||
load_file_hash(package, file);
|
||||
|
||||
TRACE("File Loaded (%s)\n",debugstr_w(file->File));
|
||||
|
@ -2895,6 +2876,7 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
|
|||
LPWSTR ptr, ptr2;
|
||||
WCHAR source[MAX_PATH];
|
||||
WCHAR base[MAX_PATH];
|
||||
LPWSTR sourcepath;
|
||||
|
||||
static const WCHAR fmt[] = {'%','0','2','d','\\',0};
|
||||
static const WCHAR query[] = {
|
||||
|
@ -2917,8 +2899,10 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
|
|||
ptr = strrchrW(base, '\\');
|
||||
*(ptr + 1) = '\0';
|
||||
|
||||
ptr = file->SourcePath + lstrlenW(base);
|
||||
sourcepath = resolve_file_source(package, file);
|
||||
ptr = sourcepath + lstrlenW(base);
|
||||
lstrcpyW(ptr2, ptr);
|
||||
msi_free(sourcepath);
|
||||
|
||||
msi_reg_set_val_str(hkey, squished_pc, source);
|
||||
}
|
||||
|
@ -5931,7 +5915,6 @@ static UINT ACTION_MsiPublishAssemblies( MSIPACKAGE *package )
|
|||
struct list assemblies = LIST_INIT(assemblies);
|
||||
MSIASSEMBLY *assembly;
|
||||
MSIMEDIAINFO *mi;
|
||||
WCHAR path[MAX_PATH];
|
||||
|
||||
r = load_assemblies(package, &assemblies);
|
||||
if (r != ERROR_SUCCESS)
|
||||
|
@ -5980,11 +5963,13 @@ static UINT ACTION_MsiPublishAssemblies( MSIPACKAGE *package )
|
|||
|
||||
if (!assembly->file->IsCompressed)
|
||||
{
|
||||
lstrcpyW(path, assembly->file->SourcePath);
|
||||
LPWSTR source = resolve_file_source(package, assembly->file);
|
||||
|
||||
r = install_assembly(package, assembly, path);
|
||||
r = install_assembly(package, assembly, source);
|
||||
if (r != ERROR_SUCCESS)
|
||||
ERR("Failed to install assembly\n");
|
||||
|
||||
msi_free(source);
|
||||
}
|
||||
|
||||
/* FIXME: write Installer assembly reg values */
|
||||
|
|
|
@ -126,11 +126,11 @@ static void schedule_install_files(MSIPACKAGE *package)
|
|||
}
|
||||
}
|
||||
|
||||
static UINT copy_file(MSIFILE *file)
|
||||
static UINT copy_file(MSIFILE *file, LPWSTR source)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
ret = CopyFileW(file->SourcePath, file->TargetPath, FALSE);
|
||||
ret = CopyFileW(source, file->TargetPath, FALSE);
|
||||
if (!ret)
|
||||
return GetLastError();
|
||||
|
||||
|
@ -140,14 +140,14 @@ static UINT copy_file(MSIFILE *file)
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT copy_install_file(MSIFILE *file)
|
||||
static UINT copy_install_file(MSIFILE *file, LPWSTR source)
|
||||
{
|
||||
UINT gle;
|
||||
|
||||
TRACE("Copying %s to %s\n", debugstr_w(file->SourcePath),
|
||||
TRACE("Copying %s to %s\n", debugstr_w(source),
|
||||
debugstr_w(file->TargetPath));
|
||||
|
||||
gle = copy_file(file);
|
||||
gle = copy_file(file, source);
|
||||
if (gle == ERROR_SUCCESS)
|
||||
return gle;
|
||||
|
||||
|
@ -160,7 +160,7 @@ static UINT copy_install_file(MSIFILE *file)
|
|||
{
|
||||
SetFileAttributesW(file->TargetPath, FILE_ATTRIBUTE_NORMAL);
|
||||
|
||||
gle = copy_file(file);
|
||||
gle = copy_file(file, source);
|
||||
TRACE("Overwriting existing file: %d\n", gle);
|
||||
}
|
||||
|
||||
|
@ -291,22 +291,28 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
|||
|
||||
if (!file->IsCompressed)
|
||||
{
|
||||
TRACE("file paths %s to %s\n", debugstr_w(file->SourcePath),
|
||||
LPWSTR source = resolve_file_source(package, file);
|
||||
|
||||
TRACE("file paths %s to %s\n", debugstr_w(source),
|
||||
debugstr_w(file->TargetPath));
|
||||
|
||||
msi_file_update_ui(package, file, szInstallFiles);
|
||||
rc = copy_install_file(file);
|
||||
rc = copy_install_file(file, source);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
ERR("Failed to copy %s to %s (%d)\n", debugstr_w(file->SourcePath),
|
||||
ERR("Failed to copy %s to %s (%d)\n", debugstr_w(source),
|
||||
debugstr_w(file->TargetPath), rc);
|
||||
rc = ERROR_INSTALL_FAILURE;
|
||||
msi_free(source);
|
||||
break;
|
||||
}
|
||||
|
||||
msi_free(source);
|
||||
}
|
||||
else if (file->state != msifs_installed)
|
||||
{
|
||||
ERR("compressed file wasn't extracted (%s)\n", debugstr_w(file->TargetPath));
|
||||
ERR("compressed file wasn't extracted (%s)\n",
|
||||
debugstr_w(file->TargetPath));
|
||||
rc = ERROR_INSTALL_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -161,6 +161,25 @@ MSIFOLDER *get_loaded_folder( MSIPACKAGE *package, LPCWSTR dir )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void msi_reset_folders( MSIPACKAGE *package, BOOL source )
|
||||
{
|
||||
MSIFOLDER *folder;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry )
|
||||
{
|
||||
if ( source )
|
||||
{
|
||||
msi_free( folder->ResolvedSource );
|
||||
folder->ResolvedSource = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
msi_free( folder->ResolvedTarget );
|
||||
folder->ResolvedTarget = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static LPWSTR get_source_root( MSIPACKAGE *package )
|
||||
{
|
||||
LPWSTR path, p;
|
||||
|
@ -218,6 +237,34 @@ static void clean_spaces_from_path( LPWSTR p )
|
|||
}
|
||||
}
|
||||
|
||||
LPWSTR resolve_file_source(MSIPACKAGE *package, MSIFILE *file)
|
||||
{
|
||||
LPWSTR p, path;
|
||||
|
||||
TRACE("Working to resolve source of file %s\n", debugstr_w(file->File));
|
||||
|
||||
if (file->IsCompressed)
|
||||
return NULL;
|
||||
|
||||
p = resolve_folder(package, file->Component->Directory,
|
||||
TRUE, FALSE, TRUE, NULL);
|
||||
path = build_directory_name(2, p, file->ShortName);
|
||||
|
||||
if (file->LongName &&
|
||||
GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
msi_free(path);
|
||||
path = build_directory_name(2, p, file->LongName);
|
||||
}
|
||||
|
||||
msi_free(p);
|
||||
|
||||
TRACE("file %s source resolves to %s\n", debugstr_w(file->File),
|
||||
debugstr_w(path));
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
|
||||
BOOL set_prop, BOOL load_prop, MSIFOLDER **folder)
|
||||
{
|
||||
|
@ -518,7 +565,6 @@ void ACTION_free_package_structures( MSIPACKAGE* package)
|
|||
msi_free( file->LongName );
|
||||
msi_free( file->Version );
|
||||
msi_free( file->Language );
|
||||
msi_free( file->SourcePath );
|
||||
msi_free( file->TargetPath );
|
||||
msi_free( file );
|
||||
}
|
||||
|
|
|
@ -453,7 +453,6 @@ typedef struct tagMSIFILE
|
|||
INT Attributes;
|
||||
INT Sequence;
|
||||
msi_file_state state;
|
||||
LPWSTR SourcePath;
|
||||
LPWSTR TargetPath;
|
||||
BOOL IsCompressed;
|
||||
MSIFILEHASHINFO hash;
|
||||
|
@ -969,10 +968,12 @@ extern LPWSTR msi_dup_property(MSIPACKAGE *package, LPCWSTR prop);
|
|||
extern int msi_get_property_int( MSIPACKAGE *package, LPCWSTR prop, int def );
|
||||
extern LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
|
||||
BOOL set_prop, BOOL load_prop, MSIFOLDER **folder);
|
||||
extern LPWSTR resolve_file_source(MSIPACKAGE *package, MSIFILE *file);
|
||||
extern MSICOMPONENT *get_loaded_component( MSIPACKAGE* package, LPCWSTR Component );
|
||||
extern MSIFEATURE *get_loaded_feature( MSIPACKAGE* package, LPCWSTR Feature );
|
||||
extern MSIFILE *get_loaded_file( MSIPACKAGE* package, LPCWSTR file );
|
||||
extern MSIFOLDER *get_loaded_folder( MSIPACKAGE *package, LPCWSTR dir );
|
||||
extern void msi_reset_folders( MSIPACKAGE *package, BOOL source );
|
||||
extern int track_tempfile(MSIPACKAGE *package, LPCWSTR path);
|
||||
extern UINT schedule_action(MSIPACKAGE *package, UINT script, LPCWSTR action);
|
||||
extern void msi_free_action_script(MSIPACKAGE *package, UINT script);
|
||||
|
|
|
@ -1345,6 +1345,9 @@ UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
|
|||
|
||||
msiobj_release(&row->hdr);
|
||||
|
||||
if (rc == ERROR_SUCCESS && (!lstrcmpW(szName, cszSourceDir)))
|
||||
msi_reset_folders(package, TRUE);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -648,7 +648,9 @@ static const CHAR ca51_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
|
|||
"GoodSetProperty\t\t725\n"
|
||||
"BadSetProperty\t\t750\n"
|
||||
"CostInitialize\t\t800\n"
|
||||
"ResolveSource\t\t810\n"
|
||||
"FileCost\t\t900\n"
|
||||
"SetSourceDir\tSRCDIR\t910\n"
|
||||
"CostFinalize\t\t1000\n"
|
||||
"InstallValidate\t\t1400\n"
|
||||
"InstallInitialize\t\t1500\n"
|
||||
|
@ -659,7 +661,8 @@ static const CHAR ca51_custom_action_dat[] = "Action\tType\tSource\tTarget\n"
|
|||
"s72\ti2\tS64\tS0\n"
|
||||
"CustomAction\tAction\n"
|
||||
"GoodSetProperty\t51\tMYPROP\t42\n"
|
||||
"BadSetProperty\t51\t\tMYPROP\n";
|
||||
"BadSetProperty\t51\t\tMYPROP\n"
|
||||
"SetSourceDir\t51\tSourceDir\t[SRCDIR]\n";
|
||||
|
||||
static const CHAR is_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
|
||||
"s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
|
||||
|
@ -5434,6 +5437,43 @@ static void test_missingcomponent(void)
|
|||
RemoveDirectoryA("msitest");
|
||||
}
|
||||
|
||||
static void test_sourcedirprop(void)
|
||||
{
|
||||
UINT r;
|
||||
CHAR props[MAX_PATH];
|
||||
|
||||
CreateDirectoryA("msitest", NULL);
|
||||
create_file("msitest\\augustus", 500);
|
||||
|
||||
create_database(msifile, ca51_tables, sizeof(ca51_tables) / sizeof(msi_table));
|
||||
|
||||
MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
|
||||
|
||||
r = MsiInstallProductA(msifile, NULL);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
|
||||
ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
|
||||
ok(delete_pf("msitest", FALSE), "File installed\n");
|
||||
|
||||
DeleteFile("msitest\\augustus");
|
||||
RemoveDirectory("msitest");
|
||||
|
||||
CreateDirectoryA("altsource", NULL);
|
||||
CreateDirectoryA("altsource\\msitest", NULL);
|
||||
create_file("altsource\\msitest\\augustus", 500);
|
||||
|
||||
sprintf(props, "SRCDIR=%s\\altsource\\", CURR_DIR);
|
||||
|
||||
r = MsiInstallProductA(msifile, props);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
|
||||
ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
|
||||
ok(delete_pf("msitest", FALSE), "File installed\n");
|
||||
|
||||
DeleteFile(msifile);
|
||||
DeleteFile("altsource\\msitest\\augustus");
|
||||
RemoveDirectory("altsource\\msitest");
|
||||
RemoveDirectory("altsource");
|
||||
}
|
||||
|
||||
START_TEST(install)
|
||||
{
|
||||
DWORD len;
|
||||
|
@ -5504,6 +5544,7 @@ START_TEST(install)
|
|||
test_sourcepath();
|
||||
test_MsiConfigureProductEx();
|
||||
test_missingcomponent();
|
||||
test_sourcedirprop();
|
||||
|
||||
DeleteFileA("msitest.log");
|
||||
|
||||
|
|
Loading…
Reference in New Issue