Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
a23514ee
Commit
a23514ee
authored
Nov 11, 2010
by
Hans Leidekker
Committed by
Alexandre Julliard
Nov 11, 2010
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
msi: Add support for installing side-by-side assemblies.
parent
3faddc21
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
469 additions
and
500 deletions
+469
-500
Makefile.in
dlls/msi/Makefile.in
+1
-0
action.c
dlls/msi/action.c
+42
-491
assembly.c
dlls/msi/assembly.c
+371
-0
files.c
dlls/msi/files.c
+24
-9
msipriv.h
dlls/msi/msipriv.h
+19
-0
package.c
dlls/msi/package.c
+12
-0
No files found.
dlls/msi/Makefile.in
View file @
a23514ee
...
...
@@ -7,6 +7,7 @@ C_SRCS = \
action.c
\
alter.c
\
appsearch.c
\
assembly.c
\
automation.c
\
classes.c
\
create.c
\
...
...
dlls/msi/action.c
View file @
a23514ee
...
...
@@ -35,7 +35,6 @@
#include "shlobj.h"
#include "objbase.h"
#include "mscoree.h"
#include "fusion.h"
#include "shlwapi.h"
#include "wine/unicode.h"
#include "winver.h"
...
...
@@ -110,8 +109,6 @@ static const WCHAR szIsolateComponents[] =
{
'I'
,
's'
,
'o'
,
'l'
,
'a'
,
't'
,
'e'
,
'C'
,
'o'
,
'm'
,
'p'
,
'o'
,
'n'
,
'e'
,
'n'
,
't'
,
's'
,
0
};
static
const
WCHAR
szMigrateFeatureStates
[]
=
{
'M'
,
'i'
,
'g'
,
'r'
,
'a'
,
't'
,
'e'
,
'F'
,
'e'
,
'a'
,
't'
,
'u'
,
'r'
,
'e'
,
'S'
,
't'
,
'a'
,
't'
,
'e'
,
's'
,
0
};
static
const
WCHAR
szMsiPublishAssemblies
[]
=
{
'M'
,
's'
,
'i'
,
'P'
,
'u'
,
'b'
,
'l'
,
'i'
,
's'
,
'h'
,
'A'
,
's'
,
's'
,
'e'
,
'm'
,
'b'
,
'l'
,
'i'
,
'e'
,
's'
,
0
};
static
const
WCHAR
szMsiUnpublishAssemblies
[]
=
{
'M'
,
's'
,
'i'
,
'U'
,
'n'
,
'p'
,
'u'
,
'b'
,
'l'
,
'i'
,
's'
,
'h'
,
'A'
,
's'
,
's'
,
'e'
,
'm'
,
'b'
,
'l'
,
'i'
,
'e'
,
's'
,
0
};
static
const
WCHAR
szInstallODBC
[]
=
...
...
@@ -1227,6 +1224,7 @@ static UINT load_component( MSIRECORD *row, LPVOID param )
comp
->
Installed
=
INSTALLSTATE_UNKNOWN
;
msi_component_set_state
(
package
,
comp
,
INSTALLSTATE_UNKNOWN
);
comp
->
assembly
=
load_assembly
(
package
,
comp
);
return
ERROR_SUCCESS
;
}
...
...
@@ -2151,6 +2149,43 @@ static BOOL hash_matches( MSIFILE *file )
return
!
memcmp
(
&
hash
,
&
file
->
hash
,
sizeof
(
MSIFILEHASHINFO
)
);
}
static
WCHAR
*
get_temp_dir
(
void
)
{
static
UINT
id
;
WCHAR
tmp
[
MAX_PATH
],
dir
[
MAX_PATH
];
GetTempPathW
(
MAX_PATH
,
tmp
);
for
(;;)
{
if
(
!
GetTempFileNameW
(
tmp
,
szMsi
,
++
id
,
dir
))
return
NULL
;
if
(
CreateDirectoryW
(
dir
,
NULL
))
break
;
}
return
strdupW
(
dir
);
}
static
void
set_target_path
(
MSIPACKAGE
*
package
,
MSIFILE
*
file
)
{
MSIASSEMBLY
*
assembly
=
file
->
Component
->
assembly
;
TRACE
(
"file %s is named %s
\n
"
,
debugstr_w
(
file
->
File
),
debugstr_w
(
file
->
FileName
));
msi_free
(
file
->
TargetPath
);
if
(
assembly
)
{
if
(
!
assembly
->
tempdir
)
assembly
->
tempdir
=
get_temp_dir
();
file
->
TargetPath
=
build_directory_name
(
2
,
assembly
->
tempdir
,
file
->
FileName
);
track_tempfile
(
package
,
file
->
TargetPath
);
}
else
{
WCHAR
*
dir
=
resolve_folder
(
package
,
file
->
Component
->
Directory
,
FALSE
,
FALSE
,
TRUE
,
NULL
);
file
->
TargetPath
=
build_directory_name
(
2
,
dir
,
file
->
FileName
);
msi_free
(
dir
);
}
TRACE
(
"resolves to %s
\n
"
,
debugstr_w
(
file
->
TargetPath
));
}
static
UINT
set_file_install_states
(
MSIPACKAGE
*
package
)
{
VS_FIXEDFILEINFO
*
file_version
;
...
...
@@ -2158,27 +2193,18 @@ static UINT set_file_install_states( MSIPACKAGE *package )
LIST_FOR_EACH_ENTRY
(
file
,
&
package
->
files
,
MSIFILE
,
entry
)
{
MSICOMPONENT
*
comp
=
file
->
Component
;
MSICOMPONENT
*
comp
=
file
->
Component
;
DWORD
file_size
;
LPWSTR
p
;
if
(
!
comp
->
Enabled
)
continue
;
if
(
file
->
IsCompressed
)
comp
->
ForceLocalState
=
TRUE
;
/* calculate target */
p
=
resolve_folder
(
package
,
comp
->
Directory
,
FALSE
,
FALSE
,
TRUE
,
NULL
);
msi_free
(
file
->
TargetPath
);
set_target_path
(
package
,
file
);
TRACE
(
"file %s is named %s
\n
"
,
debugstr_w
(
file
->
File
),
debugstr_w
(
file
->
FileName
));
file
->
TargetPath
=
build_directory_name
(
2
,
p
,
file
->
FileName
);
msi_free
(
p
);
TRACE
(
"file %s resolves to %s
\n
"
,
debugstr_w
(
file
->
File
),
debugstr_w
(
file
->
TargetPath
));
if
(
GetFileAttributesW
(
file
->
TargetPath
)
==
INVALID_FILE_ATTRIBUTES
)
if
((
comp
->
assembly
&&
!
comp
->
assembly
->
installed
)
||
GetFileAttributesW
(
file
->
TargetPath
)
==
INVALID_FILE_ATTRIBUTES
)
{
file
->
state
=
msifs_missing
;
comp
->
Cost
+=
file
->
FileSize
;
...
...
@@ -6698,481 +6724,6 @@ static UINT ACTION_RemoveEnvironmentStrings( MSIPACKAGE *package )
return
rc
;
}
typedef
struct
tagMSIASSEMBLY
{
struct
list
entry
;
MSICOMPONENT
*
component
;
MSIFEATURE
*
feature
;
MSIFILE
*
file
;
LPWSTR
manifest
;
LPWSTR
application
;
LPWSTR
display_name
;
DWORD
attributes
;
BOOL
installed
;
}
MSIASSEMBLY
;
static
HRESULT
(
WINAPI
*
pCreateAssemblyCache
)(
IAssemblyCache
**
ppAsmCache
,
DWORD
dwReserved
);
static
HRESULT
(
WINAPI
*
pLoadLibraryShim
)(
LPCWSTR
szDllName
,
LPCWSTR
szVersion
,
LPVOID
pvReserved
,
HMODULE
*
phModDll
);
static
BOOL
init_functionpointers
(
void
)
{
HRESULT
hr
;
HMODULE
hfusion
;
HMODULE
hmscoree
;
static
const
WCHAR
szFusion
[]
=
{
'f'
,
'u'
,
's'
,
'i'
,
'o'
,
'n'
,
'.'
,
'd'
,
'l'
,
'l'
,
0
};
hmscoree
=
LoadLibraryA
(
"mscoree.dll"
);
if
(
!
hmscoree
)
{
WARN
(
"mscoree.dll not available
\n
"
);
return
FALSE
;
}
pLoadLibraryShim
=
(
void
*
)
GetProcAddress
(
hmscoree
,
"LoadLibraryShim"
);
if
(
!
pLoadLibraryShim
)
{
WARN
(
"LoadLibraryShim not available
\n
"
);
FreeLibrary
(
hmscoree
);
return
FALSE
;
}
hr
=
pLoadLibraryShim
(
szFusion
,
NULL
,
NULL
,
&
hfusion
);
if
(
FAILED
(
hr
))
{
WARN
(
"fusion.dll not available
\n
"
);
FreeLibrary
(
hmscoree
);
return
FALSE
;
}
pCreateAssemblyCache
=
(
void
*
)
GetProcAddress
(
hfusion
,
"CreateAssemblyCache"
);
FreeLibrary
(
hmscoree
);
return
TRUE
;
}
static
UINT
install_assembly
(
MSIPACKAGE
*
package
,
MSIASSEMBLY
*
assembly
,
LPWSTR
path
)
{
IAssemblyCache
*
cache
;
MSIRECORD
*
uirow
;
HRESULT
hr
;
UINT
r
=
ERROR_FUNCTION_FAILED
;
TRACE
(
"installing assembly: %s
\n
"
,
debugstr_w
(
path
));
uirow
=
MSI_CreateRecord
(
2
);
MSI_RecordSetStringW
(
uirow
,
2
,
assembly
->
display_name
);
ui_actiondata
(
package
,
szMsiPublishAssemblies
,
uirow
);
msiobj_release
(
&
uirow
->
hdr
);
if
(
assembly
->
feature
)
msi_feature_set_state
(
package
,
assembly
->
feature
,
INSTALLSTATE_LOCAL
);
if
(
assembly
->
manifest
)
FIXME
(
"Manifest unhandled
\n
"
);
if
(
assembly
->
application
)
{
FIXME
(
"Assembly should be privately installed
\n
"
);
return
ERROR_SUCCESS
;
}
if
(
assembly
->
attributes
==
msidbAssemblyAttributesWin32
)
{
FIXME
(
"Win32 assemblies not handled
\n
"
);
return
ERROR_SUCCESS
;
}
hr
=
pCreateAssemblyCache
(
&
cache
,
0
);
if
(
FAILED
(
hr
))
goto
done
;
hr
=
IAssemblyCache_InstallAssembly
(
cache
,
0
,
path
,
NULL
);
if
(
FAILED
(
hr
))
ERR
(
"Failed to install assembly: %s %08x
\n
"
,
debugstr_w
(
path
),
hr
);
r
=
ERROR_SUCCESS
;
done:
IAssemblyCache_Release
(
cache
);
return
r
;
}
typedef
struct
tagASSEMBLY_LIST
{
MSIPACKAGE
*
package
;
IAssemblyCache
*
cache
;
struct
list
*
assemblies
;
}
ASSEMBLY_LIST
;
typedef
struct
tagASSEMBLY_NAME
{
LPWSTR
name
;
LPWSTR
version
;
LPWSTR
culture
;
LPWSTR
pubkeytoken
;
}
ASSEMBLY_NAME
;
static
UINT
parse_assembly_name
(
MSIRECORD
*
rec
,
LPVOID
param
)
{
ASSEMBLY_NAME
*
asmname
=
param
;
LPCWSTR
name
=
MSI_RecordGetString
(
rec
,
2
);
LPWSTR
val
=
msi_dup_record_field
(
rec
,
3
);
static
const
WCHAR
Name
[]
=
{
'N'
,
'a'
,
'm'
,
'e'
,
0
};
static
const
WCHAR
Version
[]
=
{
'V'
,
'e'
,
'r'
,
's'
,
'i'
,
'o'
,
'n'
,
0
};
static
const
WCHAR
Culture
[]
=
{
'C'
,
'u'
,
'l'
,
't'
,
'u'
,
'r'
,
'e'
,
0
};
static
const
WCHAR
PublicKeyToken
[]
=
{
'P'
,
'u'
,
'b'
,
'l'
,
'i'
,
'c'
,
'K'
,
'e'
,
'y'
,
'T'
,
'o'
,
'k'
,
'e'
,
'n'
,
0
};
if
(
!
strcmpiW
(
name
,
Name
))
asmname
->
name
=
val
;
else
if
(
!
strcmpiW
(
name
,
Version
))
asmname
->
version
=
val
;
else
if
(
!
strcmpiW
(
name
,
Culture
))
asmname
->
culture
=
val
;
else
if
(
!
strcmpiW
(
name
,
PublicKeyToken
))
asmname
->
pubkeytoken
=
val
;
else
msi_free
(
val
);
return
ERROR_SUCCESS
;
}
static
void
append_str
(
LPWSTR
*
str
,
DWORD
*
size
,
LPCWSTR
append
)
{
if
(
!*
str
)
{
*
size
=
lstrlenW
(
append
)
+
1
;
*
str
=
msi_alloc
((
*
size
)
*
sizeof
(
WCHAR
));
lstrcpyW
(
*
str
,
append
);
return
;
}
(
*
size
)
+=
lstrlenW
(
append
);
*
str
=
msi_realloc
(
*
str
,
(
*
size
)
*
sizeof
(
WCHAR
));
lstrcatW
(
*
str
,
append
);
}
static
WCHAR
*
get_assembly_display_name
(
MSIDATABASE
*
db
,
MSICOMPONENT
*
comp
)
{
static
const
WCHAR
separator
[]
=
{
','
,
' '
,
0
};
static
const
WCHAR
Version
[]
=
{
'V'
,
'e'
,
'r'
,
's'
,
'i'
,
'o'
,
'n'
,
'='
,
0
};
static
const
WCHAR
Culture
[]
=
{
'C'
,
'u'
,
'l'
,
't'
,
'u'
,
'r'
,
'e'
,
'='
,
0
};
static
const
WCHAR
PublicKeyToken
[]
=
{
'P'
,
'u'
,
'b'
,
'l'
,
'i'
,
'c'
,
'K'
,
'e'
,
'y'
,
'T'
,
'o'
,
'k'
,
'e'
,
'n'
,
'='
,
0
};
static
const
WCHAR
query
[]
=
{
'S'
,
'E'
,
'L'
,
'E'
,
'C'
,
'T'
,
' '
,
'*'
,
' '
,
'F'
,
'R'
,
'O'
,
'M'
,
' '
,
'`'
,
'M'
,
's'
,
'i'
,
'A'
,
's'
,
's'
,
'e'
,
'm'
,
'b'
,
'l'
,
'y'
,
'N'
,
'a'
,
'm'
,
'e'
,
'`'
,
' '
,
'W'
,
'H'
,
'E'
,
'R'
,
'E'
,
' '
,
'`'
,
'C'
,
'o'
,
'm'
,
'p'
,
'o'
,
'n'
,
'e'
,
'n'
,
't'
,
'_'
,
'`'
,
'='
,
'\''
,
'%'
,
's'
,
'\''
,
0
};
ASSEMBLY_NAME
name
;
MSIQUERY
*
view
;
LPWSTR
display_name
;
DWORD
size
;
UINT
r
;
display_name
=
NULL
;
memset
(
&
name
,
0
,
sizeof
(
ASSEMBLY_NAME
)
);
r
=
MSI_OpenQuery
(
db
,
&
view
,
query
,
comp
->
Component
);
if
(
r
!=
ERROR_SUCCESS
)
return
NULL
;
MSI_IterateRecords
(
view
,
NULL
,
parse_assembly_name
,
&
name
);
msiobj_release
(
&
view
->
hdr
);
if
(
!
name
.
name
)
{
ERR
(
"No assembly name specified!
\n
"
);
return
NULL
;
}
append_str
(
&
display_name
,
&
size
,
name
.
name
);
if
(
name
.
version
)
{
append_str
(
&
display_name
,
&
size
,
separator
);
append_str
(
&
display_name
,
&
size
,
Version
);
append_str
(
&
display_name
,
&
size
,
name
.
version
);
}
if
(
name
.
culture
)
{
append_str
(
&
display_name
,
&
size
,
separator
);
append_str
(
&
display_name
,
&
size
,
Culture
);
append_str
(
&
display_name
,
&
size
,
name
.
culture
);
}
if
(
name
.
pubkeytoken
)
{
append_str
(
&
display_name
,
&
size
,
separator
);
append_str
(
&
display_name
,
&
size
,
PublicKeyToken
);
append_str
(
&
display_name
,
&
size
,
name
.
pubkeytoken
);
}
msi_free
(
name
.
name
);
msi_free
(
name
.
version
);
msi_free
(
name
.
culture
);
msi_free
(
name
.
pubkeytoken
);
return
display_name
;
}
static
BOOL
check_assembly_installed
(
MSIDATABASE
*
db
,
IAssemblyCache
*
cache
,
MSICOMPONENT
*
comp
)
{
ASSEMBLY_INFO
asminfo
;
LPWSTR
disp
;
BOOL
found
=
FALSE
;
HRESULT
hr
;
disp
=
get_assembly_display_name
(
db
,
comp
);
if
(
!
disp
)
return
FALSE
;
memset
(
&
asminfo
,
0
,
sizeof
(
ASSEMBLY_INFO
)
);
asminfo
.
cbAssemblyInfo
=
sizeof
(
ASSEMBLY_INFO
);
hr
=
IAssemblyCache_QueryAssemblyInfo
(
cache
,
QUERYASMINFO_FLAG_VALIDATE
,
disp
,
&
asminfo
);
if
(
SUCCEEDED
(
hr
))
found
=
(
asminfo
.
dwAssemblyFlags
==
ASSEMBLYINFO_FLAG_INSTALLED
);
msi_free
(
disp
);
return
found
;
}
static
UINT
load_assembly
(
MSIRECORD
*
rec
,
LPVOID
param
)
{
ASSEMBLY_LIST
*
list
=
param
;
MSIASSEMBLY
*
assembly
;
LPCWSTR
component
;
assembly
=
msi_alloc_zero
(
sizeof
(
MSIASSEMBLY
));
if
(
!
assembly
)
return
ERROR_OUTOFMEMORY
;
component
=
MSI_RecordGetString
(
rec
,
1
);
assembly
->
component
=
get_loaded_component
(
list
->
package
,
component
);
if
(
!
assembly
->
component
)
return
ERROR_SUCCESS
;
if
(
assembly
->
component
->
ActionRequest
!=
INSTALLSTATE_LOCAL
&&
assembly
->
component
->
ActionRequest
!=
INSTALLSTATE_SOURCE
)
{
TRACE
(
"Component not scheduled for installation: %s
\n
"
,
debugstr_w
(
component
));
assembly
->
component
->
Action
=
assembly
->
component
->
Installed
;
return
ERROR_SUCCESS
;
}
assembly
->
component
->
Action
=
assembly
->
component
->
ActionRequest
;
assembly
->
feature
=
find_feature_by_name
(
list
->
package
,
MSI_RecordGetString
(
rec
,
2
));
assembly
->
file
=
get_loaded_file
(
list
->
package
,
assembly
->
component
->
KeyPath
);
if
(
!
assembly
->
file
)
{
ERR
(
"File %s not found
\n
"
,
debugstr_w
(
assembly
->
component
->
KeyPath
));
return
ERROR_FUNCTION_FAILED
;
}
assembly
->
manifest
=
strdupW
(
MSI_RecordGetString
(
rec
,
3
));
assembly
->
application
=
strdupW
(
MSI_RecordGetString
(
rec
,
4
));
assembly
->
attributes
=
MSI_RecordGetInteger
(
rec
,
5
);
if
(
assembly
->
application
)
{
WCHAR
version
[
24
];
DWORD
size
=
sizeof
(
version
)
/
sizeof
(
WCHAR
);
/* FIXME: we should probably check the manifest file here */
if
(
!
MsiGetFileVersionW
(
assembly
->
file
->
TargetPath
,
version
,
&
size
,
NULL
,
NULL
)
&&
(
!
assembly
->
file
->
Version
||
strcmpW
(
version
,
assembly
->
file
->
Version
)
>=
0
))
{
assembly
->
installed
=
TRUE
;
}
}
else
assembly
->
installed
=
check_assembly_installed
(
list
->
package
->
db
,
list
->
cache
,
assembly
->
component
);
list_add_head
(
list
->
assemblies
,
&
assembly
->
entry
);
return
ERROR_SUCCESS
;
}
static
UINT
load_assemblies
(
MSIPACKAGE
*
package
,
struct
list
*
assemblies
)
{
IAssemblyCache
*
cache
=
NULL
;
ASSEMBLY_LIST
list
;
MSIQUERY
*
view
;
HRESULT
hr
;
UINT
r
;
static
const
WCHAR
query
[]
=
{
'S'
,
'E'
,
'L'
,
'E'
,
'C'
,
'T'
,
' '
,
'*'
,
' '
,
'F'
,
'R'
,
'O'
,
'M'
,
' '
,
'`'
,
'M'
,
's'
,
'i'
,
'A'
,
's'
,
's'
,
'e'
,
'm'
,
'b'
,
'l'
,
'y'
,
'`'
,
0
};
r
=
MSI_DatabaseOpenViewW
(
package
->
db
,
query
,
&
view
);
if
(
r
!=
ERROR_SUCCESS
)
return
ERROR_SUCCESS
;
hr
=
pCreateAssemblyCache
(
&
cache
,
0
);
if
(
FAILED
(
hr
))
return
ERROR_FUNCTION_FAILED
;
list
.
package
=
package
;
list
.
cache
=
cache
;
list
.
assemblies
=
assemblies
;
r
=
MSI_IterateRecords
(
view
,
NULL
,
load_assembly
,
&
list
);
msiobj_release
(
&
view
->
hdr
);
IAssemblyCache_Release
(
cache
);
return
r
;
}
static
void
free_assemblies
(
struct
list
*
assemblies
)
{
struct
list
*
item
,
*
cursor
;
LIST_FOR_EACH_SAFE
(
item
,
cursor
,
assemblies
)
{
MSIASSEMBLY
*
assembly
=
LIST_ENTRY
(
item
,
MSIASSEMBLY
,
entry
);
list_remove
(
&
assembly
->
entry
);
msi_free
(
assembly
->
application
);
msi_free
(
assembly
->
manifest
);
msi_free
(
assembly
->
display_name
);
msi_free
(
assembly
);
}
}
static
BOOL
find_assembly
(
struct
list
*
assemblies
,
LPCWSTR
file
,
MSIASSEMBLY
**
out
)
{
MSIASSEMBLY
*
assembly
;
LIST_FOR_EACH_ENTRY
(
assembly
,
assemblies
,
MSIASSEMBLY
,
entry
)
{
if
(
!
strcmpW
(
assembly
->
file
->
File
,
file
))
{
*
out
=
assembly
;
return
TRUE
;
}
}
return
FALSE
;
}
static
BOOL
installassembly_cb
(
MSIPACKAGE
*
package
,
LPCWSTR
file
,
DWORD
action
,
LPWSTR
*
path
,
DWORD
*
attrs
,
PVOID
user
)
{
MSIASSEMBLY
*
assembly
;
WCHAR
temppath
[
MAX_PATH
];
struct
list
*
assemblies
=
user
;
UINT
r
;
if
(
!
find_assembly
(
assemblies
,
file
,
&
assembly
))
return
FALSE
;
GetTempPathW
(
MAX_PATH
,
temppath
);
PathAddBackslashW
(
temppath
);
lstrcatW
(
temppath
,
assembly
->
file
->
FileName
);
if
(
action
==
MSICABEXTRACT_BEGINEXTRACT
)
{
if
(
assembly
->
installed
)
return
FALSE
;
*
path
=
strdupW
(
temppath
);
*
attrs
=
assembly
->
file
->
Attributes
;
}
else
if
(
action
==
MSICABEXTRACT_FILEEXTRACTED
)
{
assembly
->
installed
=
TRUE
;
r
=
install_assembly
(
package
,
assembly
,
temppath
);
if
(
r
!=
ERROR_SUCCESS
)
ERR
(
"Failed to install assembly
\n
"
);
}
return
TRUE
;
}
static
UINT
ACTION_MsiPublishAssemblies
(
MSIPACKAGE
*
package
)
{
UINT
r
;
struct
list
assemblies
=
LIST_INIT
(
assemblies
);
MSIASSEMBLY
*
assembly
;
MSIMEDIAINFO
*
mi
;
if
(
!
init_functionpointers
()
||
!
pCreateAssemblyCache
)
return
ERROR_FUNCTION_FAILED
;
r
=
load_assemblies
(
package
,
&
assemblies
);
if
(
r
!=
ERROR_SUCCESS
)
goto
done
;
if
(
list_empty
(
&
assemblies
))
goto
done
;
mi
=
msi_alloc_zero
(
sizeof
(
MSIMEDIAINFO
));
if
(
!
mi
)
{
r
=
ERROR_OUTOFMEMORY
;
goto
done
;
}
LIST_FOR_EACH_ENTRY
(
assembly
,
&
assemblies
,
MSIASSEMBLY
,
entry
)
{
if
(
assembly
->
installed
&&
!
mi
->
is_continuous
)
continue
;
if
(
assembly
->
file
->
IsCompressed
)
{
if
(
assembly
->
file
->
disk_id
!=
mi
->
disk_id
||
mi
->
is_continuous
)
{
MSICABDATA
data
;
r
=
ready_media
(
package
,
assembly
->
file
,
mi
);
if
(
r
!=
ERROR_SUCCESS
)
{
ERR
(
"Failed to ready media
\n
"
);
break
;
}
data
.
mi
=
mi
;
data
.
package
=
package
;
data
.
cb
=
installassembly_cb
;
data
.
user
=
&
assemblies
;
if
(
!
msi_cabextract
(
package
,
mi
,
&
data
))
{
ERR
(
"Failed to extract cabinet: %s
\n
"
,
debugstr_w
(
mi
->
cabinet
));
r
=
ERROR_FUNCTION_FAILED
;
break
;
}
}
}
else
{
LPWSTR
source
=
resolve_file_source
(
package
,
assembly
->
file
);
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 */
}
done:
free_assemblies
(
&
assemblies
);
return
r
;
}
static
UINT
ACTION_ValidateProductID
(
MSIPACKAGE
*
package
)
{
LPWSTR
key
,
template
,
id
;
...
...
dlls/msi/assembly.c
0 → 100644
View file @
a23514ee
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2010 Hans Leidekker for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#define COBJMACROS
#include "windef.h"
#include "winbase.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "msipriv.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
msi
);
static
HRESULT
(
WINAPI
*
pCreateAssemblyCacheNet
)(
IAssemblyCache
**
,
DWORD
);
static
HRESULT
(
WINAPI
*
pCreateAssemblyCacheSxs
)(
IAssemblyCache
**
,
DWORD
);
static
HRESULT
(
WINAPI
*
pLoadLibraryShim
)(
LPCWSTR
,
LPCWSTR
,
LPVOID
,
HMODULE
*
);
static
BOOL
init_function_pointers
(
void
)
{
static
const
WCHAR
szFusion
[]
=
{
'f'
,
'u'
,
's'
,
'i'
,
'o'
,
'n'
,
'.'
,
'd'
,
'l'
,
'l'
,
0
};
HMODULE
hfusion
,
hmscoree
,
hsxs
;
if
(
pCreateAssemblyCacheNet
)
return
TRUE
;
if
(
!
(
hmscoree
=
LoadLibraryA
(
"mscoree.dll"
)))
{
WARN
(
"mscoree.dll not available
\n
"
);
return
FALSE
;
}
if
(
!
(
pLoadLibraryShim
=
(
void
*
)
GetProcAddress
(
hmscoree
,
"LoadLibraryShim"
)))
{
WARN
(
"LoadLibraryShim not available
\n
"
);
FreeLibrary
(
hmscoree
);
return
FALSE
;
}
if
(
FAILED
(
pLoadLibraryShim
(
szFusion
,
NULL
,
NULL
,
&
hfusion
)))
{
WARN
(
"fusion.dll not available
\n
"
);
FreeLibrary
(
hmscoree
);
return
FALSE
;
}
pCreateAssemblyCacheNet
=
(
void
*
)
GetProcAddress
(
hfusion
,
"CreateAssemblyCache"
);
FreeLibrary
(
hmscoree
);
if
(
!
(
hsxs
=
LoadLibraryA
(
"sxs.dll"
)))
{
WARN
(
"sxs.dll not available
\n
"
);
FreeLibrary
(
hfusion
);
return
FALSE
;
}
pCreateAssemblyCacheSxs
=
(
void
*
)
GetProcAddress
(
hsxs
,
"CreateAssemblyCache"
);
return
TRUE
;
}
static
BOOL
init_assembly_caches
(
MSIPACKAGE
*
package
)
{
HRESULT
hr
;
if
(
!
init_function_pointers
())
return
FALSE
;
if
(
package
->
cache_net
)
return
TRUE
;
hr
=
pCreateAssemblyCacheNet
(
&
package
->
cache_net
,
0
);
if
(
hr
!=
S_OK
)
return
FALSE
;
hr
=
pCreateAssemblyCacheSxs
(
&
package
->
cache_sxs
,
0
);
if
(
hr
!=
S_OK
)
{
IAssemblyCache_Release
(
package
->
cache_net
);
package
->
cache_net
=
NULL
;
return
FALSE
;
}
return
TRUE
;
}
MSIRECORD
*
get_assembly_record
(
MSIPACKAGE
*
package
,
const
WCHAR
*
comp
)
{
static
const
WCHAR
query
[]
=
{
'S'
,
'E'
,
'L'
,
'E'
,
'C'
,
'T'
,
' '
,
'*'
,
' '
,
'F'
,
'R'
,
'O'
,
'M'
,
' '
,
'`'
,
'M'
,
's'
,
'i'
,
'A'
,
's'
,
's'
,
'e'
,
'm'
,
'b'
,
'l'
,
'y'
,
'`'
,
' '
,
'W'
,
'H'
,
'E'
,
'R'
,
'E'
,
' '
,
'`'
,
'C'
,
'o'
,
'm'
,
'p'
,
'o'
,
'n'
,
'e'
,
'n'
,
't'
,
'_'
,
'`'
,
' '
,
'='
,
' '
,
'\''
,
'%'
,
's'
,
'\''
,
0
};
MSIQUERY
*
view
;
MSIRECORD
*
rec
;
UINT
r
;
r
=
MSI_OpenQuery
(
package
->
db
,
&
view
,
query
,
comp
);
if
(
r
!=
ERROR_SUCCESS
)
return
NULL
;
r
=
MSI_ViewExecute
(
view
,
NULL
);
if
(
r
!=
ERROR_SUCCESS
)
{
msiobj_release
(
&
view
->
hdr
);
return
NULL
;
}
r
=
MSI_ViewFetch
(
view
,
&
rec
);
if
(
r
!=
ERROR_SUCCESS
)
{
msiobj_release
(
&
view
->
hdr
);
return
NULL
;
}
if
(
!
MSI_RecordGetString
(
rec
,
4
))
TRACE
(
"component is a global assembly
\n
"
);
msiobj_release
(
&
view
->
hdr
);
return
rec
;
}
struct
assembly_name
{
WCHAR
*
type
;
WCHAR
*
name
;
WCHAR
*
version
;
WCHAR
*
culture
;
WCHAR
*
token
;
WCHAR
*
arch
;
};
static
UINT
get_assembly_name_attribute
(
MSIRECORD
*
rec
,
LPVOID
param
)
{
static
const
WCHAR
typeW
[]
=
{
't'
,
'y'
,
'p'
,
'e'
,
0
};
static
const
WCHAR
nameW
[]
=
{
'n'
,
'a'
,
'm'
,
'e'
,
0
};
static
const
WCHAR
versionW
[]
=
{
'v'
,
'e'
,
'r'
,
's'
,
'i'
,
'o'
,
'n'
,
0
};
static
const
WCHAR
cultureW
[]
=
{
'c'
,
'u'
,
'l'
,
't'
,
'u'
,
'r'
,
'e'
,
0
};
static
const
WCHAR
tokenW
[]
=
{
'p'
,
'u'
,
'b'
,
'l'
,
'i'
,
'c'
,
'K'
,
'e'
,
'y'
,
'T'
,
'o'
,
'k'
,
'e'
,
'n'
,
0
};
static
const
WCHAR
archW
[]
=
{
'p'
,
'r'
,
'o'
,
'c'
,
'e'
,
's'
,
's'
,
'o'
,
'r'
,
'A'
,
'r'
,
'c'
,
'h'
,
'i'
,
't'
,
'e'
,
'c'
,
't'
,
'u'
,
'r'
,
'e'
,
0
};
struct
assembly_name
*
name
=
param
;
const
WCHAR
*
attr
=
MSI_RecordGetString
(
rec
,
2
);
WCHAR
*
value
=
msi_dup_record_field
(
rec
,
3
);
if
(
!
strcmpiW
(
attr
,
typeW
))
name
->
type
=
value
;
else
if
(
!
strcmpiW
(
attr
,
nameW
))
name
->
name
=
value
;
else
if
(
!
strcmpiW
(
attr
,
versionW
))
name
->
version
=
value
;
else
if
(
!
strcmpiW
(
attr
,
cultureW
))
name
->
culture
=
value
;
else
if
(
!
strcmpiW
(
attr
,
tokenW
))
name
->
token
=
value
;
else
if
(
!
strcmpiW
(
attr
,
archW
))
name
->
arch
=
value
;
else
msi_free
(
value
);
return
ERROR_SUCCESS
;
}
static
WCHAR
*
get_assembly_display_name
(
MSIDATABASE
*
db
,
const
WCHAR
*
comp
,
MSIASSEMBLY
*
assembly
)
{
static
const
WCHAR
fmt_netW
[]
=
{
'%'
,
's'
,
','
,
' '
,
'v'
,
'e'
,
'r'
,
's'
,
'i'
,
'o'
,
'n'
,
'='
,
'%'
,
's'
,
','
,
' '
,
'c'
,
'u'
,
'l'
,
't'
,
'u'
,
'r'
,
'e'
,
'='
,
'%'
,
's'
,
','
,
' '
,
'p'
,
'u'
,
'b'
,
'l'
,
'i'
,
'c'
,
'K'
,
'e'
,
'y'
,
'T'
,
'o'
,
'k'
,
'e'
,
'n'
,
'='
,
'%'
,
's'
,
0
};
static
const
WCHAR
fmt_sxsW
[]
=
{
'%'
,
's'
,
','
,
' '
,
'v'
,
'e'
,
'r'
,
's'
,
'i'
,
'o'
,
'n'
,
'='
,
'%'
,
's'
,
','
,
' '
,
'p'
,
'u'
,
'b'
,
'l'
,
'i'
,
'c'
,
'K'
,
'e'
,
'y'
,
'T'
,
'o'
,
'k'
,
'e'
,
'n'
,
'='
,
'%'
,
's'
,
','
,
' '
,
'p'
,
'r'
,
'o'
,
'c'
,
'e'
,
's'
,
's'
,
'o'
,
'r'
,
'A'
,
'r'
,
'c'
,
'h'
,
'i'
,
't'
,
'e'
,
'c'
,
't'
,
'u'
,
'r'
,
'e'
,
'='
,
'%'
,
's'
,
0
};
static
const
WCHAR
queryW
[]
=
{
'S'
,
'E'
,
'L'
,
'E'
,
'C'
,
'T'
,
' '
,
'*'
,
' '
,
'F'
,
'R'
,
'O'
,
'M'
,
' '
,
'`'
,
'M'
,
's'
,
'i'
,
'A'
,
's'
,
's'
,
'e'
,
'm'
,
'b'
,
'l'
,
'y'
,
'N'
,
'a'
,
'm'
,
'e'
,
'`'
,
' '
,
'W'
,
'H'
,
'E'
,
'R'
,
'E'
,
' '
,
'`'
,
'C'
,
'o'
,
'm'
,
'p'
,
'o'
,
'n'
,
'e'
,
'n'
,
't'
,
'_'
,
'`'
,
' '
,
'='
,
' '
,
'\''
,
'%'
,
's'
,
'\''
,
0
};
struct
assembly_name
name
;
WCHAR
*
display_name
=
NULL
;
MSIQUERY
*
view
;
int
len
;
UINT
r
;
memset
(
&
name
,
0
,
sizeof
(
name
)
);
r
=
MSI_OpenQuery
(
db
,
&
view
,
queryW
,
comp
);
if
(
r
!=
ERROR_SUCCESS
)
return
NULL
;
MSI_IterateRecords
(
view
,
NULL
,
get_assembly_name_attribute
,
&
name
);
msiobj_release
(
&
view
->
hdr
);
if
(
assembly
->
attributes
==
msidbAssemblyAttributesWin32
)
{
if
(
!
name
.
type
||
!
name
.
name
||
!
name
.
version
||
!
name
.
token
||
!
name
.
arch
)
{
WARN
(
"invalid win32 assembly name
\n
"
);
goto
done
;
}
len
=
strlenW
(
fmt_sxsW
);
len
+=
strlenW
(
name
.
name
);
len
+=
strlenW
(
name
.
version
);
len
+=
strlenW
(
name
.
token
);
len
+=
strlenW
(
name
.
arch
);
if
(
!
(
display_name
=
msi_alloc
(
len
*
sizeof
(
WCHAR
)
)))
goto
done
;
sprintfW
(
display_name
,
fmt_sxsW
,
name
.
name
,
name
.
version
,
name
.
token
,
name
.
arch
);
}
else
{
if
(
!
name
.
name
||
!
name
.
version
||
!
name
.
culture
||
!
name
.
token
)
{
WARN
(
"invalid assembly name
\n
"
);
goto
done
;
}
len
=
strlenW
(
fmt_netW
);
len
+=
strlenW
(
name
.
name
);
len
+=
strlenW
(
name
.
version
);
len
+=
strlenW
(
name
.
culture
);
len
+=
strlenW
(
name
.
token
);
if
(
!
(
display_name
=
msi_alloc
(
len
*
sizeof
(
WCHAR
)
)))
goto
done
;
sprintfW
(
display_name
,
fmt_netW
,
name
.
name
,
name
.
version
,
name
.
culture
,
name
.
token
);
}
done:
msi_free
(
name
.
type
);
msi_free
(
name
.
name
);
msi_free
(
name
.
version
);
msi_free
(
name
.
culture
);
msi_free
(
name
.
token
);
msi_free
(
name
.
arch
);
return
display_name
;
}
static
BOOL
check_assembly_installed
(
MSIPACKAGE
*
package
,
MSIASSEMBLY
*
assembly
)
{
IAssemblyCache
*
cache
;
ASSEMBLY_INFO
info
;
HRESULT
hr
;
if
(
assembly
->
application
)
{
/* FIXME: we should probably check the manifest file here */
return
FALSE
;
}
if
(
!
init_assembly_caches
(
package
))
return
FALSE
;
if
(
assembly
->
attributes
==
msidbAssemblyAttributesWin32
)
cache
=
package
->
cache_sxs
;
else
cache
=
package
->
cache_net
;
memset
(
&
info
,
0
,
sizeof
(
info
)
);
info
.
cbAssemblyInfo
=
sizeof
(
info
);
hr
=
IAssemblyCache_QueryAssemblyInfo
(
cache
,
QUERYASMINFO_FLAG_VALIDATE
,
assembly
->
display_name
,
&
info
);
if
(
hr
!=
S_OK
)
return
FALSE
;
return
(
info
.
dwAssemblyFlags
==
ASSEMBLYINFO_FLAG_INSTALLED
);
}
MSIASSEMBLY
*
load_assembly
(
MSIPACKAGE
*
package
,
MSICOMPONENT
*
comp
)
{
MSIRECORD
*
rec
;
MSIASSEMBLY
*
a
;
if
(
!
(
rec
=
get_assembly_record
(
package
,
comp
->
Component
)))
return
NULL
;
if
(
!
(
a
=
msi_alloc_zero
(
sizeof
(
MSIASSEMBLY
)
)))
{
msiobj_release
(
&
rec
->
hdr
);
return
NULL
;
}
a
->
feature
=
strdupW
(
MSI_RecordGetString
(
rec
,
2
)
);
TRACE
(
"feature %s
\n
"
,
debugstr_w
(
a
->
feature
));
a
->
manifest
=
strdupW
(
MSI_RecordGetString
(
rec
,
3
)
);
TRACE
(
"manifest %s
\n
"
,
debugstr_w
(
a
->
manifest
));
a
->
application
=
strdupW
(
MSI_RecordGetString
(
rec
,
4
)
);
TRACE
(
"application %s
\n
"
,
debugstr_w
(
a
->
application
));
a
->
attributes
=
MSI_RecordGetInteger
(
rec
,
5
);
TRACE
(
"attributes %u
\n
"
,
a
->
attributes
);
if
(
!
(
a
->
display_name
=
get_assembly_display_name
(
package
->
db
,
comp
->
Component
,
a
)))
{
WARN
(
"can't get display name
\n
"
);
msiobj_release
(
&
rec
->
hdr
);
msi_free
(
a
);
return
NULL
;
}
TRACE
(
"display name %s
\n
"
,
debugstr_w
(
a
->
display_name
));
a
->
installed
=
check_assembly_installed
(
package
,
a
);
TRACE
(
"assembly is %s
\n
"
,
a
->
installed
?
"installed"
:
"not installed"
);
msiobj_release
(
&
rec
->
hdr
);
return
a
;
}
UINT
install_assembly
(
MSIPACKAGE
*
package
,
MSICOMPONENT
*
comp
)
{
HRESULT
hr
;
const
WCHAR
*
manifest
;
IAssemblyCache
*
cache
;
MSIASSEMBLY
*
assembly
=
comp
->
assembly
;
MSIFEATURE
*
feature
=
NULL
;
if
(
comp
->
assembly
->
feature
)
feature
=
get_loaded_feature
(
package
,
comp
->
assembly
->
feature
);
if
(
assembly
->
application
)
{
if
(
feature
)
feature
->
Action
=
INSTALLSTATE_LOCAL
;
return
ERROR_SUCCESS
;
}
if
(
assembly
->
attributes
==
msidbAssemblyAttributesWin32
)
{
if
(
!
assembly
->
manifest
)
{
WARN
(
"no manifest
\n
"
);
return
ERROR_FUNCTION_FAILED
;
}
manifest
=
get_loaded_file
(
package
,
assembly
->
manifest
)
->
TargetPath
;
cache
=
package
->
cache_sxs
;
}
else
{
manifest
=
get_loaded_file
(
package
,
comp
->
KeyPath
)
->
TargetPath
;
cache
=
package
->
cache_net
;
}
TRACE
(
"installing assembly %s
\n
"
,
debugstr_w
(
manifest
));
hr
=
IAssemblyCache_InstallAssembly
(
cache
,
0
,
manifest
,
NULL
);
if
(
hr
!=
S_OK
)
{
ERR
(
"Failed to install assembly %s (0x%08x)
\n
"
,
debugstr_w
(
manifest
),
hr
);
return
ERROR_FUNCTION_FAILED
;
}
if
(
feature
)
feature
->
Action
=
INSTALLSTATE_LOCAL
;
assembly
->
installed
=
TRUE
;
return
ERROR_SUCCESS
;
}
UINT
ACTION_MsiPublishAssemblies
(
MSIPACKAGE
*
package
)
{
MSIRECORD
*
uirow
;
MSICOMPONENT
*
comp
;
LIST_FOR_EACH_ENTRY
(
comp
,
&
package
->
components
,
MSICOMPONENT
,
entry
)
{
if
(
!
comp
->
assembly
||
!
comp
->
Enabled
)
continue
;
/* FIXME: write assembly registry values */
uirow
=
MSI_CreateRecord
(
2
);
MSI_RecordSetStringW
(
uirow
,
2
,
comp
->
assembly
->
display_name
);
ui_actiondata
(
package
,
szMsiPublishAssemblies
,
uirow
);
msiobj_release
(
&
uirow
->
hdr
);
}
return
ERROR_SUCCESS
;
}
dlls/msi/files.c
View file @
a23514ee
...
...
@@ -186,7 +186,8 @@ static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
return
FALSE
;
msi_file_update_ui
(
package
,
f
,
szInstallFiles
);
msi_create_directory
(
package
,
f
->
Component
->
Directory
);
if
(
!
f
->
Component
->
assembly
)
msi_create_directory
(
package
,
f
->
Component
->
Directory
);
*
path
=
strdupW
(
f
->
TargetPath
);
*
attrs
=
f
->
Attributes
;
...
...
@@ -210,6 +211,7 @@ static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
UINT
ACTION_InstallFiles
(
MSIPACKAGE
*
package
)
{
MSIMEDIAINFO
*
mi
;
MSICOMPONENT
*
comp
;
UINT
rc
=
ERROR_SUCCESS
;
MSIFILE
*
file
;
...
...
@@ -234,7 +236,7 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
if
(
rc
!=
ERROR_SUCCESS
)
{
ERR
(
"Failed to ready media for %s
\n
"
,
debugstr_w
(
file
->
File
));
break
;
goto
done
;
}
data
.
mi
=
mi
;
...
...
@@ -247,7 +249,7 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
{
ERR
(
"Failed to extract cabinet: %s
\n
"
,
debugstr_w
(
mi
->
cabinet
));
rc
=
ERROR_INSTALL_FAILURE
;
break
;
goto
done
;
}
}
...
...
@@ -255,11 +257,11 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
{
LPWSTR
source
=
resolve_file_source
(
package
,
file
);
TRACE
(
"file paths %s to %s
\n
"
,
debugstr_w
(
source
),
debugstr_w
(
file
->
TargetPath
));
TRACE
(
"copying %s to %s
\n
"
,
debugstr_w
(
source
),
debugstr_w
(
file
->
TargetPath
));
msi_file_update_ui
(
package
,
file
,
szInstallFiles
);
msi_create_directory
(
package
,
file
->
Component
->
Directory
);
if
(
!
file
->
Component
->
assembly
)
msi_create_directory
(
package
,
file
->
Component
->
Directory
);
rc
=
copy_install_file
(
package
,
file
,
source
);
if
(
rc
!=
ERROR_SUCCESS
)
...
...
@@ -268,19 +270,32 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
debugstr_w
(
file
->
TargetPath
),
rc
);
rc
=
ERROR_INSTALL_FAILURE
;
msi_free
(
source
);
break
;
goto
done
;
}
msi_free
(
source
);
}
else
if
(
file
->
state
!=
msifs_installed
)
{
ERR
(
"compressed file wasn't installed (%s)
\n
"
,
debugstr_w
(
file
->
TargetPath
));
rc
=
ERROR_INSTALL_FAILURE
;
break
;
goto
done
;
}
}
LIST_FOR_EACH_ENTRY
(
comp
,
&
package
->
components
,
MSICOMPONENT
,
entry
)
{
if
(
comp
->
Enabled
&&
comp
->
assembly
&&
!
comp
->
assembly
->
installed
)
{
rc
=
install_assembly
(
package
,
comp
);
if
(
rc
!=
ERROR_SUCCESS
)
{
ERR
(
"Failed to install assembly
\n
"
);
rc
=
ERROR_INSTALL_FAILURE
;
break
;
}
}
}
done:
msi_free_media_info
(
mi
);
return
rc
;
}
...
...
dlls/msi/msipriv.h
View file @
a23514ee
...
...
@@ -32,6 +32,7 @@
#include "msidefs.h"
#include "objbase.h"
#include "objidl.h"
#include "fusion.h"
#include "winnls.h"
#include "winver.h"
#include "wine/list.h"
...
...
@@ -332,6 +333,8 @@ typedef struct tagMSIPACKAGE
LPWSTR
ActionFormat
;
LPWSTR
LastAction
;
HANDLE
log_file
;
IAssemblyCache
*
cache_net
;
IAssemblyCache
*
cache_sxs
;
struct
list
classes
;
struct
list
extensions
;
...
...
@@ -402,6 +405,17 @@ typedef struct tagMSIFEATURE
struct
list
Components
;
}
MSIFEATURE
;
typedef
struct
tagMSIASSEMBLY
{
LPWSTR
feature
;
LPWSTR
manifest
;
LPWSTR
application
;
DWORD
attributes
;
LPWSTR
display_name
;
LPWSTR
tempdir
;
BOOL
installed
;
}
MSIASSEMBLY
;
typedef
struct
tagMSICOMPONENT
{
struct
list
entry
;
...
...
@@ -420,6 +434,7 @@ typedef struct tagMSICOMPONENT
INT
RefCount
;
LPWSTR
FullKeypath
;
LPWSTR
AdvertiseString
;
MSIASSEMBLY
*
assembly
;
unsigned
int
anyAbsent
:
1
;
unsigned
int
hasAdvertiseFeature
:
1
;
...
...
@@ -908,6 +923,7 @@ extern UINT ACTION_UnregisterExtensionInfo(MSIPACKAGE *package);
extern
UINT
ACTION_UnregisterFonts
(
MSIPACKAGE
*
package
);
extern
UINT
ACTION_UnregisterMIMEInfo
(
MSIPACKAGE
*
package
);
extern
UINT
ACTION_UnregisterProgIdInfo
(
MSIPACKAGE
*
package
);
extern
UINT
ACTION_MsiPublishAssemblies
(
MSIPACKAGE
*
package
);
/* Helpers */
extern
DWORD
deformat_string
(
MSIPACKAGE
*
package
,
LPCWSTR
ptr
,
WCHAR
**
data
);
...
...
@@ -942,6 +958,8 @@ extern UINT msi_get_local_package_name(LPWSTR path, LPCWSTR suffix);
extern
UINT
msi_set_sourcedir_props
(
MSIPACKAGE
*
package
,
BOOL
replace
);
extern
void
msi_component_set_state
(
MSIPACKAGE
*
,
MSICOMPONENT
*
,
INSTALLSTATE
);
extern
void
msi_feature_set_state
(
MSIPACKAGE
*
,
MSIFEATURE
*
,
INSTALLSTATE
);
extern
MSIASSEMBLY
*
load_assembly
(
MSIPACKAGE
*
,
MSICOMPONENT
*
);
extern
UINT
install_assembly
(
MSIPACKAGE
*
,
MSICOMPONENT
*
);
/* media */
...
...
@@ -1060,6 +1078,7 @@ static const WCHAR szWow6432NodeCLSID[] = {'W','o','w','6','4','3','2','N','o','
static
const
WCHAR
szWow6432Node
[]
=
{
'W'
,
'o'
,
'w'
,
'6'
,
'4'
,
'3'
,
'2'
,
'N'
,
'o'
,
'd'
,
'e'
,
0
};
static
const
WCHAR
szStreams
[]
=
{
'_'
,
'S'
,
't'
,
'r'
,
'e'
,
'a'
,
'm'
,
's'
,
0
};
static
const
WCHAR
szStorages
[]
=
{
'_'
,
'S'
,
't'
,
'o'
,
'r'
,
'a'
,
'g'
,
'e'
,
's'
,
0
};
static
const
WCHAR
szMsiPublishAssemblies
[]
=
{
'M'
,
's'
,
'i'
,
'P'
,
'u'
,
'b'
,
'l'
,
'i'
,
's'
,
'h'
,
'A'
,
's'
,
's'
,
'e'
,
'm'
,
'b'
,
'l'
,
'i'
,
'e'
,
's'
,
0
};
/* memory allocation macro functions */
static
void
*
msi_alloc
(
size_t
len
)
__WINE_ALLOC_SIZE
(
1
);
...
...
dlls/msi/package.c
View file @
a23514ee
...
...
@@ -111,6 +111,14 @@ static void free_extension( MSIEXTENSION *ext )
msi_free
(
ext
);
}
static
void
free_assembly
(
MSIASSEMBLY
*
assembly
)
{
msi_free
(
assembly
->
display_name
);
if
(
assembly
->
tempdir
)
RemoveDirectoryW
(
assembly
->
tempdir
);
msi_free
(
assembly
->
tempdir
);
msi_free
(
assembly
);
}
static
void
free_package_structures
(
MSIPACKAGE
*
package
)
{
INT
i
;
...
...
@@ -154,6 +162,7 @@ static void free_package_structures( MSIPACKAGE *package )
msi_free
(
comp
->
Condition
);
msi_free
(
comp
->
KeyPath
);
msi_free
(
comp
->
FullKeypath
);
if
(
comp
->
assembly
)
free_assembly
(
comp
->
assembly
);
msi_free
(
comp
);
}
...
...
@@ -296,6 +305,9 @@ static void MSI_FreePackage( MSIOBJECTHDR *arg)
msiobj_release
(
&
package
->
db
->
hdr
);
free_package_structures
(
package
);
CloseHandle
(
package
->
log_file
);
if
(
package
->
cache_net
)
IAssemblyCache_Release
(
package
->
cache_net
);
if
(
package
->
cache_sxs
)
IAssemblyCache_Release
(
package
->
cache_sxs
);
}
static
UINT
create_temp_property_table
(
MSIPACKAGE
*
package
)
...
...
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