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
aaf4227a
Commit
aaf4227a
authored
Nov 05, 2010
by
Hans Leidekker
Committed by
Alexandre Julliard
Nov 05, 2010
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
sxs: Add support for installing side-by-side assemblies.
parent
54a61744
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
376 additions
and
2 deletions
+376
-2
Makefile.in
dlls/sxs/Makefile.in
+1
-0
cache.c
dlls/sxs/cache.c
+375
-2
No files found.
dlls/sxs/Makefile.in
View file @
aaf4227a
MODULE
=
sxs.dll
IMPORTS
=
oleaut32 ole32
C_SRCS
=
\
cache.c
\
...
...
dlls/sxs/cache.c
View file @
aaf4227a
...
...
@@ -27,10 +27,22 @@
#include "winbase.h"
#include "ole2.h"
#include "winsxs.h"
#include "msxml2.h"
#include "wine/debug.h"
#include "wine/list.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
sxs
);
static
inline
WCHAR
*
strdupW
(
const
WCHAR
*
s
)
{
WCHAR
*
t
;
if
(
!
s
)
return
NULL
;
if
((
t
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
strlenW
(
s
)
+
1
)
*
sizeof
(
WCHAR
)
)))
strcpyW
(
t
,
s
);
return
t
;
}
struct
cache
{
const
IAssemblyCacheVtbl
*
vtbl
;
...
...
@@ -118,14 +130,375 @@ static HRESULT WINAPI cache_Reserved(
return
E_NOTIMPL
;
}
static
BSTR
get_attribute_value
(
IXMLDOMNamedNodeMap
*
map
,
const
WCHAR
*
value_name
)
{
HRESULT
hr
;
IXMLDOMNode
*
attr
;
VARIANT
var
;
BSTR
str
;
str
=
SysAllocString
(
value_name
);
hr
=
IXMLDOMNamedNodeMap_getNamedItem
(
map
,
str
,
&
attr
);
SysFreeString
(
str
);
if
(
hr
!=
S_OK
)
return
NULL
;
hr
=
IXMLDOMNode_get_nodeValue
(
attr
,
&
var
);
IXMLDOMNode_Release
(
attr
);
if
(
hr
!=
S_OK
)
return
NULL
;
if
(
V_VT
(
&
var
)
!=
VT_BSTR
)
{
VariantClear
(
&
var
);
return
NULL
;
}
TRACE
(
"%s=%s
\n
"
,
debugstr_w
(
value_name
),
debugstr_w
(
V_BSTR
(
&
var
)));
return
V_BSTR
(
&
var
);
}
struct
file
{
struct
list
entry
;
BSTR
name
;
};
struct
assembly
{
BSTR
type
;
BSTR
name
;
BSTR
version
;
BSTR
arch
;
BSTR
token
;
struct
list
files
;
};
static
void
free_assembly
(
struct
assembly
*
assembly
)
{
struct
list
*
item
,
*
cursor
;
if
(
!
assembly
)
return
;
SysFreeString
(
assembly
->
type
);
SysFreeString
(
assembly
->
name
);
SysFreeString
(
assembly
->
version
);
SysFreeString
(
assembly
->
arch
);
SysFreeString
(
assembly
->
token
);
LIST_FOR_EACH_SAFE
(
item
,
cursor
,
&
assembly
->
files
)
{
struct
file
*
file
=
LIST_ENTRY
(
item
,
struct
file
,
entry
);
list_remove
(
&
file
->
entry
);
SysFreeString
(
file
->
name
);
HeapFree
(
GetProcessHeap
(),
0
,
file
);
}
HeapFree
(
GetProcessHeap
(),
0
,
assembly
);
}
static
HRESULT
parse_files
(
IXMLDOMDocument
*
doc
,
struct
assembly
*
assembly
)
{
static
const
WCHAR
fileW
[]
=
{
'f'
,
'i'
,
'l'
,
'e'
,
0
};
static
const
WCHAR
nameW
[]
=
{
'n'
,
'a'
,
'm'
,
'e'
,
0
};
IXMLDOMNamedNodeMap
*
attrs
;
IXMLDOMNodeList
*
list
;
IXMLDOMNode
*
node
;
struct
file
*
f
;
BSTR
str
;
HRESULT
hr
;
LONG
len
;
str
=
SysAllocString
(
fileW
);
hr
=
IXMLDOMDocument_getElementsByTagName
(
doc
,
str
,
&
list
);
SysFreeString
(
str
);
if
(
hr
!=
S_OK
)
return
hr
;
hr
=
IXMLDOMNodeList_get_length
(
list
,
&
len
);
if
(
hr
!=
S_OK
)
goto
done
;
TRACE
(
"found %d files
\n
"
,
len
);
if
(
!
len
)
{
hr
=
ERROR_SXS_MANIFEST_FORMAT_ERROR
;
goto
done
;
}
for
(;;)
{
hr
=
IXMLDOMNodeList_nextNode
(
list
,
&
node
);
if
(
hr
!=
S_OK
||
!
node
)
{
hr
=
S_OK
;
break
;
}
/* FIXME: validate node type */
hr
=
IXMLDOMNode_get_attributes
(
node
,
&
attrs
);
IXMLDOMNode_Release
(
node
);
if
(
hr
!=
S_OK
)
goto
done
;
if
(
!
(
f
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
struct
file
)
)))
{
IXMLDOMNamedNodeMap_Release
(
attrs
);
hr
=
E_OUTOFMEMORY
;
goto
done
;
}
f
->
name
=
get_attribute_value
(
attrs
,
nameW
);
IXMLDOMNamedNodeMap_Release
(
attrs
);
if
(
!
f
->
name
)
{
HeapFree
(
GetProcessHeap
(),
0
,
f
);
hr
=
ERROR_SXS_MANIFEST_FORMAT_ERROR
;
goto
done
;
}
list_add_tail
(
&
assembly
->
files
,
&
f
->
entry
);
}
if
(
list_empty
(
&
assembly
->
files
))
{
WARN
(
"no files found
\n
"
);
hr
=
ERROR_SXS_MANIFEST_FORMAT_ERROR
;
}
done:
IXMLDOMNodeList_Release
(
list
);
return
hr
;
}
static
HRESULT
parse_assembly
(
IXMLDOMDocument
*
doc
,
struct
assembly
**
assembly
)
{
static
const
WCHAR
identityW
[]
=
{
'a'
,
's'
,
's'
,
'e'
,
'm'
,
'b'
,
'l'
,
'y'
,
'I'
,
'd'
,
'e'
,
'n'
,
't'
,
'i'
,
't'
,
'y'
,
0
};
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
architectureW
[]
=
{
'p'
,
'r'
,
'o'
,
'c'
,
'e'
,
's'
,
's'
,
'o'
,
'r'
,
'A'
,
'r'
,
'c'
,
'h'
,
'i'
,
't'
,
'e'
,
'c'
,
'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
win32W
[]
=
{
'w'
,
'i'
,
'n'
,
'3'
,
'2'
,
0
};
static
const
WCHAR
policyW
[]
=
{
'w'
,
'i'
,
'n'
,
'3'
,
'2'
,
'-'
,
'p'
,
'o'
,
'l'
,
'i'
,
'c'
,
'y'
,
0
};
IXMLDOMNodeList
*
list
=
NULL
;
IXMLDOMNode
*
node
=
NULL
;
IXMLDOMNamedNodeMap
*
attrs
=
NULL
;
struct
assembly
*
a
=
NULL
;
BSTR
str
;
HRESULT
hr
;
LONG
len
;
str
=
SysAllocString
(
identityW
);
hr
=
IXMLDOMDocument_getElementsByTagName
(
doc
,
str
,
&
list
);
SysFreeString
(
str
);
if
(
hr
!=
S_OK
)
goto
done
;
hr
=
IXMLDOMNodeList_get_length
(
list
,
&
len
);
if
(
hr
!=
S_OK
)
goto
done
;
if
(
!
len
)
{
hr
=
ERROR_SXS_MANIFEST_FORMAT_ERROR
;
goto
done
;
}
hr
=
IXMLDOMNodeList_nextNode
(
list
,
&
node
);
if
(
hr
!=
S_OK
)
goto
done
;
if
(
!
node
)
{
hr
=
ERROR_SXS_MANIFEST_FORMAT_ERROR
;
goto
done
;
}
if
(
!
(
a
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
struct
assembly
)
)))
{
hr
=
E_OUTOFMEMORY
;
goto
done
;
}
list_init
(
&
a
->
files
);
hr
=
IXMLDOMNode_get_attributes
(
node
,
&
attrs
);
if
(
hr
!=
S_OK
)
goto
done
;
a
->
type
=
get_attribute_value
(
attrs
,
typeW
);
if
(
a
->
type
&&
!
strcmpW
(
a
->
type
,
policyW
))
{
FIXME
(
"ignoring policy assembly
\n
"
);
hr
=
ERROR_SXS_MANIFEST_FORMAT_ERROR
;
goto
done
;
}
a
->
name
=
get_attribute_value
(
attrs
,
nameW
);
a
->
version
=
get_attribute_value
(
attrs
,
versionW
);
a
->
arch
=
get_attribute_value
(
attrs
,
architectureW
);
a
->
token
=
get_attribute_value
(
attrs
,
tokenW
);
if
(
!
a
->
type
||
strcmpW
(
a
->
type
,
win32W
)
||
!
a
->
name
||
!
a
->
version
||
!
a
->
arch
||
!
a
->
token
)
{
WARN
(
"invalid win32 assembly
\n
"
);
hr
=
ERROR_SXS_MANIFEST_FORMAT_ERROR
;
goto
done
;
}
hr
=
parse_files
(
doc
,
a
);
done:
if
(
attrs
)
IXMLDOMNamedNodeMap_Release
(
attrs
);
if
(
node
)
IXMLDOMNode_Release
(
node
);
if
(
list
)
IXMLDOMNodeList_Release
(
list
);
if
(
hr
==
S_OK
)
*
assembly
=
a
;
else
free_assembly
(
a
);
return
hr
;
}
static
WCHAR
*
build_source_filename
(
const
WCHAR
*
manifest
,
struct
file
*
file
)
{
WCHAR
*
src
;
const
WCHAR
*
p
;
int
len
;
p
=
strrchrW
(
manifest
,
'\\'
);
if
(
!
p
)
p
=
strrchrW
(
manifest
,
'/'
);
if
(
!
p
)
return
strdupW
(
manifest
);
len
=
p
-
manifest
+
1
;
if
(
!
(
src
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
len
+
strlenW
(
file
->
name
)
+
1
)
*
sizeof
(
WCHAR
)
)))
return
NULL
;
memcpy
(
src
,
manifest
,
len
*
sizeof
(
WCHAR
)
);
strcpyW
(
src
+
len
,
file
->
name
);
return
src
;
}
static
HRESULT
install_assembly
(
const
WCHAR
*
manifest
,
struct
assembly
*
assembly
)
{
static
const
WCHAR
winsxsW
[]
=
{
'\\'
,
'w'
,
'i'
,
'n'
,
's'
,
'x'
,
's'
,
'\\'
,
0
};
static
const
WCHAR
manifestsW
[]
=
{
'm'
,
'a'
,
'n'
,
'i'
,
'f'
,
'e'
,
's'
,
't'
,
's'
,
'\\'
,
0
};
static
const
WCHAR
deadbeefW
[]
=
{
'n'
,
'o'
,
'n'
,
'e'
,
'_'
,
'd'
,
'e'
,
'a'
,
'd'
,
'b'
,
'e'
,
'e'
,
'f'
,
0
};
static
const
WCHAR
suffixW
[]
=
{
'.'
,
'm'
,
'a'
,
'n'
,
'i'
,
'f'
,
'e'
,
's'
,
't'
,
0
};
static
const
WCHAR
backslashW
[]
=
{
'\\'
,
0
};
static
const
WCHAR
fmtW
[]
=
{
'%'
,
's'
,
'_'
,
'%'
,
's'
,
'_'
,
'%'
,
's'
,
'_'
,
'%'
,
's'
,
'_'
,
'%'
,
's'
,
0
};
WCHAR
sxsdir
[
MAX_PATH
],
*
p
,
*
name
,
*
dst
,
*
src
;
int
len
;
struct
file
*
file
;
HRESULT
hr
=
S_OK
;
BOOL
ret
;
GetWindowsDirectoryW
(
sxsdir
,
MAX_PATH
);
strcatW
(
sxsdir
,
winsxsW
);
len
=
strlenW
(
fmtW
);
len
+=
strlenW
(
assembly
->
arch
);
len
+=
strlenW
(
assembly
->
name
);
len
+=
strlenW
(
assembly
->
token
);
len
+=
strlenW
(
assembly
->
version
);
len
+=
strlenW
(
deadbeefW
);
if
(
!
(
name
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
)
)))
return
E_OUTOFMEMORY
;
len
=
sprintfW
(
name
,
fmtW
,
assembly
->
arch
,
assembly
->
name
,
assembly
->
token
,
assembly
->
version
,
deadbeefW
);
for
(
p
=
name
;
*
p
;
p
++
)
*
p
=
tolowerW
(
*
p
);
len
+=
strlenW
(
sxsdir
);
len
+=
strlenW
(
manifestsW
);
len
+=
strlenW
(
suffixW
);
if
(
!
(
dst
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
len
+
1
)
*
sizeof
(
WCHAR
)
)))
{
HeapFree
(
GetProcessHeap
(),
0
,
name
);
return
E_OUTOFMEMORY
;
}
strcpyW
(
dst
,
sxsdir
);
strcatW
(
dst
,
manifestsW
);
strcatW
(
dst
,
name
);
strcatW
(
dst
,
suffixW
);
ret
=
CopyFileW
(
manifest
,
dst
,
FALSE
);
HeapFree
(
GetProcessHeap
(),
0
,
dst
);
if
(
!
ret
)
{
hr
=
HRESULT_FROM_WIN32
(
GetLastError
()
);
WARN
(
"failed to copy manifest file 0x%08x
\n
"
,
hr
);
goto
done
;
}
/* FIXME: this should be a transaction */
LIST_FOR_EACH_ENTRY
(
file
,
&
assembly
->
files
,
struct
file
,
entry
)
{
if
(
!
(
src
=
build_source_filename
(
manifest
,
file
)))
{
hr
=
E_OUTOFMEMORY
;
goto
done
;
}
len
=
strlenW
(
sxsdir
)
+
strlenW
(
name
)
+
strlenW
(
file
->
name
);
if
(
!
(
dst
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
len
+
2
)
*
sizeof
(
WCHAR
)
)))
{
HeapFree
(
GetProcessHeap
(),
0
,
src
);
hr
=
E_OUTOFMEMORY
;
goto
done
;
}
strcpyW
(
dst
,
sxsdir
);
strcatW
(
dst
,
name
);
CreateDirectoryW
(
dst
,
NULL
);
strcatW
(
dst
,
backslashW
);
strcatW
(
dst
,
file
->
name
);
for
(
p
=
dst
;
*
p
;
p
++
)
*
p
=
tolowerW
(
*
p
);
ret
=
CopyFileW
(
src
,
dst
,
FALSE
);
HeapFree
(
GetProcessHeap
(),
0
,
src
);
HeapFree
(
GetProcessHeap
(),
0
,
dst
);
if
(
!
ret
)
{
hr
=
HRESULT_FROM_WIN32
(
GetLastError
()
);
WARN
(
"failed to copy file 0x%08x
\n
"
,
hr
);
goto
done
;
}
}
done:
HeapFree
(
GetProcessHeap
(),
0
,
name
);
return
hr
;
}
static
HRESULT
WINAPI
cache_InstallAssembly
(
IAssemblyCache
*
iface
,
DWORD
flags
,
LPCWSTR
path
,
LPCFUSION_INSTALL_REFERENCE
ref
)
{
FIXME
(
"%p, 0x%08x, %s, %p
\n
"
,
iface
,
flags
,
debugstr_w
(
path
),
ref
);
return
E_NOTIMPL
;
HRESULT
hr
,
init
;
IXMLDOMDocument
*
doc
=
NULL
;
struct
assembly
*
assembly
=
NULL
;
BSTR
str
;
VARIANT
var
;
VARIANT_BOOL
b
;
TRACE
(
"%p, 0x%08x, %s, %p
\n
"
,
iface
,
flags
,
debugstr_w
(
path
),
ref
);
init
=
CoInitialize
(
NULL
);
hr
=
CoCreateInstance
(
&
CLSID_DOMDocument
,
NULL
,
CLSCTX_INPROC_SERVER
,
&
IID_IXMLDOMDocument
,
(
void
**
)
&
doc
);
if
(
hr
!=
S_OK
)
goto
done
;
str
=
SysAllocString
(
path
);
VariantInit
(
&
var
);
V_VT
(
&
var
)
=
VT_BSTR
;
V_BSTR
(
&
var
)
=
str
;
hr
=
IXMLDOMDocument_load
(
doc
,
var
,
&
b
);
SysFreeString
(
str
);
if
(
hr
!=
S_OK
)
goto
done
;
if
(
!
b
)
{
WARN
(
"failed to load manifest
\n
"
);
hr
=
S_FALSE
;
goto
done
;
}
hr
=
parse_assembly
(
doc
,
&
assembly
);
if
(
hr
!=
S_OK
)
goto
done
;
/* FIXME: verify name attributes */
hr
=
install_assembly
(
path
,
assembly
);
done:
free_assembly
(
assembly
);
if
(
doc
)
IXMLDOMDocument_Release
(
doc
);
if
(
SUCCEEDED
(
init
))
CoUninitialize
();
return
hr
;
}
static
const
IAssemblyCacheVtbl
cache_vtbl
=
...
...
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