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
);
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, refcount %lu.\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, refcount %lu.\n", iface
, refcount
);
216 IOpcPartSet_Release(&part_enum
->part_set
->IOpcPartSet_iface
);
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
= calloc(1, 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, refcount %lu.\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, refcount %lu.\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
= calloc(1, 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, refcount %lu.\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, refcount %lu.\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("%p, %p, %lu, %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("%p, %p, %lu, %p.\n", iface
, data
, size
, num_written
);
575 num_written
= &written
;
579 if (size
> stream
->content
->size
.QuadPart
- stream
->pos
.QuadPart
)
581 void *ptr
= 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("%p, %s, %ld, %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 %ld.\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 %#lx 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 %ld 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 %ld 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 %ld 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
= calloc(1, 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, refcount %lu.\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, refcount %lu.\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
= calloc(1, 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
= calloc(1, 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, refcount %lu.\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, refcount %lu.\n", iface
, refcount
);
952 for (i
= 0; i
< part_set
->count
; ++i
)
953 IOpcPart_Release(&part_set
->parts
[i
]->IOpcPart_iface
);
954 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, refcount %lu.\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, refcount %lu.\n", iface
, refcount
);
1087 CoTaskMemFree(relationship
->id
);
1088 CoTaskMemFree(relationship
->type
);
1089 IOpcUri_Release(relationship
->source_uri
);
1090 IUri_Release(relationship
->target
);
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
= calloc(1, 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
)
1206 /* FIXME: test that generated id is unique */
1207 RtlGenRandom(&generated
, sizeof(generated
));
1208 swprintf(relationship
->id
, 10, L
"R%08X", generated
);
1210 if (opc_relationshipset_get_rel(set
, relationship
->id
))
1212 WARN("Newly generated id %s already exists.\n", debugstr_w(relationship
->id
));
1213 IOpcRelationship_Release(&relationship
->IOpcRelationship_iface
);
1219 relationship
->type
= opc_strdupW(type
);
1220 if (!relationship
->id
|| !relationship
->type
)
1222 IOpcRelationship_Release(&relationship
->IOpcRelationship_iface
);
1223 return E_OUTOFMEMORY
;
1226 set
->relationships
[set
->count
++] = relationship
;
1227 IOpcRelationship_AddRef(&relationship
->IOpcRelationship_iface
);
1228 CoCreateGuid(&set
->id
);
1230 *out
= &relationship
->IOpcRelationship_iface
;
1231 TRACE("Created relationship %p.\n", *out
);
1235 static HRESULT WINAPI
opc_relationship_set_QueryInterface(IOpcRelationshipSet
*iface
, REFIID iid
, void **out
)
1237 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1239 if (IsEqualIID(iid
, &IID_IOpcRelationshipSet
) ||
1240 IsEqualIID(iid
, &IID_IUnknown
))
1243 IOpcRelationshipSet_AddRef(iface
);
1247 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
1248 return E_NOINTERFACE
;
1251 static ULONG WINAPI
opc_relationship_set_AddRef(IOpcRelationshipSet
*iface
)
1253 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1254 ULONG refcount
= InterlockedIncrement(&relationship_set
->refcount
);
1256 TRACE("%p, refcount %lu.\n", iface
, refcount
);
1261 static ULONG WINAPI
opc_relationship_set_Release(IOpcRelationshipSet
*iface
)
1263 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1264 ULONG refcount
= InterlockedDecrement(&relationship_set
->refcount
);
1266 TRACE("%p, refcount %lu.\n", iface
, refcount
);
1272 for (i
= 0; i
< relationship_set
->count
; ++i
)
1273 IOpcRelationship_Release(&relationship_set
->relationships
[i
]->IOpcRelationship_iface
);
1274 IOpcUri_Release(relationship_set
->source_uri
);
1275 free(relationship_set
->relationships
);
1276 free(relationship_set
);
1282 static HRESULT WINAPI
opc_relationship_set_GetRelationship(IOpcRelationshipSet
*iface
, const WCHAR
*id
,
1283 IOpcRelationship
**relationship
)
1285 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1286 struct opc_relationship
*ret
;
1288 TRACE("iface %p, id %s, relationship %p.\n", iface
, debugstr_w(id
), relationship
);
1293 *relationship
= NULL
;
1298 if ((ret
= opc_relationshipset_get_rel(relationship_set
, id
)))
1300 *relationship
= &ret
->IOpcRelationship_iface
;
1301 IOpcRelationship_AddRef(*relationship
);
1304 return *relationship
? S_OK
: OPC_E_NO_SUCH_RELATIONSHIP
;
1307 static HRESULT WINAPI
opc_relationship_set_CreateRelationship(IOpcRelationshipSet
*iface
, const WCHAR
*id
,
1308 const WCHAR
*type
, IUri
*target_uri
, OPC_URI_TARGET_MODE target_mode
, IOpcRelationship
**relationship
)
1310 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1313 TRACE("iface %p, id %s, type %s, target_uri %p, target_mode %d, relationship %p.\n", iface
, debugstr_w(id
),
1314 debugstr_w(type
), target_uri
, target_mode
, relationship
);
1319 *relationship
= NULL
;
1321 if (!type
|| !target_uri
)
1324 if (id
&& opc_relationshipset_get_rel(relationship_set
, id
))
1325 return OPC_E_DUPLICATE_RELATIONSHIP
;
1327 if (IUri_GetPropertyLength(target_uri
, Uri_PROPERTY_SCHEME_NAME
, &length
, 0) == S_OK
&& length
!= 0
1328 && target_mode
== OPC_URI_TARGET_MODE_INTERNAL
)
1329 return OPC_E_INVALID_RELATIONSHIP_TARGET
;
1331 return opc_relationship_create(relationship_set
, id
, type
, target_uri
, target_mode
, relationship
);
1334 static HRESULT WINAPI
opc_relationship_set_DeleteRelationship(IOpcRelationshipSet
*iface
, const WCHAR
*id
)
1336 FIXME("iface %p, id %s stub!\n", iface
, debugstr_w(id
));
1341 static HRESULT WINAPI
opc_relationship_set_RelationshipExists(IOpcRelationshipSet
*iface
, const WCHAR
*id
, BOOL
*exists
)
1343 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1345 TRACE("iface %p, id %s, exists %p.\n", iface
, debugstr_w(id
), exists
);
1350 *exists
= opc_relationshipset_get_rel(relationship_set
, id
) != NULL
;
1355 static HRESULT WINAPI
opc_relationship_set_GetEnumerator(IOpcRelationshipSet
*iface
,
1356 IOpcRelationshipEnumerator
**enumerator
)
1358 struct opc_relationship_set
*relationship_set
= impl_from_IOpcRelationshipSet(iface
);
1360 TRACE("iface %p, enumerator %p.\n", iface
, enumerator
);
1365 return opc_rel_enum_create(relationship_set
, enumerator
);
1368 static HRESULT WINAPI
opc_relationship_set_GetEnumeratorForType(IOpcRelationshipSet
*iface
, const WCHAR
*type
,
1369 IOpcRelationshipEnumerator
**enumerator
)
1371 FIXME("iface %p, type %s, enumerator %p stub!\n", iface
, debugstr_w(type
), enumerator
);
1376 static HRESULT WINAPI
opc_relationship_set_GetRelationshipsContentStream(IOpcRelationshipSet
*iface
, IStream
**stream
)
1378 FIXME("iface %p, stream %p stub!\n", iface
, stream
);
1383 static const IOpcRelationshipSetVtbl opc_relationship_set_vtbl
=
1385 opc_relationship_set_QueryInterface
,
1386 opc_relationship_set_AddRef
,
1387 opc_relationship_set_Release
,
1388 opc_relationship_set_GetRelationship
,
1389 opc_relationship_set_CreateRelationship
,
1390 opc_relationship_set_DeleteRelationship
,
1391 opc_relationship_set_RelationshipExists
,
1392 opc_relationship_set_GetEnumerator
,
1393 opc_relationship_set_GetEnumeratorForType
,
1394 opc_relationship_set_GetRelationshipsContentStream
,
1397 static HRESULT
opc_relationship_set_create(IOpcUri
*source_uri
, IOpcRelationshipSet
**out
)
1399 struct opc_relationship_set
*relationship_set
;
1401 if (!(relationship_set
= calloc(1, sizeof(*relationship_set
))))
1402 return E_OUTOFMEMORY
;
1404 relationship_set
->IOpcRelationshipSet_iface
.lpVtbl
= &opc_relationship_set_vtbl
;
1405 relationship_set
->refcount
= 1;
1406 relationship_set
->source_uri
= source_uri
;
1407 IOpcUri_AddRef(relationship_set
->source_uri
);
1409 *out
= &relationship_set
->IOpcRelationshipSet_iface
;
1410 TRACE("Created relationship set %p.\n", *out
);
1414 static HRESULT WINAPI
opc_package_QueryInterface(IOpcPackage
*iface
, REFIID iid
, void **out
)
1416 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1418 if (IsEqualIID(iid
, &IID_IOpcPackage
) ||
1419 IsEqualIID(iid
, &IID_IUnknown
))
1422 IOpcPackage_AddRef(iface
);
1426 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
1427 return E_NOINTERFACE
;
1430 static ULONG WINAPI
opc_package_AddRef(IOpcPackage
*iface
)
1432 struct opc_package
*package
= impl_from_IOpcPackage(iface
);
1433 ULONG refcount
= InterlockedIncrement(&package
->refcount
);
1435 TRACE("%p, refcount %lu.\n", iface
, refcount
);
1440 static ULONG WINAPI
opc_package_Release(IOpcPackage
*iface
)
1442 struct opc_package
*package
= impl_from_IOpcPackage(iface
);
1443 ULONG refcount
= InterlockedDecrement(&package
->refcount
);
1445 TRACE("%p, refcount %lu.\n", iface
, refcount
);
1449 if (package
->part_set
)
1450 IOpcPartSet_Release(package
->part_set
);
1451 if (package
->relationship_set
)
1452 IOpcRelationshipSet_Release(package
->relationship_set
);
1453 if (package
->source_uri
)
1454 IOpcUri_Release(package
->source_uri
);
1461 static HRESULT WINAPI
opc_package_GetPartSet(IOpcPackage
*iface
, IOpcPartSet
**part_set
)
1463 struct opc_package
*package
= impl_from_IOpcPackage(iface
);
1465 TRACE("iface %p, part_set %p.\n", iface
, part_set
);
1467 if (!package
->part_set
)
1469 struct opc_part_set
*part_set
= calloc(1, sizeof(*part_set
));
1471 return E_OUTOFMEMORY
;
1473 part_set
->IOpcPartSet_iface
.lpVtbl
= &opc_part_set_vtbl
;
1474 part_set
->refcount
= 1;
1476 package
->part_set
= &part_set
->IOpcPartSet_iface
;
1479 *part_set
= package
->part_set
;
1480 IOpcPartSet_AddRef(*part_set
);
1485 static HRESULT WINAPI
opc_package_GetRelationshipSet(IOpcPackage
*iface
, IOpcRelationshipSet
**relationship_set
)
1487 struct opc_package
*package
= impl_from_IOpcPackage(iface
);
1490 TRACE("iface %p, relationship_set %p.\n", iface
, relationship_set
);
1492 if (!package
->relationship_set
)
1494 if (FAILED(hr
= opc_relationship_set_create(package
->source_uri
, &package
->relationship_set
)))
1498 *relationship_set
= package
->relationship_set
;
1499 IOpcRelationshipSet_AddRef(*relationship_set
);
1504 static const IOpcPackageVtbl opc_package_vtbl
=
1506 opc_package_QueryInterface
,
1508 opc_package_Release
,
1509 opc_package_GetPartSet
,
1510 opc_package_GetRelationshipSet
,
1513 HRESULT
opc_package_create(IOpcFactory
*factory
, IOpcPackage
**out
)
1515 struct opc_package
*package
;
1518 if (!(package
= calloc(1, sizeof(*package
))))
1519 return E_OUTOFMEMORY
;
1521 package
->IOpcPackage_iface
.lpVtbl
= &opc_package_vtbl
;
1522 package
->refcount
= 1;
1524 if (FAILED(hr
= IOpcFactory_CreatePackageRootUri(factory
, &package
->source_uri
)))
1530 *out
= &package
->IOpcPackage_iface
;
1531 TRACE("Created package %p.\n", *out
);
1535 struct content_types
1541 enum content_type_element
1543 CONTENT_TYPE_DEFAULT
,
1544 CONTENT_TYPE_OVERRIDE
,
1550 enum content_type_element element
;
1558 struct override_type
1565 static HRESULT
opc_package_add_override_content_type(struct content_types
*types
, IOpcPart
*part
)
1567 struct content_type
*type
;
1569 if (!(type
= malloc(sizeof(*type
))))
1570 return E_OUTOFMEMORY
;
1572 type
->element
= CONTENT_TYPE_OVERRIDE
;
1573 type
->u
.override
.part
= part
;
1574 IOpcPart_AddRef(part
);
1576 list_add_tail(&types
->types
, &type
->entry
);
1581 static HRESULT
opc_package_add_default_content_type(struct content_types
*types
,
1582 const WCHAR
*ext
, const WCHAR
*content_type
)
1584 struct content_type
*type
;
1586 if (!(type
= malloc(sizeof(*type
))))
1587 return E_OUTOFMEMORY
;
1589 type
->element
= CONTENT_TYPE_DEFAULT
;
1590 type
->u
.def
.ext
= opc_strdupW(ext
);
1591 type
->u
.def
.type
= opc_strdupW(content_type
);
1592 if (!type
->u
.def
.ext
|| !type
->u
.def
.type
)
1594 CoTaskMemFree(type
->u
.def
.ext
);
1595 CoTaskMemFree(type
->u
.def
.type
);
1597 return E_OUTOFMEMORY
;
1600 list_add_tail(&types
->types
, &type
->entry
);
1605 static HRESULT
opc_package_add_content_type(struct content_types
*types
, IOpcPart
*part
)
1607 struct content_type
*cur
;
1608 BSTR ext
, content_type
;
1613 if (FAILED(hr
= IOpcPart_GetName(part
, &name
)))
1616 hr
= IOpcPartUri_GetExtension(name
, &ext
);
1617 IOpcPartUri_Release(name
);
1620 hr
= opc_package_add_override_content_type(types
, part
);
1628 if (FAILED(hr
= IOpcPart_GetContentType(part
, &content_type
)))
1631 LIST_FOR_EACH_ENTRY(cur
, &types
->types
, struct content_type
, entry
)
1633 if (cur
->element
== CONTENT_TYPE_OVERRIDE
)
1636 if (!wcsicmp(cur
->u
.def
.ext
, ext
))
1640 if (!wcscmp(cur
->u
.def
.type
, content_type
))
1643 hr
= opc_package_add_override_content_type(types
, part
);
1649 hr
= opc_package_add_default_content_type(types
, ext
, content_type
);
1652 SysFreeString(content_type
);
1657 static BOOL
opc_package_has_rels_part(IOpcRelationshipSet
*rel_set
)
1659 IOpcRelationshipEnumerator
*enumerator
;
1663 if (FAILED(hr
= IOpcRelationshipSet_GetEnumerator(rel_set
, &enumerator
)))
1667 IOpcRelationshipEnumerator_MoveNext(enumerator
, &has_next
);
1668 IOpcRelationshipEnumerator_Release(enumerator
);
1673 static HRESULT
opc_package_collect_content_types(IOpcPackage
*package
, struct content_types
*types
)
1675 IOpcPartEnumerator
*enumerator
;
1676 IOpcRelationshipSet
*rel_set
;
1681 if (FAILED(hr
= IOpcPackage_GetPartSet(package
, &parts
)))
1684 hr
= IOpcPackage_GetRelationshipSet(package
, &rel_set
);
1687 types
->has_rels_part
|= opc_package_has_rels_part(rel_set
);
1688 IOpcRelationshipSet_Release(rel_set
);
1691 hr
= IOpcPartSet_GetEnumerator(parts
, &enumerator
);
1692 IOpcPartSet_Release(parts
);
1696 if (FAILED(hr
= IOpcPartEnumerator_MoveNext(enumerator
, &has_next
)) || !has_next
)
1698 IOpcPartEnumerator_Release(enumerator
);
1706 if (FAILED(hr
= IOpcPartEnumerator_GetCurrent(enumerator
, &part
)))
1709 if (!types
->has_rels_part
)
1711 hr
= IOpcPart_GetRelationshipSet(part
, &rel_set
);
1714 types
->has_rels_part
|= opc_package_has_rels_part(rel_set
);
1715 IOpcRelationshipSet_Release(rel_set
);
1719 hr
= opc_package_add_content_type(types
, part
);
1720 IOpcPart_Release(part
);
1724 if (FAILED(hr
= IOpcPartEnumerator_MoveNext(enumerator
, &has_next
)))
1728 IOpcPartEnumerator_Release(enumerator
);
1733 static HRESULT
opc_package_write_default_type(const WCHAR
*ext
, const WCHAR
*type
, IXmlWriter
*writer
)
1737 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, L
"Default", NULL
);
1739 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, L
"Extension", NULL
, ext
);
1741 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, L
"ContentType", NULL
, type
);
1745 static HRESULT
opc_package_write_contenttypes(IOpcPackage
*package
, struct zip_archive
*archive
, IXmlWriter
*writer
)
1747 struct content_type
*content_type
, *content_type2
;
1748 struct content_types types
;
1749 IStream
*content
= NULL
;
1752 list_init(&types
.types
);
1753 types
.has_rels_part
= FALSE
;
1755 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &content
);
1757 hr
= opc_package_collect_content_types(package
, &types
);
1759 hr
= IXmlWriter_SetOutput(writer
, (IUnknown
*)content
);
1761 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Omit
);
1763 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, L
"Types",
1764 L
"http://schemas.openxmlformats.org/package/2006/content-types");
1766 if (SUCCEEDED(hr
) && types
.has_rels_part
)
1768 hr
= opc_package_write_default_type(L
"rels",
1769 L
"application/vnd.openxmlformats-package.relationships+xml", writer
);
1771 hr
= IXmlWriter_WriteEndElement(writer
);
1774 LIST_FOR_EACH_ENTRY_SAFE(content_type
, content_type2
, &types
.types
, struct content_type
, entry
)
1776 if (content_type
->element
== CONTENT_TYPE_DEFAULT
)
1778 hr
= opc_package_write_default_type(content_type
->u
.def
.ext
+ 1, content_type
->u
.def
.type
, writer
);
1780 CoTaskMemFree(content_type
->u
.def
.ext
);
1781 CoTaskMemFree(content_type
->u
.def
.type
);
1785 IOpcPartUri
*uri
= NULL
;
1790 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, L
"Override", NULL
);
1792 hr
= IOpcPart_GetName(content_type
->u
.override
.part
, &uri
);
1794 hr
= IOpcPartUri_GetRawUri(uri
, &name
);
1796 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, L
"PartName", NULL
, name
);
1798 hr
= IOpcPart_GetContentType(content_type
->u
.override
.part
, &type
);
1800 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, L
"ContentType", NULL
, type
);
1803 IOpcPartUri_Release(uri
);
1804 SysFreeString(name
);
1805 CoTaskMemFree(type
);
1807 IOpcPart_Release(content_type
->u
.override
.part
);
1810 hr
= IXmlWriter_WriteEndElement(writer
);
1812 list_remove(&content_type
->entry
);
1817 hr
= IXmlWriter_WriteEndDocument(writer
);
1819 hr
= IXmlWriter_Flush(writer
);
1822 hr
= compress_add_file(archive
, L
"[Content_Types].xml", content
, OPC_COMPRESSION_NORMAL
);
1825 IStream_Release(content
);
1830 static HRESULT
opc_package_write_rel(IOpcRelationship
*rel
, IXmlWriter
*writer
)
1837 if (FAILED(hr
= IXmlWriter_WriteStartElement(writer
, NULL
, L
"Relationship", NULL
)))
1840 if (FAILED(hr
= IOpcRelationship_GetTargetUri(rel
, &uri
)))
1843 IUri_GetRawUri(uri
, &target_uri
);
1846 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, L
"Target", NULL
, target_uri
);
1847 SysFreeString(target_uri
);
1851 if (FAILED(hr
= IOpcRelationship_GetId(rel
, &str
)))
1854 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, L
"Id", NULL
, str
);
1859 if (FAILED(hr
= IOpcRelationship_GetRelationshipType(rel
, &str
)))
1862 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, L
"Type", NULL
, str
);
1867 return IXmlWriter_WriteEndElement(writer
);
1870 static HRESULT
opc_package_write_rels(struct zip_archive
*archive
, IOpcRelationshipSet
*rels
,
1871 IOpcUri
*uri
, IXmlWriter
*writer
)
1873 IOpcRelationshipEnumerator
*enumerator
;
1874 BSTR rels_part_uri
= NULL
;
1875 IOpcPartUri
*rels_uri
;
1880 if (FAILED(hr
= IOpcRelationshipSet_GetEnumerator(rels
, &enumerator
)))
1883 hr
= IOpcRelationshipEnumerator_MoveNext(enumerator
, &has_next
);
1886 IOpcRelationshipEnumerator_Release(enumerator
);
1890 if (FAILED(hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &content
)))
1892 IOpcRelationshipEnumerator_Release(enumerator
);
1896 hr
= IXmlWriter_SetOutput(writer
, (IUnknown
*)content
);
1898 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
1900 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, L
"Relationships",
1901 L
"http://schemas.openxmlformats.org/package/2006/relationships");
1905 IOpcRelationship
*rel
;
1907 if (FAILED(hr
= IOpcRelationshipEnumerator_GetCurrent(enumerator
, &rel
)))
1910 hr
= opc_package_write_rel(rel
, writer
);
1911 IOpcRelationship_Release(rel
);
1915 IOpcRelationshipEnumerator_MoveNext(enumerator
, &has_next
);
1918 IOpcRelationshipEnumerator_Release(enumerator
);
1921 hr
= IXmlWriter_WriteEndDocument(writer
);
1923 hr
= IXmlWriter_Flush(writer
);
1926 hr
= IOpcUri_GetRelationshipsPartUri(uri
, &rels_uri
);
1928 hr
= IOpcPartUri_GetRawUri(rels_uri
, &rels_part_uri
);
1931 /* Relationship part names always start with root '/', skip it. */
1932 hr
= compress_add_file(archive
, rels_part_uri
+ 1, content
, OPC_COMPRESSION_NORMAL
);
1935 SysFreeString(rels_part_uri
);
1936 IStream_Release(content
);
1941 static HRESULT
opc_package_write_part(struct zip_archive
*archive
, IOpcPart
*part
, IXmlWriter
*writer
)
1943 OPC_COMPRESSION_OPTIONS options
= OPC_COMPRESSION_NORMAL
;
1944 IOpcRelationshipSet
*rels
= NULL
;
1945 IStream
*content
= NULL
;
1950 if (FAILED(hr
= IOpcPart_GetName(part
, &name
)))
1953 hr
= IOpcPartUri_GetRawUri(name
, &uri
);
1955 hr
= IOpcPart_GetCompressionOptions(part
, &options
);
1957 hr
= IOpcPart_GetContentStream(part
, &content
);
1960 /* Part names always start with root '/', skip it. */
1961 hr
= compress_add_file(archive
, uri
+ 1, content
, options
);
1964 hr
= IOpcPart_GetRelationshipSet(part
, &rels
);
1966 hr
= opc_package_write_rels(archive
, rels
, (IOpcUri
*)name
, writer
);
1968 IOpcPartUri_Release(name
);
1971 IStream_Release(content
);
1973 IOpcRelationshipSet_Release(rels
);
1978 static HRESULT
opc_package_write_parts(struct zip_archive
*archive
, IOpcPackage
*package
, IXmlWriter
*writer
)
1980 IOpcPartEnumerator
*parts
;
1981 IOpcPartSet
*part_set
;
1985 if (FAILED(hr
= IOpcPackage_GetPartSet(package
, &part_set
)))
1988 hr
= IOpcPartSet_GetEnumerator(part_set
, &parts
);
1989 IOpcPartSet_Release(part_set
);
1993 while (IOpcPartEnumerator_MoveNext(parts
, &got_next
) == S_OK
&& got_next
)
1997 if (FAILED(hr
= IOpcPartEnumerator_GetCurrent(parts
, &part
)))
2000 hr
= opc_package_write_part(archive
, part
, writer
);
2001 IOpcPart_Release(part
);
2006 IOpcPartEnumerator_Release(parts
);
2011 HRESULT
opc_package_write(IOpcPackage
*package
, OPC_WRITE_FLAGS flags
, IStream
*stream
)
2013 IOpcRelationshipSet
*rels
= NULL
;
2014 struct zip_archive
*archive
;
2015 IOpcUri
*uri
= NULL
;
2019 if (flags
!= OPC_WRITE_FORCE_ZIP32
)
2020 FIXME("Unsupported write flags %#x.\n", flags
);
2022 if (FAILED(hr
= CreateXmlWriter(&IID_IXmlWriter
, (void **)&writer
, NULL
)))
2025 if (FAILED(hr
= compress_create_archive(stream
, &archive
)))
2027 IXmlWriter_Release(writer
);
2031 /* [Content_Types].xml */
2032 hr
= opc_package_write_contenttypes(package
, archive
, writer
);
2033 /* Package relationships. */
2035 hr
= IOpcPackage_GetRelationshipSet(package
, &rels
);
2037 hr
= opc_root_uri_create(&uri
);
2039 hr
= opc_package_write_rels(archive
, rels
, uri
, writer
);
2042 hr
= opc_package_write_parts(archive
, package
, writer
);
2045 IOpcRelationshipSet_Release(rels
);
2047 IOpcUri_Release(uri
);
2049 compress_finalize_archive(archive
);
2050 IXmlWriter_Release(writer
);