2 * Copyright 2018 Nikolay Sivov for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/debug.h"
28 #include "wine/list.h"
29 #include "wine/unicode.h"
31 #include "opc_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(msopc
);
42 struct opc_content_stream
44 IStream IStream_iface
;
47 struct opc_content
*content
;
53 IOpcPackage IOpcPackage_iface
;
56 IOpcPartSet
*part_set
;
57 IOpcRelationshipSet
*relationship_set
;
63 IOpcPartEnumerator IOpcPartEnumerator_iface
;
66 struct opc_part_set
*part_set
;
73 IOpcPart IOpcPart_iface
;
78 DWORD compression_options
;
79 IOpcRelationshipSet
*relationship_set
;
80 struct opc_content
*content
;
85 IOpcPartSet IOpcPartSet_iface
;
88 struct opc_part
**parts
;
96 IOpcRelationshipEnumerator IOpcRelationshipEnumerator_iface
;
99 struct opc_relationship_set
*rel_set
;
104 struct opc_relationship
106 IOpcRelationship IOpcRelationship_iface
;
112 OPC_URI_TARGET_MODE target_mode
;
116 struct opc_relationship_set
118 IOpcRelationshipSet IOpcRelationshipSet_iface
;
121 struct opc_relationship
**relationships
;
128 static inline struct opc_package
*impl_from_IOpcPackage(IOpcPackage
*iface
)
130 return CONTAINING_RECORD(iface
, struct opc_package
, IOpcPackage_iface
);
133 static inline struct opc_part_set
*impl_from_IOpcPartSet(IOpcPartSet
*iface
)
135 return CONTAINING_RECORD(iface
, struct opc_part_set
, IOpcPartSet_iface
);
138 static inline struct opc_part
*impl_from_IOpcPart(IOpcPart
*iface
)
140 return CONTAINING_RECORD(iface
, struct opc_part
, IOpcPart_iface
);
143 static inline struct opc_relationship_set
*impl_from_IOpcRelationshipSet(IOpcRelationshipSet
*iface
)
145 return CONTAINING_RECORD(iface
, struct opc_relationship_set
, IOpcRelationshipSet_iface
);
148 static inline struct opc_relationship
*impl_from_IOpcRelationship(IOpcRelationship
*iface
)
150 return CONTAINING_RECORD(iface
, struct opc_relationship
, IOpcRelationship_iface
);
153 static inline struct opc_content_stream
*impl_from_IStream(IStream
*iface
)
155 return CONTAINING_RECORD(iface
, struct opc_content_stream
, IStream_iface
);
158 static inline struct opc_part_enum
*impl_from_IOpcPartEnumerator(IOpcPartEnumerator
*iface
)
160 return CONTAINING_RECORD(iface
, struct opc_part_enum
, IOpcPartEnumerator_iface
);
163 static inline struct opc_rel_enum
*impl_from_IOpcRelationshipEnumerator(IOpcRelationshipEnumerator
*iface
)
165 return CONTAINING_RECORD(iface
, struct opc_rel_enum
, IOpcRelationshipEnumerator_iface
);
168 static void opc_content_release(struct opc_content
*content
)
170 ULONG refcount
= InterlockedDecrement(&content
->refcount
);
174 heap_free(content
->data
);
179 static HRESULT
opc_part_enum_create(struct opc_part_set
*part_set
, IOpcPartEnumerator
**out
);
181 static HRESULT WINAPI
opc_part_enum_QueryInterface(IOpcPartEnumerator
*iface
, REFIID iid
, void **out
)
183 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
185 if (IsEqualIID(&IID_IOpcPartEnumerator
, iid
) ||
186 IsEqualIID(&IID_IUnknown
, iid
))
189 IOpcPartEnumerator_AddRef(iface
);
194 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
195 return E_NOINTERFACE
;
198 static ULONG WINAPI
opc_part_enum_AddRef(IOpcPartEnumerator
*iface
)
200 struct opc_part_enum
*part_enum
= impl_from_IOpcPartEnumerator(iface
);
201 ULONG refcount
= InterlockedIncrement(&part_enum
->refcount
);
203 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
208 static ULONG WINAPI
opc_part_enum_Release(IOpcPartEnumerator
*iface
)
210 struct opc_part_enum
*part_enum
= impl_from_IOpcPartEnumerator(iface
);
211 ULONG refcount
= InterlockedDecrement(&part_enum
->refcount
);
213 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
217 IOpcPartSet_Release(&part_enum
->part_set
->IOpcPartSet_iface
);
218 heap_free(part_enum
);
224 static BOOL
has_part_collection_changed(const struct opc_part_enum
*part_enum
)
226 return !IsEqualGUID(&part_enum
->id
, &part_enum
->part_set
->id
);
229 static HRESULT WINAPI
opc_part_enum_MoveNext(IOpcPartEnumerator
*iface
, BOOL
*has_next
)
231 struct opc_part_enum
*part_enum
= impl_from_IOpcPartEnumerator(iface
);
233 TRACE("iface %p, has_next %p.\n", iface
, has_next
);
238 if (has_part_collection_changed(part_enum
))
239 return OPC_E_ENUM_COLLECTION_CHANGED
;
241 if (part_enum
->part_set
->count
&& (part_enum
->pos
== ~(size_t)0 || part_enum
->pos
< part_enum
->part_set
->count
))
244 *has_next
= part_enum
->pos
< part_enum
->part_set
->count
;
249 static HRESULT WINAPI
opc_part_enum_MovePrevious(IOpcPartEnumerator
*iface
, BOOL
*has_previous
)
251 struct opc_part_enum
*part_enum
= impl_from_IOpcPartEnumerator(iface
);
253 TRACE("iface %p, has_previous %p.\n", iface
, has_previous
);
258 if (has_part_collection_changed(part_enum
))
259 return OPC_E_ENUM_COLLECTION_CHANGED
;
261 if (part_enum
->pos
!= ~(size_t)0)
264 *has_previous
= part_enum
->pos
!= ~(size_t)0;
269 static HRESULT WINAPI
opc_part_enum_GetCurrent(IOpcPartEnumerator
*iface
, IOpcPart
**part
)
271 struct opc_part_enum
*part_enum
= impl_from_IOpcPartEnumerator(iface
);
273 TRACE("iface %p, part %p.\n", iface
, part
);
280 if (has_part_collection_changed(part_enum
))
281 return OPC_E_ENUM_COLLECTION_CHANGED
;
283 if (part_enum
->pos
< part_enum
->part_set
->count
)
285 *part
= &part_enum
->part_set
->parts
[part_enum
->pos
]->IOpcPart_iface
;
286 IOpcPart_AddRef(*part
);
289 return *part
? S_OK
: OPC_E_ENUM_INVALID_POSITION
;
292 static HRESULT WINAPI
opc_part_enum_Clone(IOpcPartEnumerator
*iface
, IOpcPartEnumerator
**out
)
294 struct opc_part_enum
*part_enum
= impl_from_IOpcPartEnumerator(iface
);
296 TRACE("iface %p, out %p.\n", iface
, out
);
301 if (has_part_collection_changed(part_enum
))
304 return OPC_E_ENUM_COLLECTION_CHANGED
;
307 return opc_part_enum_create(part_enum
->part_set
, out
);
310 static const IOpcPartEnumeratorVtbl opc_part_enum_vtbl
=
312 opc_part_enum_QueryInterface
,
313 opc_part_enum_AddRef
,
314 opc_part_enum_Release
,
315 opc_part_enum_MoveNext
,
316 opc_part_enum_MovePrevious
,
317 opc_part_enum_GetCurrent
,
321 static HRESULT
opc_part_enum_create(struct opc_part_set
*part_set
, IOpcPartEnumerator
**out
)
323 struct opc_part_enum
*part_enum
;
325 if (!(part_enum
= heap_alloc_zero(sizeof(*part_enum
))))
326 return E_OUTOFMEMORY
;
328 part_enum
->IOpcPartEnumerator_iface
.lpVtbl
= &opc_part_enum_vtbl
;
329 part_enum
->refcount
= 1;
330 part_enum
->part_set
= part_set
;
331 IOpcPartSet_AddRef(&part_set
->IOpcPartSet_iface
);
332 part_enum
->pos
= ~(size_t)0;
333 part_enum
->id
= part_set
->id
;
335 *out
= &part_enum
->IOpcPartEnumerator_iface
;
336 TRACE("Created part enumerator %p.\n", *out
);
340 static HRESULT
opc_rel_enum_create(struct opc_relationship_set
*rel_set
, IOpcRelationshipEnumerator
**out
);
342 static HRESULT WINAPI
opc_rel_enum_QueryInterface(IOpcRelationshipEnumerator
*iface
, REFIID iid
, void **out
)
344 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
346 if (IsEqualIID(&IID_IOpcRelationshipEnumerator
, iid
) ||
347 IsEqualIID(&IID_IUnknown
, iid
))
350 IOpcRelationshipEnumerator_AddRef(iface
);
355 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
356 return E_NOINTERFACE
;
359 static ULONG WINAPI
opc_rel_enum_AddRef(IOpcRelationshipEnumerator
*iface
)
361 struct opc_rel_enum
*rel_enum
= impl_from_IOpcRelationshipEnumerator(iface
);
362 ULONG refcount
= InterlockedIncrement(&rel_enum
->refcount
);
364 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
369 static ULONG WINAPI
opc_rel_enum_Release(IOpcRelationshipEnumerator
*iface
)
371 struct opc_rel_enum
*rel_enum
= impl_from_IOpcRelationshipEnumerator(iface
);
372 ULONG refcount
= InterlockedDecrement(&rel_enum
->refcount
);
374 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
378 IOpcRelationshipSet_Release(&rel_enum
->rel_set
->IOpcRelationshipSet_iface
);
385 static BOOL
has_rel_collection_changed(const struct opc_rel_enum
*rel_enum
)
387 return !IsEqualGUID(&rel_enum
->id
, &rel_enum
->rel_set
->id
);
390 static HRESULT WINAPI
opc_rel_enum_MoveNext(IOpcRelationshipEnumerator
*iface
, BOOL
*has_next
)
392 struct opc_rel_enum
*rel_enum
= impl_from_IOpcRelationshipEnumerator(iface
);
394 TRACE("iface %p, has_next %p.\n", iface
, has_next
);
399 if (has_rel_collection_changed(rel_enum
))
400 return OPC_E_ENUM_COLLECTION_CHANGED
;
402 if (rel_enum
->rel_set
->count
&& (rel_enum
->pos
== ~(size_t)0 || rel_enum
->pos
< rel_enum
->rel_set
->count
))
405 *has_next
= rel_enum
->pos
< rel_enum
->rel_set
->count
;
410 static HRESULT WINAPI
opc_rel_enum_MovePrevious(IOpcRelationshipEnumerator
*iface
, BOOL
*has_previous
)
412 struct opc_rel_enum
*rel_enum
= impl_from_IOpcRelationshipEnumerator(iface
);
414 TRACE("iface %p, has_previous %p.\n", iface
, has_previous
);
419 if (has_rel_collection_changed(rel_enum
))
420 return OPC_E_ENUM_COLLECTION_CHANGED
;
422 if (rel_enum
->pos
!= ~(size_t)0)
425 *has_previous
= rel_enum
->pos
!= ~(size_t)0;
430 static HRESULT WINAPI
opc_rel_enum_GetCurrent(IOpcRelationshipEnumerator
*iface
, IOpcRelationship
**rel
)
432 struct opc_rel_enum
*rel_enum
= impl_from_IOpcRelationshipEnumerator(iface
);
434 TRACE("iface %p, rel %p.\n", iface
, rel
);
441 if (has_rel_collection_changed(rel_enum
))
442 return OPC_E_ENUM_COLLECTION_CHANGED
;
444 if (rel_enum
->pos
< rel_enum
->rel_set
->count
)
446 *rel
= &rel_enum
->rel_set
->relationships
[rel_enum
->pos
]->IOpcRelationship_iface
;
447 IOpcRelationship_AddRef(*rel
);
450 return *rel
? S_OK
: OPC_E_ENUM_INVALID_POSITION
;
453 static HRESULT WINAPI
opc_rel_enum_Clone(IOpcRelationshipEnumerator
*iface
, IOpcRelationshipEnumerator
**out
)
455 struct opc_rel_enum
*rel_enum
= impl_from_IOpcRelationshipEnumerator(iface
);
457 TRACE("iface %p, out %p.\n", iface
, out
);
462 if (has_rel_collection_changed(rel_enum
))
465 return OPC_E_ENUM_COLLECTION_CHANGED
;
468 return opc_rel_enum_create(rel_enum
->rel_set
, out
);
471 static const IOpcRelationshipEnumeratorVtbl opc_rel_enum_vtbl
=
473 opc_rel_enum_QueryInterface
,
475 opc_rel_enum_Release
,
476 opc_rel_enum_MoveNext
,
477 opc_rel_enum_MovePrevious
,
478 opc_rel_enum_GetCurrent
,
482 static HRESULT
opc_rel_enum_create(struct opc_relationship_set
*rel_set
, IOpcRelationshipEnumerator
**out
)
484 struct opc_rel_enum
*rel_enum
;
486 if (!(rel_enum
= heap_alloc_zero(sizeof(*rel_enum
))))
487 return E_OUTOFMEMORY
;
489 rel_enum
->IOpcRelationshipEnumerator_iface
.lpVtbl
= &opc_rel_enum_vtbl
;
490 rel_enum
->refcount
= 1;
491 rel_enum
->rel_set
= rel_set
;
492 IOpcRelationshipSet_AddRef(&rel_set
->IOpcRelationshipSet_iface
);
493 rel_enum
->pos
= ~(size_t)0;
494 rel_enum
->id
= rel_set
->id
;
496 *out
= &rel_enum
->IOpcRelationshipEnumerator_iface
;
497 TRACE("Created relationship enumerator %p.\n", *out
);
501 static HRESULT WINAPI
opc_content_stream_QueryInterface(IStream
*iface
, REFIID iid
, void **out
)
503 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
505 if (IsEqualIID(iid
, &IID_IStream
) ||
506 IsEqualIID(iid
, &IID_ISequentialStream
) ||
507 IsEqualIID(iid
, &IID_IUnknown
))
510 IStream_AddRef(iface
);
515 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
516 return E_NOINTERFACE
;
519 static ULONG WINAPI
opc_content_stream_AddRef(IStream
*iface
)
521 struct opc_content_stream
*stream
= impl_from_IStream(iface
);
522 ULONG refcount
= InterlockedIncrement(&stream
->refcount
);
524 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
529 static ULONG WINAPI
opc_content_stream_Release(IStream
*iface
)
531 struct opc_content_stream
*stream
= impl_from_IStream(iface
);
532 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
534 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
538 opc_content_release(stream
->content
);
545 static HRESULT WINAPI
opc_content_stream_Read(IStream
*iface
, void *buff
, ULONG size
, ULONG
*num_read
)
547 struct opc_content_stream
*stream
= impl_from_IStream(iface
);
550 TRACE("iface %p, buff %p, size %u, num_read %p.\n", iface
, buff
, size
, num_read
);
555 if (stream
->content
->size
.QuadPart
- stream
->pos
.QuadPart
< size
)
556 *num_read
= stream
->content
->size
.QuadPart
- stream
->pos
.QuadPart
;
561 memcpy(buff
, stream
->content
->data
+ stream
->pos
.QuadPart
, *num_read
);
566 static HRESULT WINAPI
opc_content_stream_Write(IStream
*iface
, const void *data
, ULONG size
, ULONG
*num_written
)
568 struct opc_content_stream
*stream
= impl_from_IStream(iface
);
571 TRACE("iface %p, data %p, size %u, num_written %p.\n", iface
, data
, size
, num_written
);
574 num_written
= &written
;
578 if (size
> stream
->content
->size
.QuadPart
- stream
->pos
.QuadPart
)
580 void *ptr
= heap_realloc(stream
->content
->data
, stream
->pos
.QuadPart
+ size
);
582 return E_OUTOFMEMORY
;
583 stream
->content
->data
= ptr
;
586 memcpy(stream
->content
->data
+ stream
->pos
.QuadPart
, data
, size
);
587 stream
->pos
.QuadPart
+= size
;
588 stream
->content
->size
.QuadPart
+= size
;
594 static HRESULT WINAPI
opc_content_stream_Seek(IStream
*iface
, LARGE_INTEGER move
, DWORD origin
, ULARGE_INTEGER
*newpos
)
596 struct opc_content_stream
*stream
= impl_from_IStream(iface
);
599 TRACE("iface %p, move %s, origin %d, newpos %p.\n", iface
, wine_dbgstr_longlong(move
.QuadPart
), origin
, newpos
);
603 case STREAM_SEEK_SET
:
604 pos
.QuadPart
= move
.QuadPart
;
606 case STREAM_SEEK_CUR
:
607 pos
.QuadPart
= stream
->pos
.QuadPart
+ move
.QuadPart
;
609 case STREAM_SEEK_END
:
610 pos
.QuadPart
= stream
->content
->size
.QuadPart
+ move
.QuadPart
;
613 WARN("Unknown origin mode %d.\n", origin
);
620 *newpos
= stream
->pos
;
625 static HRESULT WINAPI
opc_content_stream_SetSize(IStream
*iface
, ULARGE_INTEGER size
)
627 FIXME("iface %p, size %s stub!\n", iface
, wine_dbgstr_longlong(size
.QuadPart
));
632 static HRESULT WINAPI
opc_content_stream_CopyTo(IStream
*iface
, IStream
*dest
, ULARGE_INTEGER size
,
633 ULARGE_INTEGER
*num_read
, ULARGE_INTEGER
*written
)
635 FIXME("iface %p, dest %p, size %s, num_read %p, written %p stub!\n", iface
, dest
,
636 wine_dbgstr_longlong(size
.QuadPart
), num_read
, written
);
641 static HRESULT WINAPI
opc_content_stream_Commit(IStream
*iface
, DWORD flags
)
643 FIXME("iface %p, flags %#x stub!\n", iface
, flags
);
648 static HRESULT WINAPI
opc_content_stream_Revert(IStream
*iface
)
650 FIXME("iface %p stub!\n", iface
);
655 static HRESULT WINAPI
opc_content_stream_LockRegion(IStream
*iface
, ULARGE_INTEGER offset
,
656 ULARGE_INTEGER size
, DWORD lock_type
)
658 FIXME("iface %p, offset %s, size %s, lock_type %d stub!\n", iface
, wine_dbgstr_longlong(offset
.QuadPart
),
659 wine_dbgstr_longlong(size
.QuadPart
), lock_type
);
664 static HRESULT WINAPI
opc_content_stream_UnlockRegion(IStream
*iface
, ULARGE_INTEGER offset
, ULARGE_INTEGER size
,
667 FIXME("iface %p, offset %s, size %s, lock_type %d stub!\n", iface
, wine_dbgstr_longlong(offset
.QuadPart
),
668 wine_dbgstr_longlong(size
.QuadPart
), lock_type
);
673 static HRESULT WINAPI
opc_content_stream_Stat(IStream
*iface
, STATSTG
*statstg
, DWORD flag
)
675 FIXME("iface %p, statstg %p, flag %d stub!\n", iface
, statstg
, flag
);
680 static HRESULT WINAPI
opc_content_stream_Clone(IStream
*iface
, IStream
**result
)
682 FIXME("iface %p, result %p stub!\n", iface
, result
);
687 static const IStreamVtbl opc_content_stream_vtbl
=
689 opc_content_stream_QueryInterface
,
690 opc_content_stream_AddRef
,
691 opc_content_stream_Release
,
692 opc_content_stream_Read
,
693 opc_content_stream_Write
,
694 opc_content_stream_Seek
,
695 opc_content_stream_SetSize
,
696 opc_content_stream_CopyTo
,
697 opc_content_stream_Commit
,
698 opc_content_stream_Revert
,
699 opc_content_stream_LockRegion
,
700 opc_content_stream_UnlockRegion
,
701 opc_content_stream_Stat
,
702 opc_content_stream_Clone
,
705 static HRESULT
opc_content_stream_create(struct opc_content
*content
, IStream
**out
)
707 struct opc_content_stream
*stream
;
709 if (!(stream
= heap_alloc_zero(sizeof(*stream
))))
710 return E_OUTOFMEMORY
;
712 stream
->IStream_iface
.lpVtbl
= &opc_content_stream_vtbl
;
713 stream
->refcount
= 1;
714 stream
->content
= content
;
715 InterlockedIncrement(&content
->refcount
);
717 *out
= &stream
->IStream_iface
;
719 TRACE("Created content stream %p.\n", *out
);
723 static HRESULT
opc_relationship_set_create(IOpcUri
*source_uri
, IOpcRelationshipSet
**relationship_set
);
725 static WCHAR
*opc_strdupW(const WCHAR
*str
)
733 size
= (strlenW(str
) + 1) * sizeof(WCHAR
);
734 ret
= CoTaskMemAlloc(size
);
736 memcpy(ret
, str
, size
);
742 static HRESULT WINAPI
opc_part_QueryInterface(IOpcPart
*iface
, REFIID iid
, void **out
)
744 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
746 if (IsEqualIID(iid
, &IID_IOpcPart
) ||
747 IsEqualIID(iid
, &IID_IUnknown
))
750 IOpcPart_AddRef(iface
);
754 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
755 return E_NOINTERFACE
;
758 static ULONG WINAPI
opc_part_AddRef(IOpcPart
*iface
)
760 struct opc_part
*part
= impl_from_IOpcPart(iface
);
761 ULONG refcount
= InterlockedIncrement(&part
->refcount
);
763 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
768 static ULONG WINAPI
opc_part_Release(IOpcPart
*iface
)
770 struct opc_part
*part
= impl_from_IOpcPart(iface
);
771 ULONG refcount
= InterlockedDecrement(&part
->refcount
);
773 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
777 if (part
->relationship_set
)
778 IOpcRelationshipSet_Release(part
->relationship_set
);
779 IOpcPartUri_Release(part
->name
);
780 CoTaskMemFree(part
->content_type
);
781 opc_content_release(part
->content
);
788 static HRESULT WINAPI
opc_part_GetRelationshipSet(IOpcPart
*iface
, IOpcRelationshipSet
**relationship_set
)
790 struct opc_part
*part
= impl_from_IOpcPart(iface
);
793 TRACE("iface %p, relationship_set %p.\n", iface
, relationship_set
);
795 if (!part
->relationship_set
&& FAILED(hr
= opc_relationship_set_create((IOpcUri
*)part
->name
, &part
->relationship_set
)))
798 *relationship_set
= part
->relationship_set
;
799 IOpcRelationshipSet_AddRef(*relationship_set
);
804 static HRESULT WINAPI
opc_part_GetContentStream(IOpcPart
*iface
, IStream
**stream
)
806 struct opc_part
*part
= impl_from_IOpcPart(iface
);
808 TRACE("iface %p, stream %p.\n", iface
, stream
);
813 return opc_content_stream_create(part
->content
, stream
);
816 static HRESULT WINAPI
opc_part_GetName(IOpcPart
*iface
, IOpcPartUri
**name
)
818 struct opc_part
*part
= impl_from_IOpcPart(iface
);
820 TRACE("iface %p, name %p.\n", iface
, name
);
823 IOpcPartUri_AddRef(*name
);
828 static HRESULT WINAPI
opc_part_GetContentType(IOpcPart
*iface
, LPWSTR
*type
)
830 struct opc_part
*part
= impl_from_IOpcPart(iface
);
832 TRACE("iface %p, type %p.\n", iface
, type
);
834 *type
= opc_strdupW(part
->content_type
);
835 return *type
? S_OK
: E_OUTOFMEMORY
;
838 static HRESULT WINAPI
opc_part_GetCompressionOptions(IOpcPart
*iface
, OPC_COMPRESSION_OPTIONS
*options
)
840 struct opc_part
*part
= impl_from_IOpcPart(iface
);
842 TRACE("iface %p, options %p.\n", iface
, options
);
844 *options
= part
->compression_options
;
848 static const IOpcPartVtbl opc_part_vtbl
=
850 opc_part_QueryInterface
,
853 opc_part_GetRelationshipSet
,
854 opc_part_GetContentStream
,
856 opc_part_GetContentType
,
857 opc_part_GetCompressionOptions
,
860 static HRESULT
opc_part_create(struct opc_part_set
*set
, IOpcPartUri
*name
, const WCHAR
*content_type
,
861 DWORD compression_options
, IOpcPart
**out
)
863 struct opc_part
*part
;
865 if (!opc_array_reserve((void **)&set
->parts
, &set
->size
, set
->count
+ 1, sizeof(*set
->parts
)))
866 return E_OUTOFMEMORY
;
868 if (!(part
= heap_alloc_zero(sizeof(*part
))))
869 return E_OUTOFMEMORY
;
871 part
->IOpcPart_iface
.lpVtbl
= &opc_part_vtbl
;
874 IOpcPartUri_AddRef(name
);
875 part
->compression_options
= compression_options
;
876 if (!(part
->content_type
= opc_strdupW(content_type
)))
878 IOpcPart_Release(&part
->IOpcPart_iface
);
879 return E_OUTOFMEMORY
;
882 part
->content
= heap_alloc_zero(sizeof(*part
->content
));
885 IOpcPart_Release(&part
->IOpcPart_iface
);
886 return E_OUTOFMEMORY
;
888 part
->content
->refcount
= 1;
890 set
->parts
[set
->count
++] = part
;
891 IOpcPart_AddRef(&part
->IOpcPart_iface
);
892 CoCreateGuid(&set
->id
);
894 *out
= &part
->IOpcPart_iface
;
895 TRACE("Created part %p.\n", *out
);
899 static struct opc_part
*opc_part_set_get_part(const struct opc_part_set
*part_set
, IOpcPartUri
*name
)
904 for (i
= 0; i
< part_set
->count
; ++i
)
907 if (IOpcPartUri_IsEqual(part_set
->parts
[i
]->name
, (IUri
*)name
, &is_equal
) == S_OK
&& is_equal
)
908 return part_set
->parts
[i
];
914 static HRESULT WINAPI
opc_part_set_QueryInterface(IOpcPartSet
*iface
, REFIID iid
, void **out
)
916 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
918 if (IsEqualIID(iid
, &IID_IOpcPartSet
) ||
919 IsEqualIID(iid
, &IID_IUnknown
))
922 IOpcPartSet_AddRef(iface
);
926 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
927 return E_NOINTERFACE
;
930 static ULONG WINAPI
opc_part_set_AddRef(IOpcPartSet
*iface
)
932 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
933 ULONG refcount
= InterlockedIncrement(&part_set
->refcount
);
935 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
940 static ULONG WINAPI
opc_part_set_Release(IOpcPartSet
*iface
)
942 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
943 ULONG refcount
= InterlockedDecrement(&part_set
->refcount
);
945 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
951 for (i
= 0; i
< part_set
->count
; ++i
)
952 IOpcPart_Release(&part_set
->parts
[i
]->IOpcPart_iface
);
953 heap_free(part_set
->parts
);
960 static HRESULT WINAPI
opc_part_set_GetPart(IOpcPartSet
*iface
, IOpcPartUri
*name
, IOpcPart
**out
)
962 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
963 struct opc_part
*part
;
965 TRACE("iface %p, name %p, out %p.\n", iface
, name
, out
);
975 if ((part
= opc_part_set_get_part(part_set
, name
)))
977 *out
= &part
->IOpcPart_iface
;
978 IOpcPart_AddRef(*out
);
981 return *out
? S_OK
: OPC_E_NO_SUCH_PART
;
984 static HRESULT WINAPI
opc_part_set_CreatePart(IOpcPartSet
*iface
, IOpcPartUri
*name
, LPCWSTR content_type
,
985 OPC_COMPRESSION_OPTIONS compression_options
, IOpcPart
**part
)
987 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
989 TRACE("iface %p, name %p, content_type %s, compression_options %#x, part %p.\n", iface
, name
,
990 debugstr_w(content_type
), compression_options
, part
);
1000 if (opc_part_set_get_part(part_set
, name
))
1001 return OPC_E_DUPLICATE_PART
;
1003 return opc_part_create(part_set
, name
, content_type
, compression_options
, part
);
1006 static HRESULT WINAPI
opc_part_set_DeletePart(IOpcPartSet
*iface
, IOpcPartUri
*name
)
1008 FIXME("iface %p, name %p stub!\n", iface
, name
);
1013 static HRESULT WINAPI
opc_part_set_PartExists(IOpcPartSet
*iface
, IOpcPartUri
*name
, BOOL
*exists
)
1015 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
1017 TRACE("iface %p, name %p, exists %p.\n", iface
, name
, exists
);
1019 if (!name
|| !exists
)
1022 *exists
= opc_part_set_get_part(part_set
, name
) != NULL
;
1027 static HRESULT WINAPI
opc_part_set_GetEnumerator(IOpcPartSet
*iface
, IOpcPartEnumerator
**enumerator
)
1029 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
1031 TRACE("iface %p, enumerator %p.\n", iface
, enumerator
);
1036 return opc_part_enum_create(part_set
, enumerator
);
1039 static const IOpcPartSetVtbl opc_part_set_vtbl
=
1041 opc_part_set_QueryInterface
,
1042 opc_part_set_AddRef
,
1043 opc_part_set_Release
,
1044 opc_part_set_GetPart
,
1045 opc_part_set_CreatePart
,
1046 opc_part_set_DeletePart
,
1047 opc_part_set_PartExists
,
1048 opc_part_set_GetEnumerator
,
1051 static HRESULT WINAPI
opc_relationship_QueryInterface(IOpcRelationship
*iface
, REFIID iid
, void **out
)
1053 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1055 if (IsEqualIID(iid
, &IID_IOpcRelationship
) ||
1056 IsEqualIID(iid
, &IID_IUnknown
))
1059 IOpcRelationship_AddRef(iface
);
1063 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
1064 return E_NOINTERFACE
;
1067 static ULONG WINAPI
opc_relationship_AddRef(IOpcRelationship
*iface
)
1069 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1070 ULONG refcount
= InterlockedIncrement(&relationship
->refcount
);
1072 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
1077 static ULONG WINAPI
opc_relationship_Release(IOpcRelationship
*iface
)
1079 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1080 ULONG refcount
= InterlockedDecrement(&relationship
->refcount
);
1082 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
1086 CoTaskMemFree(relationship
->id
);
1087 CoTaskMemFree(relationship
->type
);
1088 IOpcUri_Release(relationship
->source_uri
);
1089 IUri_Release(relationship
->target
);
1090 heap_free(relationship
);
1096 static HRESULT WINAPI
opc_relationship_GetId(IOpcRelationship
*iface
, WCHAR
**id
)
1098 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1100 TRACE("iface %p, id %p.\n", iface
, id
);
1102 *id
= opc_strdupW(relationship
->id
);
1103 return *id
? S_OK
: E_OUTOFMEMORY
;
1106 static HRESULT WINAPI
opc_relationship_GetRelationshipType(IOpcRelationship
*iface
, WCHAR
**type
)
1108 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1110 TRACE("iface %p, type %p.\n", iface
, type
);
1112 *type
= opc_strdupW(relationship
->type
);
1113 return *type
? S_OK
: E_OUTOFMEMORY
;
1116 static HRESULT WINAPI
opc_relationship_GetSourceUri(IOpcRelationship
*iface
, IOpcUri
**uri
)
1118 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1120 TRACE("iface %p, uri %p.\n", iface
, uri
);
1122 *uri
= relationship
->source_uri
;
1123 IOpcUri_AddRef(*uri
);
1128 static HRESULT WINAPI
opc_relationship_GetTargetUri(IOpcRelationship
*iface
, IUri
**target
)
1130 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1132 TRACE("iface %p, target %p.\n", iface
, target
);
1134 *target
= relationship
->target
;
1135 IUri_AddRef(*target
);
1140 static HRESULT WINAPI
opc_relationship_GetTargetMode(IOpcRelationship
*iface
, OPC_URI_TARGET_MODE
*target_mode
)
1142 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1144 TRACE("iface %p, target_mode %p.\n", iface
, target_mode
);
1146 *target_mode
= relationship
->target_mode
;
1151 static const IOpcRelationshipVtbl opc_relationship_vtbl
=
1153 opc_relationship_QueryInterface
,
1154 opc_relationship_AddRef
,
1155 opc_relationship_Release
,
1156 opc_relationship_GetId
,
1157 opc_relationship_GetRelationshipType
,
1158 opc_relationship_GetSourceUri
,
1159 opc_relationship_GetTargetUri
,
1160 opc_relationship_GetTargetMode
,
1163 static struct opc_relationship
*opc_relationshipset_get_rel(struct opc_relationship_set
*relationship_set
,
1168 for (i
= 0; i
< relationship_set
->count
; i
++)
1170 if (!strcmpW(id
, relationship_set
->relationships
[i
]->id
))
1171 return relationship_set
->relationships
[i
];
1177 static HRESULT
opc_relationship_create(struct opc_relationship_set
*set
, const WCHAR
*id
, const WCHAR
*type
,
1178 IUri
*target_uri
, OPC_URI_TARGET_MODE target_mode
, IOpcRelationship
**out
)
1180 struct opc_relationship
*relationship
;
1182 if (!opc_array_reserve((void **)&set
->relationships
, &set
->size
, set
->count
+ 1, sizeof(*set
->relationships
)))
1183 return E_OUTOFMEMORY
;
1185 if (!(relationship
= heap_alloc_zero(sizeof(*relationship
))))
1186 return E_OUTOFMEMORY
;
1188 relationship
->IOpcRelationship_iface
.lpVtbl
= &opc_relationship_vtbl
;
1189 relationship
->refcount
= 1;
1191 relationship
->target
= target_uri
;
1192 IUri_AddRef(relationship
->target
);
1193 relationship
->source_uri
= set
->source_uri
;
1194 IOpcUri_AddRef(relationship
->source_uri
);
1197 relationship
->id
= opc_strdupW(id
);
1200 relationship
->id
= CoTaskMemAlloc(10 * sizeof(WCHAR
));
1201 if (relationship
->id
)
1203 static const WCHAR fmtW
[] = {'R','%','0','8','X',0};
1206 /* FIXME: test that generated id is unique */
1207 RtlGenRandom(&generated
, sizeof(generated
));
1208 sprintfW(relationship
->id
, fmtW
, generated
);
1210 if (opc_relationshipset_get_rel(set
, relationship
->id
))
1212 WARN("Newly generated id %s already exists.\n", debugstr_w(relationship
->id
));
1213 IOpcRelationship_Release(&relationship
->IOpcRelationship_iface
);
1219 relationship
->type
= opc_strdupW(type
);
1220 if (!relationship
->id
|| !relationship
->type
)
1222 IOpcRelationship_Release(&relationship
->IOpcRelationship_iface
);
1223 return E_OUTOFMEMORY
;
1226 set
->relationships
[set
->count
++] = relationship
;
1227 IOpcRelationship_AddRef(&relationship
->IOpcRelationship_iface
);
1228 CoCreateGuid(&set
->id
);
1230 *out
= &relationship
->IOpcRelationship_iface
;
1231 TRACE("Created relationship %p.\n", *out
);
1235 static HRESULT WINAPI
opc_relationship_set_QueryInterface(IOpcRelationshipSet
*iface
, REFIID iid
, void **out
)
1237 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1239 if (IsEqualIID(iid
, &IID_IOpcRelationshipSet
) ||
1240 IsEqualIID(iid
, &IID_IUnknown
))
1243 IOpcRelationshipSet_AddRef(iface
);
1247 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
1248 return E_NOINTERFACE
;
1251 static ULONG WINAPI
opc_relationship_set_AddRef(IOpcRelationshipSet
*iface
)
1253 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1254 ULONG refcount
= InterlockedIncrement(&relationship_set
->refcount
);
1256 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
1261 static ULONG WINAPI
opc_relationship_set_Release(IOpcRelationshipSet
*iface
)
1263 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1264 ULONG refcount
= InterlockedDecrement(&relationship_set
->refcount
);
1266 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
1272 for (i
= 0; i
< relationship_set
->count
; ++i
)
1273 IOpcRelationship_Release(&relationship_set
->relationships
[i
]->IOpcRelationship_iface
);
1274 IOpcUri_Release(relationship_set
->source_uri
);
1275 heap_free(relationship_set
->relationships
);
1276 heap_free(relationship_set
);
1282 static HRESULT WINAPI
opc_relationship_set_GetRelationship(IOpcRelationshipSet
*iface
, const WCHAR
*id
,
1283 IOpcRelationship
**relationship
)
1285 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1286 struct opc_relationship
*ret
;
1288 TRACE("iface %p, id %s, relationship %p.\n", iface
, debugstr_w(id
), relationship
);
1293 *relationship
= NULL
;
1298 if ((ret
= opc_relationshipset_get_rel(relationship_set
, id
)))
1300 *relationship
= &ret
->IOpcRelationship_iface
;
1301 IOpcRelationship_AddRef(*relationship
);
1304 return *relationship
? S_OK
: OPC_E_NO_SUCH_RELATIONSHIP
;
1307 static HRESULT WINAPI
opc_relationship_set_CreateRelationship(IOpcRelationshipSet
*iface
, const WCHAR
*id
,
1308 const WCHAR
*type
, IUri
*target_uri
, OPC_URI_TARGET_MODE target_mode
, IOpcRelationship
**relationship
)
1310 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1313 TRACE("iface %p, id %s, type %s, target_uri %p, target_mode %d, relationship %p.\n", iface
, debugstr_w(id
),
1314 debugstr_w(type
), target_uri
, target_mode
, relationship
);
1319 *relationship
= NULL
;
1321 if (!type
|| !target_uri
)
1324 if (id
&& opc_relationshipset_get_rel(relationship_set
, id
))
1325 return OPC_E_DUPLICATE_RELATIONSHIP
;
1327 if (IUri_GetPropertyLength(target_uri
, Uri_PROPERTY_SCHEME_NAME
, &length
, 0) == S_OK
&& length
!= 0
1328 && target_mode
== OPC_URI_TARGET_MODE_INTERNAL
)
1329 return OPC_E_INVALID_RELATIONSHIP_TARGET
;
1331 return opc_relationship_create(relationship_set
, id
, type
, target_uri
, target_mode
, relationship
);
1334 static HRESULT WINAPI
opc_relationship_set_DeleteRelationship(IOpcRelationshipSet
*iface
, const WCHAR
*id
)
1336 FIXME("iface %p, id %s stub!\n", iface
, debugstr_w(id
));
1341 static HRESULT WINAPI
opc_relationship_set_RelationshipExists(IOpcRelationshipSet
*iface
, const WCHAR
*id
, BOOL
*exists
)
1343 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1345 TRACE("iface %p, id %s, exists %p.\n", iface
, debugstr_w(id
), exists
);
1350 *exists
= opc_relationshipset_get_rel(relationship_set
, id
) != NULL
;
1355 static HRESULT WINAPI
opc_relationship_set_GetEnumerator(IOpcRelationshipSet
*iface
,
1356 IOpcRelationshipEnumerator
**enumerator
)
1358 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1360 TRACE("iface %p, enumerator %p.\n", iface
, enumerator
);
1365 return opc_rel_enum_create(relationship_set
, enumerator
);
1368 static HRESULT WINAPI
opc_relationship_set_GetEnumeratorForType(IOpcRelationshipSet
*iface
, const WCHAR
*type
,
1369 IOpcRelationshipEnumerator
**enumerator
)
1371 FIXME("iface %p, type %s, enumerator %p stub!\n", iface
, debugstr_w(type
), enumerator
);
1376 static HRESULT WINAPI
opc_relationship_set_GetRelationshipsContentStream(IOpcRelationshipSet
*iface
, IStream
**stream
)
1378 FIXME("iface %p, stream %p stub!\n", iface
, stream
);
1383 static const IOpcRelationshipSetVtbl opc_relationship_set_vtbl
=
1385 opc_relationship_set_QueryInterface
,
1386 opc_relationship_set_AddRef
,
1387 opc_relationship_set_Release
,
1388 opc_relationship_set_GetRelationship
,
1389 opc_relationship_set_CreateRelationship
,
1390 opc_relationship_set_DeleteRelationship
,
1391 opc_relationship_set_RelationshipExists
,
1392 opc_relationship_set_GetEnumerator
,
1393 opc_relationship_set_GetEnumeratorForType
,
1394 opc_relationship_set_GetRelationshipsContentStream
,
1397 static HRESULT
opc_relationship_set_create(IOpcUri
*source_uri
, IOpcRelationshipSet
**out
)
1399 struct opc_relationship_set
*relationship_set
;
1401 if (!(relationship_set
= heap_alloc_zero(sizeof(*relationship_set
))))
1402 return E_OUTOFMEMORY
;
1404 relationship_set
->IOpcRelationshipSet_iface
.lpVtbl
= &opc_relationship_set_vtbl
;
1405 relationship_set
->refcount
= 1;
1406 relationship_set
->source_uri
= source_uri
;
1407 IOpcUri_AddRef(relationship_set
->source_uri
);
1409 *out
= &relationship_set
->IOpcRelationshipSet_iface
;
1410 TRACE("Created relationship set %p.\n", *out
);
1414 static HRESULT WINAPI
opc_package_QueryInterface(IOpcPackage
*iface
, REFIID iid
, void **out
)
1416 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1418 if (IsEqualIID(iid
, &IID_IOpcPackage
) ||
1419 IsEqualIID(iid
, &IID_IUnknown
))
1422 IOpcPackage_AddRef(iface
);
1426 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
1427 return E_NOINTERFACE
;
1430 static ULONG WINAPI
opc_package_AddRef(IOpcPackage
*iface
)
1432 struct opc_package
*package
= impl_from_IOpcPackage(iface
);
1433 ULONG refcount
= InterlockedIncrement(&package
->refcount
);
1435 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
1440 static ULONG WINAPI
opc_package_Release(IOpcPackage
*iface
)
1442 struct opc_package
*package
= impl_from_IOpcPackage(iface
);
1443 ULONG refcount
= InterlockedDecrement(&package
->refcount
);
1445 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
1449 if (package
->part_set
)
1450 IOpcPartSet_Release(package
->part_set
);
1451 if (package
->relationship_set
)
1452 IOpcRelationshipSet_Release(package
->relationship_set
);
1453 if (package
->source_uri
)
1454 IOpcUri_Release(package
->source_uri
);
1461 static HRESULT WINAPI
opc_package_GetPartSet(IOpcPackage
*iface
, IOpcPartSet
**part_set
)
1463 struct opc_package
*package
= impl_from_IOpcPackage(iface
);
1465 TRACE("iface %p, part_set %p.\n", iface
, part_set
);
1467 if (!package
->part_set
)
1469 struct opc_part_set
*part_set
= heap_alloc_zero(sizeof(*part_set
));
1471 return E_OUTOFMEMORY
;
1473 part_set
->IOpcPartSet_iface
.lpVtbl
= &opc_part_set_vtbl
;
1474 part_set
->refcount
= 1;
1476 package
->part_set
= &part_set
->IOpcPartSet_iface
;
1479 *part_set
= package
->part_set
;
1480 IOpcPartSet_AddRef(*part_set
);
1485 static HRESULT WINAPI
opc_package_GetRelationshipSet(IOpcPackage
*iface
, IOpcRelationshipSet
**relationship_set
)
1487 struct opc_package
*package
= impl_from_IOpcPackage(iface
);
1490 TRACE("iface %p, relationship_set %p.\n", iface
, relationship_set
);
1492 if (!package
->relationship_set
)
1494 if (FAILED(hr
= opc_relationship_set_create(package
->source_uri
, &package
->relationship_set
)))
1498 *relationship_set
= package
->relationship_set
;
1499 IOpcRelationshipSet_AddRef(*relationship_set
);
1504 static const IOpcPackageVtbl opc_package_vtbl
=
1506 opc_package_QueryInterface
,
1508 opc_package_Release
,
1509 opc_package_GetPartSet
,
1510 opc_package_GetRelationshipSet
,
1513 HRESULT
opc_package_create(IOpcFactory
*factory
, IOpcPackage
**out
)
1515 struct opc_package
*package
;
1518 if (!(package
= heap_alloc_zero(sizeof(*package
))))
1519 return E_OUTOFMEMORY
;
1521 package
->IOpcPackage_iface
.lpVtbl
= &opc_package_vtbl
;
1522 package
->refcount
= 1;
1524 if (FAILED(hr
= IOpcFactory_CreatePackageRootUri(factory
, &package
->source_uri
)))
1530 *out
= &package
->IOpcPackage_iface
;
1531 TRACE("Created package %p.\n", *out
);
1535 struct content_types
1541 enum content_type_element
1543 CONTENT_TYPE_DEFAULT
,
1544 CONTENT_TYPE_OVERRIDE
,
1550 enum content_type_element element
;
1558 struct override_type
1565 static HRESULT
opc_package_add_override_content_type(struct content_types
*types
, IOpcPart
*part
)
1567 struct content_type
*type
;
1569 if (!(type
= heap_alloc(sizeof(*type
))))
1570 return E_OUTOFMEMORY
;
1572 type
->element
= CONTENT_TYPE_OVERRIDE
;
1573 type
->u
.override
.part
= part
;
1574 IOpcPart_AddRef(part
);
1576 list_add_tail(&types
->types
, &type
->entry
);
1581 static HRESULT
opc_package_add_default_content_type(struct content_types
*types
,
1582 const WCHAR
*ext
, const WCHAR
*content_type
)
1584 struct content_type
*type
;
1586 if (!(type
= heap_alloc(sizeof(*type
))))
1587 return E_OUTOFMEMORY
;
1589 type
->element
= CONTENT_TYPE_DEFAULT
;
1590 type
->u
.def
.ext
= opc_strdupW(ext
);
1591 type
->u
.def
.type
= opc_strdupW(content_type
);
1592 if (!type
->u
.def
.ext
|| !type
->u
.def
.type
)
1594 CoTaskMemFree(type
->u
.def
.ext
);
1595 CoTaskMemFree(type
->u
.def
.type
);
1597 return E_OUTOFMEMORY
;
1600 list_add_tail(&types
->types
, &type
->entry
);
1605 static HRESULT
opc_package_add_content_type(struct content_types
*types
, IOpcPart
*part
)
1607 struct content_type
*cur
;
1608 BSTR ext
, content_type
;
1613 if (FAILED(hr
= IOpcPart_GetName(part
, &name
)))
1616 hr
= IOpcPartUri_GetExtension(name
, &ext
);
1617 IOpcPartUri_Release(name
);
1620 hr
= opc_package_add_override_content_type(types
, part
);
1628 if (FAILED(hr
= IOpcPart_GetContentType(part
, &content_type
)))
1631 LIST_FOR_EACH_ENTRY(cur
, &types
->types
, struct content_type
, entry
)
1633 if (cur
->element
== CONTENT_TYPE_OVERRIDE
)
1636 if (!strcmpiW(cur
->u
.def
.ext
, ext
))
1640 if (!strcmpW(cur
->u
.def
.type
, content_type
))
1643 hr
= opc_package_add_override_content_type(types
, part
);
1649 hr
= opc_package_add_default_content_type(types
, ext
, content_type
);
1652 SysFreeString(content_type
);
1657 static BOOL
opc_package_has_rels_part(IOpcRelationshipSet
*rel_set
)
1659 IOpcRelationshipEnumerator
*enumerator
;
1663 if (FAILED(hr
= IOpcRelationshipSet_GetEnumerator(rel_set
, &enumerator
)))
1667 IOpcRelationshipEnumerator_MoveNext(enumerator
, &has_next
);
1668 IOpcRelationshipEnumerator_Release(enumerator
);
1673 static HRESULT
opc_package_collect_content_types(IOpcPackage
*package
, struct content_types
*types
)
1675 IOpcPartEnumerator
*enumerator
;
1676 IOpcRelationshipSet
*rel_set
;
1681 if (FAILED(hr
= IOpcPackage_GetPartSet(package
, &parts
)))
1684 hr
= IOpcPackage_GetRelationshipSet(package
, &rel_set
);
1687 types
->has_rels_part
|= opc_package_has_rels_part(rel_set
);
1688 IOpcRelationshipSet_Release(rel_set
);
1691 hr
= IOpcPartSet_GetEnumerator(parts
, &enumerator
);
1692 IOpcPartSet_Release(parts
);
1696 if (FAILED(hr
= IOpcPartEnumerator_MoveNext(enumerator
, &has_next
)) || !has_next
)
1698 IOpcPartEnumerator_Release(enumerator
);
1706 if (FAILED(hr
= IOpcPartEnumerator_GetCurrent(enumerator
, &part
)))
1709 if (!types
->has_rels_part
)
1711 hr
= IOpcPart_GetRelationshipSet(part
, &rel_set
);
1714 types
->has_rels_part
|= opc_package_has_rels_part(rel_set
);
1715 IOpcRelationshipSet_Release(rel_set
);
1719 hr
= opc_package_add_content_type(types
, part
);
1720 IOpcPart_Release(part
);
1724 IOpcPartEnumerator_MoveNext(enumerator
, &has_next
);
1727 IOpcPartEnumerator_Release(enumerator
);
1732 static HRESULT
opc_package_write_default_type(const WCHAR
*ext
, const WCHAR
*type
, IXmlWriter
*writer
)
1734 static const WCHAR contenttypeW
[] = {'C','o','n','t','e','n','t','T','y','p','e',0};
1735 static const WCHAR extensionW
[] = {'E','x','t','e','n','s','i','o','n',0};
1736 static const WCHAR defaultW
[] = {'D','e','f','a','u','l','t',0};
1739 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, defaultW
, NULL
);
1741 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, extensionW
, NULL
, ext
);
1743 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, contenttypeW
, NULL
, type
);
1747 static HRESULT
opc_package_write_contenttypes(IOpcPackage
*package
, struct zip_archive
*archive
, IXmlWriter
*writer
)
1749 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','/',
1750 'p','a','c','k','a','g','e','/','2','0','0','6','/','c','o','n','t','e','n','t','-','t','y','p','e','s',0};
1751 static const WCHAR relstypeW
[] = {'a','p','p','l','i','c','a','t','i','o','n','/','v','n','d','.','o','p','e','n','x','m','l','f','o','r','m','a','t','s','-',
1752 'p','a','c','k','a','g','e','.','r','e','l','a','t','i','o','n','s','h','i','p','s','+','x','m','l',0};
1753 static const WCHAR contenttypesW
[] = {'[','C','o','n','t','e','n','t','_','T','y','p','e','s',']','.','x','m','l',0};
1754 static const WCHAR contenttypeW
[] = {'C','o','n','t','e','n','t','T','y','p','e',0};
1755 static const WCHAR overrideW
[] = {'O','v','e','r','r','i','d','e',0};
1756 static const WCHAR partnameW
[] = {'P','a','r','t','N','a','m','e',0};
1757 static const WCHAR typesW
[] = {'T','y','p','e','s',0};
1758 static const WCHAR relsW
[] = {'r','e','l','s',0};
1759 struct content_type
*content_type
, *content_type2
;
1760 struct content_types types
;
1761 IStream
*content
= NULL
;
1764 list_init(&types
.types
);
1765 types
.has_rels_part
= FALSE
;
1767 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &content
);
1769 hr
= opc_package_collect_content_types(package
, &types
);
1771 hr
= IXmlWriter_SetOutput(writer
, (IUnknown
*)content
);
1773 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Omit
);
1775 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, typesW
, uriW
);
1777 if (SUCCEEDED(hr
) && types
.has_rels_part
)
1779 hr
= opc_package_write_default_type(relsW
, relstypeW
, writer
);
1781 hr
= IXmlWriter_WriteEndElement(writer
);
1784 LIST_FOR_EACH_ENTRY_SAFE(content_type
, content_type2
, &types
.types
, struct content_type
, entry
)
1786 if (content_type
->element
== CONTENT_TYPE_DEFAULT
)
1788 hr
= opc_package_write_default_type(content_type
->u
.def
.ext
+ 1, content_type
->u
.def
.type
, writer
);
1790 CoTaskMemFree(content_type
->u
.def
.ext
);
1791 CoTaskMemFree(content_type
->u
.def
.type
);
1795 IOpcPartUri
*uri
= NULL
;
1800 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, overrideW
, NULL
);
1802 hr
= IOpcPart_GetName(content_type
->u
.override
.part
, &uri
);
1804 hr
= IOpcPartUri_GetRawUri(uri
, &name
);
1806 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, partnameW
, NULL
, name
);
1808 hr
= IOpcPart_GetContentType(content_type
->u
.override
.part
, &type
);
1810 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, contenttypeW
, NULL
, type
);
1813 IOpcPartUri_Release(uri
);
1814 SysFreeString(name
);
1815 CoTaskMemFree(type
);
1817 IOpcPart_Release(content_type
->u
.override
.part
);
1820 hr
= IXmlWriter_WriteEndElement(writer
);
1822 list_remove(&content_type
->entry
);
1823 heap_free(content_type
);
1827 hr
= IXmlWriter_WriteEndDocument(writer
);
1829 hr
= IXmlWriter_Flush(writer
);
1832 hr
= compress_add_file(archive
, contenttypesW
, content
, OPC_COMPRESSION_NORMAL
);
1835 IStream_Release(content
);
1840 static HRESULT
opc_package_write_rel(IOpcRelationship
*rel
, IXmlWriter
*writer
)
1842 static const WCHAR relationshipW
[] = {'R','e','l','a','t','i','o','n','s','h','i','p',0};
1843 static const WCHAR targetW
[] = {'T','a','r','g','e','t',0};
1844 static const WCHAR typeW
[] = {'T','y','p','e',0};
1845 static const WCHAR idW
[] = {'I','d',0};
1851 if (FAILED(hr
= IXmlWriter_WriteStartElement(writer
, NULL
, relationshipW
, NULL
)))
1854 if (FAILED(hr
= IOpcRelationship_GetTargetUri(rel
, &uri
)))
1857 IUri_GetRawUri(uri
, &target_uri
);
1860 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, targetW
, NULL
, target_uri
);
1861 SysFreeString(target_uri
);
1865 if (FAILED(hr
= IOpcRelationship_GetId(rel
, &str
)))
1868 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, idW
, NULL
, str
);
1873 if (FAILED(hr
= IOpcRelationship_GetRelationshipType(rel
, &str
)))
1876 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, typeW
, NULL
, str
);
1881 return IXmlWriter_WriteEndElement(writer
);
1884 static HRESULT
opc_package_write_rels(struct zip_archive
*archive
, IOpcRelationshipSet
*rels
,
1885 IOpcUri
*uri
, IXmlWriter
*writer
)
1887 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','/',
1888 'p','a','c','k','a','g','e','/','2','0','0','6','/','r','e','l','a','t','i','o','n','s','h','i','p','s',0};
1889 static const WCHAR relationshipsW
[] = {'R','e','l','a','t','i','o','n','s','h','i','p','s',0};
1890 IOpcRelationshipEnumerator
*enumerator
;
1891 IOpcPartUri
*rels_uri
;
1897 if (FAILED(hr
= IOpcRelationshipSet_GetEnumerator(rels
, &enumerator
)))
1900 hr
= IOpcRelationshipEnumerator_MoveNext(enumerator
, &has_next
);
1903 IOpcRelationshipEnumerator_Release(enumerator
);
1907 if (FAILED(hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &content
)))
1909 IOpcRelationshipEnumerator_Release(enumerator
);
1913 hr
= IXmlWriter_SetOutput(writer
, (IUnknown
*)content
);
1915 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
1917 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, relationshipsW
, uriW
);
1921 IOpcRelationship
*rel
;
1923 if (FAILED(hr
= IOpcRelationshipEnumerator_GetCurrent(enumerator
, &rel
)))
1926 hr
= opc_package_write_rel(rel
, writer
);
1927 IOpcRelationship_Release(rel
);
1931 IOpcRelationshipEnumerator_MoveNext(enumerator
, &has_next
);
1934 IOpcRelationshipEnumerator_Release(enumerator
);
1937 hr
= IXmlWriter_WriteEndDocument(writer
);
1939 hr
= IXmlWriter_Flush(writer
);
1941 hr
= IOpcUri_GetRelationshipsPartUri(uri
, &rels_uri
);
1943 hr
= IOpcPartUri_GetRawUri(rels_uri
, &rels_part_uri
);
1946 /* Relationship part names always start with root '/', skip it. */
1947 hr
= compress_add_file(archive
, rels_part_uri
+ 1, content
, OPC_COMPRESSION_NORMAL
);
1950 SysFreeString(rels_part_uri
);
1951 IStream_Release(content
);
1956 static HRESULT
opc_package_write_part(struct zip_archive
*archive
, IOpcPart
*part
, IXmlWriter
*writer
)
1958 OPC_COMPRESSION_OPTIONS options
= OPC_COMPRESSION_NORMAL
;
1959 IOpcRelationshipSet
*rels
= NULL
;
1960 IStream
*content
= NULL
;
1965 if (FAILED(hr
= IOpcPart_GetName(part
, &name
)))
1968 hr
= IOpcPartUri_GetRawUri(name
, &uri
);
1970 hr
= IOpcPart_GetCompressionOptions(part
, &options
);
1972 hr
= IOpcPart_GetContentStream(part
, &content
);
1975 /* Part names always start with root '/', skip it. */
1976 hr
= compress_add_file(archive
, uri
+ 1, content
, options
);
1979 hr
= IOpcPart_GetRelationshipSet(part
, &rels
);
1981 hr
= opc_package_write_rels(archive
, rels
, (IOpcUri
*)name
, writer
);
1983 IOpcPartUri_Release(name
);
1986 IStream_Release(content
);
1988 IOpcRelationshipSet_Release(rels
);
1993 static HRESULT
opc_package_write_parts(struct zip_archive
*archive
, IOpcPackage
*package
, IXmlWriter
*writer
)
1995 IOpcPartEnumerator
*parts
;
1996 IOpcPartSet
*part_set
;
2000 if (FAILED(hr
= IOpcPackage_GetPartSet(package
, &part_set
)))
2003 hr
= IOpcPartSet_GetEnumerator(part_set
, &parts
);
2004 IOpcPartSet_Release(part_set
);
2008 while (IOpcPartEnumerator_MoveNext(parts
, &got_next
) == S_OK
&& got_next
)
2012 if (FAILED(hr
= IOpcPartEnumerator_GetCurrent(parts
, &part
)))
2015 hr
= opc_package_write_part(archive
, part
, writer
);
2016 IOpcPart_Release(part
);
2021 IOpcPartEnumerator_Release(parts
);
2026 HRESULT
opc_package_write(IOpcPackage
*package
, OPC_WRITE_FLAGS flags
, IStream
*stream
)
2028 IOpcRelationshipSet
*rels
= NULL
;
2029 struct zip_archive
*archive
;
2030 IOpcUri
*uri
= NULL
;
2034 if (flags
!= OPC_WRITE_FORCE_ZIP32
)
2035 FIXME("Unsupported write flags %#x.\n", flags
);
2037 if (FAILED(hr
= CreateXmlWriter(&IID_IXmlWriter
, (void **)&writer
, NULL
)))
2040 if (FAILED(hr
= compress_create_archive(stream
, &archive
)))
2042 IXmlWriter_Release(writer
);
2046 /* [Content_Types].xml */
2047 hr
= opc_package_write_contenttypes(package
, archive
, writer
);
2048 /* Package relationships. */
2050 hr
= IOpcPackage_GetRelationshipSet(package
, &rels
);
2052 hr
= opc_root_uri_create(&uri
);
2054 hr
= opc_package_write_rels(archive
, rels
, uri
, writer
);
2057 hr
= opc_package_write_parts(archive
, package
, writer
);
2060 IOpcRelationshipSet_Release(rels
);
2062 IOpcUri_Release(uri
);
2064 compress_finalize_archive(archive
);
2065 IXmlWriter_Release(writer
);