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
46680915
Commit
46680915
authored
May 02, 2011
by
Hans Leidekker
Committed by
Alexandre Julliard
May 02, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
msi: Rewrite the folder resolution code to keep track of the parent-child relationship.
parent
8fb5368d
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
195 additions
and
272 deletions
+195
-272
action.c
dlls/msi/action.c
+109
-72
helpers.c
dlls/msi/helpers.c
+0
-130
install.c
dlls/msi/install.c
+47
-58
msipriv.h
dlls/msi/msipriv.h
+10
-2
package.c
dlls/msi/package.c
+21
-10
package.c
dlls/msi/tests/package.c
+8
-0
No files found.
dlls/msi/action.c
View file @
46680915
...
...
@@ -2056,16 +2056,14 @@ static UINT load_folder( MSIRECORD *row, LPVOID param )
LPWSTR
p
,
tgt_short
,
tgt_long
,
src_short
,
src_long
;
MSIFOLDER
*
folder
;
folder
=
msi_alloc_zero
(
sizeof
(
MSIFOLDER
)
);
if
(
!
folder
)
return
ERROR_NOT_ENOUGH_MEMORY
;
if
(
!
(
folder
=
msi_alloc_zero
(
sizeof
(
*
folder
)
)))
return
ERROR_NOT_ENOUGH_MEMORY
;
list_init
(
&
folder
->
children
);
folder
->
Directory
=
msi_dup_record_field
(
row
,
1
);
folder
->
Parent
=
msi_dup_record_field
(
row
,
2
);
p
=
msi_dup_record_field
(
row
,
3
);
TRACE
(
"%s
\n
"
,
debugstr_w
(
folder
->
Directory
));
p
=
msi_dup_record_field
(
row
,
3
);
/* split src and target dir */
tgt_short
=
p
;
src_short
=
folder_split_path
(
p
,
':'
);
...
...
@@ -2101,17 +2099,36 @@ static UINT load_folder( MSIRECORD *row, LPVOID param )
TRACE
(
"SourceLong = %s
\n
"
,
debugstr_w
(
folder
->
SourceLongPath
));
TRACE
(
"SourceShort = %s
\n
"
,
debugstr_w
(
folder
->
SourceShortPath
));
folder
->
Parent
=
msi_dup_record_field
(
row
,
2
);
folder
->
Property
=
msi_dup_property
(
package
->
db
,
folder
->
Directory
);
list_add_tail
(
&
package
->
folders
,
&
folder
->
entry
);
return
ERROR_SUCCESS
;
}
TRACE
(
"returning %p
\n
"
,
folder
);
static
UINT
add_folder_child
(
MSIFOLDER
*
parent
,
MSIFOLDER
*
child
)
{
FolderList
*
fl
;
if
(
!
(
fl
=
msi_alloc
(
sizeof
(
*
fl
)
)))
return
ERROR_NOT_ENOUGH_MEMORY
;
fl
->
folder
=
child
;
list_add_tail
(
&
parent
->
children
,
&
fl
->
entry
);
return
ERROR_SUCCESS
;
}
static
UINT
find_folder_children
(
MSIRECORD
*
row
,
LPVOID
param
)
{
MSIPACKAGE
*
package
=
param
;
MSIFOLDER
*
parent
,
*
child
;
if
(
!
(
child
=
get_loaded_folder
(
package
,
MSI_RecordGetString
(
row
,
1
)
)))
return
ERROR_FUNCTION_FAILED
;
if
(
!
child
->
Parent
)
return
ERROR_SUCCESS
;
if
(
!
(
parent
=
get_loaded_folder
(
package
,
child
->
Parent
)))
return
ERROR_FUNCTION_FAILED
;
return
add_folder_child
(
parent
,
child
);
}
static
UINT
load_all_folders
(
MSIPACKAGE
*
package
)
{
static
const
WCHAR
query
[]
=
{
...
...
@@ -2127,24 +2144,17 @@ static UINT load_all_folders( MSIPACKAGE *package )
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
r
=
MSI_IterateRecords
(
view
,
NULL
,
load_folder
,
package
);
msiobj_release
(
&
view
->
hdr
);
r
=
MSI_IterateRecords
(
view
,
NULL
,
load_folder
,
package
);
if
(
r
!=
ERROR_SUCCESS
)
{
msiobj_release
(
&
view
->
hdr
);
return
r
;
}
r
=
MSI_IterateRecords
(
view
,
NULL
,
find_folder_children
,
package
);
msiobj_release
(
&
view
->
hdr
);
return
r
;
}
/*
* I am not doing any of the costing functionality yet.
* Mostly looking at doing the Component and Feature loading
*
* The native MSI does A LOT of modification to tables here. Mostly adding
* a lot of temporary columns to the Feature and Component tables.
*
* note: Native msi also tracks the short filename. But I am only going to
* track the long ones. Also looking at this directory table
* it appears that the directory table does not get the parents
* resolved base on property only based on their entries in the
* directory table.
*/
static
UINT
ACTION_CostInitialize
(
MSIPACKAGE
*
package
)
{
msi_set_property
(
package
->
db
,
szCostingComplete
,
szZero
);
...
...
@@ -2554,30 +2564,6 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
return
ERROR_SUCCESS
;
}
static
UINT
ITERATE_CostFinalizeDirectories
(
MSIRECORD
*
row
,
LPVOID
param
)
{
MSIPACKAGE
*
package
=
param
;
LPCWSTR
name
;
LPWSTR
path
;
MSIFOLDER
*
f
;
name
=
MSI_RecordGetString
(
row
,
1
);
f
=
get_loaded_folder
(
package
,
name
);
if
(
!
f
)
return
ERROR_SUCCESS
;
/* reset the ResolvedTarget */
msi_free
(
f
->
ResolvedTarget
);
f
->
ResolvedTarget
=
NULL
;
TRACE
(
"directory %s ...
\n
"
,
debugstr_w
(
name
));
path
=
resolve_target_folder
(
package
,
name
,
TRUE
,
TRUE
,
NULL
);
TRACE
(
"resolves to %s
\n
"
,
debugstr_w
(
path
));
msi_free
(
path
);
return
ERROR_SUCCESS
;
}
static
UINT
ITERATE_CostFinalizeConditions
(
MSIRECORD
*
row
,
LPVOID
param
)
{
MSIPACKAGE
*
package
=
param
;
...
...
@@ -2782,20 +2768,78 @@ static UINT calculate_file_cost( MSIPACKAGE *package )
return
ERROR_SUCCESS
;
}
/*
* A lot is done in this function aside from just the costing.
* The costing needs to be implemented at some point but for now I am going
* to focus on the directory building
*
*/
void
msi_clean_path
(
WCHAR
*
p
)
{
WCHAR
*
q
=
p
;
int
n
,
len
=
0
;
while
(
1
)
{
/* copy until the end of the string or a space */
while
(
*
p
!=
' '
&&
(
*
q
=
*
p
))
{
p
++
,
len
++
;
/* reduce many backslashes to one */
if
(
*
p
!=
'\\'
||
*
q
!=
'\\'
)
q
++
;
}
/* quit at the end of the string */
if
(
!*
p
)
break
;
/* count the number of spaces */
n
=
0
;
while
(
p
[
n
]
==
' '
)
n
++
;
/* if it's leading or trailing space, skip it */
if
(
len
==
0
||
p
[
-
1
]
==
'\\'
||
p
[
n
]
==
'\\'
)
p
+=
n
;
else
/* copy n spaces */
while
(
n
&&
(
*
q
++
=
*
p
++
))
n
--
;
}
}
void
msi_resolve_target_folder
(
MSIPACKAGE
*
package
,
const
WCHAR
*
name
,
BOOL
load_prop
)
{
FolderList
*
fl
;
MSIFOLDER
*
folder
,
*
parent
,
*
child
;
WCHAR
*
path
;
TRACE
(
"resolving %s
\n
"
,
debugstr_w
(
name
));
if
(
!
(
folder
=
get_loaded_folder
(
package
,
name
)))
return
;
if
(
!
strcmpW
(
folder
->
Directory
,
cszTargetDir
))
/* special resolving for target root dir */
{
if
(
!
load_prop
||
!
(
path
=
msi_dup_property
(
package
->
db
,
cszTargetDir
)))
{
path
=
msi_dup_property
(
package
->
db
,
cszRootDrive
);
}
}
else
if
(
!
load_prop
||
!
(
path
=
msi_dup_property
(
package
->
db
,
folder
->
Directory
)))
{
parent
=
get_loaded_folder
(
package
,
folder
->
Parent
);
path
=
build_directory_name
(
3
,
parent
->
ResolvedTarget
,
folder
->
TargetDefault
,
NULL
);
}
msi_clean_path
(
path
);
msi_set_property
(
package
->
db
,
folder
->
Directory
,
path
);
msi_free
(
folder
->
ResolvedTarget
);
folder
->
ResolvedTarget
=
path
;
LIST_FOR_EACH_ENTRY
(
fl
,
&
folder
->
children
,
FolderList
,
entry
)
{
child
=
fl
->
folder
;
msi_resolve_target_folder
(
package
,
child
->
Directory
,
load_prop
);
}
TRACE
(
"%s resolves to %s
\n
"
,
debugstr_w
(
name
),
debugstr_w
(
folder
->
ResolvedTarget
));
}
static
UINT
ACTION_CostFinalize
(
MSIPACKAGE
*
package
)
{
static
const
WCHAR
ExecSeqQuery
[]
=
{
'S'
,
'E'
,
'L'
,
'E'
,
'C'
,
'T'
,
' '
,
'*'
,
' '
,
'F'
,
'R'
,
'O'
,
'M'
,
' '
,
'`'
,
'D'
,
'i'
,
'r'
,
'e'
,
'c'
,
't'
,
'o'
,
'r'
,
'y'
,
'`'
,
0
};
static
const
WCHAR
ConditionQuery
[]
=
{
'S'
,
'E'
,
'L'
,
'E'
,
'C'
,
'T'
,
' '
,
'*'
,
' '
,
'F'
,
'R'
,
'O'
,
'M'
,
' '
,
'`'
,
'C'
,
'o'
,
'n'
,
'd'
,
'i'
,
't'
,
'i'
,
'o'
,
'n'
,
'`'
,
0
};
static
const
WCHAR
condition_query
[]
=
{
'S'
,
'E'
,
'L'
,
'E'
,
'C'
,
'T'
,
' '
,
'*'
,
' '
,
'F'
,
'R'
,
'O'
,
'M'
,
' '
,
'`'
,
'C'
,
'o'
,
'n'
,
'd'
,
'i'
,
't'
,
'i'
,
'o'
,
'n'
,
'`'
,
0
};
static
const
WCHAR
szlevel
[]
=
{
'I'
,
'N'
,
'S'
,
'T'
,
'A'
,
'L'
,
'L'
,
'L'
,
'E'
,
'V'
,
'E'
,
'L'
,
0
};
static
const
WCHAR
szOutOfDiskSpace
[]
=
...
...
@@ -2805,15 +2849,8 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
MSIQUERY
*
view
;
LPWSTR
level
;
TRACE
(
"Building Directory properties
\n
"
);
rc
=
MSI_DatabaseOpenViewW
(
package
->
db
,
ExecSeqQuery
,
&
view
);
if
(
rc
==
ERROR_SUCCESS
)
{
rc
=
MSI_IterateRecords
(
view
,
NULL
,
ITERATE_CostFinalizeDirectories
,
package
);
msiobj_release
(
&
view
->
hdr
);
}
TRACE
(
"Building directory properties
\n
"
);
msi_resolve_target_folder
(
package
,
cszTargetDir
,
TRUE
);
TRACE
(
"Evaluating component conditions
\n
"
);
LIST_FOR_EACH_ENTRY
(
comp
,
&
package
->
components
,
MSICOMPONENT
,
entry
)
...
...
@@ -2835,7 +2872,7 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
{
TRACE
(
"Evaluating feature conditions
\n
"
);
rc
=
MSI_DatabaseOpenViewW
(
package
->
db
,
ConditionQ
uery
,
&
view
);
rc
=
MSI_DatabaseOpenViewW
(
package
->
db
,
condition_q
uery
,
&
view
);
if
(
rc
==
ERROR_SUCCESS
)
{
rc
=
MSI_IterateRecords
(
view
,
NULL
,
ITERATE_CostFinalizeConditions
,
package
);
...
...
dlls/msi/helpers.c
View file @
46680915
...
...
@@ -34,7 +34,6 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
msi
);
static
const
WCHAR
cszTargetDir
[]
=
{
'T'
,
'A'
,
'R'
,
'G'
,
'E'
,
'T'
,
'D'
,
'I'
,
'R'
,
0
};
static
const
WCHAR
cszDatabase
[]
=
{
'D'
,
'A'
,
'T'
,
'A'
,
'B'
,
'A'
,
'S'
,
'E'
,
0
};
LPWSTR
build_icon_path
(
MSIPACKAGE
*
package
,
LPCWSTR
icon_name
)
...
...
@@ -198,45 +197,6 @@ static LPWSTR get_source_root( MSIPACKAGE *package )
return
path
;
}
/*
* clean_spaces_from_path()
*
* removes spaces from the beginning and end of path segments
* removes multiple \\ characters
*/
static
void
clean_spaces_from_path
(
LPWSTR
p
)
{
LPWSTR
q
=
p
;
int
n
,
len
=
0
;
while
(
1
)
{
/* copy until the end of the string or a space */
while
(
*
p
!=
' '
&&
(
*
q
=
*
p
))
{
p
++
,
len
++
;
/* reduce many backslashes to one */
if
(
*
p
!=
'\\'
||
*
q
!=
'\\'
)
q
++
;
}
/* quit at the end of the string */
if
(
!*
p
)
break
;
/* count the number of spaces */
n
=
0
;
while
(
p
[
n
]
==
' '
)
n
++
;
/* if it's leading or trailing space, skip it */
if
(
len
==
0
||
p
[
-
1
]
==
'\\'
||
p
[
n
]
==
'\\'
)
p
+=
n
;
else
/* copy n spaces */
while
(
n
&&
(
*
q
++
=
*
p
++
))
n
--
;
}
}
LPWSTR
resolve_file_source
(
MSIPACKAGE
*
package
,
MSIFILE
*
file
)
{
LPWSTR
p
,
path
;
...
...
@@ -315,96 +275,6 @@ LPWSTR resolve_source_folder( MSIPACKAGE *package, LPCWSTR name, MSIFOLDER **fol
return
path
;
}
const
WCHAR
*
msi_get_target_folder
(
MSIPACKAGE
*
package
,
const
WCHAR
*
name
)
{
MSIFOLDER
*
folder
=
get_loaded_folder
(
package
,
name
);
if
(
folder
)
return
folder
->
ResolvedTarget
;
return
NULL
;
}
LPWSTR
resolve_target_folder
(
MSIPACKAGE
*
package
,
LPCWSTR
name
,
BOOL
set_prop
,
BOOL
load_prop
,
MSIFOLDER
**
folder
)
{
MSIFOLDER
*
f
;
LPWSTR
p
,
path
=
NULL
,
parent
;
TRACE
(
"working to resolve %s
\n
"
,
debugstr_w
(
name
));
f
=
get_loaded_folder
(
package
,
name
);
if
(
!
f
)
return
NULL
;
/* special resolving for Target and Source root dir */
if
(
!
strcmpW
(
name
,
cszTargetDir
))
{
if
(
!
f
->
ResolvedTarget
&&
!
f
->
Property
)
{
LPWSTR
check_path
;
check_path
=
msi_dup_property
(
package
->
db
,
cszTargetDir
);
if
(
!
check_path
)
{
check_path
=
msi_dup_property
(
package
->
db
,
cszRootDrive
);
if
(
set_prop
)
msi_set_property
(
package
->
db
,
cszTargetDir
,
check_path
);
}
/* correct misbuilt target dir */
path
=
build_directory_name
(
2
,
check_path
,
NULL
);
clean_spaces_from_path
(
path
);
if
(
strcmpiW
(
path
,
check_path
))
msi_set_property
(
package
->
db
,
cszTargetDir
,
path
);
msi_free
(
check_path
);
f
->
ResolvedTarget
=
path
;
}
}
if
(
folder
)
*
folder
=
f
;
if
(
f
->
ResolvedTarget
)
{
path
=
strdupW
(
f
->
ResolvedTarget
);
TRACE
(
" already resolved to %s
\n
"
,
debugstr_w
(
path
));
return
path
;
}
if
(
f
->
Property
)
{
path
=
build_directory_name
(
2
,
f
->
Property
,
NULL
);
TRACE
(
" internally set to %s
\n
"
,
debugstr_w
(
path
));
if
(
set_prop
)
msi_set_property
(
package
->
db
,
name
,
path
);
return
path
;
}
if
(
load_prop
&&
(
path
=
msi_dup_property
(
package
->
db
,
name
)))
{
f
->
ResolvedTarget
=
strdupW
(
path
);
TRACE
(
" property set to %s
\n
"
,
debugstr_w
(
path
));
return
path
;
}
if
(
!
f
->
Parent
)
return
path
;
parent
=
f
->
Parent
;
TRACE
(
" ! parent is %s
\n
"
,
debugstr_w
(
parent
));
p
=
resolve_target_folder
(
package
,
parent
,
set_prop
,
load_prop
,
NULL
);
TRACE
(
" TargetDefault = %s
\n
"
,
debugstr_w
(
f
->
TargetDefault
));
path
=
build_directory_name
(
3
,
p
,
f
->
TargetDefault
,
NULL
);
clean_spaces_from_path
(
path
);
f
->
ResolvedTarget
=
strdupW
(
path
);
TRACE
(
"-> %s
\n
"
,
debugstr_w
(
path
));
if
(
set_prop
)
msi_set_property
(
package
->
db
,
name
,
path
);
msi_free
(
p
);
return
path
;
}
/* wrapper to resist a need for a full rewrite right now */
DWORD
deformat_string
(
MSIPACKAGE
*
package
,
LPCWSTR
ptr
,
WCHAR
**
data
)
{
...
...
dlls/msi/install.c
View file @
46680915
...
...
@@ -212,6 +212,13 @@ UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
return
r
;
}
const
WCHAR
*
msi_get_target_folder
(
MSIPACKAGE
*
package
,
const
WCHAR
*
name
)
{
MSIFOLDER
*
folder
=
get_loaded_folder
(
package
,
name
);
if
(
folder
)
return
folder
->
ResolvedTarget
;
return
NULL
;
}
/***********************************************************************
* MsiGetTargetPath (internal)
*/
...
...
@@ -219,7 +226,7 @@ static UINT MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder,
awstring
*
szPathBuf
,
LPDWORD
pcchPathBuf
)
{
MSIPACKAGE
*
package
;
LPWSTR
path
;
const
WCHAR
*
path
;
UINT
r
=
ERROR_FUNCTION_FAILED
;
if
(
!
szFolder
)
...
...
@@ -280,14 +287,13 @@ done:
return
r
;
}
path
=
resolve_target_folder
(
package
,
szFolder
,
FALSE
,
TRUE
,
NULL
);
path
=
msi_get_target_folder
(
package
,
szFolder
);
msiobj_release
(
&
package
->
hdr
);
if
(
!
path
)
return
ERROR_DIRECTORY
;
r
=
msi_strcpy_to_awstring
(
path
,
szPathBuf
,
pcchPathBuf
);
msi_free
(
path
);
return
r
;
}
...
...
@@ -485,80 +491,63 @@ end:
return
rc
;
}
/*
* Ok my original interpretation of this was wrong. And it looks like msdn has
* changed a bit also. The given folder path does not have to actually already
* exist, it just cannot be read only and must be a legal folder path.
*/
UINT
MSI_SetTargetPathW
(
MSIPACKAGE
*
package
,
LPCWSTR
szFolder
,
LPCWSTR
szFolderPath
)
static
void
set_target_path
(
MSIPACKAGE
*
package
,
MSIFOLDER
*
folder
,
const
WCHAR
*
path
)
{
DWORD
attrib
;
LPWSTR
path
=
NULL
;
LPWSTR
path2
=
NULL
;
FolderList
*
fl
;
MSIFOLDER
*
child
;
msi_free
(
folder
->
ResolvedTarget
);
folder
->
ResolvedTarget
=
strdupW
(
path
);
msi_clean_path
(
folder
->
ResolvedTarget
);
msi_set_property
(
package
->
db
,
folder
->
Directory
,
folder
->
ResolvedTarget
);
LIST_FOR_EACH_ENTRY
(
fl
,
&
folder
->
children
,
FolderList
,
entry
)
{
child
=
fl
->
folder
;
msi_resolve_target_folder
(
package
,
child
->
Directory
,
FALSE
);
}
}
UINT
MSI_SetTargetPathW
(
MSIPACKAGE
*
package
,
LPCWSTR
szFolder
,
LPCWSTR
szFolderPath
)
{
DWORD
attrib
,
len
;
MSIFOLDER
*
folder
;
MSIFILE
*
file
;
TRACE
(
"%p %s %s
\n
"
,
package
,
debugstr_w
(
szFolder
),
debugstr_w
(
szFolderPath
));
TRACE
(
"%p %s %s
\n
"
,
package
,
debugstr_w
(
szFolder
),
debugstr_w
(
szFolderPath
));
attrib
=
GetFileAttributesW
(
szFolderPath
);
/* native MSI tests writeability by making temporary files at each drive */
if
(
attrib
!=
INVALID_FILE_ATTRIBUTES
&&
(
attrib
&
FILE_ATTRIBUTE_OFFLINE
||
attrib
&
FILE_ATTRIBUTE_READONLY
))
return
ERROR_FUNCTION_FAILED
;
path
=
resolve_target_folder
(
package
,
szFolder
,
FALSE
,
FALSE
,
&
folder
);
if
(
!
path
)
return
ERROR_DIRECTORY
;
msi_free
(
folder
->
Property
);
folder
->
Property
=
build_directory_name
(
2
,
szFolderPath
,
NULL
);
if
(
!
strcmpiW
(
path
,
folder
->
Property
))
{
/*
* Resolved Target has not really changed, so just
* set this folder and do not recalculate everything.
*/
msi_free
(
folder
->
ResolvedTarget
);
folder
->
ResolvedTarget
=
NULL
;
path2
=
resolve_target_folder
(
package
,
szFolder
,
TRUE
,
FALSE
,
NULL
);
msi_free
(
path2
);
}
else
{
MSIFOLDER
*
f
;
LIST_FOR_EACH_ENTRY
(
f
,
&
package
->
folders
,
MSIFOLDER
,
entry
)
if
(
attrib
!=
INVALID_FILE_ATTRIBUTES
&&
(
attrib
&
FILE_ATTRIBUTE_OFFLINE
||
attrib
&
FILE_ATTRIBUTE_READONLY
))
{
msi_free
(
f
->
ResolvedTarget
);
f
->
ResolvedTarget
=
NULL
;
return
ERROR_FUNCTION_FAILED
;
}
if
(
!
(
folder
=
get_loaded_folder
(
package
,
szFolder
)))
return
ERROR_DIRECTORY
;
LIST_FOR_EACH_ENTRY
(
f
,
&
package
->
folders
,
MSIFOLDER
,
entry
)
len
=
strlenW
(
szFolderPath
);
if
(
len
&&
szFolderPath
[
len
-
1
]
!=
'\\'
)
{
path2
=
resolve_target_folder
(
package
,
f
->
Directory
,
TRUE
,
FALSE
,
NULL
);
msi_free
(
path2
);
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
);
LIST_FOR_EACH_ENTRY
(
file
,
&
package
->
files
,
MSIFILE
,
entry
)
{
const
WCHAR
*
dir
;
MSICOMPONENT
*
comp
=
file
->
Component
;
LPWSTR
dir
;
if
(
!
comp
->
Enabled
||
(
comp
->
assembly
&&
!
comp
->
assembly
->
application
))
continue
;
dir
=
resolve_target_folder
(
package
,
comp
->
Directory
,
FALSE
,
FALSE
,
NULL
);
msi_free
(
file
->
TargetPath
);
if
(
!
comp
->
Enabled
||
(
comp
->
assembly
&&
!
comp
->
assembly
->
application
))
continue
;
file
->
TargetPath
=
build_directory_name
(
2
,
dir
,
file
->
FileName
);
msi_free
(
dir
);
dir
=
msi_get_target_folder
(
package
,
comp
->
Directory
);
msi_free
(
file
->
TargetPath
);
file
->
TargetPath
=
build_directory_name
(
2
,
dir
,
file
->
FileName
);
}
}
msi_free
(
path
);
return
ERROR_SUCCESS
;
}
...
...
dlls/msi/msipriv.h
View file @
46680915
...
...
@@ -489,6 +489,7 @@ typedef struct tagFeatureList
typedef
struct
tagMSIFOLDER
{
struct
list
entry
;
struct
list
children
;
LPWSTR
Directory
;
LPWSTR
Parent
;
LPWSTR
TargetDefault
;
...
...
@@ -497,7 +498,6 @@ typedef struct tagMSIFOLDER
LPWSTR
ResolvedTarget
;
LPWSTR
ResolvedSource
;
LPWSTR
Property
;
/* initially set property */
INT
State
;
/* 0 = uninitialized */
/* 1 = existing */
...
...
@@ -507,6 +507,12 @@ typedef struct tagMSIFOLDER
INT
Space
;
}
MSIFOLDER
;
typedef
struct
tagFolderList
{
struct
list
entry
;
MSIFOLDER
*
folder
;
}
FolderList
;
typedef
enum
_msi_file_state
{
msifs_invalid
,
msifs_missing
,
...
...
@@ -969,7 +975,8 @@ extern UINT msi_set_property( MSIDATABASE *, LPCWSTR, LPCWSTR ) DECLSPEC_HIDDEN;
extern
UINT
msi_get_property
(
MSIDATABASE
*
,
LPCWSTR
,
LPWSTR
,
LPDWORD
)
DECLSPEC_HIDDEN
;
extern
int
msi_get_property_int
(
MSIDATABASE
*
package
,
LPCWSTR
prop
,
int
def
)
DECLSPEC_HIDDEN
;
extern
LPWSTR
resolve_source_folder
(
MSIPACKAGE
*
package
,
LPCWSTR
name
,
MSIFOLDER
**
folder
)
DECLSPEC_HIDDEN
;
extern
LPWSTR
resolve_target_folder
(
MSIPACKAGE
*
package
,
LPCWSTR
name
,
BOOL
set_prop
,
BOOL
load_prop
,
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
LPWSTR
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
;
...
...
@@ -1045,6 +1052,7 @@ extern void ui_actiondata(MSIPACKAGE *, LPCWSTR, MSIRECORD *) DECLSPEC_HIDDEN;
static
const
WCHAR
cszSourceDir
[]
=
{
'S'
,
'o'
,
'u'
,
'r'
,
'c'
,
'e'
,
'D'
,
'i'
,
'r'
,
0
};
static
const
WCHAR
cszSOURCEDIR
[]
=
{
'S'
,
'O'
,
'U'
,
'R'
,
'C'
,
'E'
,
'D'
,
'I'
,
'R'
,
0
};
static
const
WCHAR
cszRootDrive
[]
=
{
'R'
,
'O'
,
'O'
,
'T'
,
'D'
,
'R'
,
'I'
,
'V'
,
'E'
,
0
};
static
const
WCHAR
cszTargetDir
[]
=
{
'T'
,
'A'
,
'R'
,
'G'
,
'E'
,
'T'
,
'D'
,
'I'
,
'R'
,
0
};
static
const
WCHAR
szLocalSid
[]
=
{
'S'
,
'-'
,
'1'
,
'-'
,
'5'
,
'-'
,
'1'
,
'8'
,
0
};
static
const
WCHAR
szEmpty
[]
=
{
0
};
static
const
WCHAR
szAll
[]
=
{
'A'
,
'L'
,
'L'
,
0
};
...
...
dlls/msi/package.c
View file @
46680915
...
...
@@ -90,6 +90,26 @@ static void free_feature( MSIFEATURE *feature )
msi_free
(
feature
);
}
static
void
free_folder
(
MSIFOLDER
*
folder
)
{
struct
list
*
item
,
*
cursor
;
LIST_FOR_EACH_SAFE
(
item
,
cursor
,
&
folder
->
children
)
{
FolderList
*
fl
=
LIST_ENTRY
(
item
,
FolderList
,
entry
);
list_remove
(
&
fl
->
entry
);
msi_free
(
fl
);
}
msi_free
(
folder
->
Parent
);
msi_free
(
folder
->
Directory
);
msi_free
(
folder
->
TargetDefault
);
msi_free
(
folder
->
SourceLongPath
);
msi_free
(
folder
->
SourceShortPath
);
msi_free
(
folder
->
ResolvedTarget
);
msi_free
(
folder
->
ResolvedSource
);
msi_free
(
folder
);
}
static
void
free_extension
(
MSIEXTENSION
*
ext
)
{
struct
list
*
item
,
*
cursor
;
...
...
@@ -140,17 +160,8 @@ static void free_package_structures( MSIPACKAGE *package )
LIST_FOR_EACH_SAFE
(
item
,
cursor
,
&
package
->
folders
)
{
MSIFOLDER
*
folder
=
LIST_ENTRY
(
item
,
MSIFOLDER
,
entry
);
list_remove
(
&
folder
->
entry
);
msi_free
(
folder
->
Parent
);
msi_free
(
folder
->
Directory
);
msi_free
(
folder
->
TargetDefault
);
msi_free
(
folder
->
SourceLongPath
);
msi_free
(
folder
->
SourceShortPath
);
msi_free
(
folder
->
ResolvedTarget
);
msi_free
(
folder
->
ResolvedSource
);
msi_free
(
folder
->
Property
);
msi_free
(
folder
);
free_folder
(
folder
);
}
LIST_FOR_EACH_SAFE
(
item
,
cursor
,
&
package
->
components
)
...
...
dlls/msi/tests/package.c
View file @
46680915
...
...
@@ -1164,6 +1164,14 @@ static void test_settargetpath(void)
ok
(
r
==
ERROR_SUCCESS
,
"failed to get target path: %d
\n
"
,
r
);
ok
(
!
lstrcmpi
(
buffer
,
"C:
\\
one
\\
two
\\
three
\\
"
),
"Expected C:
\\
one
\\
two
\\
three
\\
, got %s
\n
"
,
buffer
);
r
=
MsiSetTargetPath
(
hpkg
,
"TestParent"
,
"C:
\\\\
one
\\\\
two "
);
ok
(
r
==
ERROR_SUCCESS
,
"MsiSetTargetPath returned %d
\n
"
,
r
);
sz
=
sizeof
buffer
-
1
;
r
=
MsiGetTargetPath
(
hpkg
,
"TestParent"
,
buffer
,
&
sz
);
ok
(
r
==
ERROR_SUCCESS
,
"failed to get target path: %d
\n
"
,
r
);
ok
(
!
lstrcmpi
(
buffer
,
"C:
\\
one
\\
two
\\
"
),
"Expected
\"
C:
\\
one
\\
two
\\\"
, got %s
\n
"
,
buffer
);
MsiCloseHandle
(
hpkg
);
}
...
...
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