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"
30 #include "opc_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(msopc
);
41 struct opc_content_stream
43 IStream IStream_iface
;
46 struct opc_content
*content
;
52 IOpcPackage IOpcPackage_iface
;
55 IOpcPartSet
*part_set
;
56 IOpcRelationshipSet
*relationship_set
;
62 IOpcPartEnumerator IOpcPartEnumerator_iface
;
65 struct opc_part_set
*part_set
;
72 IOpcPart IOpcPart_iface
;
77 DWORD compression_options
;
78 IOpcRelationshipSet
*relationship_set
;
79 struct opc_content
*content
;
84 IOpcPartSet IOpcPartSet_iface
;
87 struct opc_part
**parts
;
95 IOpcRelationshipEnumerator IOpcRelationshipEnumerator_iface
;
98 struct opc_relationship_set
*rel_set
;
103 struct opc_relationship
105 IOpcRelationship IOpcRelationship_iface
;
111 OPC_URI_TARGET_MODE target_mode
;
115 struct opc_relationship_set
117 IOpcRelationshipSet IOpcRelationshipSet_iface
;
120 struct opc_relationship
**relationships
;
127 static inline struct opc_package
*impl_from_IOpcPackage(IOpcPackage
*iface
)
129 return CONTAINING_RECORD(iface
, struct opc_package
, IOpcPackage_iface
);
132 static inline struct opc_part_set
*impl_from_IOpcPartSet(IOpcPartSet
*iface
)
134 return CONTAINING_RECORD(iface
, struct opc_part_set
, IOpcPartSet_iface
);
137 static inline struct opc_part
*impl_from_IOpcPart(IOpcPart
*iface
)
139 return CONTAINING_RECORD(iface
, struct opc_part
, IOpcPart_iface
);
142 static inline struct opc_relationship_set
*impl_from_IOpcRelationshipSet(IOpcRelationshipSet
*iface
)
144 return CONTAINING_RECORD(iface
, struct opc_relationship_set
, IOpcRelationshipSet_iface
);
147 static inline struct opc_relationship
*impl_from_IOpcRelationship(IOpcRelationship
*iface
)
149 return CONTAINING_RECORD(iface
, struct opc_relationship
, IOpcRelationship_iface
);
152 static inline struct opc_content_stream
*impl_from_IStream(IStream
*iface
)
154 return CONTAINING_RECORD(iface
, struct opc_content_stream
, IStream_iface
);
157 static inline struct opc_part_enum
*impl_from_IOpcPartEnumerator(IOpcPartEnumerator
*iface
)
159 return CONTAINING_RECORD(iface
, struct opc_part_enum
, IOpcPartEnumerator_iface
);
162 static inline struct opc_rel_enum
*impl_from_IOpcRelationshipEnumerator(IOpcRelationshipEnumerator
*iface
)
164 return CONTAINING_RECORD(iface
, struct opc_rel_enum
, IOpcRelationshipEnumerator_iface
);
167 static void opc_content_release(struct opc_content
*content
)
169 ULONG refcount
= InterlockedDecrement(&content
->refcount
);
173 heap_free(content
->data
);
178 static HRESULT
opc_part_enum_create(struct opc_part_set
*part_set
, IOpcPartEnumerator
**out
);
180 static HRESULT WINAPI
opc_part_enum_QueryInterface(IOpcPartEnumerator
*iface
, REFIID iid
, void **out
)
182 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
184 if (IsEqualIID(&IID_IOpcPartEnumerator
, iid
) ||
185 IsEqualIID(&IID_IUnknown
, iid
))
188 IOpcPartEnumerator_AddRef(iface
);
193 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
194 return E_NOINTERFACE
;
197 static ULONG WINAPI
opc_part_enum_AddRef(IOpcPartEnumerator
*iface
)
199 struct opc_part_enum
*part_enum
= impl_from_IOpcPartEnumerator(iface
);
200 ULONG refcount
= InterlockedIncrement(&part_enum
->refcount
);
202 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
207 static ULONG WINAPI
opc_part_enum_Release(IOpcPartEnumerator
*iface
)
209 struct opc_part_enum
*part_enum
= impl_from_IOpcPartEnumerator(iface
);
210 ULONG refcount
= InterlockedDecrement(&part_enum
->refcount
);
212 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
216 IOpcPartSet_Release(&part_enum
->part_set
->IOpcPartSet_iface
);
217 heap_free(part_enum
);
223 static BOOL
has_part_collection_changed(const struct opc_part_enum
*part_enum
)
225 return !IsEqualGUID(&part_enum
->id
, &part_enum
->part_set
->id
);
228 static HRESULT WINAPI
opc_part_enum_MoveNext(IOpcPartEnumerator
*iface
, BOOL
*has_next
)
230 struct opc_part_enum
*part_enum
= impl_from_IOpcPartEnumerator(iface
);
232 TRACE("iface %p, has_next %p.\n", iface
, has_next
);
237 if (has_part_collection_changed(part_enum
))
238 return OPC_E_ENUM_COLLECTION_CHANGED
;
240 if (part_enum
->part_set
->count
&& (part_enum
->pos
== ~(size_t)0 || part_enum
->pos
< part_enum
->part_set
->count
))
243 *has_next
= part_enum
->pos
< part_enum
->part_set
->count
;
248 static HRESULT WINAPI
opc_part_enum_MovePrevious(IOpcPartEnumerator
*iface
, BOOL
*has_previous
)
250 struct opc_part_enum
*part_enum
= impl_from_IOpcPartEnumerator(iface
);
252 TRACE("iface %p, has_previous %p.\n", iface
, has_previous
);
257 if (has_part_collection_changed(part_enum
))
258 return OPC_E_ENUM_COLLECTION_CHANGED
;
260 if (part_enum
->pos
!= ~(size_t)0)
263 *has_previous
= part_enum
->pos
!= ~(size_t)0;
268 static HRESULT WINAPI
opc_part_enum_GetCurrent(IOpcPartEnumerator
*iface
, IOpcPart
**part
)
270 struct opc_part_enum
*part_enum
= impl_from_IOpcPartEnumerator(iface
);
272 TRACE("iface %p, part %p.\n", iface
, part
);
279 if (has_part_collection_changed(part_enum
))
280 return OPC_E_ENUM_COLLECTION_CHANGED
;
282 if (part_enum
->pos
< part_enum
->part_set
->count
)
284 *part
= &part_enum
->part_set
->parts
[part_enum
->pos
]->IOpcPart_iface
;
285 IOpcPart_AddRef(*part
);
288 return *part
? S_OK
: OPC_E_ENUM_INVALID_POSITION
;
291 static HRESULT WINAPI
opc_part_enum_Clone(IOpcPartEnumerator
*iface
, IOpcPartEnumerator
**out
)
293 struct opc_part_enum
*part_enum
= impl_from_IOpcPartEnumerator(iface
);
295 TRACE("iface %p, out %p.\n", iface
, out
);
300 if (has_part_collection_changed(part_enum
))
303 return OPC_E_ENUM_COLLECTION_CHANGED
;
306 return opc_part_enum_create(part_enum
->part_set
, out
);
309 static const IOpcPartEnumeratorVtbl opc_part_enum_vtbl
=
311 opc_part_enum_QueryInterface
,
312 opc_part_enum_AddRef
,
313 opc_part_enum_Release
,
314 opc_part_enum_MoveNext
,
315 opc_part_enum_MovePrevious
,
316 opc_part_enum_GetCurrent
,
320 static HRESULT
opc_part_enum_create(struct opc_part_set
*part_set
, IOpcPartEnumerator
**out
)
322 struct opc_part_enum
*part_enum
;
324 if (!(part_enum
= heap_alloc_zero(sizeof(*part_enum
))))
325 return E_OUTOFMEMORY
;
327 part_enum
->IOpcPartEnumerator_iface
.lpVtbl
= &opc_part_enum_vtbl
;
328 part_enum
->refcount
= 1;
329 part_enum
->part_set
= part_set
;
330 IOpcPartSet_AddRef(&part_set
->IOpcPartSet_iface
);
331 part_enum
->pos
= ~(size_t)0;
332 part_enum
->id
= part_set
->id
;
334 *out
= &part_enum
->IOpcPartEnumerator_iface
;
335 TRACE("Created part enumerator %p.\n", *out
);
339 static HRESULT
opc_rel_enum_create(struct opc_relationship_set
*rel_set
, IOpcRelationshipEnumerator
**out
);
341 static HRESULT WINAPI
opc_rel_enum_QueryInterface(IOpcRelationshipEnumerator
*iface
, REFIID iid
, void **out
)
343 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
345 if (IsEqualIID(&IID_IOpcRelationshipEnumerator
, iid
) ||
346 IsEqualIID(&IID_IUnknown
, iid
))
349 IOpcRelationshipEnumerator_AddRef(iface
);
354 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
355 return E_NOINTERFACE
;
358 static ULONG WINAPI
opc_rel_enum_AddRef(IOpcRelationshipEnumerator
*iface
)
360 struct opc_rel_enum
*rel_enum
= impl_from_IOpcRelationshipEnumerator(iface
);
361 ULONG refcount
= InterlockedIncrement(&rel_enum
->refcount
);
363 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
368 static ULONG WINAPI
opc_rel_enum_Release(IOpcRelationshipEnumerator
*iface
)
370 struct opc_rel_enum
*rel_enum
= impl_from_IOpcRelationshipEnumerator(iface
);
371 ULONG refcount
= InterlockedDecrement(&rel_enum
->refcount
);
373 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
377 IOpcRelationshipSet_Release(&rel_enum
->rel_set
->IOpcRelationshipSet_iface
);
384 static BOOL
has_rel_collection_changed(const struct opc_rel_enum
*rel_enum
)
386 return !IsEqualGUID(&rel_enum
->id
, &rel_enum
->rel_set
->id
);
389 static HRESULT WINAPI
opc_rel_enum_MoveNext(IOpcRelationshipEnumerator
*iface
, BOOL
*has_next
)
391 struct opc_rel_enum
*rel_enum
= impl_from_IOpcRelationshipEnumerator(iface
);
393 TRACE("iface %p, has_next %p.\n", iface
, has_next
);
398 if (has_rel_collection_changed(rel_enum
))
399 return OPC_E_ENUM_COLLECTION_CHANGED
;
401 if (rel_enum
->rel_set
->count
&& (rel_enum
->pos
== ~(size_t)0 || rel_enum
->pos
< rel_enum
->rel_set
->count
))
404 *has_next
= rel_enum
->pos
< rel_enum
->rel_set
->count
;
409 static HRESULT WINAPI
opc_rel_enum_MovePrevious(IOpcRelationshipEnumerator
*iface
, BOOL
*has_previous
)
411 struct opc_rel_enum
*rel_enum
= impl_from_IOpcRelationshipEnumerator(iface
);
413 TRACE("iface %p, has_previous %p.\n", iface
, has_previous
);
418 if (has_rel_collection_changed(rel_enum
))
419 return OPC_E_ENUM_COLLECTION_CHANGED
;
421 if (rel_enum
->pos
!= ~(size_t)0)
424 *has_previous
= rel_enum
->pos
!= ~(size_t)0;
429 static HRESULT WINAPI
opc_rel_enum_GetCurrent(IOpcRelationshipEnumerator
*iface
, IOpcRelationship
**rel
)
431 struct opc_rel_enum
*rel_enum
= impl_from_IOpcRelationshipEnumerator(iface
);
433 TRACE("iface %p, rel %p.\n", iface
, rel
);
440 if (has_rel_collection_changed(rel_enum
))
441 return OPC_E_ENUM_COLLECTION_CHANGED
;
443 if (rel_enum
->pos
< rel_enum
->rel_set
->count
)
445 *rel
= &rel_enum
->rel_set
->relationships
[rel_enum
->pos
]->IOpcRelationship_iface
;
446 IOpcRelationship_AddRef(*rel
);
449 return *rel
? S_OK
: OPC_E_ENUM_INVALID_POSITION
;
452 static HRESULT WINAPI
opc_rel_enum_Clone(IOpcRelationshipEnumerator
*iface
, IOpcRelationshipEnumerator
**out
)
454 struct opc_rel_enum
*rel_enum
= impl_from_IOpcRelationshipEnumerator(iface
);
456 TRACE("iface %p, out %p.\n", iface
, out
);
461 if (has_rel_collection_changed(rel_enum
))
464 return OPC_E_ENUM_COLLECTION_CHANGED
;
467 return opc_rel_enum_create(rel_enum
->rel_set
, out
);
470 static const IOpcRelationshipEnumeratorVtbl opc_rel_enum_vtbl
=
472 opc_rel_enum_QueryInterface
,
474 opc_rel_enum_Release
,
475 opc_rel_enum_MoveNext
,
476 opc_rel_enum_MovePrevious
,
477 opc_rel_enum_GetCurrent
,
481 static HRESULT
opc_rel_enum_create(struct opc_relationship_set
*rel_set
, IOpcRelationshipEnumerator
**out
)
483 struct opc_rel_enum
*rel_enum
;
485 if (!(rel_enum
= heap_alloc_zero(sizeof(*rel_enum
))))
486 return E_OUTOFMEMORY
;
488 rel_enum
->IOpcRelationshipEnumerator_iface
.lpVtbl
= &opc_rel_enum_vtbl
;
489 rel_enum
->refcount
= 1;
490 rel_enum
->rel_set
= rel_set
;
491 IOpcRelationshipSet_AddRef(&rel_set
->IOpcRelationshipSet_iface
);
492 rel_enum
->pos
= ~(size_t)0;
493 rel_enum
->id
= rel_set
->id
;
495 *out
= &rel_enum
->IOpcRelationshipEnumerator_iface
;
496 TRACE("Created relationship enumerator %p.\n", *out
);
500 static HRESULT WINAPI
opc_content_stream_QueryInterface(IStream
*iface
, REFIID iid
, void **out
)
502 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
504 if (IsEqualIID(iid
, &IID_IStream
) ||
505 IsEqualIID(iid
, &IID_ISequentialStream
) ||
506 IsEqualIID(iid
, &IID_IUnknown
))
509 IStream_AddRef(iface
);
514 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
515 return E_NOINTERFACE
;
518 static ULONG WINAPI
opc_content_stream_AddRef(IStream
*iface
)
520 struct opc_content_stream
*stream
= impl_from_IStream(iface
);
521 ULONG refcount
= InterlockedIncrement(&stream
->refcount
);
523 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
528 static ULONG WINAPI
opc_content_stream_Release(IStream
*iface
)
530 struct opc_content_stream
*stream
= impl_from_IStream(iface
);
531 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
533 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
537 opc_content_release(stream
->content
);
544 static HRESULT WINAPI
opc_content_stream_Read(IStream
*iface
, void *buff
, ULONG size
, ULONG
*num_read
)
546 struct opc_content_stream
*stream
= impl_from_IStream(iface
);
549 TRACE("iface %p, buff %p, size %u, num_read %p.\n", iface
, buff
, size
, num_read
);
554 if (stream
->content
->size
.QuadPart
- stream
->pos
.QuadPart
< size
)
555 *num_read
= stream
->content
->size
.QuadPart
- stream
->pos
.QuadPart
;
560 memcpy(buff
, stream
->content
->data
+ stream
->pos
.QuadPart
, *num_read
);
562 stream
->pos
.QuadPart
+= *num_read
;
567 static HRESULT WINAPI
opc_content_stream_Write(IStream
*iface
, const void *data
, ULONG size
, ULONG
*num_written
)
569 struct opc_content_stream
*stream
= impl_from_IStream(iface
);
572 TRACE("iface %p, data %p, size %u, num_written %p.\n", iface
, data
, size
, num_written
);
575 num_written
= &written
;
579 if (size
> stream
->content
->size
.QuadPart
- stream
->pos
.QuadPart
)
581 void *ptr
= heap_realloc(stream
->content
->data
, stream
->pos
.QuadPart
+ size
);
583 return E_OUTOFMEMORY
;
584 stream
->content
->data
= ptr
;
587 memcpy(stream
->content
->data
+ stream
->pos
.QuadPart
, data
, size
);
588 stream
->pos
.QuadPart
+= size
;
589 stream
->content
->size
.QuadPart
+= size
;
595 static HRESULT WINAPI
opc_content_stream_Seek(IStream
*iface
, LARGE_INTEGER move
, DWORD origin
, ULARGE_INTEGER
*newpos
)
597 struct opc_content_stream
*stream
= impl_from_IStream(iface
);
600 TRACE("iface %p, move %s, origin %d, newpos %p.\n", iface
, wine_dbgstr_longlong(move
.QuadPart
), origin
, newpos
);
604 case STREAM_SEEK_SET
:
605 pos
.QuadPart
= move
.QuadPart
;
607 case STREAM_SEEK_CUR
:
608 pos
.QuadPart
= stream
->pos
.QuadPart
+ move
.QuadPart
;
610 case STREAM_SEEK_END
:
611 pos
.QuadPart
= stream
->content
->size
.QuadPart
+ move
.QuadPart
;
614 WARN("Unknown origin mode %d.\n", origin
);
621 *newpos
= stream
->pos
;
626 static HRESULT WINAPI
opc_content_stream_SetSize(IStream
*iface
, ULARGE_INTEGER size
)
628 FIXME("iface %p, size %s stub!\n", iface
, wine_dbgstr_longlong(size
.QuadPart
));
633 static HRESULT WINAPI
opc_content_stream_CopyTo(IStream
*iface
, IStream
*dest
, ULARGE_INTEGER size
,
634 ULARGE_INTEGER
*num_read
, ULARGE_INTEGER
*written
)
636 FIXME("iface %p, dest %p, size %s, num_read %p, written %p stub!\n", iface
, dest
,
637 wine_dbgstr_longlong(size
.QuadPart
), num_read
, written
);
642 static HRESULT WINAPI
opc_content_stream_Commit(IStream
*iface
, DWORD flags
)
644 FIXME("iface %p, flags %#x stub!\n", iface
, flags
);
649 static HRESULT WINAPI
opc_content_stream_Revert(IStream
*iface
)
651 FIXME("iface %p stub!\n", iface
);
656 static HRESULT WINAPI
opc_content_stream_LockRegion(IStream
*iface
, ULARGE_INTEGER offset
,
657 ULARGE_INTEGER size
, DWORD lock_type
)
659 FIXME("iface %p, offset %s, size %s, lock_type %d stub!\n", iface
, wine_dbgstr_longlong(offset
.QuadPart
),
660 wine_dbgstr_longlong(size
.QuadPart
), lock_type
);
665 static HRESULT WINAPI
opc_content_stream_UnlockRegion(IStream
*iface
, ULARGE_INTEGER offset
, ULARGE_INTEGER size
,
668 FIXME("iface %p, offset %s, size %s, lock_type %d stub!\n", iface
, wine_dbgstr_longlong(offset
.QuadPart
),
669 wine_dbgstr_longlong(size
.QuadPart
), lock_type
);
674 static HRESULT WINAPI
opc_content_stream_Stat(IStream
*iface
, STATSTG
*statstg
, DWORD flag
)
676 FIXME("iface %p, statstg %p, flag %d stub!\n", iface
, statstg
, flag
);
681 static HRESULT WINAPI
opc_content_stream_Clone(IStream
*iface
, IStream
**result
)
683 FIXME("iface %p, result %p stub!\n", iface
, result
);
688 static const IStreamVtbl opc_content_stream_vtbl
=
690 opc_content_stream_QueryInterface
,
691 opc_content_stream_AddRef
,
692 opc_content_stream_Release
,
693 opc_content_stream_Read
,
694 opc_content_stream_Write
,
695 opc_content_stream_Seek
,
696 opc_content_stream_SetSize
,
697 opc_content_stream_CopyTo
,
698 opc_content_stream_Commit
,
699 opc_content_stream_Revert
,
700 opc_content_stream_LockRegion
,
701 opc_content_stream_UnlockRegion
,
702 opc_content_stream_Stat
,
703 opc_content_stream_Clone
,
706 static HRESULT
opc_content_stream_create(struct opc_content
*content
, IStream
**out
)
708 struct opc_content_stream
*stream
;
710 if (!(stream
= heap_alloc_zero(sizeof(*stream
))))
711 return E_OUTOFMEMORY
;
713 stream
->IStream_iface
.lpVtbl
= &opc_content_stream_vtbl
;
714 stream
->refcount
= 1;
715 stream
->content
= content
;
716 InterlockedIncrement(&content
->refcount
);
718 *out
= &stream
->IStream_iface
;
720 TRACE("Created content stream %p.\n", *out
);
724 static HRESULT
opc_relationship_set_create(IOpcUri
*source_uri
, IOpcRelationshipSet
**relationship_set
);
726 static WCHAR
*opc_strdupW(const WCHAR
*str
)
734 size
= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
735 ret
= CoTaskMemAlloc(size
);
737 memcpy(ret
, str
, size
);
743 static HRESULT WINAPI
opc_part_QueryInterface(IOpcPart
*iface
, REFIID iid
, void **out
)
745 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
747 if (IsEqualIID(iid
, &IID_IOpcPart
) ||
748 IsEqualIID(iid
, &IID_IUnknown
))
751 IOpcPart_AddRef(iface
);
755 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
756 return E_NOINTERFACE
;
759 static ULONG WINAPI
opc_part_AddRef(IOpcPart
*iface
)
761 struct opc_part
*part
= impl_from_IOpcPart(iface
);
762 ULONG refcount
= InterlockedIncrement(&part
->refcount
);
764 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
769 static ULONG WINAPI
opc_part_Release(IOpcPart
*iface
)
771 struct opc_part
*part
= impl_from_IOpcPart(iface
);
772 ULONG refcount
= InterlockedDecrement(&part
->refcount
);
774 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
778 if (part
->relationship_set
)
779 IOpcRelationshipSet_Release(part
->relationship_set
);
780 IOpcPartUri_Release(part
->name
);
781 CoTaskMemFree(part
->content_type
);
782 opc_content_release(part
->content
);
789 static HRESULT WINAPI
opc_part_GetRelationshipSet(IOpcPart
*iface
, IOpcRelationshipSet
**relationship_set
)
791 struct opc_part
*part
= impl_from_IOpcPart(iface
);
794 TRACE("iface %p, relationship_set %p.\n", iface
, relationship_set
);
796 if (!part
->relationship_set
&& FAILED(hr
= opc_relationship_set_create((IOpcUri
*)part
->name
, &part
->relationship_set
)))
799 *relationship_set
= part
->relationship_set
;
800 IOpcRelationshipSet_AddRef(*relationship_set
);
805 static HRESULT WINAPI
opc_part_GetContentStream(IOpcPart
*iface
, IStream
**stream
)
807 struct opc_part
*part
= impl_from_IOpcPart(iface
);
809 TRACE("iface %p, stream %p.\n", iface
, stream
);
814 return opc_content_stream_create(part
->content
, stream
);
817 static HRESULT WINAPI
opc_part_GetName(IOpcPart
*iface
, IOpcPartUri
**name
)
819 struct opc_part
*part
= impl_from_IOpcPart(iface
);
821 TRACE("iface %p, name %p.\n", iface
, name
);
824 IOpcPartUri_AddRef(*name
);
829 static HRESULT WINAPI
opc_part_GetContentType(IOpcPart
*iface
, LPWSTR
*type
)
831 struct opc_part
*part
= impl_from_IOpcPart(iface
);
833 TRACE("iface %p, type %p.\n", iface
, type
);
835 *type
= opc_strdupW(part
->content_type
);
836 return *type
? S_OK
: E_OUTOFMEMORY
;
839 static HRESULT WINAPI
opc_part_GetCompressionOptions(IOpcPart
*iface
, OPC_COMPRESSION_OPTIONS
*options
)
841 struct opc_part
*part
= impl_from_IOpcPart(iface
);
843 TRACE("iface %p, options %p.\n", iface
, options
);
845 *options
= part
->compression_options
;
849 static const IOpcPartVtbl opc_part_vtbl
=
851 opc_part_QueryInterface
,
854 opc_part_GetRelationshipSet
,
855 opc_part_GetContentStream
,
857 opc_part_GetContentType
,
858 opc_part_GetCompressionOptions
,
861 static HRESULT
opc_part_create(struct opc_part_set
*set
, IOpcPartUri
*name
, const WCHAR
*content_type
,
862 DWORD compression_options
, IOpcPart
**out
)
864 struct opc_part
*part
;
866 if (!opc_array_reserve((void **)&set
->parts
, &set
->size
, set
->count
+ 1, sizeof(*set
->parts
)))
867 return E_OUTOFMEMORY
;
869 if (!(part
= heap_alloc_zero(sizeof(*part
))))
870 return E_OUTOFMEMORY
;
872 part
->IOpcPart_iface
.lpVtbl
= &opc_part_vtbl
;
875 IOpcPartUri_AddRef(name
);
876 part
->compression_options
= compression_options
;
877 if (!(part
->content_type
= opc_strdupW(content_type
)))
879 IOpcPart_Release(&part
->IOpcPart_iface
);
880 return E_OUTOFMEMORY
;
883 part
->content
= heap_alloc_zero(sizeof(*part
->content
));
886 IOpcPart_Release(&part
->IOpcPart_iface
);
887 return E_OUTOFMEMORY
;
889 part
->content
->refcount
= 1;
891 set
->parts
[set
->count
++] = part
;
892 IOpcPart_AddRef(&part
->IOpcPart_iface
);
893 CoCreateGuid(&set
->id
);
895 *out
= &part
->IOpcPart_iface
;
896 TRACE("Created part %p.\n", *out
);
900 static struct opc_part
*opc_part_set_get_part(const struct opc_part_set
*part_set
, IOpcPartUri
*name
)
905 for (i
= 0; i
< part_set
->count
; ++i
)
908 if (IOpcPartUri_IsEqual(part_set
->parts
[i
]->name
, (IUri
*)name
, &is_equal
) == S_OK
&& is_equal
)
909 return part_set
->parts
[i
];
915 static HRESULT WINAPI
opc_part_set_QueryInterface(IOpcPartSet
*iface
, REFIID iid
, void **out
)
917 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
919 if (IsEqualIID(iid
, &IID_IOpcPartSet
) ||
920 IsEqualIID(iid
, &IID_IUnknown
))
923 IOpcPartSet_AddRef(iface
);
927 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
928 return E_NOINTERFACE
;
931 static ULONG WINAPI
opc_part_set_AddRef(IOpcPartSet
*iface
)
933 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
934 ULONG refcount
= InterlockedIncrement(&part_set
->refcount
);
936 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
941 static ULONG WINAPI
opc_part_set_Release(IOpcPartSet
*iface
)
943 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
944 ULONG refcount
= InterlockedDecrement(&part_set
->refcount
);
946 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
952 for (i
= 0; i
< part_set
->count
; ++i
)
953 IOpcPart_Release(&part_set
->parts
[i
]->IOpcPart_iface
);
954 heap_free(part_set
->parts
);
961 static HRESULT WINAPI
opc_part_set_GetPart(IOpcPartSet
*iface
, IOpcPartUri
*name
, IOpcPart
**out
)
963 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
964 struct opc_part
*part
;
966 TRACE("iface %p, name %p, out %p.\n", iface
, name
, out
);
976 if ((part
= opc_part_set_get_part(part_set
, name
)))
978 *out
= &part
->IOpcPart_iface
;
979 IOpcPart_AddRef(*out
);
982 return *out
? S_OK
: OPC_E_NO_SUCH_PART
;
985 static HRESULT WINAPI
opc_part_set_CreatePart(IOpcPartSet
*iface
, IOpcPartUri
*name
, LPCWSTR content_type
,
986 OPC_COMPRESSION_OPTIONS compression_options
, IOpcPart
**part
)
988 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
990 TRACE("iface %p, name %p, content_type %s, compression_options %#x, part %p.\n", iface
, name
,
991 debugstr_w(content_type
), compression_options
, part
);
1001 if (opc_part_set_get_part(part_set
, name
))
1002 return OPC_E_DUPLICATE_PART
;
1004 return opc_part_create(part_set
, name
, content_type
, compression_options
, part
);
1007 static HRESULT WINAPI
opc_part_set_DeletePart(IOpcPartSet
*iface
, IOpcPartUri
*name
)
1009 FIXME("iface %p, name %p stub!\n", iface
, name
);
1014 static HRESULT WINAPI
opc_part_set_PartExists(IOpcPartSet
*iface
, IOpcPartUri
*name
, BOOL
*exists
)
1016 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
1018 TRACE("iface %p, name %p, exists %p.\n", iface
, name
, exists
);
1020 if (!name
|| !exists
)
1023 *exists
= opc_part_set_get_part(part_set
, name
) != NULL
;
1028 static HRESULT WINAPI
opc_part_set_GetEnumerator(IOpcPartSet
*iface
, IOpcPartEnumerator
**enumerator
)
1030 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
1032 TRACE("iface %p, enumerator %p.\n", iface
, enumerator
);
1037 return opc_part_enum_create(part_set
, enumerator
);
1040 static const IOpcPartSetVtbl opc_part_set_vtbl
=
1042 opc_part_set_QueryInterface
,
1043 opc_part_set_AddRef
,
1044 opc_part_set_Release
,
1045 opc_part_set_GetPart
,
1046 opc_part_set_CreatePart
,
1047 opc_part_set_DeletePart
,
1048 opc_part_set_PartExists
,
1049 opc_part_set_GetEnumerator
,
1052 static HRESULT WINAPI
opc_relationship_QueryInterface(IOpcRelationship
*iface
, REFIID iid
, void **out
)
1054 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1056 if (IsEqualIID(iid
, &IID_IOpcRelationship
) ||
1057 IsEqualIID(iid
, &IID_IUnknown
))
1060 IOpcRelationship_AddRef(iface
);
1064 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
1065 return E_NOINTERFACE
;
1068 static ULONG WINAPI
opc_relationship_AddRef(IOpcRelationship
*iface
)
1070 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1071 ULONG refcount
= InterlockedIncrement(&relationship
->refcount
);
1073 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
1078 static ULONG WINAPI
opc_relationship_Release(IOpcRelationship
*iface
)
1080 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1081 ULONG refcount
= InterlockedDecrement(&relationship
->refcount
);
1083 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
1087 CoTaskMemFree(relationship
->id
);
1088 CoTaskMemFree(relationship
->type
);
1089 IOpcUri_Release(relationship
->source_uri
);
1090 IUri_Release(relationship
->target
);
1091 heap_free(relationship
);
1097 static HRESULT WINAPI
opc_relationship_GetId(IOpcRelationship
*iface
, WCHAR
**id
)
1099 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1101 TRACE("iface %p, id %p.\n", iface
, id
);
1103 *id
= opc_strdupW(relationship
->id
);
1104 return *id
? S_OK
: E_OUTOFMEMORY
;
1107 static HRESULT WINAPI
opc_relationship_GetRelationshipType(IOpcRelationship
*iface
, WCHAR
**type
)
1109 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1111 TRACE("iface %p, type %p.\n", iface
, type
);
1113 *type
= opc_strdupW(relationship
->type
);
1114 return *type
? S_OK
: E_OUTOFMEMORY
;
1117 static HRESULT WINAPI
opc_relationship_GetSourceUri(IOpcRelationship
*iface
, IOpcUri
**uri
)
1119 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1121 TRACE("iface %p, uri %p.\n", iface
, uri
);
1123 *uri
= relationship
->source_uri
;
1124 IOpcUri_AddRef(*uri
);
1129 static HRESULT WINAPI
opc_relationship_GetTargetUri(IOpcRelationship
*iface
, IUri
**target
)
1131 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1133 TRACE("iface %p, target %p.\n", iface
, target
);
1135 *target
= relationship
->target
;
1136 IUri_AddRef(*target
);
1141 static HRESULT WINAPI
opc_relationship_GetTargetMode(IOpcRelationship
*iface
, OPC_URI_TARGET_MODE
*target_mode
)
1143 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1145 TRACE("iface %p, target_mode %p.\n", iface
, target_mode
);
1147 *target_mode
= relationship
->target_mode
;
1152 static const IOpcRelationshipVtbl opc_relationship_vtbl
=
1154 opc_relationship_QueryInterface
,
1155 opc_relationship_AddRef
,
1156 opc_relationship_Release
,
1157 opc_relationship_GetId
,
1158 opc_relationship_GetRelationshipType
,
1159 opc_relationship_GetSourceUri
,
1160 opc_relationship_GetTargetUri
,
1161 opc_relationship_GetTargetMode
,
1164 static struct opc_relationship
*opc_relationshipset_get_rel(struct opc_relationship_set
*relationship_set
,
1169 for (i
= 0; i
< relationship_set
->count
; i
++)
1171 if (!wcscmp(id
, relationship_set
->relationships
[i
]->id
))
1172 return relationship_set
->relationships
[i
];
1178 static HRESULT
opc_relationship_create(struct opc_relationship_set
*set
, const WCHAR
*id
, const WCHAR
*type
,
1179 IUri
*target_uri
, OPC_URI_TARGET_MODE target_mode
, IOpcRelationship
**out
)
1181 struct opc_relationship
*relationship
;
1183 if (!opc_array_reserve((void **)&set
->relationships
, &set
->size
, set
->count
+ 1, sizeof(*set
->relationships
)))
1184 return E_OUTOFMEMORY
;
1186 if (!(relationship
= heap_alloc_zero(sizeof(*relationship
))))
1187 return E_OUTOFMEMORY
;
1189 relationship
->IOpcRelationship_iface
.lpVtbl
= &opc_relationship_vtbl
;
1190 relationship
->refcount
= 1;
1192 relationship
->target
= target_uri
;
1193 IUri_AddRef(relationship
->target
);
1194 relationship
->source_uri
= set
->source_uri
;
1195 IOpcUri_AddRef(relationship
->source_uri
);
1198 relationship
->id
= opc_strdupW(id
);
1201 relationship
->id
= CoTaskMemAlloc(10 * sizeof(WCHAR
));
1202 if (relationship
->id
)
1204 static const WCHAR fmtW
[] = {'R','%','0','8','X',0};
1207 /* FIXME: test that generated id is unique */
1208 RtlGenRandom(&generated
, sizeof(generated
));
1209 swprintf(relationship
->id
, 10, fmtW
, generated
);
1211 if (opc_relationshipset_get_rel(set
, relationship
->id
))
1213 WARN("Newly generated id %s already exists.\n", debugstr_w(relationship
->id
));
1214 IOpcRelationship_Release(&relationship
->IOpcRelationship_iface
);
1220 relationship
->type
= opc_strdupW(type
);
1221 if (!relationship
->id
|| !relationship
->type
)
1223 IOpcRelationship_Release(&relationship
->IOpcRelationship_iface
);
1224 return E_OUTOFMEMORY
;
1227 set
->relationships
[set
->count
++] = relationship
;
1228 IOpcRelationship_AddRef(&relationship
->IOpcRelationship_iface
);
1229 CoCreateGuid(&set
->id
);
1231 *out
= &relationship
->IOpcRelationship_iface
;
1232 TRACE("Created relationship %p.\n", *out
);
1236 static HRESULT WINAPI
opc_relationship_set_QueryInterface(IOpcRelationshipSet
*iface
, REFIID iid
, void **out
)
1238 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1240 if (IsEqualIID(iid
, &IID_IOpcRelationshipSet
) ||
1241 IsEqualIID(iid
, &IID_IUnknown
))
1244 IOpcRelationshipSet_AddRef(iface
);
1248 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
1249 return E_NOINTERFACE
;
1252 static ULONG WINAPI
opc_relationship_set_AddRef(IOpcRelationshipSet
*iface
)
1254 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1255 ULONG refcount
= InterlockedIncrement(&relationship_set
->refcount
);
1257 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
1262 static ULONG WINAPI
opc_relationship_set_Release(IOpcRelationshipSet
*iface
)
1264 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1265 ULONG refcount
= InterlockedDecrement(&relationship_set
->refcount
);
1267 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
1273 for (i
= 0; i
< relationship_set
->count
; ++i
)
1274 IOpcRelationship_Release(&relationship_set
->relationships
[i
]->IOpcRelationship_iface
);
1275 IOpcUri_Release(relationship_set
->source_uri
);
1276 heap_free(relationship_set
->relationships
);
1277 heap_free(relationship_set
);
1283 static HRESULT WINAPI
opc_relationship_set_GetRelationship(IOpcRelationshipSet
*iface
, const WCHAR
*id
,
1284 IOpcRelationship
**relationship
)
1286 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1287 struct opc_relationship
*ret
;
1289 TRACE("iface %p, id %s, relationship %p.\n", iface
, debugstr_w(id
), relationship
);
1294 *relationship
= NULL
;
1299 if ((ret
= opc_relationshipset_get_rel(relationship_set
, id
)))
1301 *relationship
= &ret
->IOpcRelationship_iface
;
1302 IOpcRelationship_AddRef(*relationship
);
1305 return *relationship
? S_OK
: OPC_E_NO_SUCH_RELATIONSHIP
;
1308 static HRESULT WINAPI
opc_relationship_set_CreateRelationship(IOpcRelationshipSet
*iface
, const WCHAR
*id
,
1309 const WCHAR
*type
, IUri
*target_uri
, OPC_URI_TARGET_MODE target_mode
, IOpcRelationship
**relationship
)
1311 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1314 TRACE("iface %p, id %s, type %s, target_uri %p, target_mode %d, relationship %p.\n", iface
, debugstr_w(id
),
1315 debugstr_w(type
), target_uri
, target_mode
, relationship
);
1320 *relationship
= NULL
;
1322 if (!type
|| !target_uri
)
1325 if (id
&& opc_relationshipset_get_rel(relationship_set
, id
))
1326 return OPC_E_DUPLICATE_RELATIONSHIP
;
1328 if (IUri_GetPropertyLength(target_uri
, Uri_PROPERTY_SCHEME_NAME
, &length
, 0) == S_OK
&& length
!= 0
1329 && target_mode
== OPC_URI_TARGET_MODE_INTERNAL
)
1330 return OPC_E_INVALID_RELATIONSHIP_TARGET
;
1332 return opc_relationship_create(relationship_set
, id
, type
, target_uri
, target_mode
, relationship
);
1335 static HRESULT WINAPI
opc_relationship_set_DeleteRelationship(IOpcRelationshipSet
*iface
, const WCHAR
*id
)
1337 FIXME("iface %p, id %s stub!\n", iface
, debugstr_w(id
));
1342 static HRESULT WINAPI
opc_relationship_set_RelationshipExists(IOpcRelationshipSet
*iface
, const WCHAR
*id
, BOOL
*exists
)
1344 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1346 TRACE("iface %p, id %s, exists %p.\n", iface
, debugstr_w(id
), exists
);
1351 *exists
= opc_relationshipset_get_rel(relationship_set
, id
) != NULL
;
1356 static HRESULT WINAPI
opc_relationship_set_GetEnumerator(IOpcRelationshipSet
*iface
,
1357 IOpcRelationshipEnumerator
**enumerator
)
1359 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1361 TRACE("iface %p, enumerator %p.\n", iface
, enumerator
);
1366 return opc_rel_enum_create(relationship_set
, enumerator
);
1369 static HRESULT WINAPI
opc_relationship_set_GetEnumeratorForType(IOpcRelationshipSet
*iface
, const WCHAR
*type
,
1370 IOpcRelationshipEnumerator
**enumerator
)
1372 FIXME("iface %p, type %s, enumerator %p stub!\n", iface
, debugstr_w(type
), enumerator
);
1377 static HRESULT WINAPI
opc_relationship_set_GetRelationshipsContentStream(IOpcRelationshipSet
*iface
, IStream
**stream
)
1379 FIXME("iface %p, stream %p stub!\n", iface
, stream
);
1384 static const IOpcRelationshipSetVtbl opc_relationship_set_vtbl
=
1386 opc_relationship_set_QueryInterface
,
1387 opc_relationship_set_AddRef
,
1388 opc_relationship_set_Release
,
1389 opc_relationship_set_GetRelationship
,
1390 opc_relationship_set_CreateRelationship
,
1391 opc_relationship_set_DeleteRelationship
,
1392 opc_relationship_set_RelationshipExists
,
1393 opc_relationship_set_GetEnumerator
,
1394 opc_relationship_set_GetEnumeratorForType
,
1395 opc_relationship_set_GetRelationshipsContentStream
,
1398 static HRESULT
opc_relationship_set_create(IOpcUri
*source_uri
, IOpcRelationshipSet
**out
)
1400 struct opc_relationship_set
*relationship_set
;
1402 if (!(relationship_set
= heap_alloc_zero(sizeof(*relationship_set
))))
1403 return E_OUTOFMEMORY
;
1405 relationship_set
->IOpcRelationshipSet_iface
.lpVtbl
= &opc_relationship_set_vtbl
;
1406 relationship_set
->refcount
= 1;
1407 relationship_set
->source_uri
= source_uri
;
1408 IOpcUri_AddRef(relationship_set
->source_uri
);
1410 *out
= &relationship_set
->IOpcRelationshipSet_iface
;
1411 TRACE("Created relationship set %p.\n", *out
);
1415 static HRESULT WINAPI
opc_package_QueryInterface(IOpcPackage
*iface
, REFIID iid
, void **out
)
1417 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1419 if (IsEqualIID(iid
, &IID_IOpcPackage
) ||
1420 IsEqualIID(iid
, &IID_IUnknown
))
1423 IOpcPackage_AddRef(iface
);
1427 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
1428 return E_NOINTERFACE
;
1431 static ULONG WINAPI
opc_package_AddRef(IOpcPackage
*iface
)
1433 struct opc_package
*package
= impl_from_IOpcPackage(iface
);
1434 ULONG refcount
= InterlockedIncrement(&package
->refcount
);
1436 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
1441 static ULONG WINAPI
opc_package_Release(IOpcPackage
*iface
)
1443 struct opc_package
*package
= impl_from_IOpcPackage(iface
);
1444 ULONG refcount
= InterlockedDecrement(&package
->refcount
);
1446 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
1450 if (package
->part_set
)
1451 IOpcPartSet_Release(package
->part_set
);
1452 if (package
->relationship_set
)
1453 IOpcRelationshipSet_Release(package
->relationship_set
);
1454 if (package
->source_uri
)
1455 IOpcUri_Release(package
->source_uri
);
1462 static HRESULT WINAPI
opc_package_GetPartSet(IOpcPackage
*iface
, IOpcPartSet
**part_set
)
1464 struct opc_package
*package
= impl_from_IOpcPackage(iface
);
1466 TRACE("iface %p, part_set %p.\n", iface
, part_set
);
1468 if (!package
->part_set
)
1470 struct opc_part_set
*part_set
= heap_alloc_zero(sizeof(*part_set
));
1472 return E_OUTOFMEMORY
;
1474 part_set
->IOpcPartSet_iface
.lpVtbl
= &opc_part_set_vtbl
;
1475 part_set
->refcount
= 1;
1477 package
->part_set
= &part_set
->IOpcPartSet_iface
;
1480 *part_set
= package
->part_set
;
1481 IOpcPartSet_AddRef(*part_set
);
1486 static HRESULT WINAPI
opc_package_GetRelationshipSet(IOpcPackage
*iface
, IOpcRelationshipSet
**relationship_set
)
1488 struct opc_package
*package
= impl_from_IOpcPackage(iface
);
1491 TRACE("iface %p, relationship_set %p.\n", iface
, relationship_set
);
1493 if (!package
->relationship_set
)
1495 if (FAILED(hr
= opc_relationship_set_create(package
->source_uri
, &package
->relationship_set
)))
1499 *relationship_set
= package
->relationship_set
;
1500 IOpcRelationshipSet_AddRef(*relationship_set
);
1505 static const IOpcPackageVtbl opc_package_vtbl
=
1507 opc_package_QueryInterface
,
1509 opc_package_Release
,
1510 opc_package_GetPartSet
,
1511 opc_package_GetRelationshipSet
,
1514 HRESULT
opc_package_create(IOpcFactory
*factory
, IOpcPackage
**out
)
1516 struct opc_package
*package
;
1519 if (!(package
= heap_alloc_zero(sizeof(*package
))))
1520 return E_OUTOFMEMORY
;
1522 package
->IOpcPackage_iface
.lpVtbl
= &opc_package_vtbl
;
1523 package
->refcount
= 1;
1525 if (FAILED(hr
= IOpcFactory_CreatePackageRootUri(factory
, &package
->source_uri
)))
1531 *out
= &package
->IOpcPackage_iface
;
1532 TRACE("Created package %p.\n", *out
);
1536 struct content_types
1542 enum content_type_element
1544 CONTENT_TYPE_DEFAULT
,
1545 CONTENT_TYPE_OVERRIDE
,
1551 enum content_type_element element
;
1559 struct override_type
1566 static HRESULT
opc_package_add_override_content_type(struct content_types
*types
, IOpcPart
*part
)
1568 struct content_type
*type
;
1570 if (!(type
= heap_alloc(sizeof(*type
))))
1571 return E_OUTOFMEMORY
;
1573 type
->element
= CONTENT_TYPE_OVERRIDE
;
1574 type
->u
.override
.part
= part
;
1575 IOpcPart_AddRef(part
);
1577 list_add_tail(&types
->types
, &type
->entry
);
1582 static HRESULT
opc_package_add_default_content_type(struct content_types
*types
,
1583 const WCHAR
*ext
, const WCHAR
*content_type
)
1585 struct content_type
*type
;
1587 if (!(type
= heap_alloc(sizeof(*type
))))
1588 return E_OUTOFMEMORY
;
1590 type
->element
= CONTENT_TYPE_DEFAULT
;
1591 type
->u
.def
.ext
= opc_strdupW(ext
);
1592 type
->u
.def
.type
= opc_strdupW(content_type
);
1593 if (!type
->u
.def
.ext
|| !type
->u
.def
.type
)
1595 CoTaskMemFree(type
->u
.def
.ext
);
1596 CoTaskMemFree(type
->u
.def
.type
);
1598 return E_OUTOFMEMORY
;
1601 list_add_tail(&types
->types
, &type
->entry
);
1606 static HRESULT
opc_package_add_content_type(struct content_types
*types
, IOpcPart
*part
)
1608 struct content_type
*cur
;
1609 BSTR ext
, content_type
;
1614 if (FAILED(hr
= IOpcPart_GetName(part
, &name
)))
1617 hr
= IOpcPartUri_GetExtension(name
, &ext
);
1618 IOpcPartUri_Release(name
);
1621 hr
= opc_package_add_override_content_type(types
, part
);
1629 if (FAILED(hr
= IOpcPart_GetContentType(part
, &content_type
)))
1632 LIST_FOR_EACH_ENTRY(cur
, &types
->types
, struct content_type
, entry
)
1634 if (cur
->element
== CONTENT_TYPE_OVERRIDE
)
1637 if (!wcsicmp(cur
->u
.def
.ext
, ext
))
1641 if (!wcscmp(cur
->u
.def
.type
, content_type
))
1644 hr
= opc_package_add_override_content_type(types
, part
);
1650 hr
= opc_package_add_default_content_type(types
, ext
, content_type
);
1653 SysFreeString(content_type
);
1658 static BOOL
opc_package_has_rels_part(IOpcRelationshipSet
*rel_set
)
1660 IOpcRelationshipEnumerator
*enumerator
;
1664 if (FAILED(hr
= IOpcRelationshipSet_GetEnumerator(rel_set
, &enumerator
)))
1668 IOpcRelationshipEnumerator_MoveNext(enumerator
, &has_next
);
1669 IOpcRelationshipEnumerator_Release(enumerator
);
1674 static HRESULT
opc_package_collect_content_types(IOpcPackage
*package
, struct content_types
*types
)
1676 IOpcPartEnumerator
*enumerator
;
1677 IOpcRelationshipSet
*rel_set
;
1682 if (FAILED(hr
= IOpcPackage_GetPartSet(package
, &parts
)))
1685 hr
= IOpcPackage_GetRelationshipSet(package
, &rel_set
);
1688 types
->has_rels_part
|= opc_package_has_rels_part(rel_set
);
1689 IOpcRelationshipSet_Release(rel_set
);
1692 hr
= IOpcPartSet_GetEnumerator(parts
, &enumerator
);
1693 IOpcPartSet_Release(parts
);
1697 if (FAILED(hr
= IOpcPartEnumerator_MoveNext(enumerator
, &has_next
)) || !has_next
)
1699 IOpcPartEnumerator_Release(enumerator
);
1707 if (FAILED(hr
= IOpcPartEnumerator_GetCurrent(enumerator
, &part
)))
1710 if (!types
->has_rels_part
)
1712 hr
= IOpcPart_GetRelationshipSet(part
, &rel_set
);
1715 types
->has_rels_part
|= opc_package_has_rels_part(rel_set
);
1716 IOpcRelationshipSet_Release(rel_set
);
1720 hr
= opc_package_add_content_type(types
, part
);
1721 IOpcPart_Release(part
);
1725 if (FAILED(hr
= IOpcPartEnumerator_MoveNext(enumerator
, &has_next
)))
1729 IOpcPartEnumerator_Release(enumerator
);
1734 static HRESULT
opc_package_write_default_type(const WCHAR
*ext
, const WCHAR
*type
, IXmlWriter
*writer
)
1736 static const WCHAR contenttypeW
[] = {'C','o','n','t','e','n','t','T','y','p','e',0};
1737 static const WCHAR extensionW
[] = {'E','x','t','e','n','s','i','o','n',0};
1738 static const WCHAR defaultW
[] = {'D','e','f','a','u','l','t',0};
1741 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, defaultW
, NULL
);
1743 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, extensionW
, NULL
, ext
);
1745 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, contenttypeW
, NULL
, type
);
1749 static HRESULT
opc_package_write_contenttypes(IOpcPackage
*package
, struct zip_archive
*archive
, IXmlWriter
*writer
)
1751 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','/',
1752 'p','a','c','k','a','g','e','/','2','0','0','6','/','c','o','n','t','e','n','t','-','t','y','p','e','s',0};
1753 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','-',
1754 'p','a','c','k','a','g','e','.','r','e','l','a','t','i','o','n','s','h','i','p','s','+','x','m','l',0};
1755 static const WCHAR contenttypesW
[] = {'[','C','o','n','t','e','n','t','_','T','y','p','e','s',']','.','x','m','l',0};
1756 static const WCHAR contenttypeW
[] = {'C','o','n','t','e','n','t','T','y','p','e',0};
1757 static const WCHAR overrideW
[] = {'O','v','e','r','r','i','d','e',0};
1758 static const WCHAR partnameW
[] = {'P','a','r','t','N','a','m','e',0};
1759 static const WCHAR typesW
[] = {'T','y','p','e','s',0};
1760 static const WCHAR relsW
[] = {'r','e','l','s',0};
1761 struct content_type
*content_type
, *content_type2
;
1762 struct content_types types
;
1763 IStream
*content
= NULL
;
1766 list_init(&types
.types
);
1767 types
.has_rels_part
= FALSE
;
1769 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &content
);
1771 hr
= opc_package_collect_content_types(package
, &types
);
1773 hr
= IXmlWriter_SetOutput(writer
, (IUnknown
*)content
);
1775 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Omit
);
1777 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, typesW
, uriW
);
1779 if (SUCCEEDED(hr
) && types
.has_rels_part
)
1781 hr
= opc_package_write_default_type(relsW
, relstypeW
, writer
);
1783 hr
= IXmlWriter_WriteEndElement(writer
);
1786 LIST_FOR_EACH_ENTRY_SAFE(content_type
, content_type2
, &types
.types
, struct content_type
, entry
)
1788 if (content_type
->element
== CONTENT_TYPE_DEFAULT
)
1790 hr
= opc_package_write_default_type(content_type
->u
.def
.ext
+ 1, content_type
->u
.def
.type
, writer
);
1792 CoTaskMemFree(content_type
->u
.def
.ext
);
1793 CoTaskMemFree(content_type
->u
.def
.type
);
1797 IOpcPartUri
*uri
= NULL
;
1802 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, overrideW
, NULL
);
1804 hr
= IOpcPart_GetName(content_type
->u
.override
.part
, &uri
);
1806 hr
= IOpcPartUri_GetRawUri(uri
, &name
);
1808 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, partnameW
, NULL
, name
);
1810 hr
= IOpcPart_GetContentType(content_type
->u
.override
.part
, &type
);
1812 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, contenttypeW
, NULL
, type
);
1815 IOpcPartUri_Release(uri
);
1816 SysFreeString(name
);
1817 CoTaskMemFree(type
);
1819 IOpcPart_Release(content_type
->u
.override
.part
);
1822 hr
= IXmlWriter_WriteEndElement(writer
);
1824 list_remove(&content_type
->entry
);
1825 heap_free(content_type
);
1829 hr
= IXmlWriter_WriteEndDocument(writer
);
1831 hr
= IXmlWriter_Flush(writer
);
1834 hr
= compress_add_file(archive
, contenttypesW
, content
, OPC_COMPRESSION_NORMAL
);
1837 IStream_Release(content
);
1842 static HRESULT
opc_package_write_rel(IOpcRelationship
*rel
, IXmlWriter
*writer
)
1844 static const WCHAR relationshipW
[] = {'R','e','l','a','t','i','o','n','s','h','i','p',0};
1845 static const WCHAR targetW
[] = {'T','a','r','g','e','t',0};
1846 static const WCHAR typeW
[] = {'T','y','p','e',0};
1847 static const WCHAR idW
[] = {'I','d',0};
1853 if (FAILED(hr
= IXmlWriter_WriteStartElement(writer
, NULL
, relationshipW
, NULL
)))
1856 if (FAILED(hr
= IOpcRelationship_GetTargetUri(rel
, &uri
)))
1859 IUri_GetRawUri(uri
, &target_uri
);
1862 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, targetW
, NULL
, target_uri
);
1863 SysFreeString(target_uri
);
1867 if (FAILED(hr
= IOpcRelationship_GetId(rel
, &str
)))
1870 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, idW
, NULL
, str
);
1875 if (FAILED(hr
= IOpcRelationship_GetRelationshipType(rel
, &str
)))
1878 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, typeW
, NULL
, str
);
1883 return IXmlWriter_WriteEndElement(writer
);
1886 static HRESULT
opc_package_write_rels(struct zip_archive
*archive
, IOpcRelationshipSet
*rels
,
1887 IOpcUri
*uri
, IXmlWriter
*writer
)
1889 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','/',
1890 '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};
1891 static const WCHAR relationshipsW
[] = {'R','e','l','a','t','i','o','n','s','h','i','p','s',0};
1892 IOpcRelationshipEnumerator
*enumerator
;
1893 BSTR rels_part_uri
= NULL
;
1894 IOpcPartUri
*rels_uri
;
1899 if (FAILED(hr
= IOpcRelationshipSet_GetEnumerator(rels
, &enumerator
)))
1902 hr
= IOpcRelationshipEnumerator_MoveNext(enumerator
, &has_next
);
1905 IOpcRelationshipEnumerator_Release(enumerator
);
1909 if (FAILED(hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &content
)))
1911 IOpcRelationshipEnumerator_Release(enumerator
);
1915 hr
= IXmlWriter_SetOutput(writer
, (IUnknown
*)content
);
1917 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
1919 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, relationshipsW
, uriW
);
1923 IOpcRelationship
*rel
;
1925 if (FAILED(hr
= IOpcRelationshipEnumerator_GetCurrent(enumerator
, &rel
)))
1928 hr
= opc_package_write_rel(rel
, writer
);
1929 IOpcRelationship_Release(rel
);
1933 IOpcRelationshipEnumerator_MoveNext(enumerator
, &has_next
);
1936 IOpcRelationshipEnumerator_Release(enumerator
);
1939 hr
= IXmlWriter_WriteEndDocument(writer
);
1941 hr
= IXmlWriter_Flush(writer
);
1944 hr
= IOpcUri_GetRelationshipsPartUri(uri
, &rels_uri
);
1946 hr
= IOpcPartUri_GetRawUri(rels_uri
, &rels_part_uri
);
1949 /* Relationship part names always start with root '/', skip it. */
1950 hr
= compress_add_file(archive
, rels_part_uri
+ 1, content
, OPC_COMPRESSION_NORMAL
);
1953 SysFreeString(rels_part_uri
);
1954 IStream_Release(content
);
1959 static HRESULT
opc_package_write_part(struct zip_archive
*archive
, IOpcPart
*part
, IXmlWriter
*writer
)
1961 OPC_COMPRESSION_OPTIONS options
= OPC_COMPRESSION_NORMAL
;
1962 IOpcRelationshipSet
*rels
= NULL
;
1963 IStream
*content
= NULL
;
1968 if (FAILED(hr
= IOpcPart_GetName(part
, &name
)))
1971 hr
= IOpcPartUri_GetRawUri(name
, &uri
);
1973 hr
= IOpcPart_GetCompressionOptions(part
, &options
);
1975 hr
= IOpcPart_GetContentStream(part
, &content
);
1978 /* Part names always start with root '/', skip it. */
1979 hr
= compress_add_file(archive
, uri
+ 1, content
, options
);
1982 hr
= IOpcPart_GetRelationshipSet(part
, &rels
);
1984 hr
= opc_package_write_rels(archive
, rels
, (IOpcUri
*)name
, writer
);
1986 IOpcPartUri_Release(name
);
1989 IStream_Release(content
);
1991 IOpcRelationshipSet_Release(rels
);
1996 static HRESULT
opc_package_write_parts(struct zip_archive
*archive
, IOpcPackage
*package
, IXmlWriter
*writer
)
1998 IOpcPartEnumerator
*parts
;
1999 IOpcPartSet
*part_set
;
2003 if (FAILED(hr
= IOpcPackage_GetPartSet(package
, &part_set
)))
2006 hr
= IOpcPartSet_GetEnumerator(part_set
, &parts
);
2007 IOpcPartSet_Release(part_set
);
2011 while (IOpcPartEnumerator_MoveNext(parts
, &got_next
) == S_OK
&& got_next
)
2015 if (FAILED(hr
= IOpcPartEnumerator_GetCurrent(parts
, &part
)))
2018 hr
= opc_package_write_part(archive
, part
, writer
);
2019 IOpcPart_Release(part
);
2024 IOpcPartEnumerator_Release(parts
);
2029 HRESULT
opc_package_write(IOpcPackage
*package
, OPC_WRITE_FLAGS flags
, IStream
*stream
)
2031 IOpcRelationshipSet
*rels
= NULL
;
2032 struct zip_archive
*archive
;
2033 IOpcUri
*uri
= NULL
;
2037 if (flags
!= OPC_WRITE_FORCE_ZIP32
)
2038 FIXME("Unsupported write flags %#x.\n", flags
);
2040 if (FAILED(hr
= CreateXmlWriter(&IID_IXmlWriter
, (void **)&writer
, NULL
)))
2043 if (FAILED(hr
= compress_create_archive(stream
, &archive
)))
2045 IXmlWriter_Release(writer
);
2049 /* [Content_Types].xml */
2050 hr
= opc_package_write_contenttypes(package
, archive
, writer
);
2051 /* Package relationships. */
2053 hr
= IOpcPackage_GetRelationshipSet(package
, &rels
);
2055 hr
= opc_root_uri_create(&uri
);
2057 hr
= opc_package_write_rels(archive
, rels
, uri
, writer
);
2060 hr
= opc_package_write_parts(archive
, package
, writer
);
2063 IOpcRelationshipSet_Release(rels
);
2065 IOpcUri_Release(uri
);
2067 compress_finalize_archive(archive
);
2068 IXmlWriter_Release(writer
);