Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
c3df74e2
Commit
c3df74e2
authored
Nov 01, 2007
by
James Hawkins
Committed by
Alexandre Julliard
Nov 01, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
msi: Implement the MoveFiles standard action.
parent
b9a29e22
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
338 additions
and
30 deletions
+338
-30
action.c
dlls/msi/action.c
+309
-6
install.c
dlls/msi/tests/install.c
+24
-24
msidefs.h
include/msidefs.h
+5
-0
No files found.
dlls/msi/action.c
View file @
c3df74e2
...
...
@@ -4965,6 +4965,315 @@ static UINT ACTION_WriteEnvironmentStrings( MSIPACKAGE *package )
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
;
}
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
)
{
free_list
(
&
files
);
return
FALSE
;
}
add_wildcard
(
&
files
,
path
,
dest
);
msi_free
(
path
);
}
/* 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
)
{
free_list
(
&
files
);
return
FALSE
;
}
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
((
LPCWSTR
)
file
->
source
,
(
LPCWSTR
)
file
->
dest
,
options
);
list_remove
(
&
file
->
entry
);
free_file_entry
(
file
);
}
return
TRUE
;
}
static
UINT
ITERATE_MoveFiles
(
MSIRECORD
*
rec
,
LPVOID
param
)
{
MSIPACKAGE
*
package
=
param
;
MSICOMPONENT
*
comp
;
LPCWSTR
sourcename
,
destname
;
LPWSTR
sourcedir
=
NULL
,
destdir
=
NULL
;
LPWSTR
source
=
NULL
,
dest
=
NULL
;
int
options
;
DWORD
size
;
BOOL
ret
,
wildcards
;
static
const
WCHAR
backslash
[]
=
{
'\\'
,
0
};
comp
=
get_loaded_component
(
package
,
MSI_RecordGetString
(
rec
,
2
));
if
(
!
comp
||
!
comp
->
Enabled
||
!
(
comp
->
Action
&
(
INSTALLSTATE_LOCAL
|
INSTALLSTATE_SOURCE
)))
{
TRACE
(
"Component not set for install, not moving file
\n
"
);
return
ERROR_SUCCESS
;
}
sourcename
=
MSI_RecordGetString
(
rec
,
3
);
destname
=
MSI_RecordGetString
(
rec
,
4
);
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
,
backslash
);
lstrcatW
(
source
,
sourcename
);
}
wildcards
=
strchrW
(
source
,
'*'
)
||
strchrW
(
source
,
'?'
);
if
(
!
destname
&&
!
wildcards
)
{
destname
=
strdupW
(
sourcename
);
if
(
!
destname
)
goto
done
;
}
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
,
backslash
);
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
(
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
;
}
static
UINT
msi_unimplemented_action_stub
(
MSIPACKAGE
*
package
,
LPCSTR
action
,
LPCWSTR
table
)
{
...
...
@@ -5002,12 +5311,6 @@ static UINT ACTION_RemoveIniValues( MSIPACKAGE *package )
return
msi_unimplemented_action_stub
(
package
,
"RemoveIniValues"
,
table
);
}
static
UINT
ACTION_MoveFiles
(
MSIPACKAGE
*
package
)
{
static
const
WCHAR
table
[]
=
{
'M'
,
'o'
,
'v'
,
'e'
,
'F'
,
'i'
,
'l'
,
'e'
,
0
};
return
msi_unimplemented_action_stub
(
package
,
"MoveFiles"
,
table
);
}
static
UINT
ACTION_PatchFiles
(
MSIPACKAGE
*
package
)
{
static
const
WCHAR
table
[]
=
{
'P'
,
'a'
,
't'
,
'c'
,
'h'
,
0
};
...
...
dlls/msi/tests/install.c
View file @
c3df74e2
...
...
@@ -2981,54 +2981,54 @@ static void test_movefiles(void)
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %u
\n
"
,
r
);
ok
(
delete_pf
(
"msitest
\\
augustus"
,
TRUE
),
"File not installed
\n
"
);
ok
(
!
delete_pf
(
"msitest
\\
dest"
,
TRUE
),
"File copied
\n
"
);
todo_wine
ok
(
delete_pf
(
"msitest
\\
canada"
,
TRUE
),
"File not copied
\n
"
);
todo_wine
ok
(
delete_pf
(
"msitest
\\
dominica"
,
TRUE
),
"File not moved
\n
"
);
ok
(
delete_pf
(
"msitest
\\
canada"
,
TRUE
),
"File not copied
\n
"
);
ok
(
delete_pf
(
"msitest
\\
dominica"
,
TRUE
),
"File not moved
\n
"
);
ok
(
!
delete_pf
(
"msitest
\\
elsalvador"
,
TRUE
),
"File moved
\n
"
);
ok
(
!
delete_pf
(
"msitest
\\
france"
,
TRUE
),
"File moved
\n
"
);
ok
(
!
delete_pf
(
"msitest
\\
georgia"
,
TRUE
),
"File moved
\n
"
);
todo_wine
ok
(
delete_pf
(
"msitest
\\
hungary"
,
TRUE
),
"File not moved
\n
"
);
ok
(
delete_pf
(
"msitest
\\
hungary"
,
TRUE
),
"File not moved
\n
"
);
ok
(
!
delete_pf
(
"msitest
\\
indonesia"
,
TRUE
),
"File moved
\n
"
);
ok
(
!
delete_pf
(
"msitest
\\
jordan"
,
TRUE
),
"File moved
\n
"
);
todo_wine
ok
(
delete_pf
(
"msitest
\\
kiribati"
,
TRUE
),
"File not moved
\n
"
);
ok
(
delete_pf
(
"msitest
\\
kiribati"
,
TRUE
),
"File not moved
\n
"
);
ok
(
!
delete_pf
(
"msitest
\\
lebanon"
,
TRUE
),
"File moved
\n
"
);
ok
(
!
delete_pf
(
"msitest
\\
lebanon"
,
FALSE
),
"Directory moved
\n
"
);
ok
(
!
delete_pf
(
"msitest
\\
apple"
,
TRUE
),
"File should not exist
\n
"
);
todo_wine
ok
(
delete_pf
(
"msitest
\\
wildcard"
,
TRUE
),
"File not moved
\n
"
);
todo_wine
ok
(
delete_pf
(
"msitest
\\
application"
,
TRUE
),
"File not moved
\n
"
);
ok
(
delete_pf
(
"msitest
\\
wildcard"
,
TRUE
),
"File not moved
\n
"
);
ok
(
delete_pf
(
"msitest
\\
application"
,
TRUE
),
"File not moved
\n
"
);
ok
(
!
delete_pf
(
"msitest
\\
ape"
,
TRUE
),
"File moved
\n
"
);
todo_wine
ok
(
delete_pf
(
"msitest
\\
foo"
,
TRUE
),
"File not moved
\n
"
);
ok
(
delete_pf
(
"msitest
\\
foo"
,
TRUE
),
"File not moved
\n
"
);
ok
(
!
delete_pf
(
"msitest
\\
fao"
,
TRUE
),
"File should not exist
\n
"
);
todo_wine
ok
(
delete_pf
(
"msitest
\\
single"
,
TRUE
),
"File not moved
\n
"
);
ok
(
delete_pf
(
"msitest
\\
single"
,
TRUE
),
"File not moved
\n
"
);
ok
(
!
delete_pf
(
"msitest
\\
fbod"
,
TRUE
),
"File moved
\n
"
);
todo_wine
ok
(
delete_pf
(
"msitest
\\
budding"
,
TRUE
),
"File not moved
\n
"
);
todo_wine
ok
(
delete_pf
(
"msitest
\\
buddy"
,
TRUE
),
"File not moved
\n
"
);
ok
(
delete_pf
(
"msitest
\\
budding"
,
TRUE
),
"File not moved
\n
"
);
ok
(
delete_pf
(
"msitest
\\
buddy"
,
TRUE
),
"File not moved
\n
"
);
ok
(
!
delete_pf
(
"msitest
\\
bud"
,
TRUE
),
"File moved
\n
"
);
todo_wine
ok
(
delete_pf
(
"msitest
\\
bar"
,
TRUE
),
"File not moved
\n
"
);
todo_wine
ok
(
delete_pf
(
"msitest
\\
bur"
,
TRUE
),
"File not moved
\n
"
);
ok
(
delete_pf
(
"msitest
\\
bar"
,
TRUE
),
"File not moved
\n
"
);
ok
(
delete_pf
(
"msitest
\\
bur"
,
TRUE
),
"File not moved
\n
"
);
ok
(
!
delete_pf
(
"msitest
\\
bird"
,
TRUE
),
"File moved
\n
"
);
ok
(
delete_pf
(
"msitest"
,
FALSE
),
"File not installed
\n
"
);
ok
(
DeleteFileA
(
"cameroon"
),
"File moved
\n
"
);
todo_wine
ok
(
!
DeleteFileA
(
"djibouti"
),
"File not moved
\n
"
);
ok
(
!
DeleteFileA
(
"djibouti"
),
"File not moved
\n
"
);
ok
(
DeleteFileA
(
"egypt"
),
"File moved
\n
"
);
ok
(
DeleteFileA
(
"finland"
),
"File moved
\n
"
);
ok
(
DeleteFileA
(
"gambai"
),
"File moved
\n
"
);
todo_wine
ok
(
!
DeleteFileA
(
"honduras"
),
"File not moved
\n
"
);
ok
(
!
DeleteFileA
(
"honduras"
),
"File not moved
\n
"
);
ok
(
DeleteFileA
(
"msitest
\\
india"
),
"File moved
\n
"
);
ok
(
DeleteFileA
(
"japan"
),
"File moved
\n
"
);
todo_wine
ok
(
!
DeleteFileA
(
"kenya"
),
"File not moved
\n
"
);
ok
(
!
DeleteFileA
(
"kenya"
),
"File not moved
\n
"
);
ok
(
RemoveDirectoryA
(
"latvia"
),
"Directory moved
\n
"
);
todo_wine
ok
(
!
DeleteFileA
(
"nauru"
),
"File not moved
\n
"
);
todo_wine
ok
(
!
DeleteFileA
(
"apple"
),
"File not moved
\n
"
);
todo_wine
ok
(
!
DeleteFileA
(
"application"
),
"File not moved
\n
"
);
ok
(
!
DeleteFileA
(
"nauru"
),
"File not moved
\n
"
);
ok
(
!
DeleteFileA
(
"apple"
),
"File not moved
\n
"
);
ok
(
!
DeleteFileA
(
"application"
),
"File not moved
\n
"
);
ok
(
DeleteFileA
(
"ape"
),
"File moved
\n
"
);
todo_wine
ok
(
!
DeleteFileA
(
"foo"
),
"File not moved
\n
"
);
todo_wine
ok
(
!
DeleteFileA
(
"fao"
),
"File not moved
\n
"
);
ok
(
!
DeleteFileA
(
"foo"
),
"File not moved
\n
"
);
ok
(
!
DeleteFileA
(
"fao"
),
"File not moved
\n
"
);
ok
(
DeleteFileA
(
"fbod"
),
"File moved
\n
"
);
todo_wine
ok
(
!
DeleteFileA
(
"budding"
),
"File not moved
\n
"
);
todo_wine
ok
(
!
DeleteFileA
(
"buddy"
),
"File not moved
\n
"
);
ok
(
!
DeleteFileA
(
"budding"
),
"File not moved
\n
"
);
ok
(
!
DeleteFileA
(
"buddy"
),
"File not moved
\n
"
);
ok
(
DeleteFileA
(
"bud"
),
"File moved
\n
"
);
todo_wine
ok
(
!
DeleteFileA
(
"bar"
),
"File not moved
\n
"
);
todo_wine
ok
(
!
DeleteFileA
(
"bur"
),
"File not moved
\n
"
);
ok
(
!
DeleteFileA
(
"bar"
),
"File not moved
\n
"
);
ok
(
!
DeleteFileA
(
"bur"
),
"File not moved
\n
"
);
ok
(
DeleteFileA
(
"bird"
),
"File moved
\n
"
);
DeleteFile
(
"msitest
\\
augustus"
);
...
...
include/msidefs.h
View file @
c3df74e2
...
...
@@ -196,6 +196,11 @@ enum msidbServiceControlEvent
msidbServiceControlEventUninstallDelete
=
0x00000080
,
};
enum
msidbMoveFileOptions
{
msidbMoveFileOptionsMove
=
0x00000001
,
};
/*
* Windows SDK braindamage alert
*
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment