msi: Move the implementation of the MoveFiles action to files.c.
This commit is contained in:
parent
a5549305de
commit
aba6afc85e
|
@ -6266,342 +6266,6 @@ static UINT ACTION_RemoveEnvironmentStrings( MSIPACKAGE *package )
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define is_dot_dir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
struct list entry;
|
|
||||||
LPWSTR sourcename;
|
|
||||||
LPWSTR destname;
|
|
||||||
LPWSTR source;
|
|
||||||
LPWSTR dest;
|
|
||||||
} FILE_LIST;
|
|
||||||
|
|
||||||
static BOOL msi_move_file(LPCWSTR source, LPCWSTR dest, int options)
|
|
||||||
{
|
|
||||||
BOOL ret;
|
|
||||||
|
|
||||||
if (GetFileAttributesW(source) == FILE_ATTRIBUTE_DIRECTORY ||
|
|
||||||
GetFileAttributesW(dest) == FILE_ATTRIBUTE_DIRECTORY)
|
|
||||||
{
|
|
||||||
WARN("Source or dest is directory, not moving\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options == msidbMoveFileOptionsMove)
|
|
||||||
{
|
|
||||||
TRACE("moving %s -> %s\n", debugstr_w(source), debugstr_w(dest));
|
|
||||||
ret = MoveFileExW(source, dest, MOVEFILE_REPLACE_EXISTING);
|
|
||||||
if (!ret)
|
|
||||||
{
|
|
||||||
WARN("MoveFile failed: %d\n", GetLastError());
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TRACE("copying %s -> %s\n", debugstr_w(source), debugstr_w(dest));
|
|
||||||
ret = CopyFileW(source, dest, FALSE);
|
|
||||||
if (!ret)
|
|
||||||
{
|
|
||||||
WARN("CopyFile failed: %d\n", GetLastError());
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static LPWSTR wildcard_to_file(LPWSTR wildcard, LPWSTR filename)
|
|
||||||
{
|
|
||||||
LPWSTR path, ptr;
|
|
||||||
DWORD dirlen, pathlen;
|
|
||||||
|
|
||||||
ptr = strrchrW(wildcard, '\\');
|
|
||||||
dirlen = ptr - wildcard + 1;
|
|
||||||
|
|
||||||
pathlen = dirlen + lstrlenW(filename) + 1;
|
|
||||||
path = msi_alloc(pathlen * sizeof(WCHAR));
|
|
||||||
|
|
||||||
lstrcpynW(path, wildcard, dirlen + 1);
|
|
||||||
lstrcatW(path, filename);
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_file_entry(FILE_LIST *file)
|
|
||||||
{
|
|
||||||
msi_free(file->source);
|
|
||||||
msi_free(file->dest);
|
|
||||||
msi_free(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_list(FILE_LIST *list)
|
|
||||||
{
|
|
||||||
while (!list_empty(&list->entry))
|
|
||||||
{
|
|
||||||
FILE_LIST *file = LIST_ENTRY(list_head(&list->entry), FILE_LIST, entry);
|
|
||||||
|
|
||||||
list_remove(&file->entry);
|
|
||||||
free_file_entry(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL add_wildcard(FILE_LIST *files, LPWSTR source, LPWSTR dest)
|
|
||||||
{
|
|
||||||
FILE_LIST *new, *file;
|
|
||||||
LPWSTR ptr, filename;
|
|
||||||
DWORD size;
|
|
||||||
|
|
||||||
new = msi_alloc_zero(sizeof(FILE_LIST));
|
|
||||||
if (!new)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
new->source = strdupW(source);
|
|
||||||
ptr = strrchrW(dest, '\\') + 1;
|
|
||||||
filename = strrchrW(new->source, '\\') + 1;
|
|
||||||
|
|
||||||
new->sourcename = filename;
|
|
||||||
|
|
||||||
if (*ptr)
|
|
||||||
new->destname = ptr;
|
|
||||||
else
|
|
||||||
new->destname = new->sourcename;
|
|
||||||
|
|
||||||
size = (ptr - dest) + lstrlenW(filename) + 1;
|
|
||||||
new->dest = msi_alloc(size * sizeof(WCHAR));
|
|
||||||
if (!new->dest)
|
|
||||||
{
|
|
||||||
free_file_entry(new);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
lstrcpynW(new->dest, dest, ptr - dest + 1);
|
|
||||||
lstrcatW(new->dest, filename);
|
|
||||||
|
|
||||||
if (list_empty(&files->entry))
|
|
||||||
{
|
|
||||||
list_add_head(&files->entry, &new->entry);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY(file, &files->entry, FILE_LIST, entry)
|
|
||||||
{
|
|
||||||
if (lstrcmpW(source, file->source) < 0)
|
|
||||||
{
|
|
||||||
list_add_before(&file->entry, &new->entry);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list_add_after(&file->entry, &new->entry);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL move_files_wildcard(LPWSTR source, LPWSTR dest, int options)
|
|
||||||
{
|
|
||||||
WIN32_FIND_DATAW wfd;
|
|
||||||
HANDLE hfile;
|
|
||||||
LPWSTR path;
|
|
||||||
BOOL res;
|
|
||||||
FILE_LIST files, *file;
|
|
||||||
DWORD size;
|
|
||||||
|
|
||||||
hfile = FindFirstFileW(source, &wfd);
|
|
||||||
if (hfile == INVALID_HANDLE_VALUE) return FALSE;
|
|
||||||
|
|
||||||
list_init(&files.entry);
|
|
||||||
|
|
||||||
for (res = TRUE; res; res = FindNextFileW(hfile, &wfd))
|
|
||||||
{
|
|
||||||
if (is_dot_dir(wfd.cFileName)) continue;
|
|
||||||
|
|
||||||
path = wildcard_to_file(source, wfd.cFileName);
|
|
||||||
if (!path)
|
|
||||||
{
|
|
||||||
res = FALSE;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
add_wildcard(&files, path, dest);
|
|
||||||
msi_free(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no files match the wildcard */
|
|
||||||
if (list_empty(&files.entry))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* only the first wildcard match gets renamed to dest */
|
|
||||||
file = LIST_ENTRY(list_head(&files.entry), FILE_LIST, entry);
|
|
||||||
size = (strrchrW(file->dest, '\\') - file->dest) + lstrlenW(file->destname) + 2;
|
|
||||||
file->dest = msi_realloc(file->dest, size * sizeof(WCHAR));
|
|
||||||
if (!file->dest)
|
|
||||||
{
|
|
||||||
res = FALSE;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* file->dest may be shorter after the reallocation, so add a NULL
|
|
||||||
* terminator. This is needed for the call to strrchrW, as there will no
|
|
||||||
* longer be a NULL terminator within the bounds of the allocation in this case.
|
|
||||||
*/
|
|
||||||
file->dest[size - 1] = '\0';
|
|
||||||
lstrcpyW(strrchrW(file->dest, '\\') + 1, file->destname);
|
|
||||||
|
|
||||||
while (!list_empty(&files.entry))
|
|
||||||
{
|
|
||||||
file = LIST_ENTRY(list_head(&files.entry), FILE_LIST, entry);
|
|
||||||
|
|
||||||
msi_move_file(file->source, file->dest, options);
|
|
||||||
|
|
||||||
list_remove(&file->entry);
|
|
||||||
free_file_entry(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
res = TRUE;
|
|
||||||
|
|
||||||
done:
|
|
||||||
free_list(&files);
|
|
||||||
FindClose(hfile);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static UINT ITERATE_MoveFiles( MSIRECORD *rec, LPVOID param )
|
|
||||||
{
|
|
||||||
MSIPACKAGE *package = param;
|
|
||||||
MSICOMPONENT *comp;
|
|
||||||
LPCWSTR sourcename, component;
|
|
||||||
LPWSTR destname = NULL;
|
|
||||||
LPWSTR sourcedir = NULL, destdir = NULL;
|
|
||||||
LPWSTR source = NULL, dest = NULL;
|
|
||||||
int options;
|
|
||||||
DWORD size;
|
|
||||||
BOOL ret, wildcards;
|
|
||||||
|
|
||||||
component = MSI_RecordGetString(rec, 2);
|
|
||||||
comp = get_loaded_component(package, component);
|
|
||||||
if (!comp)
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
|
|
||||||
if (comp->ActionRequest != INSTALLSTATE_LOCAL && comp->ActionRequest != INSTALLSTATE_SOURCE)
|
|
||||||
{
|
|
||||||
TRACE("Component not scheduled for installation: %s\n", debugstr_w(component));
|
|
||||||
comp->Action = comp->Installed;
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
comp->Action = comp->ActionRequest;
|
|
||||||
|
|
||||||
sourcename = MSI_RecordGetString(rec, 3);
|
|
||||||
options = MSI_RecordGetInteger(rec, 7);
|
|
||||||
|
|
||||||
sourcedir = msi_dup_property(package, MSI_RecordGetString(rec, 5));
|
|
||||||
if (!sourcedir)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
destdir = msi_dup_property(package, MSI_RecordGetString(rec, 6));
|
|
||||||
if (!destdir)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
if (!sourcename)
|
|
||||||
{
|
|
||||||
if (GetFileAttributesW(sourcedir) == INVALID_FILE_ATTRIBUTES)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
source = strdupW(sourcedir);
|
|
||||||
if (!source)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
size = lstrlenW(sourcedir) + lstrlenW(sourcename) + 2;
|
|
||||||
source = msi_alloc(size * sizeof(WCHAR));
|
|
||||||
if (!source)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
lstrcpyW(source, sourcedir);
|
|
||||||
if (source[lstrlenW(source) - 1] != '\\')
|
|
||||||
lstrcatW(source, szBackSlash);
|
|
||||||
lstrcatW(source, sourcename);
|
|
||||||
}
|
|
||||||
|
|
||||||
wildcards = strchrW(source, '*') || strchrW(source, '?');
|
|
||||||
|
|
||||||
if (MSI_RecordIsNull(rec, 4))
|
|
||||||
{
|
|
||||||
if (!wildcards)
|
|
||||||
{
|
|
||||||
destname = strdupW(sourcename);
|
|
||||||
if (!destname)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
destname = strdupW(MSI_RecordGetString(rec, 4));
|
|
||||||
if (destname)
|
|
||||||
reduce_to_longfilename(destname);
|
|
||||||
}
|
|
||||||
|
|
||||||
size = 0;
|
|
||||||
if (destname)
|
|
||||||
size = lstrlenW(destname);
|
|
||||||
|
|
||||||
size += lstrlenW(destdir) + 2;
|
|
||||||
dest = msi_alloc(size * sizeof(WCHAR));
|
|
||||||
if (!dest)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
lstrcpyW(dest, destdir);
|
|
||||||
if (dest[lstrlenW(dest) - 1] != '\\')
|
|
||||||
lstrcatW(dest, szBackSlash);
|
|
||||||
|
|
||||||
if (destname)
|
|
||||||
lstrcatW(dest, destname);
|
|
||||||
|
|
||||||
if (GetFileAttributesW(destdir) == INVALID_FILE_ATTRIBUTES)
|
|
||||||
{
|
|
||||||
ret = CreateDirectoryW(destdir, NULL);
|
|
||||||
if (!ret)
|
|
||||||
{
|
|
||||||
WARN("CreateDirectory failed: %d\n", GetLastError());
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wildcards)
|
|
||||||
msi_move_file(source, dest, options);
|
|
||||||
else
|
|
||||||
move_files_wildcard(source, dest, options);
|
|
||||||
|
|
||||||
done:
|
|
||||||
msi_free(sourcedir);
|
|
||||||
msi_free(destdir);
|
|
||||||
msi_free(destname);
|
|
||||||
msi_free(source);
|
|
||||||
msi_free(dest);
|
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static UINT ACTION_MoveFiles( MSIPACKAGE *package )
|
|
||||||
{
|
|
||||||
UINT rc;
|
|
||||||
MSIQUERY *view;
|
|
||||||
|
|
||||||
static const WCHAR ExecSeqQuery[] =
|
|
||||||
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
|
||||||
'`','M','o','v','e','F','i','l','e','`',0};
|
|
||||||
|
|
||||||
rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
|
|
||||||
if (rc != ERROR_SUCCESS)
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
|
|
||||||
rc = MSI_IterateRecords(view, NULL, ITERATE_MoveFiles, package);
|
|
||||||
msiobj_release(&view->hdr);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct tagMSIASSEMBLY
|
typedef struct tagMSIASSEMBLY
|
||||||
{
|
{
|
||||||
struct list entry;
|
struct list entry;
|
||||||
|
|
336
dlls/msi/files.c
336
dlls/msi/files.c
|
@ -328,6 +328,342 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define is_dot_dir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
struct list entry;
|
||||||
|
LPWSTR sourcename;
|
||||||
|
LPWSTR destname;
|
||||||
|
LPWSTR source;
|
||||||
|
LPWSTR dest;
|
||||||
|
} FILE_LIST;
|
||||||
|
|
||||||
|
static BOOL msi_move_file(LPCWSTR source, LPCWSTR dest, int options)
|
||||||
|
{
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
if (GetFileAttributesW(source) == FILE_ATTRIBUTE_DIRECTORY ||
|
||||||
|
GetFileAttributesW(dest) == FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
{
|
||||||
|
WARN("Source or dest is directory, not moving\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options == msidbMoveFileOptionsMove)
|
||||||
|
{
|
||||||
|
TRACE("moving %s -> %s\n", debugstr_w(source), debugstr_w(dest));
|
||||||
|
ret = MoveFileExW(source, dest, MOVEFILE_REPLACE_EXISTING);
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
WARN("MoveFile failed: %d\n", GetLastError());
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE("copying %s -> %s\n", debugstr_w(source), debugstr_w(dest));
|
||||||
|
ret = CopyFileW(source, dest, FALSE);
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
WARN("CopyFile failed: %d\n", GetLastError());
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LPWSTR wildcard_to_file(LPWSTR wildcard, LPWSTR filename)
|
||||||
|
{
|
||||||
|
LPWSTR path, ptr;
|
||||||
|
DWORD dirlen, pathlen;
|
||||||
|
|
||||||
|
ptr = strrchrW(wildcard, '\\');
|
||||||
|
dirlen = ptr - wildcard + 1;
|
||||||
|
|
||||||
|
pathlen = dirlen + lstrlenW(filename) + 1;
|
||||||
|
path = msi_alloc(pathlen * sizeof(WCHAR));
|
||||||
|
|
||||||
|
lstrcpynW(path, wildcard, dirlen + 1);
|
||||||
|
lstrcatW(path, filename);
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_file_entry(FILE_LIST *file)
|
||||||
|
{
|
||||||
|
msi_free(file->source);
|
||||||
|
msi_free(file->dest);
|
||||||
|
msi_free(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_list(FILE_LIST *list)
|
||||||
|
{
|
||||||
|
while (!list_empty(&list->entry))
|
||||||
|
{
|
||||||
|
FILE_LIST *file = LIST_ENTRY(list_head(&list->entry), FILE_LIST, entry);
|
||||||
|
|
||||||
|
list_remove(&file->entry);
|
||||||
|
free_file_entry(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL add_wildcard(FILE_LIST *files, LPWSTR source, LPWSTR dest)
|
||||||
|
{
|
||||||
|
FILE_LIST *new, *file;
|
||||||
|
LPWSTR ptr, filename;
|
||||||
|
DWORD size;
|
||||||
|
|
||||||
|
new = msi_alloc_zero(sizeof(FILE_LIST));
|
||||||
|
if (!new)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
new->source = strdupW(source);
|
||||||
|
ptr = strrchrW(dest, '\\') + 1;
|
||||||
|
filename = strrchrW(new->source, '\\') + 1;
|
||||||
|
|
||||||
|
new->sourcename = filename;
|
||||||
|
|
||||||
|
if (*ptr)
|
||||||
|
new->destname = ptr;
|
||||||
|
else
|
||||||
|
new->destname = new->sourcename;
|
||||||
|
|
||||||
|
size = (ptr - dest) + lstrlenW(filename) + 1;
|
||||||
|
new->dest = msi_alloc(size * sizeof(WCHAR));
|
||||||
|
if (!new->dest)
|
||||||
|
{
|
||||||
|
free_file_entry(new);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
lstrcpynW(new->dest, dest, ptr - dest + 1);
|
||||||
|
lstrcatW(new->dest, filename);
|
||||||
|
|
||||||
|
if (list_empty(&files->entry))
|
||||||
|
{
|
||||||
|
list_add_head(&files->entry, &new->entry);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY(file, &files->entry, FILE_LIST, entry)
|
||||||
|
{
|
||||||
|
if (lstrcmpW(source, file->source) < 0)
|
||||||
|
{
|
||||||
|
list_add_before(&file->entry, &new->entry);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list_add_after(&file->entry, &new->entry);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL move_files_wildcard(LPWSTR source, LPWSTR dest, int options)
|
||||||
|
{
|
||||||
|
WIN32_FIND_DATAW wfd;
|
||||||
|
HANDLE hfile;
|
||||||
|
LPWSTR path;
|
||||||
|
BOOL res;
|
||||||
|
FILE_LIST files, *file;
|
||||||
|
DWORD size;
|
||||||
|
|
||||||
|
hfile = FindFirstFileW(source, &wfd);
|
||||||
|
if (hfile == INVALID_HANDLE_VALUE) return FALSE;
|
||||||
|
|
||||||
|
list_init(&files.entry);
|
||||||
|
|
||||||
|
for (res = TRUE; res; res = FindNextFileW(hfile, &wfd))
|
||||||
|
{
|
||||||
|
if (is_dot_dir(wfd.cFileName)) continue;
|
||||||
|
|
||||||
|
path = wildcard_to_file(source, wfd.cFileName);
|
||||||
|
if (!path)
|
||||||
|
{
|
||||||
|
res = FALSE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_wildcard(&files, path, dest);
|
||||||
|
msi_free(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no files match the wildcard */
|
||||||
|
if (list_empty(&files.entry))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* only the first wildcard match gets renamed to dest */
|
||||||
|
file = LIST_ENTRY(list_head(&files.entry), FILE_LIST, entry);
|
||||||
|
size = (strrchrW(file->dest, '\\') - file->dest) + lstrlenW(file->destname) + 2;
|
||||||
|
file->dest = msi_realloc(file->dest, size * sizeof(WCHAR));
|
||||||
|
if (!file->dest)
|
||||||
|
{
|
||||||
|
res = FALSE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* file->dest may be shorter after the reallocation, so add a NULL
|
||||||
|
* terminator. This is needed for the call to strrchrW, as there will no
|
||||||
|
* longer be a NULL terminator within the bounds of the allocation in this case.
|
||||||
|
*/
|
||||||
|
file->dest[size - 1] = '\0';
|
||||||
|
lstrcpyW(strrchrW(file->dest, '\\') + 1, file->destname);
|
||||||
|
|
||||||
|
while (!list_empty(&files.entry))
|
||||||
|
{
|
||||||
|
file = LIST_ENTRY(list_head(&files.entry), FILE_LIST, entry);
|
||||||
|
|
||||||
|
msi_move_file(file->source, file->dest, options);
|
||||||
|
|
||||||
|
list_remove(&file->entry);
|
||||||
|
free_file_entry(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
res = TRUE;
|
||||||
|
|
||||||
|
done:
|
||||||
|
free_list(&files);
|
||||||
|
FindClose(hfile);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT ITERATE_MoveFiles( MSIRECORD *rec, LPVOID param )
|
||||||
|
{
|
||||||
|
MSIPACKAGE *package = param;
|
||||||
|
MSICOMPONENT *comp;
|
||||||
|
LPCWSTR sourcename, component;
|
||||||
|
LPWSTR destname = NULL;
|
||||||
|
LPWSTR sourcedir = NULL, destdir = NULL;
|
||||||
|
LPWSTR source = NULL, dest = NULL;
|
||||||
|
int options;
|
||||||
|
DWORD size;
|
||||||
|
BOOL ret, wildcards;
|
||||||
|
|
||||||
|
component = MSI_RecordGetString(rec, 2);
|
||||||
|
comp = get_loaded_component(package, component);
|
||||||
|
if (!comp)
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if (comp->ActionRequest != INSTALLSTATE_LOCAL && comp->ActionRequest != INSTALLSTATE_SOURCE)
|
||||||
|
{
|
||||||
|
TRACE("Component not scheduled for installation: %s\n", debugstr_w(component));
|
||||||
|
comp->Action = comp->Installed;
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
comp->Action = comp->ActionRequest;
|
||||||
|
|
||||||
|
sourcename = MSI_RecordGetString(rec, 3);
|
||||||
|
options = MSI_RecordGetInteger(rec, 7);
|
||||||
|
|
||||||
|
sourcedir = msi_dup_property(package, MSI_RecordGetString(rec, 5));
|
||||||
|
if (!sourcedir)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
destdir = msi_dup_property(package, MSI_RecordGetString(rec, 6));
|
||||||
|
if (!destdir)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (!sourcename)
|
||||||
|
{
|
||||||
|
if (GetFileAttributesW(sourcedir) == INVALID_FILE_ATTRIBUTES)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
source = strdupW(sourcedir);
|
||||||
|
if (!source)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size = lstrlenW(sourcedir) + lstrlenW(sourcename) + 2;
|
||||||
|
source = msi_alloc(size * sizeof(WCHAR));
|
||||||
|
if (!source)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
lstrcpyW(source, sourcedir);
|
||||||
|
if (source[lstrlenW(source) - 1] != '\\')
|
||||||
|
lstrcatW(source, szBackSlash);
|
||||||
|
lstrcatW(source, sourcename);
|
||||||
|
}
|
||||||
|
|
||||||
|
wildcards = strchrW(source, '*') || strchrW(source, '?');
|
||||||
|
|
||||||
|
if (MSI_RecordIsNull(rec, 4))
|
||||||
|
{
|
||||||
|
if (!wildcards)
|
||||||
|
{
|
||||||
|
destname = strdupW(sourcename);
|
||||||
|
if (!destname)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
destname = strdupW(MSI_RecordGetString(rec, 4));
|
||||||
|
if (destname)
|
||||||
|
reduce_to_longfilename(destname);
|
||||||
|
}
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
if (destname)
|
||||||
|
size = lstrlenW(destname);
|
||||||
|
|
||||||
|
size += lstrlenW(destdir) + 2;
|
||||||
|
dest = msi_alloc(size * sizeof(WCHAR));
|
||||||
|
if (!dest)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
lstrcpyW(dest, destdir);
|
||||||
|
if (dest[lstrlenW(dest) - 1] != '\\')
|
||||||
|
lstrcatW(dest, szBackSlash);
|
||||||
|
|
||||||
|
if (destname)
|
||||||
|
lstrcatW(dest, destname);
|
||||||
|
|
||||||
|
if (GetFileAttributesW(destdir) == INVALID_FILE_ATTRIBUTES)
|
||||||
|
{
|
||||||
|
ret = CreateDirectoryW(destdir, NULL);
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
WARN("CreateDirectory failed: %d\n", GetLastError());
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wildcards)
|
||||||
|
msi_move_file(source, dest, options);
|
||||||
|
else
|
||||||
|
move_files_wildcard(source, dest, options);
|
||||||
|
|
||||||
|
done:
|
||||||
|
msi_free(sourcedir);
|
||||||
|
msi_free(destdir);
|
||||||
|
msi_free(destname);
|
||||||
|
msi_free(source);
|
||||||
|
msi_free(dest);
|
||||||
|
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT ACTION_MoveFiles( MSIPACKAGE *package )
|
||||||
|
{
|
||||||
|
UINT rc;
|
||||||
|
MSIQUERY *view;
|
||||||
|
|
||||||
|
static const WCHAR ExecSeqQuery[] =
|
||||||
|
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
||||||
|
'`','M','o','v','e','F','i','l','e','`',0};
|
||||||
|
|
||||||
|
rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
|
rc = MSI_IterateRecords(view, NULL, ITERATE_MoveFiles, package);
|
||||||
|
msiobj_release(&view->hdr);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static WCHAR *get_duplicate_filename( MSIPACKAGE *package, MSIRECORD *row, const WCHAR *file_key, const WCHAR *src )
|
static WCHAR *get_duplicate_filename( MSIPACKAGE *package, MSIRECORD *row, const WCHAR *file_key, const WCHAR *src )
|
||||||
{
|
{
|
||||||
DWORD len;
|
DWORD len;
|
||||||
|
|
|
@ -955,6 +955,7 @@ extern UINT ACTION_CCPSearch(MSIPACKAGE *package);
|
||||||
extern UINT ACTION_FindRelatedProducts(MSIPACKAGE *package);
|
extern UINT ACTION_FindRelatedProducts(MSIPACKAGE *package);
|
||||||
extern UINT ACTION_InstallFiles(MSIPACKAGE *package);
|
extern UINT ACTION_InstallFiles(MSIPACKAGE *package);
|
||||||
extern UINT ACTION_RemoveFiles(MSIPACKAGE *package);
|
extern UINT ACTION_RemoveFiles(MSIPACKAGE *package);
|
||||||
|
extern UINT ACTION_MoveFiles(MSIPACKAGE *package);
|
||||||
extern UINT ACTION_DuplicateFiles(MSIPACKAGE *package);
|
extern UINT ACTION_DuplicateFiles(MSIPACKAGE *package);
|
||||||
extern UINT ACTION_RemoveDuplicateFiles(MSIPACKAGE *package);
|
extern UINT ACTION_RemoveDuplicateFiles(MSIPACKAGE *package);
|
||||||
extern UINT ACTION_RegisterClassInfo(MSIPACKAGE *package);
|
extern UINT ACTION_RegisterClassInfo(MSIPACKAGE *package);
|
||||||
|
|
Loading…
Reference in New Issue