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
adccf12e
Commit
adccf12e
authored
Sep 19, 2018
by
Nikolay Sivov
Committed by
Alexandre Julliard
Sep 19, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
opcservices: Write full content type stream.
Signed-off-by:
Nikolay Sivov
<
nsivov@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
c009967b
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
317 additions
and
9 deletions
+317
-9
factory.c
dlls/opcservices/factory.c
+3
-0
package.c
dlls/opcservices/package.c
+235
-9
opcservices.c
dlls/opcservices/tests/opcservices.c
+79
-0
No files found.
dlls/opcservices/factory.c
View file @
adccf12e
...
...
@@ -387,6 +387,9 @@ static HRESULT WINAPI opc_factory_WritePackageToStream(IOpcFactory *iface, IOpcP
{
TRACE
(
"iface %p, package %p, flags %#x, stream %p.
\n
"
,
iface
,
package
,
flags
,
stream
);
if
(
!
package
||
!
stream
)
return
E_POINTER
;
return
opc_package_write
(
package
,
flags
,
stream
);
}
...
...
dlls/opcservices/package.c
View file @
adccf12e
...
...
@@ -25,6 +25,7 @@
#include "xmllite.h"
#include "wine/debug.h"
#include "wine/list.h"
#include "wine/unicode.h"
#include "opc_private.h"
...
...
@@ -1511,23 +1512,243 @@ HRESULT opc_package_create(IOpcFactory *factory, IOpcPackage **out)
return
S_OK
;
}
static
HRESULT
opc_package_write_contenttypes
(
struct
zip_archive
*
archive
,
IXmlWriter
*
writer
)
struct
content_types
{
struct
list
types
;
};
enum
content_type_element
{
CONTENT_TYPE_DEFAULT
,
CONTENT_TYPE_OVERRIDE
,
};
struct
content_type
{
struct
list
entry
;
enum
content_type_element
element
;
union
{
struct
default_type
{
WCHAR
*
ext
;
WCHAR
*
type
;
}
def
;
struct
override_type
{
IOpcPart
*
part
;
}
override
;
}
u
;
};
static
HRESULT
opc_package_add_override_content_type
(
struct
content_types
*
types
,
IOpcPart
*
part
)
{
struct
content_type
*
type
;
if
(
!
(
type
=
heap_alloc
(
sizeof
(
*
type
))))
return
E_OUTOFMEMORY
;
type
->
element
=
CONTENT_TYPE_OVERRIDE
;
type
->
u
.
override
.
part
=
part
;
IOpcPart_AddRef
(
part
);
list_add_tail
(
&
types
->
types
,
&
type
->
entry
);
return
S_OK
;
}
static
HRESULT
opc_package_add_default_content_type
(
struct
content_types
*
types
,
const
WCHAR
*
ext
,
const
WCHAR
*
content_type
)
{
struct
content_type
*
type
;
if
(
!
(
type
=
heap_alloc
(
sizeof
(
*
type
))))
return
E_OUTOFMEMORY
;
type
->
element
=
CONTENT_TYPE_DEFAULT
;
type
->
u
.
def
.
ext
=
opc_strdupW
(
ext
);
type
->
u
.
def
.
type
=
opc_strdupW
(
content_type
);
if
(
!
type
->
u
.
def
.
ext
||
!
type
->
u
.
def
.
type
)
{
CoTaskMemFree
(
type
->
u
.
def
.
ext
);
CoTaskMemFree
(
type
->
u
.
def
.
type
);
heap_free
(
type
);
return
E_OUTOFMEMORY
;
}
list_add_tail
(
&
types
->
types
,
&
type
->
entry
);
return
S_OK
;
}
static
HRESULT
opc_package_add_content_type
(
struct
content_types
*
types
,
IOpcPart
*
part
)
{
struct
content_type
*
cur
;
BSTR
ext
,
content_type
;
BOOL
added
=
FALSE
;
IOpcPartUri
*
name
;
HRESULT
hr
;
if
(
FAILED
(
hr
=
IOpcPart_GetName
(
part
,
&
name
)))
return
hr
;
hr
=
IOpcPartUri_GetExtension
(
name
,
&
ext
);
IOpcPartUri_Release
(
name
);
if
(
hr
==
S_FALSE
)
{
hr
=
opc_package_add_override_content_type
(
types
,
part
);
SysFreeString
(
ext
);
return
hr
;
}
if
(
FAILED
(
hr
))
return
hr
;
if
(
FAILED
(
hr
=
IOpcPart_GetContentType
(
part
,
&
content_type
)))
return
hr
;
LIST_FOR_EACH_ENTRY
(
cur
,
&
types
->
types
,
struct
content_type
,
entry
)
{
if
(
cur
->
element
==
CONTENT_TYPE_OVERRIDE
)
continue
;
if
(
!
strcmpiW
(
cur
->
u
.
def
.
ext
,
ext
))
{
added
=
TRUE
;
if
(
!
strcmpW
(
cur
->
u
.
def
.
type
,
content_type
))
break
;
hr
=
opc_package_add_override_content_type
(
types
,
part
);
break
;
}
}
if
(
!
added
)
hr
=
opc_package_add_default_content_type
(
types
,
ext
,
content_type
);
SysFreeString
(
ext
);
SysFreeString
(
content_type
);
return
hr
;
}
static
HRESULT
opc_package_collect_content_types
(
IOpcPackage
*
package
,
struct
content_types
*
types
)
{
IOpcPartEnumerator
*
enumerator
;
IOpcPartSet
*
parts
;
BOOL
has_next
;
HRESULT
hr
;
if
(
FAILED
(
hr
=
IOpcPackage_GetPartSet
(
package
,
&
parts
)))
return
hr
;
hr
=
IOpcPartSet_GetEnumerator
(
parts
,
&
enumerator
);
IOpcPartSet_Release
(
parts
);
if
(
FAILED
(
hr
))
return
hr
;
if
(
FAILED
(
hr
=
IOpcPartEnumerator_MoveNext
(
enumerator
,
&
has_next
))
||
!
has_next
)
{
IOpcPartEnumerator_Release
(
enumerator
);
return
hr
;
}
while
(
has_next
)
{
IOpcPart
*
part
;
if
(
FAILED
(
hr
=
IOpcPartEnumerator_GetCurrent
(
enumerator
,
&
part
)))
break
;
hr
=
opc_package_add_content_type
(
types
,
part
);
IOpcPart_Release
(
part
);
if
(
FAILED
(
hr
))
break
;
IOpcPartEnumerator_MoveNext
(
enumerator
,
&
has_next
);
}
IOpcPartEnumerator_Release
(
enumerator
);
return
hr
;
}
static
HRESULT
opc_package_write_contenttypes
(
IOpcPackage
*
package
,
struct
zip_archive
*
archive
,
IXmlWriter
*
writer
)
{
static
const
WCHAR
uriW
[]
=
{
'h'
,
't'
,
't'
,
'p'
,
':'
,
'/'
,
'/'
,
's'
,
'c'
,
'h'
,
'e'
,
'm'
,
'a'
,
's'
,
'.'
,
'o'
,
'p'
,
'e'
,
'n'
,
'x'
,
'm'
,
'l'
,
'f'
,
'o'
,
'r'
,
'm'
,
'a'
,
't'
,
's'
,
'.'
,
'o'
,
'r'
,
'g'
,
'/'
,
'p'
,
'a'
,
'c'
,
'k'
,
'a'
,
'g'
,
'e'
,
'/'
,
'2'
,
'0'
,
'0'
,
'6'
,
'/'
,
'c'
,
'o'
,
'n'
,
't'
,
'e'
,
'n'
,
't'
,
'-'
,
't'
,
'y'
,
'p'
,
'e'
,
's'
,
0
};
static
const
WCHAR
contenttypesW
[]
=
{
'['
,
'C'
,
'o'
,
'n'
,
't'
,
'e'
,
'n'
,
't'
,
'_'
,
'T'
,
'y'
,
'p'
,
'e'
,
's'
,
']'
,
'.'
,
'x'
,
'm'
,
'l'
,
0
};
static
const
WCHAR
contenttypeW
[]
=
{
'C'
,
'o'
,
'n'
,
't'
,
'e'
,
'n'
,
't'
,
'T'
,
'y'
,
'p'
,
'e'
,
0
};
static
const
WCHAR
extensionW
[]
=
{
'E'
,
'x'
,
't'
,
'e'
,
'n'
,
's'
,
'i'
,
'o'
,
'n'
,
0
};
static
const
WCHAR
overrideW
[]
=
{
'O'
,
'v'
,
'e'
,
'r'
,
'r'
,
'i'
,
'd'
,
'e'
,
0
};
static
const
WCHAR
partnameW
[]
=
{
'P'
,
'a'
,
'r'
,
't'
,
'N'
,
'a'
,
'm'
,
'e'
,
0
};
static
const
WCHAR
defaultW
[]
=
{
'D'
,
'e'
,
'f'
,
'a'
,
'u'
,
'l'
,
't'
,
0
};
static
const
WCHAR
typesW
[]
=
{
'T'
,
'y'
,
'p'
,
'e'
,
's'
,
0
};
IStream
*
content
;
struct
content_type
*
content_type
,
*
content_type2
;
struct
content_types
types
;
IStream
*
content
=
NULL
;
HRESULT
hr
;
if
(
FAILED
(
hr
=
CreateStreamOnHGlobal
(
NULL
,
TRUE
,
&
content
)))
return
hr
;
list_init
(
&
types
.
types
);
hr
=
IXmlWriter_SetOutput
(
writer
,
(
IUnknown
*
)
content
);
hr
=
CreateStreamOnHGlobal
(
NULL
,
TRUE
,
&
content
);
if
(
SUCCEEDED
(
hr
))
hr
=
opc_package_collect_content_types
(
package
,
&
types
);
if
(
SUCCEEDED
(
hr
))
hr
=
IXmlWriter_SetOutput
(
writer
,
(
IUnknown
*
)
content
);
if
(
SUCCEEDED
(
hr
))
hr
=
IXmlWriter_WriteStartDocument
(
writer
,
XmlStandalone_Omit
);
if
(
SUCCEEDED
(
hr
))
hr
=
IXmlWriter_WriteStartElement
(
writer
,
NULL
,
typesW
,
uriW
);
LIST_FOR_EACH_ENTRY_SAFE
(
content_type
,
content_type2
,
&
types
.
types
,
struct
content_type
,
entry
)
{
if
(
content_type
->
element
==
CONTENT_TYPE_DEFAULT
)
{
if
(
SUCCEEDED
(
hr
))
hr
=
IXmlWriter_WriteStartElement
(
writer
,
NULL
,
defaultW
,
NULL
);
if
(
SUCCEEDED
(
hr
))
hr
=
IXmlWriter_WriteAttributeString
(
writer
,
NULL
,
extensionW
,
NULL
,
content_type
->
u
.
def
.
ext
+
1
);
if
(
SUCCEEDED
(
hr
))
hr
=
IXmlWriter_WriteAttributeString
(
writer
,
NULL
,
contenttypeW
,
NULL
,
content_type
->
u
.
def
.
type
);
CoTaskMemFree
(
content_type
->
u
.
def
.
ext
);
CoTaskMemFree
(
content_type
->
u
.
def
.
type
);
}
else
{
IOpcPartUri
*
uri
=
NULL
;
WCHAR
*
type
=
NULL
;
BSTR
name
=
NULL
;
if
(
SUCCEEDED
(
hr
))
hr
=
IXmlWriter_WriteStartElement
(
writer
,
NULL
,
overrideW
,
NULL
);
if
(
SUCCEEDED
(
hr
))
hr
=
IOpcPart_GetName
(
content_type
->
u
.
override
.
part
,
&
uri
);
if
(
SUCCEEDED
(
hr
))
hr
=
IOpcPartUri_GetRawUri
(
uri
,
&
name
);
if
(
SUCCEEDED
(
hr
))
hr
=
IXmlWriter_WriteAttributeString
(
writer
,
NULL
,
partnameW
,
NULL
,
name
);
if
(
SUCCEEDED
(
hr
))
hr
=
IOpcPart_GetContentType
(
content_type
->
u
.
override
.
part
,
&
type
);
if
(
SUCCEEDED
(
hr
))
hr
=
IXmlWriter_WriteAttributeString
(
writer
,
NULL
,
contenttypeW
,
NULL
,
type
);
if
(
uri
)
IOpcPartUri_Release
(
uri
);
SysFreeString
(
name
);
CoTaskMemFree
(
type
);
IOpcPart_Release
(
content_type
->
u
.
override
.
part
);
}
if
(
SUCCEEDED
(
hr
))
hr
=
IXmlWriter_WriteEndElement
(
writer
);
list_remove
(
&
content_type
->
entry
);
heap_free
(
content_type
);
}
if
(
SUCCEEDED
(
hr
))
hr
=
IXmlWriter_WriteEndDocument
(
writer
);
if
(
SUCCEEDED
(
hr
))
...
...
@@ -1535,7 +1756,9 @@ static HRESULT opc_package_write_contenttypes(struct zip_archive *archive, IXmlW
if
(
SUCCEEDED
(
hr
))
hr
=
compress_add_file
(
archive
,
contenttypesW
,
content
,
OPC_COMPRESSION_NORMAL
);
IStream_Release
(
content
);
if
(
content
)
IStream_Release
(
content
);
return
hr
;
}
...
...
@@ -1736,7 +1959,7 @@ HRESULT opc_package_write(IOpcPackage *package, OPC_WRITE_FLAGS flags, IStream *
}
/* [Content_Types].xml */
hr
=
opc_package_write_contenttypes
(
archive
,
writer
);
hr
=
opc_package_write_contenttypes
(
package
,
archive
,
writer
);
/* Package relationships. */
if
(
SUCCEEDED
(
hr
))
hr
=
IOpcPackage_GetRelationshipSet
(
package
,
&
rels
);
...
...
@@ -1748,10 +1971,13 @@ HRESULT opc_package_write(IOpcPackage *package, OPC_WRITE_FLAGS flags, IStream *
if
(
SUCCEEDED
(
hr
))
hr
=
opc_package_write_parts
(
archive
,
package
,
writer
);
IOpcRelationshipSet_Release
(
rels
);
if
(
rels
)
IOpcRelationshipSet_Release
(
rels
);
if
(
uri
)
IOpcUri_Release
(
uri
);
compress_finalize_archive
(
archive
);
IXmlWriter_Release
(
writer
);
IOpcUri_Release
(
uri
);
return
hr
;
}
dlls/opcservices/tests/opcservices.c
View file @
adccf12e
...
...
@@ -1194,6 +1194,84 @@ static void test_create_part_uri(void)
IOpcFactory_Release
(
factory
);
}
static
HRESULT
WINAPI
custom_package_QueryInterface
(
IOpcPackage
*
iface
,
REFIID
iid
,
void
**
out
)
{
if
(
IsEqualIID
(
iid
,
&
IID_IOpcPackage
)
||
IsEqualIID
(
iid
,
&
IID_IUnknown
))
{
*
out
=
iface
;
IOpcPackage_AddRef
(
iface
);
return
S_OK
;
}
*
out
=
NULL
;
return
E_NOINTERFACE
;
}
static
ULONG
WINAPI
custom_package_AddRef
(
IOpcPackage
*
iface
)
{
return
2
;
}
static
ULONG
WINAPI
custom_package_Release
(
IOpcPackage
*
iface
)
{
return
1
;
}
static
HRESULT
WINAPI
custom_package_GetPartSet
(
IOpcPackage
*
iface
,
IOpcPartSet
**
part_set
)
{
return
0x80000001
;
}
static
HRESULT
WINAPI
custom_package_GetRelationshipSet
(
IOpcPackage
*
iface
,
IOpcRelationshipSet
**
relationship_set
)
{
return
0x80000001
;
}
static
const
IOpcPackageVtbl
custom_package_vtbl
=
{
custom_package_QueryInterface
,
custom_package_AddRef
,
custom_package_Release
,
custom_package_GetPartSet
,
custom_package_GetRelationshipSet
,
};
static
void
test_write_package
(
void
)
{
IOpcPackage
custom_package
=
{
&
custom_package_vtbl
};
IOpcFactory
*
factory
;
IOpcPackage
*
package
;
IStream
*
stream
;
HRESULT
hr
;
factory
=
create_factory
();
hr
=
IOpcFactory_CreatePackage
(
factory
,
&
package
);
ok
(
SUCCEEDED
(
hr
)
||
broken
(
hr
==
E_NOTIMPL
)
/* Vista */
,
"Failed to create a package, hr %#x.
\n
"
,
hr
);
if
(
FAILED
(
hr
))
{
IOpcFactory_Release
(
factory
);
return
;
}
hr
=
IOpcFactory_WritePackageToStream
(
factory
,
NULL
,
OPC_WRITE_FORCE_ZIP32
,
NULL
);
ok
(
hr
==
E_POINTER
,
"Unexpected hr %#x.
\n
"
,
hr
);
hr
=
CreateStreamOnHGlobal
(
NULL
,
TRUE
,
&
stream
);
ok
(
SUCCEEDED
(
hr
),
"Failed to create a stream, hr %#x.
\n
"
,
hr
);
hr
=
IOpcFactory_WritePackageToStream
(
factory
,
NULL
,
OPC_WRITE_FORCE_ZIP32
,
stream
);
ok
(
hr
==
E_POINTER
,
"Unexpected hr %#x.
\n
"
,
hr
);
hr
=
IOpcFactory_WritePackageToStream
(
factory
,
&
custom_package
,
OPC_WRITE_FORCE_ZIP32
,
stream
);
ok
(
hr
==
0x80000001
,
"Unexpected hr %#x.
\n
"
,
hr
);
IStream_Release
(
stream
);
IOpcFactory_Release
(
factory
);
IOpcPackage_Release
(
package
);
}
START_TEST
(
opcservices
)
{
IOpcFactory
*
factory
;
...
...
@@ -1217,6 +1295,7 @@ START_TEST(opcservices)
test_relative_uri
();
test_combine_uri
();
test_create_part_uri
();
test_write_package
();
IOpcFactory_Release
(
factory
);
...
...
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