Commit d15fddf6 authored by James Hawkins's avatar James Hawkins Committed by Alexandre Julliard

msi: Resolve file source paths dynamically, as the source directory can be changed.

parent 15c82061
......@@ -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");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment