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
);
563 stream
->pos
.QuadPart
+= *num_read
;
568 static HRESULT WINAPI
opc_content_stream_Write(IStream
*iface
, const void *data
, ULONG size
, ULONG
*num_written
)
570 struct opc_content_stream
*stream
= impl_from_IStream(iface
);
573 TRACE("iface %p, data %p, size %u, num_written %p.\n", iface
, data
, size
, num_written
);
576 num_written
= &written
;
580 if (size
> stream
->content
->size
.QuadPart
- stream
->pos
.QuadPart
)
582 void *ptr
= heap_realloc(stream
->content
->data
, stream
->pos
.QuadPart
+ size
);
584 return E_OUTOFMEMORY
;
585 stream
->content
->data
= ptr
;
588 memcpy(stream
->content
->data
+ stream
->pos
.QuadPart
, data
, size
);
589 stream
->pos
.QuadPart
+= size
;
590 stream
->content
->size
.QuadPart
+= size
;
596 static HRESULT WINAPI
opc_content_stream_Seek(IStream
*iface
, LARGE_INTEGER move
, DWORD origin
, ULARGE_INTEGER
*newpos
)
598 struct opc_content_stream
*stream
= impl_from_IStream(iface
);
601 TRACE("iface %p, move %s, origin %d, newpos %p.\n", iface
, wine_dbgstr_longlong(move
.QuadPart
), origin
, newpos
);
605 case STREAM_SEEK_SET
:
606 pos
.QuadPart
= move
.QuadPart
;
608 case STREAM_SEEK_CUR
:
609 pos
.QuadPart
= stream
->pos
.QuadPart
+ move
.QuadPart
;
611 case STREAM_SEEK_END
:
612 pos
.QuadPart
= stream
->content
->size
.QuadPart
+ move
.QuadPart
;
615 WARN("Unknown origin mode %d.\n", origin
);
622 *newpos
= stream
->pos
;
627 static HRESULT WINAPI
opc_content_stream_SetSize(IStream
*iface
, ULARGE_INTEGER size
)
629 FIXME("iface %p, size %s stub!\n", iface
, wine_dbgstr_longlong(size
.QuadPart
));
634 static HRESULT WINAPI
opc_content_stream_CopyTo(IStream
*iface
, IStream
*dest
, ULARGE_INTEGER size
,
635 ULARGE_INTEGER
*num_read
, ULARGE_INTEGER
*written
)
637 FIXME("iface %p, dest %p, size %s, num_read %p, written %p stub!\n", iface
, dest
,
638 wine_dbgstr_longlong(size
.QuadPart
), num_read
, written
);
643 static HRESULT WINAPI
opc_content_stream_Commit(IStream
*iface
, DWORD flags
)
645 FIXME("iface %p, flags %#x stub!\n", iface
, flags
);
650 static HRESULT WINAPI
opc_content_stream_Revert(IStream
*iface
)
652 FIXME("iface %p stub!\n", iface
);
657 static HRESULT WINAPI
opc_content_stream_LockRegion(IStream
*iface
, ULARGE_INTEGER offset
,
658 ULARGE_INTEGER size
, DWORD lock_type
)
660 FIXME("iface %p, offset %s, size %s, lock_type %d stub!\n", iface
, wine_dbgstr_longlong(offset
.QuadPart
),
661 wine_dbgstr_longlong(size
.QuadPart
), lock_type
);
666 static HRESULT WINAPI
opc_content_stream_UnlockRegion(IStream
*iface
, ULARGE_INTEGER offset
, ULARGE_INTEGER size
,
669 FIXME("iface %p, offset %s, size %s, lock_type %d stub!\n", iface
, wine_dbgstr_longlong(offset
.QuadPart
),
670 wine_dbgstr_longlong(size
.QuadPart
), lock_type
);
675 static HRESULT WINAPI
opc_content_stream_Stat(IStream
*iface
, STATSTG
*statstg
, DWORD flag
)
677 FIXME("iface %p, statstg %p, flag %d stub!\n", iface
, statstg
, flag
);
682 static HRESULT WINAPI
opc_content_stream_Clone(IStream
*iface
, IStream
**result
)
684 FIXME("iface %p, result %p stub!\n", iface
, result
);
689 static const IStreamVtbl opc_content_stream_vtbl
=
691 opc_content_stream_QueryInterface
,
692 opc_content_stream_AddRef
,
693 opc_content_stream_Release
,
694 opc_content_stream_Read
,
695 opc_content_stream_Write
,
696 opc_content_stream_Seek
,
697 opc_content_stream_SetSize
,
698 opc_content_stream_CopyTo
,
699 opc_content_stream_Commit
,
700 opc_content_stream_Revert
,
701 opc_content_stream_LockRegion
,
702 opc_content_stream_UnlockRegion
,
703 opc_content_stream_Stat
,
704 opc_content_stream_Clone
,
707 static HRESULT
opc_content_stream_create(struct opc_content
*content
, IStream
**out
)
709 struct opc_content_stream
*stream
;
711 if (!(stream
= heap_alloc_zero(sizeof(*stream
))))
712 return E_OUTOFMEMORY
;
714 stream
->IStream_iface
.lpVtbl
= &opc_content_stream_vtbl
;
715 stream
->refcount
= 1;
716 stream
->content
= content
;
717 InterlockedIncrement(&content
->refcount
);
719 *out
= &stream
->IStream_iface
;
721 TRACE("Created content stream %p.\n", *out
);
725 static HRESULT
opc_relationship_set_create(IOpcUri
*source_uri
, IOpcRelationshipSet
**relationship_set
);
727 static WCHAR
*opc_strdupW(const WCHAR
*str
)
735 size
= (strlenW(str
) + 1) * sizeof(WCHAR
);
736 ret
= CoTaskMemAlloc(size
);
738 memcpy(ret
, str
, size
);
744 static HRESULT WINAPI
opc_part_QueryInterface(IOpcPart
*iface
, REFIID iid
, void **out
)
746 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
748 if (IsEqualIID(iid
, &IID_IOpcPart
) ||
749 IsEqualIID(iid
, &IID_IUnknown
))
752 IOpcPart_AddRef(iface
);
756 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
757 return E_NOINTERFACE
;
760 static ULONG WINAPI
opc_part_AddRef(IOpcPart
*iface
)
762 struct opc_part
*part
= impl_from_IOpcPart(iface
);
763 ULONG refcount
= InterlockedIncrement(&part
->refcount
);
765 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
770 static ULONG WINAPI
opc_part_Release(IOpcPart
*iface
)
772 struct opc_part
*part
= impl_from_IOpcPart(iface
);
773 ULONG refcount
= InterlockedDecrement(&part
->refcount
);
775 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
779 if (part
->relationship_set
)
780 IOpcRelationshipSet_Release(part
->relationship_set
);
781 IOpcPartUri_Release(part
->name
);
782 CoTaskMemFree(part
->content_type
);
783 opc_content_release(part
->content
);
790 static HRESULT WINAPI
opc_part_GetRelationshipSet(IOpcPart
*iface
, IOpcRelationshipSet
**relationship_set
)
792 struct opc_part
*part
= impl_from_IOpcPart(iface
);
795 TRACE("iface %p, relationship_set %p.\n", iface
, relationship_set
);
797 if (!part
->relationship_set
&& FAILED(hr
= opc_relationship_set_create((IOpcUri
*)part
->name
, &part
->relationship_set
)))
800 *relationship_set
= part
->relationship_set
;
801 IOpcRelationshipSet_AddRef(*relationship_set
);
806 static HRESULT WINAPI
opc_part_GetContentStream(IOpcPart
*iface
, IStream
**stream
)
808 struct opc_part
*part
= impl_from_IOpcPart(iface
);
810 TRACE("iface %p, stream %p.\n", iface
, stream
);
815 return opc_content_stream_create(part
->content
, stream
);
818 static HRESULT WINAPI
opc_part_GetName(IOpcPart
*iface
, IOpcPartUri
**name
)
820 struct opc_part
*part
= impl_from_IOpcPart(iface
);
822 TRACE("iface %p, name %p.\n", iface
, name
);
825 IOpcPartUri_AddRef(*name
);
830 static HRESULT WINAPI
opc_part_GetContentType(IOpcPart
*iface
, LPWSTR
*type
)
832 struct opc_part
*part
= impl_from_IOpcPart(iface
);
834 TRACE("iface %p, type %p.\n", iface
, type
);
836 *type
= opc_strdupW(part
->content_type
);
837 return *type
? S_OK
: E_OUTOFMEMORY
;
840 static HRESULT WINAPI
opc_part_GetCompressionOptions(IOpcPart
*iface
, OPC_COMPRESSION_OPTIONS
*options
)
842 struct opc_part
*part
= impl_from_IOpcPart(iface
);
844 TRACE("iface %p, options %p.\n", iface
, options
);
846 *options
= part
->compression_options
;
850 static const IOpcPartVtbl opc_part_vtbl
=
852 opc_part_QueryInterface
,
855 opc_part_GetRelationshipSet
,
856 opc_part_GetContentStream
,
858 opc_part_GetContentType
,
859 opc_part_GetCompressionOptions
,
862 static HRESULT
opc_part_create(struct opc_part_set
*set
, IOpcPartUri
*name
, const WCHAR
*content_type
,
863 DWORD compression_options
, IOpcPart
**out
)
865 struct opc_part
*part
;
867 if (!opc_array_reserve((void **)&set
->parts
, &set
->size
, set
->count
+ 1, sizeof(*set
->parts
)))
868 return E_OUTOFMEMORY
;
870 if (!(part
= heap_alloc_zero(sizeof(*part
))))
871 return E_OUTOFMEMORY
;
873 part
->IOpcPart_iface
.lpVtbl
= &opc_part_vtbl
;
876 IOpcPartUri_AddRef(name
);
877 part
->compression_options
= compression_options
;
878 if (!(part
->content_type
= opc_strdupW(content_type
)))
880 IOpcPart_Release(&part
->IOpcPart_iface
);
881 return E_OUTOFMEMORY
;
884 part
->content
= heap_alloc_zero(sizeof(*part
->content
));
887 IOpcPart_Release(&part
->IOpcPart_iface
);
888 return E_OUTOFMEMORY
;
890 part
->content
->refcount
= 1;
892 set
->parts
[set
->count
++] = part
;
893 IOpcPart_AddRef(&part
->IOpcPart_iface
);
894 CoCreateGuid(&set
->id
);
896 *out
= &part
->IOpcPart_iface
;
897 TRACE("Created part %p.\n", *out
);
901 static struct opc_part
*opc_part_set_get_part(const struct opc_part_set
*part_set
, IOpcPartUri
*name
)
906 for (i
= 0; i
< part_set
->count
; ++i
)
909 if (IOpcPartUri_IsEqual(part_set
->parts
[i
]->name
, (IUri
*)name
, &is_equal
) == S_OK
&& is_equal
)
910 return part_set
->parts
[i
];
916 static HRESULT WINAPI
opc_part_set_QueryInterface(IOpcPartSet
*iface
, REFIID iid
, void **out
)
918 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
920 if (IsEqualIID(iid
, &IID_IOpcPartSet
) ||
921 IsEqualIID(iid
, &IID_IUnknown
))
924 IOpcPartSet_AddRef(iface
);
928 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
929 return E_NOINTERFACE
;
932 static ULONG WINAPI
opc_part_set_AddRef(IOpcPartSet
*iface
)
934 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
935 ULONG refcount
= InterlockedIncrement(&part_set
->refcount
);
937 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
942 static ULONG WINAPI
opc_part_set_Release(IOpcPartSet
*iface
)
944 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
945 ULONG refcount
= InterlockedDecrement(&part_set
->refcount
);
947 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
953 for (i
= 0; i
< part_set
->count
; ++i
)
954 IOpcPart_Release(&part_set
->parts
[i
]->IOpcPart_iface
);
955 heap_free(part_set
->parts
);
962 static HRESULT WINAPI
opc_part_set_GetPart(IOpcPartSet
*iface
, IOpcPartUri
*name
, IOpcPart
**out
)
964 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
965 struct opc_part
*part
;
967 TRACE("iface %p, name %p, out %p.\n", iface
, name
, out
);
977 if ((part
= opc_part_set_get_part(part_set
, name
)))
979 *out
= &part
->IOpcPart_iface
;
980 IOpcPart_AddRef(*out
);
983 return *out
? S_OK
: OPC_E_NO_SUCH_PART
;
986 static HRESULT WINAPI
opc_part_set_CreatePart(IOpcPartSet
*iface
, IOpcPartUri
*name
, LPCWSTR content_type
,
987 OPC_COMPRESSION_OPTIONS compression_options
, IOpcPart
**part
)
989 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
991 TRACE("iface %p, name %p, content_type %s, compression_options %#x, part %p.\n", iface
, name
,
992 debugstr_w(content_type
), compression_options
, part
);
1002 if (opc_part_set_get_part(part_set
, name
))
1003 return OPC_E_DUPLICATE_PART
;
1005 return opc_part_create(part_set
, name
, content_type
, compression_options
, part
);
1008 static HRESULT WINAPI
opc_part_set_DeletePart(IOpcPartSet
*iface
, IOpcPartUri
*name
)
1010 FIXME("iface %p, name %p stub!\n", iface
, name
);
1015 static HRESULT WINAPI
opc_part_set_PartExists(IOpcPartSet
*iface
, IOpcPartUri
*name
, BOOL
*exists
)
1017 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
1019 TRACE("iface %p, name %p, exists %p.\n", iface
, name
, exists
);
1021 if (!name
|| !exists
)
1024 *exists
= opc_part_set_get_part(part_set
, name
) != NULL
;
1029 static HRESULT WINAPI
opc_part_set_GetEnumerator(IOpcPartSet
*iface
, IOpcPartEnumerator
**enumerator
)
1031 struct opc_part_set
*part_set
= impl_from_IOpcPartSet(iface
);
1033 TRACE("iface %p, enumerator %p.\n", iface
, enumerator
);
1038 return opc_part_enum_create(part_set
, enumerator
);
1041 static const IOpcPartSetVtbl opc_part_set_vtbl
=
1043 opc_part_set_QueryInterface
,
1044 opc_part_set_AddRef
,
1045 opc_part_set_Release
,
1046 opc_part_set_GetPart
,
1047 opc_part_set_CreatePart
,
1048 opc_part_set_DeletePart
,
1049 opc_part_set_PartExists
,
1050 opc_part_set_GetEnumerator
,
1053 static HRESULT WINAPI
opc_relationship_QueryInterface(IOpcRelationship
*iface
, REFIID iid
, void **out
)
1055 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1057 if (IsEqualIID(iid
, &IID_IOpcRelationship
) ||
1058 IsEqualIID(iid
, &IID_IUnknown
))
1061 IOpcRelationship_AddRef(iface
);
1065 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
1066 return E_NOINTERFACE
;
1069 static ULONG WINAPI
opc_relationship_AddRef(IOpcRelationship
*iface
)
1071 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1072 ULONG refcount
= InterlockedIncrement(&relationship
->refcount
);
1074 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
1079 static ULONG WINAPI
opc_relationship_Release(IOpcRelationship
*iface
)
1081 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1082 ULONG refcount
= InterlockedDecrement(&relationship
->refcount
);
1084 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
1088 CoTaskMemFree(relationship
->id
);
1089 CoTaskMemFree(relationship
->type
);
1090 IOpcUri_Release(relationship
->source_uri
);
1091 IUri_Release(relationship
->target
);
1092 heap_free(relationship
);
1098 static HRESULT WINAPI
opc_relationship_GetId(IOpcRelationship
*iface
, WCHAR
**id
)
1100 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1102 TRACE("iface %p, id %p.\n", iface
, id
);
1104 *id
= opc_strdupW(relationship
->id
);
1105 return *id
? S_OK
: E_OUTOFMEMORY
;
1108 static HRESULT WINAPI
opc_relationship_GetRelationshipType(IOpcRelationship
*iface
, WCHAR
**type
)
1110 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1112 TRACE("iface %p, type %p.\n", iface
, type
);
1114 *type
= opc_strdupW(relationship
->type
);
1115 return *type
? S_OK
: E_OUTOFMEMORY
;
1118 static HRESULT WINAPI
opc_relationship_GetSourceUri(IOpcRelationship
*iface
, IOpcUri
**uri
)
1120 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1122 TRACE("iface %p, uri %p.\n", iface
, uri
);
1124 *uri
= relationship
->source_uri
;
1125 IOpcUri_AddRef(*uri
);
1130 static HRESULT WINAPI
opc_relationship_GetTargetUri(IOpcRelationship
*iface
, IUri
**target
)
1132 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1134 TRACE("iface %p, target %p.\n", iface
, target
);
1136 *target
= relationship
->target
;
1137 IUri_AddRef(*target
);
1142 static HRESULT WINAPI
opc_relationship_GetTargetMode(IOpcRelationship
*iface
, OPC_URI_TARGET_MODE
*target_mode
)
1144 struct opc_relationship
*relationship
= impl_from_IOpcRelationship(iface
);
1146 TRACE("iface %p, target_mode %p.\n", iface
, target_mode
);
1148 *target_mode
= relationship
->target_mode
;
1153 static const IOpcRelationshipVtbl opc_relationship_vtbl
=
1155 opc_relationship_QueryInterface
,
1156 opc_relationship_AddRef
,
1157 opc_relationship_Release
,
1158 opc_relationship_GetId
,
1159 opc_relationship_GetRelationshipType
,
1160 opc_relationship_GetSourceUri
,
1161 opc_relationship_GetTargetUri
,
1162 opc_relationship_GetTargetMode
,
1165 static struct opc_relationship
*opc_relationshipset_get_rel(struct opc_relationship_set
*relationship_set
,
1170 for (i
= 0; i
< relationship_set
->count
; i
++)
1172 if (!strcmpW(id
, relationship_set
->relationships
[i
]->id
))
1173 return relationship_set
->relationships
[i
];
1179 static HRESULT
opc_relationship_create(struct opc_relationship_set
*set
, const WCHAR
*id
, const WCHAR
*type
,
1180 IUri
*target_uri
, OPC_URI_TARGET_MODE target_mode
, IOpcRelationship
**out
)
1182 struct opc_relationship
*relationship
;
1184 if (!opc_array_reserve((void **)&set
->relationships
, &set
->size
, set
->count
+ 1, sizeof(*set
->relationships
)))
1185 return E_OUTOFMEMORY
;
1187 if (!(relationship
= heap_alloc_zero(sizeof(*relationship
))))
1188 return E_OUTOFMEMORY
;
1190 relationship
->IOpcRelationship_iface
.lpVtbl
= &opc_relationship_vtbl
;
1191 relationship
->refcount
= 1;
1193 relationship
->target
= target_uri
;
1194 IUri_AddRef(relationship
->target
);
1195 relationship
->source_uri
= set
->source_uri
;
1196 IOpcUri_AddRef(relationship
->source_uri
);
1199 relationship
->id
= opc_strdupW(id
);
1202 relationship
->id
= CoTaskMemAlloc(10 * sizeof(WCHAR
));
1203 if (relationship
->id
)
1205 static const WCHAR fmtW
[] = {'R','%','0','8','X',0};
1208 /* FIXME: test that generated id is unique */
1209 RtlGenRandom(&generated
, sizeof(generated
));
1210 sprintfW(relationship
->id
, fmtW
, generated
);
1212 if (opc_relationshipset_get_rel(set
, relationship
->id
))
1214 WARN("Newly generated id %s already exists.\n", debugstr_w(relationship
->id
));
1215 IOpcRelationship_Release(&relationship
->IOpcRelationship_iface
);
1221 relationship
->type
= opc_strdupW(type
);
1222 if (!relationship
->id
|| !relationship
->type
)
1224 IOpcRelationship_Release(&relationship
->IOpcRelationship_iface
);
1225 return E_OUTOFMEMORY
;
1228 set
->relationships
[set
->count
++] = relationship
;
1229 IOpcRelationship_AddRef(&relationship
->IOpcRelationship_iface
);
1230 CoCreateGuid(&set
->id
);
1232 *out
= &relationship
->IOpcRelationship_iface
;
1233 TRACE("Created relationship %p.\n", *out
);
1237 static HRESULT WINAPI
opc_relationship_set_QueryInterface(IOpcRelationshipSet
*iface
, REFIID iid
, void **out
)
1239 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1241 if (IsEqualIID(iid
, &IID_IOpcRelationshipSet
) ||
1242 IsEqualIID(iid
, &IID_IUnknown
))
1245 IOpcRelationshipSet_AddRef(iface
);
1249 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
1250 return E_NOINTERFACE
;
1253 static ULONG WINAPI
opc_relationship_set_AddRef(IOpcRelationshipSet
*iface
)
1255 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1256 ULONG refcount
= InterlockedIncrement(&relationship_set
->refcount
);
1258 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
1263 static ULONG WINAPI
opc_relationship_set_Release(IOpcRelationshipSet
*iface
)
1265 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1266 ULONG refcount
= InterlockedDecrement(&relationship_set
->refcount
);
1268 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
1274 for (i
= 0; i
< relationship_set
->count
; ++i
)
1275 IOpcRelationship_Release(&relationship_set
->relationships
[i
]->IOpcRelationship_iface
);
1276 IOpcUri_Release(relationship_set
->source_uri
);
1277 heap_free(relationship_set
->relationships
);
1278 heap_free(relationship_set
);
1284 static HRESULT WINAPI
opc_relationship_set_GetRelationship(IOpcRelationshipSet
*iface
, const WCHAR
*id
,
1285 IOpcRelationship
**relationship
)
1287 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1288 struct opc_relationship
*ret
;
1290 TRACE("iface %p, id %s, relationship %p.\n", iface
, debugstr_w(id
), relationship
);
1295 *relationship
= NULL
;
1300 if ((ret
= opc_relationshipset_get_rel(relationship_set
, id
)))
1302 *relationship
= &ret
->IOpcRelationship_iface
;
1303 IOpcRelationship_AddRef(*relationship
);
1306 return *relationship
? S_OK
: OPC_E_NO_SUCH_RELATIONSHIP
;
1309 static HRESULT WINAPI
opc_relationship_set_CreateRelationship(IOpcRelationshipSet
*iface
, const WCHAR
*id
,
1310 const WCHAR
*type
, IUri
*target_uri
, OPC_URI_TARGET_MODE target_mode
, IOpcRelationship
**relationship
)
1312 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1315 TRACE("iface %p, id %s, type %s, target_uri %p, target_mode %d, relationship %p.\n", iface
, debugstr_w(id
),
1316 debugstr_w(type
), target_uri
, target_mode
, relationship
);
1321 *relationship
= NULL
;
1323 if (!type
|| !target_uri
)
1326 if (id
&& opc_relationshipset_get_rel(relationship_set
, id
))
1327 return OPC_E_DUPLICATE_RELATIONSHIP
;
1329 if (IUri_GetPropertyLength(target_uri
, Uri_PROPERTY_SCHEME_NAME
, &length
, 0) == S_OK
&& length
!= 0
1330 && target_mode
== OPC_URI_TARGET_MODE_INTERNAL
)
1331 return OPC_E_INVALID_RELATIONSHIP_TARGET
;
1333 return opc_relationship_create(relationship_set
, id
, type
, target_uri
, target_mode
, relationship
);
1336 static HRESULT WINAPI
opc_relationship_set_DeleteRelationship(IOpcRelationshipSet
*iface
, const WCHAR
*id
)
1338 FIXME("iface %p, id %s stub!\n", iface
, debugstr_w(id
));
1343 static HRESULT WINAPI
opc_relationship_set_RelationshipExists(IOpcRelationshipSet
*iface
, const WCHAR
*id
, BOOL
*exists
)
1345 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1347 TRACE("iface %p, id %s, exists %p.\n", iface
, debugstr_w(id
), exists
);
1352 *exists
= opc_relationshipset_get_rel(relationship_set
, id
) != NULL
;
1357 static HRESULT WINAPI
opc_relationship_set_GetEnumerator(IOpcRelationshipSet
*iface
,
1358 IOpcRelationshipEnumerator
**enumerator
)
1360 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1362 TRACE("iface %p, enumerator %p.\n", iface
, enumerator
);
1367 return opc_rel_enum_create(relationship_set
, enumerator
);
1370 static HRESULT WINAPI
opc_relationship_set_GetEnumeratorForType(IOpcRelationshipSet
*iface
, const WCHAR
*type
,
1371 IOpcRelationshipEnumerator
**enumerator
)
1373 FIXME("iface %p, type %s, enumerator %p stub!\n", iface
, debugstr_w(type
), enumerator
);
1378 static HRESULT WINAPI
opc_relationship_set_GetRelationshipsContentStream(IOpcRelationshipSet
*iface
, IStream
**stream
)
1380 FIXME("iface %p, stream %p stub!\n", iface
, stream
);
1385 static const IOpcRelationshipSetVtbl opc_relationship_set_vtbl
=
1387 opc_relationship_set_QueryInterface
,
1388 opc_relationship_set_AddRef
,
1389 opc_relationship_set_Release
,
1390 opc_relationship_set_GetRelationship
,
1391 opc_relationship_set_CreateRelationship
,
1392 opc_relationship_set_DeleteRelationship
,
1393 opc_relationship_set_RelationshipExists
,
1394 opc_relationship_set_GetEnumerator
,
1395 opc_relationship_set_GetEnumeratorForType
,
1396 opc_relationship_set_GetRelationshipsContentStream
,
1399 static HRESULT
opc_relationship_set_create(IOpcUri
*source_uri
, IOpcRelationshipSet
**out
)
1401 struct opc_relationship_set
*relationship_set
;
1403 if (!(relationship_set
= heap_alloc_zero(sizeof(*relationship_set
))))
1404 return E_OUTOFMEMORY
;
1406 relationship_set
->IOpcRelationshipSet_iface
.lpVtbl
= &opc_relationship_set_vtbl
;
1407 relationship_set
->refcount
= 1;
1408 relationship_set
->source_uri
= source_uri
;
1409 IOpcUri_AddRef(relationship_set
->source_uri
);
1411 *out
= &relationship_set
->IOpcRelationshipSet_iface
;
1412 TRACE("Created relationship set %p.\n", *out
);
1416 static HRESULT WINAPI
opc_package_QueryInterface(IOpcPackage
*iface
, REFIID iid
, void **out
)
1418 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1420 if (IsEqualIID(iid
, &IID_IOpcPackage
) ||
1421 IsEqualIID(iid
, &IID_IUnknown
))
1424 IOpcPackage_AddRef(iface
);
1428 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
1429 return E_NOINTERFACE
;
1432 static ULONG WINAPI
opc_package_AddRef(IOpcPackage
*iface
)
1434 struct opc_package
*package
= impl_from_IOpcPackage(iface
);
1435 ULONG refcount
= InterlockedIncrement(&package
->refcount
);
1437 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
1442 static ULONG WINAPI
opc_package_Release(IOpcPackage
*iface
)
1444 struct opc_package
*package
= impl_from_IOpcPackage(iface
);
1445 ULONG refcount
= InterlockedDecrement(&package
->refcount
);
1447 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
1451 if (package
->part_set
)
1452 IOpcPartSet_Release(package
->part_set
);
1453 if (package
->relationship_set
)
1454 IOpcRelationshipSet_Release(package
->relationship_set
);
1455 if (package
->source_uri
)
1456 IOpcUri_Release(package
->source_uri
);
1463 static HRESULT WINAPI
opc_package_GetPartSet(IOpcPackage
*iface
, IOpcPartSet
**part_set
)
1465 struct opc_package
*package
= impl_from_IOpcPackage(iface
);
1467 TRACE("iface %p, part_set %p.\n", iface
, part_set
);
1469 if (!package
->part_set
)
1471 struct opc_part_set
*part_set
= heap_alloc_zero(sizeof(*part_set
));
1473 return E_OUTOFMEMORY
;
1475 part_set
->IOpcPartSet_iface
.lpVtbl
= &opc_part_set_vtbl
;
1476 part_set
->refcount
= 1;
1478 package
->part_set
= &part_set
->IOpcPartSet_iface
;
1481 *part_set
= package
->part_set
;
1482 IOpcPartSet_AddRef(*part_set
);
1487 static HRESULT WINAPI
opc_package_GetRelationshipSet(IOpcPackage
*iface
, IOpcRelationshipSet
**relationship_set
)
1489 struct opc_package
*package
= impl_from_IOpcPackage(iface
);
1492 TRACE("iface %p, relationship_set %p.\n", iface
, relationship_set
);
1494 if (!package
->relationship_set
)
1496 if (FAILED(hr
= opc_relationship_set_create(package
->source_uri
, &package
->relationship_set
)))
1500 *relationship_set
= package
->relationship_set
;
1501 IOpcRelationshipSet_AddRef(*relationship_set
);
1506 static const IOpcPackageVtbl opc_package_vtbl
=
1508 opc_package_QueryInterface
,
1510 opc_package_Release
,
1511 opc_package_GetPartSet
,
1512 opc_package_GetRelationshipSet
,
1515 HRESULT
opc_package_create(IOpcFactory
*factory
, IOpcPackage
**out
)
1517 struct opc_package
*package
;
1520 if (!(package
= heap_alloc_zero(sizeof(*package
))))
1521 return E_OUTOFMEMORY
;
1523 package
->IOpcPackage_iface
.lpVtbl
= &opc_package_vtbl
;
1524 package
->refcount
= 1;
1526 if (FAILED(hr
= IOpcFactory_CreatePackageRootUri(factory
, &package
->source_uri
)))
1532 *out
= &package
->IOpcPackage_iface
;
1533 TRACE("Created package %p.\n", *out
);
1537 struct content_types
1543 enum content_type_element
1545 CONTENT_TYPE_DEFAULT
,
1546 CONTENT_TYPE_OVERRIDE
,
1552 enum content_type_element element
;
1560 struct override_type
1567 static HRESULT
opc_package_add_override_content_type(struct content_types
*types
, IOpcPart
*part
)
1569 struct content_type
*type
;
1571 if (!(type
= heap_alloc(sizeof(*type
))))
1572 return E_OUTOFMEMORY
;
1574 type
->element
= CONTENT_TYPE_OVERRIDE
;
1575 type
->u
.override
.part
= part
;
1576 IOpcPart_AddRef(part
);
1578 list_add_tail(&types
->types
, &type
->entry
);
1583 static HRESULT
opc_package_add_default_content_type(struct content_types
*types
,
1584 const WCHAR
*ext
, const WCHAR
*content_type
)
1586 struct content_type
*type
;
1588 if (!(type
= heap_alloc(sizeof(*type
))))
1589 return E_OUTOFMEMORY
;
1591 type
->element
= CONTENT_TYPE_DEFAULT
;
1592 type
->u
.def
.ext
= opc_strdupW(ext
);
1593 type
->u
.def
.type
= opc_strdupW(content_type
);
1594 if (!type
->u
.def
.ext
|| !type
->u
.def
.type
)
1596 CoTaskMemFree(type
->u
.def
.ext
);
1597 CoTaskMemFree(type
->u
.def
.type
);
1599 return E_OUTOFMEMORY
;
1602 list_add_tail(&types
->types
, &type
->entry
);
1607 static HRESULT
opc_package_add_content_type(struct content_types
*types
, IOpcPart
*part
)
1609 struct content_type
*cur
;
1610 BSTR ext
, content_type
;
1615 if (FAILED(hr
= IOpcPart_GetName(part
, &name
)))
1618 hr
= IOpcPartUri_GetExtension(name
, &ext
);
1619 IOpcPartUri_Release(name
);
1622 hr
= opc_package_add_override_content_type(types
, part
);
1630 if (FAILED(hr
= IOpcPart_GetContentType(part
, &content_type
)))
1633 LIST_FOR_EACH_ENTRY(cur
, &types
->types
, struct content_type
, entry
)
1635 if (cur
->element
== CONTENT_TYPE_OVERRIDE
)
1638 if (!strcmpiW(cur
->u
.def
.ext
, ext
))
1642 if (!strcmpW(cur
->u
.def
.type
, content_type
))
1645 hr
= opc_package_add_override_content_type(types
, part
);
1651 hr
= opc_package_add_default_content_type(types
, ext
, content_type
);
1654 SysFreeString(content_type
);
1659 static BOOL
opc_package_has_rels_part(IOpcRelationshipSet
*rel_set
)
1661 IOpcRelationshipEnumerator
*enumerator
;
1665 if (FAILED(hr
= IOpcRelationshipSet_GetEnumerator(rel_set
, &enumerator
)))
1669 IOpcRelationshipEnumerator_MoveNext(enumerator
, &has_next
);
1670 IOpcRelationshipEnumerator_Release(enumerator
);
1675 static HRESULT
opc_package_collect_content_types(IOpcPackage
*package
, struct content_types
*types
)
1677 IOpcPartEnumerator
*enumerator
;
1678 IOpcRelationshipSet
*rel_set
;
1683 if (FAILED(hr
= IOpcPackage_GetPartSet(package
, &parts
)))
1686 hr
= IOpcPackage_GetRelationshipSet(package
, &rel_set
);
1689 types
->has_rels_part
|= opc_package_has_rels_part(rel_set
);
1690 IOpcRelationshipSet_Release(rel_set
);
1693 hr
= IOpcPartSet_GetEnumerator(parts
, &enumerator
);
1694 IOpcPartSet_Release(parts
);
1698 if (FAILED(hr
= IOpcPartEnumerator_MoveNext(enumerator
, &has_next
)) || !has_next
)
1700 IOpcPartEnumerator_Release(enumerator
);
1708 if (FAILED(hr
= IOpcPartEnumerator_GetCurrent(enumerator
, &part
)))
1711 if (!types
->has_rels_part
)
1713 hr
= IOpcPart_GetRelationshipSet(part
, &rel_set
);
1716 types
->has_rels_part
|= opc_package_has_rels_part(rel_set
);
1717 IOpcRelationshipSet_Release(rel_set
);
1721 hr
= opc_package_add_content_type(types
, part
);
1722 IOpcPart_Release(part
);
1726 if (FAILED(hr
= IOpcPartEnumerator_MoveNext(enumerator
, &has_next
)))
1730 IOpcPartEnumerator_Release(enumerator
);
1735 static HRESULT
opc_package_write_default_type(const WCHAR
*ext
, const WCHAR
*type
, IXmlWriter
*writer
)
1737 static const WCHAR contenttypeW
[] = {'C','o','n','t','e','n','t','T','y','p','e',0};
1738 static const WCHAR extensionW
[] = {'E','x','t','e','n','s','i','o','n',0};
1739 static const WCHAR defaultW
[] = {'D','e','f','a','u','l','t',0};
1742 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, defaultW
, NULL
);
1744 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, extensionW
, NULL
, ext
);
1746 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, contenttypeW
, NULL
, type
);
1750 static HRESULT
opc_package_write_contenttypes(IOpcPackage
*package
, struct zip_archive
*archive
, IXmlWriter
*writer
)
1752 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','/',
1753 'p','a','c','k','a','g','e','/','2','0','0','6','/','c','o','n','t','e','n','t','-','t','y','p','e','s',0};
1754 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','-',
1755 'p','a','c','k','a','g','e','.','r','e','l','a','t','i','o','n','s','h','i','p','s','+','x','m','l',0};
1756 static const WCHAR contenttypesW
[] = {'[','C','o','n','t','e','n','t','_','T','y','p','e','s',']','.','x','m','l',0};
1757 static const WCHAR contenttypeW
[] = {'C','o','n','t','e','n','t','T','y','p','e',0};
1758 static const WCHAR overrideW
[] = {'O','v','e','r','r','i','d','e',0};
1759 static const WCHAR partnameW
[] = {'P','a','r','t','N','a','m','e',0};
1760 static const WCHAR typesW
[] = {'T','y','p','e','s',0};
1761 static const WCHAR relsW
[] = {'r','e','l','s',0};
1762 struct content_type
*content_type
, *content_type2
;
1763 struct content_types types
;
1764 IStream
*content
= NULL
;
1767 list_init(&types
.types
);
1768 types
.has_rels_part
= FALSE
;
1770 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &content
);
1772 hr
= opc_package_collect_content_types(package
, &types
);
1774 hr
= IXmlWriter_SetOutput(writer
, (IUnknown
*)content
);
1776 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Omit
);
1778 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, typesW
, uriW
);
1780 if (SUCCEEDED(hr
) && types
.has_rels_part
)
1782 hr
= opc_package_write_default_type(relsW
, relstypeW
, writer
);
1784 hr
= IXmlWriter_WriteEndElement(writer
);
1787 LIST_FOR_EACH_ENTRY_SAFE(content_type
, content_type2
, &types
.types
, struct content_type
, entry
)
1789 if (content_type
->element
== CONTENT_TYPE_DEFAULT
)
1791 hr
= opc_package_write_default_type(content_type
->u
.def
.ext
+ 1, content_type
->u
.def
.type
, writer
);
1793 CoTaskMemFree(content_type
->u
.def
.ext
);
1794 CoTaskMemFree(content_type
->u
.def
.type
);
1798 IOpcPartUri
*uri
= NULL
;
1803 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, overrideW
, NULL
);
1805 hr
= IOpcPart_GetName(content_type
->u
.override
.part
, &uri
);
1807 hr
= IOpcPartUri_GetRawUri(uri
, &name
);
1809 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, partnameW
, NULL
, name
);
1811 hr
= IOpcPart_GetContentType(content_type
->u
.override
.part
, &type
);
1813 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, contenttypeW
, NULL
, type
);
1816 IOpcPartUri_Release(uri
);
1817 SysFreeString(name
);
1818 CoTaskMemFree(type
);
1820 IOpcPart_Release(content_type
->u
.override
.part
);
1823 hr
= IXmlWriter_WriteEndElement(writer
);
1825 list_remove(&content_type
->entry
);
1826 heap_free(content_type
);
1830 hr
= IXmlWriter_WriteEndDocument(writer
);
1832 hr
= IXmlWriter_Flush(writer
);
1835 hr
= compress_add_file(archive
, contenttypesW
, content
, OPC_COMPRESSION_NORMAL
);
1838 IStream_Release(content
);
1843 static HRESULT
opc_package_write_rel(IOpcRelationship
*rel
, IXmlWriter
*writer
)
1845 static const WCHAR relationshipW
[] = {'R','e','l','a','t','i','o','n','s','h','i','p',0};
1846 static const WCHAR targetW
[] = {'T','a','r','g','e','t',0};
1847 static const WCHAR typeW
[] = {'T','y','p','e',0};
1848 static const WCHAR idW
[] = {'I','d',0};
1854 if (FAILED(hr
= IXmlWriter_WriteStartElement(writer
, NULL
, relationshipW
, NULL
)))
1857 if (FAILED(hr
= IOpcRelationship_GetTargetUri(rel
, &uri
)))
1860 IUri_GetRawUri(uri
, &target_uri
);
1863 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, targetW
, NULL
, target_uri
);
1864 SysFreeString(target_uri
);
1868 if (FAILED(hr
= IOpcRelationship_GetId(rel
, &str
)))
1871 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, idW
, NULL
, str
);
1876 if (FAILED(hr
= IOpcRelationship_GetRelationshipType(rel
, &str
)))
1879 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, typeW
, NULL
, str
);
1884 return IXmlWriter_WriteEndElement(writer
);
1887 static HRESULT
opc_package_write_rels(struct zip_archive
*archive
, IOpcRelationshipSet
*rels
,
1888 IOpcUri
*uri
, IXmlWriter
*writer
)
1890 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','/',
1891 '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};
1892 static const WCHAR relationshipsW
[] = {'R','e','l','a','t','i','o','n','s','h','i','p','s',0};
1893 IOpcRelationshipEnumerator
*enumerator
;
1894 IOpcPartUri
*rels_uri
;
1900 if (FAILED(hr
= IOpcRelationshipSet_GetEnumerator(rels
, &enumerator
)))
1903 hr
= IOpcRelationshipEnumerator_MoveNext(enumerator
, &has_next
);
1906 IOpcRelationshipEnumerator_Release(enumerator
);
1910 if (FAILED(hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &content
)))
1912 IOpcRelationshipEnumerator_Release(enumerator
);
1916 hr
= IXmlWriter_SetOutput(writer
, (IUnknown
*)content
);
1918 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
1920 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, relationshipsW
, uriW
);
1924 IOpcRelationship
*rel
;
1926 if (FAILED(hr
= IOpcRelationshipEnumerator_GetCurrent(enumerator
, &rel
)))
1929 hr
= opc_package_write_rel(rel
, writer
);
1930 IOpcRelationship_Release(rel
);
1934 IOpcRelationshipEnumerator_MoveNext(enumerator
, &has_next
);
1937 IOpcRelationshipEnumerator_Release(enumerator
);
1940 hr
= IXmlWriter_WriteEndDocument(writer
);
1942 hr
= IXmlWriter_Flush(writer
);
1945 hr
= IOpcUri_GetRelationshipsPartUri(uri
, &rels_uri
);
1947 hr
= IOpcPartUri_GetRawUri(rels_uri
, &rels_part_uri
);
1950 /* Relationship part names always start with root '/', skip it. */
1951 hr
= compress_add_file(archive
, rels_part_uri
+ 1, content
, OPC_COMPRESSION_NORMAL
);
1954 SysFreeString(rels_part_uri
);
1955 IStream_Release(content
);
1960 static HRESULT
opc_package_write_part(struct zip_archive
*archive
, IOpcPart
*part
, IXmlWriter
*writer
)
1962 OPC_COMPRESSION_OPTIONS options
= OPC_COMPRESSION_NORMAL
;
1963 IOpcRelationshipSet
*rels
= NULL
;
1964 IStream
*content
= NULL
;
1969 if (FAILED(hr
= IOpcPart_GetName(part
, &name
)))
1972 hr
= IOpcPartUri_GetRawUri(name
, &uri
);
1974 hr
= IOpcPart_GetCompressionOptions(part
, &options
);
1976 hr
= IOpcPart_GetContentStream(part
, &content
);
1979 /* Part names always start with root '/', skip it. */
1980 hr
= compress_add_file(archive
, uri
+ 1, content
, options
);
1983 hr
= IOpcPart_GetRelationshipSet(part
, &rels
);
1985 hr
= opc_package_write_rels(archive
, rels
, (IOpcUri
*)name
, writer
);
1987 IOpcPartUri_Release(name
);
1990 IStream_Release(content
);
1992 IOpcRelationshipSet_Release(rels
);
1997 static HRESULT
opc_package_write_parts(struct zip_archive
*archive
, IOpcPackage
*package
, IXmlWriter
*writer
)
1999 IOpcPartEnumerator
*parts
;
2000 IOpcPartSet
*part_set
;
2004 if (FAILED(hr
= IOpcPackage_GetPartSet(package
, &part_set
)))
2007 hr
= IOpcPartSet_GetEnumerator(part_set
, &parts
);
2008 IOpcPartSet_Release(part_set
);
2012 while (IOpcPartEnumerator_MoveNext(parts
, &got_next
) == S_OK
&& got_next
)
2016 if (FAILED(hr
= IOpcPartEnumerator_GetCurrent(parts
, &part
)))
2019 hr
= opc_package_write_part(archive
, part
, writer
);
2020 IOpcPart_Release(part
);
2025 IOpcPartEnumerator_Release(parts
);
2030 HRESULT
opc_package_write(IOpcPackage
*package
, OPC_WRITE_FLAGS flags
, IStream
*stream
)
2032 IOpcRelationshipSet
*rels
= NULL
;
2033 struct zip_archive
*archive
;
2034 IOpcUri
*uri
= NULL
;
2038 if (flags
!= OPC_WRITE_FORCE_ZIP32
)
2039 FIXME("Unsupported write flags %#x.\n", flags
);
2041 if (FAILED(hr
= CreateXmlWriter(&IID_IXmlWriter
, (void **)&writer
, NULL
)))
2044 if (FAILED(hr
= compress_create_archive(stream
, &archive
)))
2046 IXmlWriter_Release(writer
);
2050 /* [Content_Types].xml */
2051 hr
= opc_package_write_contenttypes(package
, archive
, writer
);
2052 /* Package relationships. */
2054 hr
= IOpcPackage_GetRelationshipSet(package
, &rels
);
2056 hr
= opc_root_uri_create(&uri
);
2058 hr
= opc_package_write_rels(archive
, rels
, uri
, writer
);
2061 hr
= opc_package_write_parts(archive
, package
, writer
);
2064 IOpcRelationshipSet_Release(rels
);
2066 IOpcUri_Release(uri
);
2068 compress_finalize_archive(archive
);
2069 IXmlWriter_Release(writer
);