jscript: Store the necessary function and variable info in the TypeInfo.
[wine.git] / dlls / opcservices / package.c
blob6ed7f6bcd7c78abf043eb8b599c43937f9d8d57e
1 /*
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
19 #define COBJMACROS
21 #include <stdarg.h>
22 #include "windef.h"
23 #include "winbase.h"
24 #include "ntsecapi.h"
25 #include "xmllite.h"
27 #include "wine/debug.h"
28 #include "wine/list.h"
30 #include "opc_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(msopc);
34 struct opc_content
36 LONG refcount;
37 BYTE *data;
38 ULARGE_INTEGER size;
41 struct opc_content_stream
43 IStream IStream_iface;
44 LONG refcount;
46 struct opc_content *content;
47 ULARGE_INTEGER pos;
50 struct opc_package
52 IOpcPackage IOpcPackage_iface;
53 LONG refcount;
55 IOpcPartSet *part_set;
56 IOpcRelationshipSet *relationship_set;
57 IOpcUri *source_uri;
60 struct opc_part_enum
62 IOpcPartEnumerator IOpcPartEnumerator_iface;
63 LONG refcount;
65 struct opc_part_set *part_set;
66 size_t pos;
67 GUID id;
70 struct opc_part
72 IOpcPart IOpcPart_iface;
73 LONG refcount;
75 IOpcPartUri *name;
76 WCHAR *content_type;
77 DWORD compression_options;
78 IOpcRelationshipSet *relationship_set;
79 struct opc_content *content;
82 struct opc_part_set
84 IOpcPartSet IOpcPartSet_iface;
85 LONG refcount;
87 struct opc_part **parts;
88 size_t size;
89 size_t count;
90 GUID id;
93 struct opc_rel_enum
95 IOpcRelationshipEnumerator IOpcRelationshipEnumerator_iface;
96 LONG refcount;
98 struct opc_relationship_set *rel_set;
99 size_t pos;
100 GUID id;
103 struct opc_relationship
105 IOpcRelationship IOpcRelationship_iface;
106 LONG refcount;
108 WCHAR *id;
109 WCHAR *type;
110 IUri *target;
111 OPC_URI_TARGET_MODE target_mode;
112 IOpcUri *source_uri;
115 struct opc_relationship_set
117 IOpcRelationshipSet IOpcRelationshipSet_iface;
118 LONG refcount;
120 struct opc_relationship **relationships;
121 size_t size;
122 size_t count;
123 IOpcUri *source_uri;
124 GUID id;
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);
171 if (!refcount)
173 heap_free(content->data);
174 heap_free(content);
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))
187 *out = iface;
188 IOpcPartEnumerator_AddRef(iface);
189 return S_OK;
192 *out = NULL;
193 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
194 return E_NOINTERFACE;
197 static ULONG WINAPI opc_part_enum_AddRef(IOpcPartEnumerator *iface)
199 struct opc_part_enum *part_enum = impl_from_IOpcPartEnumerator(iface);
200 ULONG refcount = InterlockedIncrement(&part_enum->refcount);
202 TRACE("%p increasing refcount to %u.\n", iface, refcount);
204 return refcount;
207 static ULONG WINAPI opc_part_enum_Release(IOpcPartEnumerator *iface)
209 struct opc_part_enum *part_enum = impl_from_IOpcPartEnumerator(iface);
210 ULONG refcount = InterlockedDecrement(&part_enum->refcount);
212 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
214 if (!refcount)
216 IOpcPartSet_Release(&part_enum->part_set->IOpcPartSet_iface);
217 heap_free(part_enum);
220 return refcount;
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);
234 if (!has_next)
235 return E_POINTER;
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))
241 part_enum->pos++;
243 *has_next = part_enum->pos < part_enum->part_set->count;
245 return S_OK;
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);
254 if (!has_previous)
255 return E_POINTER;
257 if (has_part_collection_changed(part_enum))
258 return OPC_E_ENUM_COLLECTION_CHANGED;
260 if (part_enum->pos != ~(size_t)0)
261 part_enum->pos--;
263 *has_previous = part_enum->pos != ~(size_t)0;
265 return S_OK;
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);
274 if (!part)
275 return E_POINTER;
277 *part = NULL;
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);
297 if (!out)
298 return E_POINTER;
300 if (has_part_collection_changed(part_enum))
302 *out = NULL;
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,
317 opc_part_enum_Clone,
320 static HRESULT opc_part_enum_create(struct opc_part_set *part_set, IOpcPartEnumerator **out)
322 struct opc_part_enum *part_enum;
324 if (!(part_enum = heap_alloc_zero(sizeof(*part_enum))))
325 return E_OUTOFMEMORY;
327 part_enum->IOpcPartEnumerator_iface.lpVtbl = &opc_part_enum_vtbl;
328 part_enum->refcount = 1;
329 part_enum->part_set = part_set;
330 IOpcPartSet_AddRef(&part_set->IOpcPartSet_iface);
331 part_enum->pos = ~(size_t)0;
332 part_enum->id = part_set->id;
334 *out = &part_enum->IOpcPartEnumerator_iface;
335 TRACE("Created part enumerator %p.\n", *out);
336 return S_OK;
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))
348 *out = iface;
349 IOpcRelationshipEnumerator_AddRef(iface);
350 return S_OK;
353 *out = NULL;
354 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
355 return E_NOINTERFACE;
358 static ULONG WINAPI opc_rel_enum_AddRef(IOpcRelationshipEnumerator *iface)
360 struct opc_rel_enum *rel_enum = impl_from_IOpcRelationshipEnumerator(iface);
361 ULONG refcount = InterlockedIncrement(&rel_enum->refcount);
363 TRACE("%p increasing refcount to %u.\n", iface, refcount);
365 return refcount;
368 static ULONG WINAPI opc_rel_enum_Release(IOpcRelationshipEnumerator *iface)
370 struct opc_rel_enum *rel_enum = impl_from_IOpcRelationshipEnumerator(iface);
371 ULONG refcount = InterlockedDecrement(&rel_enum->refcount);
373 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
375 if (!refcount)
377 IOpcRelationshipSet_Release(&rel_enum->rel_set->IOpcRelationshipSet_iface);
378 heap_free(rel_enum);
381 return refcount;
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);
395 if (!has_next)
396 return E_POINTER;
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))
402 rel_enum->pos++;
404 *has_next = rel_enum->pos < rel_enum->rel_set->count;
406 return S_OK;
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);
415 if (!has_previous)
416 return E_POINTER;
418 if (has_rel_collection_changed(rel_enum))
419 return OPC_E_ENUM_COLLECTION_CHANGED;
421 if (rel_enum->pos != ~(size_t)0)
422 rel_enum->pos--;
424 *has_previous = rel_enum->pos != ~(size_t)0;
426 return S_OK;
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);
435 if (!rel)
436 return E_POINTER;
438 *rel = NULL;
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);
458 if (!out)
459 return E_POINTER;
461 if (has_rel_collection_changed(rel_enum))
463 *out = NULL;
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,
473 opc_rel_enum_AddRef,
474 opc_rel_enum_Release,
475 opc_rel_enum_MoveNext,
476 opc_rel_enum_MovePrevious,
477 opc_rel_enum_GetCurrent,
478 opc_rel_enum_Clone,
481 static HRESULT opc_rel_enum_create(struct opc_relationship_set *rel_set, IOpcRelationshipEnumerator **out)
483 struct opc_rel_enum *rel_enum;
485 if (!(rel_enum = heap_alloc_zero(sizeof(*rel_enum))))
486 return E_OUTOFMEMORY;
488 rel_enum->IOpcRelationshipEnumerator_iface.lpVtbl = &opc_rel_enum_vtbl;
489 rel_enum->refcount = 1;
490 rel_enum->rel_set = rel_set;
491 IOpcRelationshipSet_AddRef(&rel_set->IOpcRelationshipSet_iface);
492 rel_enum->pos = ~(size_t)0;
493 rel_enum->id = rel_set->id;
495 *out = &rel_enum->IOpcRelationshipEnumerator_iface;
496 TRACE("Created relationship enumerator %p.\n", *out);
497 return S_OK;
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))
508 *out = iface;
509 IStream_AddRef(iface);
510 return S_OK;
513 *out = NULL;
514 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
515 return E_NOINTERFACE;
518 static ULONG WINAPI opc_content_stream_AddRef(IStream *iface)
520 struct opc_content_stream *stream = impl_from_IStream(iface);
521 ULONG refcount = InterlockedIncrement(&stream->refcount);
523 TRACE("%p increasing refcount to %u.\n", iface, refcount);
525 return refcount;
528 static ULONG WINAPI opc_content_stream_Release(IStream *iface)
530 struct opc_content_stream *stream = impl_from_IStream(iface);
531 ULONG refcount = InterlockedDecrement(&stream->refcount);
533 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
535 if (!refcount)
537 opc_content_release(stream->content);
538 heap_free(stream);
541 return refcount;
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);
547 DWORD read = 0;
549 TRACE("iface %p, buff %p, size %u, num_read %p.\n", iface, buff, size, num_read);
551 if (!num_read)
552 num_read = &read;
554 if (stream->content->size.QuadPart - stream->pos.QuadPart < size)
555 *num_read = stream->content->size.QuadPart - stream->pos.QuadPart;
556 else
557 *num_read = size;
559 if (*num_read)
560 memcpy(buff, stream->content->data + stream->pos.QuadPart, *num_read);
562 stream->pos.QuadPart += *num_read;
564 return S_OK;
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);
570 DWORD written = 0;
572 TRACE("iface %p, data %p, size %u, num_written %p.\n", iface, data, size, num_written);
574 if (!num_written)
575 num_written = &written;
577 *num_written = 0;
579 if (size > stream->content->size.QuadPart - stream->pos.QuadPart)
581 void *ptr = heap_realloc(stream->content->data, stream->pos.QuadPart + size);
582 if (!ptr)
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;
590 *num_written = size;
592 return S_OK;
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);
598 ULARGE_INTEGER pos;
600 TRACE("iface %p, move %s, origin %d, newpos %p.\n", iface, wine_dbgstr_longlong(move.QuadPart), origin, newpos);
602 switch (origin)
604 case STREAM_SEEK_SET:
605 pos.QuadPart = move.QuadPart;
606 break;
607 case STREAM_SEEK_CUR:
608 pos.QuadPart = stream->pos.QuadPart + move.QuadPart;
609 break;
610 case STREAM_SEEK_END:
611 pos.QuadPart = stream->content->size.QuadPart + move.QuadPart;
612 break;
613 default:
614 WARN("Unknown origin mode %d.\n", origin);
615 return E_INVALIDARG;
618 stream->pos = pos;
620 if (newpos)
621 *newpos = stream->pos;
623 return S_OK;
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));
630 return E_NOTIMPL;
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);
639 return E_NOTIMPL;
642 static HRESULT WINAPI opc_content_stream_Commit(IStream *iface, DWORD flags)
644 FIXME("iface %p, flags %#x stub!\n", iface, flags);
646 return E_NOTIMPL;
649 static HRESULT WINAPI opc_content_stream_Revert(IStream *iface)
651 FIXME("iface %p stub!\n", iface);
653 return E_NOTIMPL;
656 static HRESULT WINAPI opc_content_stream_LockRegion(IStream *iface, ULARGE_INTEGER offset,
657 ULARGE_INTEGER size, DWORD lock_type)
659 FIXME("iface %p, offset %s, size %s, lock_type %d stub!\n", iface, wine_dbgstr_longlong(offset.QuadPart),
660 wine_dbgstr_longlong(size.QuadPart), lock_type);
662 return E_NOTIMPL;
665 static HRESULT WINAPI opc_content_stream_UnlockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER size,
666 DWORD lock_type)
668 FIXME("iface %p, offset %s, size %s, lock_type %d stub!\n", iface, wine_dbgstr_longlong(offset.QuadPart),
669 wine_dbgstr_longlong(size.QuadPart), lock_type);
671 return E_NOTIMPL;
674 static HRESULT WINAPI opc_content_stream_Stat(IStream *iface, STATSTG *statstg, DWORD flag)
676 FIXME("iface %p, statstg %p, flag %d stub!\n", iface, statstg, flag);
678 return E_NOTIMPL;
681 static HRESULT WINAPI opc_content_stream_Clone(IStream *iface, IStream **result)
683 FIXME("iface %p, result %p stub!\n", iface, result);
685 return E_NOTIMPL;
688 static const IStreamVtbl opc_content_stream_vtbl =
690 opc_content_stream_QueryInterface,
691 opc_content_stream_AddRef,
692 opc_content_stream_Release,
693 opc_content_stream_Read,
694 opc_content_stream_Write,
695 opc_content_stream_Seek,
696 opc_content_stream_SetSize,
697 opc_content_stream_CopyTo,
698 opc_content_stream_Commit,
699 opc_content_stream_Revert,
700 opc_content_stream_LockRegion,
701 opc_content_stream_UnlockRegion,
702 opc_content_stream_Stat,
703 opc_content_stream_Clone,
706 static HRESULT opc_content_stream_create(struct opc_content *content, IStream **out)
708 struct opc_content_stream *stream;
710 if (!(stream = heap_alloc_zero(sizeof(*stream))))
711 return E_OUTOFMEMORY;
713 stream->IStream_iface.lpVtbl = &opc_content_stream_vtbl;
714 stream->refcount = 1;
715 stream->content = content;
716 InterlockedIncrement(&content->refcount);
718 *out = &stream->IStream_iface;
720 TRACE("Created content stream %p.\n", *out);
721 return S_OK;
724 static HRESULT opc_relationship_set_create(IOpcUri *source_uri, IOpcRelationshipSet **relationship_set);
726 static WCHAR *opc_strdupW(const WCHAR *str)
728 WCHAR *ret = NULL;
730 if (str)
732 size_t size;
734 size = (lstrlenW(str) + 1) * sizeof(WCHAR);
735 ret = CoTaskMemAlloc(size);
736 if (ret)
737 memcpy(ret, str, size);
740 return ret;
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))
750 *out = iface;
751 IOpcPart_AddRef(iface);
752 return S_OK;
755 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
756 return E_NOINTERFACE;
759 static ULONG WINAPI opc_part_AddRef(IOpcPart *iface)
761 struct opc_part *part = impl_from_IOpcPart(iface);
762 ULONG refcount = InterlockedIncrement(&part->refcount);
764 TRACE("%p increasing refcount to %u.\n", iface, refcount);
766 return refcount;
769 static ULONG WINAPI opc_part_Release(IOpcPart *iface)
771 struct opc_part *part = impl_from_IOpcPart(iface);
772 ULONG refcount = InterlockedDecrement(&part->refcount);
774 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
776 if (!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);
783 heap_free(part);
786 return refcount;
789 static HRESULT WINAPI opc_part_GetRelationshipSet(IOpcPart *iface, IOpcRelationshipSet **relationship_set)
791 struct opc_part *part = impl_from_IOpcPart(iface);
792 HRESULT hr;
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)))
797 return hr;
799 *relationship_set = part->relationship_set;
800 IOpcRelationshipSet_AddRef(*relationship_set);
802 return S_OK;
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);
811 if (!stream)
812 return E_POINTER;
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);
823 *name = part->name;
824 IOpcPartUri_AddRef(*name);
826 return S_OK;
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;
846 return S_OK;
849 static const IOpcPartVtbl opc_part_vtbl =
851 opc_part_QueryInterface,
852 opc_part_AddRef,
853 opc_part_Release,
854 opc_part_GetRelationshipSet,
855 opc_part_GetContentStream,
856 opc_part_GetName,
857 opc_part_GetContentType,
858 opc_part_GetCompressionOptions,
861 static HRESULT opc_part_create(struct opc_part_set *set, IOpcPartUri *name, const WCHAR *content_type,
862 DWORD compression_options, IOpcPart **out)
864 struct opc_part *part;
866 if (!opc_array_reserve((void **)&set->parts, &set->size, set->count + 1, sizeof(*set->parts)))
867 return E_OUTOFMEMORY;
869 if (!(part = heap_alloc_zero(sizeof(*part))))
870 return E_OUTOFMEMORY;
872 part->IOpcPart_iface.lpVtbl = &opc_part_vtbl;
873 part->refcount = 1;
874 part->name = name;
875 IOpcPartUri_AddRef(name);
876 part->compression_options = compression_options;
877 if (!(part->content_type = opc_strdupW(content_type)))
879 IOpcPart_Release(&part->IOpcPart_iface);
880 return E_OUTOFMEMORY;
883 part->content = heap_alloc_zero(sizeof(*part->content));
884 if (!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);
897 return S_OK;
900 static struct opc_part *opc_part_set_get_part(const struct opc_part_set *part_set, IOpcPartUri *name)
902 BOOL is_equal;
903 size_t i;
905 for (i = 0; i < part_set->count; ++i)
907 is_equal = FALSE;
908 if (IOpcPartUri_IsEqual(part_set->parts[i]->name, (IUri *)name, &is_equal) == S_OK && is_equal)
909 return part_set->parts[i];
912 return NULL;
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))
922 *out = iface;
923 IOpcPartSet_AddRef(iface);
924 return S_OK;
927 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
928 return E_NOINTERFACE;
931 static ULONG WINAPI opc_part_set_AddRef(IOpcPartSet *iface)
933 struct opc_part_set *part_set = impl_from_IOpcPartSet(iface);
934 ULONG refcount = InterlockedIncrement(&part_set->refcount);
936 TRACE("%p increasing refcount to %u.\n", iface, refcount);
938 return refcount;
941 static ULONG WINAPI opc_part_set_Release(IOpcPartSet *iface)
943 struct opc_part_set *part_set = impl_from_IOpcPartSet(iface);
944 ULONG refcount = InterlockedDecrement(&part_set->refcount);
946 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
948 if (!refcount)
950 size_t i;
952 for (i = 0; i < part_set->count; ++i)
953 IOpcPart_Release(&part_set->parts[i]->IOpcPart_iface);
954 heap_free(part_set->parts);
955 heap_free(part_set);
958 return refcount;
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);
968 if (!out)
969 return E_POINTER;
971 *out = NULL;
973 if (!name)
974 return E_POINTER;
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);
993 if (!part)
994 return E_POINTER;
996 *part = NULL;
998 if (!name)
999 return E_POINTER;
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);
1011 return E_NOTIMPL;
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)
1021 return E_POINTER;
1023 *exists = opc_part_set_get_part(part_set, name) != NULL;
1025 return S_OK;
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);
1034 if (!enumerator)
1035 return E_POINTER;
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))
1059 *out = iface;
1060 IOpcRelationship_AddRef(iface);
1061 return S_OK;
1064 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
1065 return E_NOINTERFACE;
1068 static ULONG WINAPI opc_relationship_AddRef(IOpcRelationship *iface)
1070 struct opc_relationship *relationship = impl_from_IOpcRelationship(iface);
1071 ULONG refcount = InterlockedIncrement(&relationship->refcount);
1073 TRACE("%p increasing refcount to %u.\n", iface, refcount);
1075 return refcount;
1078 static ULONG WINAPI opc_relationship_Release(IOpcRelationship *iface)
1080 struct opc_relationship *relationship = impl_from_IOpcRelationship(iface);
1081 ULONG refcount = InterlockedDecrement(&relationship->refcount);
1083 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
1085 if (!refcount)
1087 CoTaskMemFree(relationship->id);
1088 CoTaskMemFree(relationship->type);
1089 IOpcUri_Release(relationship->source_uri);
1090 IUri_Release(relationship->target);
1091 heap_free(relationship);
1094 return refcount;
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);
1126 return S_OK;
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);
1138 return S_OK;
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;
1149 return S_OK;
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,
1165 const WCHAR *id)
1167 size_t i;
1169 for (i = 0; i < relationship_set->count; i++)
1171 if (!wcscmp(id, relationship_set->relationships[i]->id))
1172 return relationship_set->relationships[i];
1175 return NULL;
1178 static HRESULT opc_relationship_create(struct opc_relationship_set *set, const WCHAR *id, const WCHAR *type,
1179 IUri *target_uri, OPC_URI_TARGET_MODE target_mode, IOpcRelationship **out)
1181 struct opc_relationship *relationship;
1183 if (!opc_array_reserve((void **)&set->relationships, &set->size, set->count + 1, sizeof(*set->relationships)))
1184 return E_OUTOFMEMORY;
1186 if (!(relationship = heap_alloc_zero(sizeof(*relationship))))
1187 return E_OUTOFMEMORY;
1189 relationship->IOpcRelationship_iface.lpVtbl = &opc_relationship_vtbl;
1190 relationship->refcount = 1;
1192 relationship->target = target_uri;
1193 IUri_AddRef(relationship->target);
1194 relationship->source_uri = set->source_uri;
1195 IOpcUri_AddRef(relationship->source_uri);
1197 if (id)
1198 relationship->id = opc_strdupW(id);
1199 else
1201 relationship->id = CoTaskMemAlloc(10 * sizeof(WCHAR));
1202 if (relationship->id)
1204 static const WCHAR fmtW[] = {'R','%','0','8','X',0};
1205 DWORD generated;
1207 /* FIXME: test that generated id is unique */
1208 RtlGenRandom(&generated, sizeof(generated));
1209 swprintf(relationship->id, 10, fmtW, generated);
1211 if (opc_relationshipset_get_rel(set, relationship->id))
1213 WARN("Newly generated id %s already exists.\n", debugstr_w(relationship->id));
1214 IOpcRelationship_Release(&relationship->IOpcRelationship_iface);
1215 return E_FAIL;
1220 relationship->type = opc_strdupW(type);
1221 if (!relationship->id || !relationship->type)
1223 IOpcRelationship_Release(&relationship->IOpcRelationship_iface);
1224 return E_OUTOFMEMORY;
1227 set->relationships[set->count++] = relationship;
1228 IOpcRelationship_AddRef(&relationship->IOpcRelationship_iface);
1229 CoCreateGuid(&set->id);
1231 *out = &relationship->IOpcRelationship_iface;
1232 TRACE("Created relationship %p.\n", *out);
1233 return S_OK;
1236 static HRESULT WINAPI opc_relationship_set_QueryInterface(IOpcRelationshipSet *iface, REFIID iid, void **out)
1238 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1240 if (IsEqualIID(iid, &IID_IOpcRelationshipSet) ||
1241 IsEqualIID(iid, &IID_IUnknown))
1243 *out = iface;
1244 IOpcRelationshipSet_AddRef(iface);
1245 return S_OK;
1248 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
1249 return E_NOINTERFACE;
1252 static ULONG WINAPI opc_relationship_set_AddRef(IOpcRelationshipSet *iface)
1254 struct opc_relationship_set *relationship_set = impl_from_IOpcRelationshipSet(iface);
1255 ULONG refcount = InterlockedIncrement(&relationship_set->refcount);
1257 TRACE("%p increasing refcount to %u.\n", iface, refcount);
1259 return refcount;
1262 static ULONG WINAPI opc_relationship_set_Release(IOpcRelationshipSet *iface)
1264 struct opc_relationship_set *relationship_set = impl_from_IOpcRelationshipSet(iface);
1265 ULONG refcount = InterlockedDecrement(&relationship_set->refcount);
1267 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
1269 if (!refcount)
1271 size_t i;
1273 for (i = 0; i < relationship_set->count; ++i)
1274 IOpcRelationship_Release(&relationship_set->relationships[i]->IOpcRelationship_iface);
1275 IOpcUri_Release(relationship_set->source_uri);
1276 heap_free(relationship_set->relationships);
1277 heap_free(relationship_set);
1280 return refcount;
1283 static HRESULT WINAPI opc_relationship_set_GetRelationship(IOpcRelationshipSet *iface, const WCHAR *id,
1284 IOpcRelationship **relationship)
1286 struct opc_relationship_set *relationship_set = impl_from_IOpcRelationshipSet(iface);
1287 struct opc_relationship *ret;
1289 TRACE("iface %p, id %s, relationship %p.\n", iface, debugstr_w(id), relationship);
1291 if (!relationship)
1292 return E_POINTER;
1294 *relationship = NULL;
1296 if (!id)
1297 return E_POINTER;
1299 if ((ret = opc_relationshipset_get_rel(relationship_set, id)))
1301 *relationship = &ret->IOpcRelationship_iface;
1302 IOpcRelationship_AddRef(*relationship);
1305 return *relationship ? S_OK : OPC_E_NO_SUCH_RELATIONSHIP;
1308 static HRESULT WINAPI opc_relationship_set_CreateRelationship(IOpcRelationshipSet *iface, const WCHAR *id,
1309 const WCHAR *type, IUri *target_uri, OPC_URI_TARGET_MODE target_mode, IOpcRelationship **relationship)
1311 struct opc_relationship_set *relationship_set = impl_from_IOpcRelationshipSet(iface);
1312 DWORD length;
1314 TRACE("iface %p, id %s, type %s, target_uri %p, target_mode %d, relationship %p.\n", iface, debugstr_w(id),
1315 debugstr_w(type), target_uri, target_mode, relationship);
1317 if (!relationship)
1318 return E_POINTER;
1320 *relationship = NULL;
1322 if (!type || !target_uri)
1323 return E_POINTER;
1325 if (id && opc_relationshipset_get_rel(relationship_set, id))
1326 return OPC_E_DUPLICATE_RELATIONSHIP;
1328 if (IUri_GetPropertyLength(target_uri, Uri_PROPERTY_SCHEME_NAME, &length, 0) == S_OK && length != 0
1329 && target_mode == OPC_URI_TARGET_MODE_INTERNAL)
1330 return OPC_E_INVALID_RELATIONSHIP_TARGET;
1332 return opc_relationship_create(relationship_set, id, type, target_uri, target_mode, relationship);
1335 static HRESULT WINAPI opc_relationship_set_DeleteRelationship(IOpcRelationshipSet *iface, const WCHAR *id)
1337 FIXME("iface %p, id %s stub!\n", iface, debugstr_w(id));
1339 return E_NOTIMPL;
1342 static HRESULT WINAPI opc_relationship_set_RelationshipExists(IOpcRelationshipSet *iface, const WCHAR *id, BOOL *exists)
1344 struct opc_relationship_set *relationship_set = impl_from_IOpcRelationshipSet(iface);
1346 TRACE("iface %p, id %s, exists %p.\n", iface, debugstr_w(id), exists);
1348 if (!id || !exists)
1349 return E_POINTER;
1351 *exists = opc_relationshipset_get_rel(relationship_set, id) != NULL;
1353 return S_OK;
1356 static HRESULT WINAPI opc_relationship_set_GetEnumerator(IOpcRelationshipSet *iface,
1357 IOpcRelationshipEnumerator **enumerator)
1359 struct opc_relationship_set *relationship_set = impl_from_IOpcRelationshipSet(iface);
1361 TRACE("iface %p, enumerator %p.\n", iface, enumerator);
1363 if (!enumerator)
1364 return E_POINTER;
1366 return opc_rel_enum_create(relationship_set, enumerator);
1369 static HRESULT WINAPI opc_relationship_set_GetEnumeratorForType(IOpcRelationshipSet *iface, const WCHAR *type,
1370 IOpcRelationshipEnumerator **enumerator)
1372 FIXME("iface %p, type %s, enumerator %p stub!\n", iface, debugstr_w(type), enumerator);
1374 return E_NOTIMPL;
1377 static HRESULT WINAPI opc_relationship_set_GetRelationshipsContentStream(IOpcRelationshipSet *iface, IStream **stream)
1379 FIXME("iface %p, stream %p stub!\n", iface, stream);
1381 return E_NOTIMPL;
1384 static const IOpcRelationshipSetVtbl opc_relationship_set_vtbl =
1386 opc_relationship_set_QueryInterface,
1387 opc_relationship_set_AddRef,
1388 opc_relationship_set_Release,
1389 opc_relationship_set_GetRelationship,
1390 opc_relationship_set_CreateRelationship,
1391 opc_relationship_set_DeleteRelationship,
1392 opc_relationship_set_RelationshipExists,
1393 opc_relationship_set_GetEnumerator,
1394 opc_relationship_set_GetEnumeratorForType,
1395 opc_relationship_set_GetRelationshipsContentStream,
1398 static HRESULT opc_relationship_set_create(IOpcUri *source_uri, IOpcRelationshipSet **out)
1400 struct opc_relationship_set *relationship_set;
1402 if (!(relationship_set = heap_alloc_zero(sizeof(*relationship_set))))
1403 return E_OUTOFMEMORY;
1405 relationship_set->IOpcRelationshipSet_iface.lpVtbl = &opc_relationship_set_vtbl;
1406 relationship_set->refcount = 1;
1407 relationship_set->source_uri = source_uri;
1408 IOpcUri_AddRef(relationship_set->source_uri);
1410 *out = &relationship_set->IOpcRelationshipSet_iface;
1411 TRACE("Created relationship set %p.\n", *out);
1412 return S_OK;
1415 static HRESULT WINAPI opc_package_QueryInterface(IOpcPackage *iface, REFIID iid, void **out)
1417 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1419 if (IsEqualIID(iid, &IID_IOpcPackage) ||
1420 IsEqualIID(iid, &IID_IUnknown))
1422 *out = iface;
1423 IOpcPackage_AddRef(iface);
1424 return S_OK;
1427 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
1428 return E_NOINTERFACE;
1431 static ULONG WINAPI opc_package_AddRef(IOpcPackage *iface)
1433 struct opc_package *package = impl_from_IOpcPackage(iface);
1434 ULONG refcount = InterlockedIncrement(&package->refcount);
1436 TRACE("%p increasing refcount to %u.\n", iface, refcount);
1438 return refcount;
1441 static ULONG WINAPI opc_package_Release(IOpcPackage *iface)
1443 struct opc_package *package = impl_from_IOpcPackage(iface);
1444 ULONG refcount = InterlockedDecrement(&package->refcount);
1446 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
1448 if (!refcount)
1450 if (package->part_set)
1451 IOpcPartSet_Release(package->part_set);
1452 if (package->relationship_set)
1453 IOpcRelationshipSet_Release(package->relationship_set);
1454 if (package->source_uri)
1455 IOpcUri_Release(package->source_uri);
1456 heap_free(package);
1459 return refcount;
1462 static HRESULT WINAPI opc_package_GetPartSet(IOpcPackage *iface, IOpcPartSet **part_set)
1464 struct opc_package *package = impl_from_IOpcPackage(iface);
1466 TRACE("iface %p, part_set %p.\n", iface, part_set);
1468 if (!package->part_set)
1470 struct opc_part_set *part_set = heap_alloc_zero(sizeof(*part_set));
1471 if (!part_set)
1472 return E_OUTOFMEMORY;
1474 part_set->IOpcPartSet_iface.lpVtbl = &opc_part_set_vtbl;
1475 part_set->refcount = 1;
1477 package->part_set = &part_set->IOpcPartSet_iface;
1480 *part_set = package->part_set;
1481 IOpcPartSet_AddRef(*part_set);
1483 return S_OK;
1486 static HRESULT WINAPI opc_package_GetRelationshipSet(IOpcPackage *iface, IOpcRelationshipSet **relationship_set)
1488 struct opc_package *package = impl_from_IOpcPackage(iface);
1489 HRESULT hr;
1491 TRACE("iface %p, relationship_set %p.\n", iface, relationship_set);
1493 if (!package->relationship_set)
1495 if (FAILED(hr = opc_relationship_set_create(package->source_uri, &package->relationship_set)))
1496 return hr;
1499 *relationship_set = package->relationship_set;
1500 IOpcRelationshipSet_AddRef(*relationship_set);
1502 return S_OK;
1505 static const IOpcPackageVtbl opc_package_vtbl =
1507 opc_package_QueryInterface,
1508 opc_package_AddRef,
1509 opc_package_Release,
1510 opc_package_GetPartSet,
1511 opc_package_GetRelationshipSet,
1514 HRESULT opc_package_create(IOpcFactory *factory, IOpcPackage **out)
1516 struct opc_package *package;
1517 HRESULT hr;
1519 if (!(package = heap_alloc_zero(sizeof(*package))))
1520 return E_OUTOFMEMORY;
1522 package->IOpcPackage_iface.lpVtbl = &opc_package_vtbl;
1523 package->refcount = 1;
1525 if (FAILED(hr = IOpcFactory_CreatePackageRootUri(factory, &package->source_uri)))
1527 heap_free(package);
1528 return hr;
1531 *out = &package->IOpcPackage_iface;
1532 TRACE("Created package %p.\n", *out);
1533 return S_OK;
1536 struct content_types
1538 struct list types;
1539 BOOL has_rels_part;
1542 enum content_type_element
1544 CONTENT_TYPE_DEFAULT,
1545 CONTENT_TYPE_OVERRIDE,
1548 struct content_type
1550 struct list entry;
1551 enum content_type_element element;
1552 union
1554 struct default_type
1556 WCHAR *ext;
1557 WCHAR *type;
1558 } def;
1559 struct override_type
1561 IOpcPart *part;
1562 } override;
1563 } u;
1566 static HRESULT opc_package_add_override_content_type(struct content_types *types, IOpcPart *part)
1568 struct content_type *type;
1570 if (!(type = heap_alloc(sizeof(*type))))
1571 return E_OUTOFMEMORY;
1573 type->element = CONTENT_TYPE_OVERRIDE;
1574 type->u.override.part = part;
1575 IOpcPart_AddRef(part);
1577 list_add_tail(&types->types, &type->entry);
1579 return S_OK;
1582 static HRESULT opc_package_add_default_content_type(struct content_types *types,
1583 const WCHAR *ext, const WCHAR *content_type)
1585 struct content_type *type;
1587 if (!(type = heap_alloc(sizeof(*type))))
1588 return E_OUTOFMEMORY;
1590 type->element = CONTENT_TYPE_DEFAULT;
1591 type->u.def.ext = opc_strdupW(ext);
1592 type->u.def.type = opc_strdupW(content_type);
1593 if (!type->u.def.ext || !type->u.def.type)
1595 CoTaskMemFree(type->u.def.ext);
1596 CoTaskMemFree(type->u.def.type);
1597 heap_free(type);
1598 return E_OUTOFMEMORY;
1601 list_add_tail(&types->types, &type->entry);
1603 return S_OK;
1606 static HRESULT opc_package_add_content_type(struct content_types *types, IOpcPart *part)
1608 struct content_type *cur;
1609 BSTR ext, content_type;
1610 BOOL added = FALSE;
1611 IOpcPartUri *name;
1612 HRESULT hr;
1614 if (FAILED(hr = IOpcPart_GetName(part, &name)))
1615 return hr;
1617 hr = IOpcPartUri_GetExtension(name, &ext);
1618 IOpcPartUri_Release(name);
1619 if (hr == S_FALSE)
1621 hr = opc_package_add_override_content_type(types, part);
1622 SysFreeString(ext);
1623 return hr;
1626 if (FAILED(hr))
1627 return hr;
1629 if (FAILED(hr = IOpcPart_GetContentType(part, &content_type)))
1630 return hr;
1632 LIST_FOR_EACH_ENTRY(cur, &types->types, struct content_type, entry)
1634 if (cur->element == CONTENT_TYPE_OVERRIDE)
1635 continue;
1637 if (!wcsicmp(cur->u.def.ext, ext))
1639 added = TRUE;
1641 if (!wcscmp(cur->u.def.type, content_type))
1642 break;
1644 hr = opc_package_add_override_content_type(types, part);
1645 break;
1649 if (!added)
1650 hr = opc_package_add_default_content_type(types, ext, content_type);
1652 SysFreeString(ext);
1653 SysFreeString(content_type);
1655 return hr;
1658 static BOOL opc_package_has_rels_part(IOpcRelationshipSet *rel_set)
1660 IOpcRelationshipEnumerator *enumerator;
1661 BOOL has_next;
1662 HRESULT hr;
1664 if (FAILED(hr = IOpcRelationshipSet_GetEnumerator(rel_set, &enumerator)))
1665 return FALSE;
1667 has_next = FALSE;
1668 IOpcRelationshipEnumerator_MoveNext(enumerator, &has_next);
1669 IOpcRelationshipEnumerator_Release(enumerator);
1671 return has_next;
1674 static HRESULT opc_package_collect_content_types(IOpcPackage *package, struct content_types *types)
1676 IOpcPartEnumerator *enumerator;
1677 IOpcRelationshipSet *rel_set;
1678 IOpcPartSet *parts;
1679 BOOL has_next;
1680 HRESULT hr;
1682 if (FAILED(hr = IOpcPackage_GetPartSet(package, &parts)))
1683 return hr;
1685 hr = IOpcPackage_GetRelationshipSet(package, &rel_set);
1686 if (SUCCEEDED(hr))
1688 types->has_rels_part |= opc_package_has_rels_part(rel_set);
1689 IOpcRelationshipSet_Release(rel_set);
1692 hr = IOpcPartSet_GetEnumerator(parts, &enumerator);
1693 IOpcPartSet_Release(parts);
1694 if (FAILED(hr))
1695 return hr;
1697 if (FAILED(hr = IOpcPartEnumerator_MoveNext(enumerator, &has_next)) || !has_next)
1699 IOpcPartEnumerator_Release(enumerator);
1700 return hr;
1703 while (has_next)
1705 IOpcPart *part;
1707 if (FAILED(hr = IOpcPartEnumerator_GetCurrent(enumerator, &part)))
1708 break;
1710 if (!types->has_rels_part)
1712 hr = IOpcPart_GetRelationshipSet(part, &rel_set);
1713 if (SUCCEEDED(hr))
1715 types->has_rels_part |= opc_package_has_rels_part(rel_set);
1716 IOpcRelationshipSet_Release(rel_set);
1720 hr = opc_package_add_content_type(types, part);
1721 IOpcPart_Release(part);
1722 if (FAILED(hr))
1723 break;
1725 if (FAILED(hr = IOpcPartEnumerator_MoveNext(enumerator, &has_next)))
1726 break;
1729 IOpcPartEnumerator_Release(enumerator);
1731 return hr;
1734 static HRESULT opc_package_write_default_type(const WCHAR *ext, const WCHAR *type, IXmlWriter *writer)
1736 static const WCHAR contenttypeW[] = {'C','o','n','t','e','n','t','T','y','p','e',0};
1737 static const WCHAR extensionW[] = {'E','x','t','e','n','s','i','o','n',0};
1738 static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',0};
1739 HRESULT hr;
1741 hr = IXmlWriter_WriteStartElement(writer, NULL, defaultW, NULL);
1742 if (SUCCEEDED(hr))
1743 hr = IXmlWriter_WriteAttributeString(writer, NULL, extensionW, NULL, ext);
1744 if (SUCCEEDED(hr))
1745 hr = IXmlWriter_WriteAttributeString(writer, NULL, contenttypeW, NULL, type);
1746 return hr;
1749 static HRESULT opc_package_write_contenttypes(IOpcPackage *package, struct zip_archive *archive, IXmlWriter *writer)
1751 static const WCHAR uriW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','o','p','e','n','x','m','l','f','o','r','m','a','t','s','.','o','r','g','/',
1752 'p','a','c','k','a','g','e','/','2','0','0','6','/','c','o','n','t','e','n','t','-','t','y','p','e','s',0};
1753 static const WCHAR relstypeW[] = {'a','p','p','l','i','c','a','t','i','o','n','/','v','n','d','.','o','p','e','n','x','m','l','f','o','r','m','a','t','s','-',
1754 'p','a','c','k','a','g','e','.','r','e','l','a','t','i','o','n','s','h','i','p','s','+','x','m','l',0};
1755 static const WCHAR contenttypesW[] = {'[','C','o','n','t','e','n','t','_','T','y','p','e','s',']','.','x','m','l',0};
1756 static const WCHAR contenttypeW[] = {'C','o','n','t','e','n','t','T','y','p','e',0};
1757 static const WCHAR overrideW[] = {'O','v','e','r','r','i','d','e',0};
1758 static const WCHAR partnameW[] = {'P','a','r','t','N','a','m','e',0};
1759 static const WCHAR typesW[] = {'T','y','p','e','s',0};
1760 static const WCHAR relsW[] = {'r','e','l','s',0};
1761 struct content_type *content_type, *content_type2;
1762 struct content_types types;
1763 IStream *content = NULL;
1764 HRESULT hr;
1766 list_init(&types.types);
1767 types.has_rels_part = FALSE;
1769 hr = CreateStreamOnHGlobal(NULL, TRUE, &content);
1770 if (SUCCEEDED(hr))
1771 hr = opc_package_collect_content_types(package, &types);
1772 if (SUCCEEDED(hr))
1773 hr = IXmlWriter_SetOutput(writer, (IUnknown *)content);
1774 if (SUCCEEDED(hr))
1775 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1776 if (SUCCEEDED(hr))
1777 hr = IXmlWriter_WriteStartElement(writer, NULL, typesW, uriW);
1779 if (SUCCEEDED(hr) && types.has_rels_part)
1781 hr = opc_package_write_default_type(relsW, relstypeW, writer);
1782 if (SUCCEEDED(hr))
1783 hr = IXmlWriter_WriteEndElement(writer);
1786 LIST_FOR_EACH_ENTRY_SAFE(content_type, content_type2, &types.types, struct content_type, entry)
1788 if (content_type->element == CONTENT_TYPE_DEFAULT)
1790 hr = opc_package_write_default_type(content_type->u.def.ext + 1, content_type->u.def.type, writer);
1792 CoTaskMemFree(content_type->u.def.ext);
1793 CoTaskMemFree(content_type->u.def.type);
1795 else
1797 IOpcPartUri *uri = NULL;
1798 WCHAR *type = NULL;
1799 BSTR name = NULL;
1801 if (SUCCEEDED(hr))
1802 hr = IXmlWriter_WriteStartElement(writer, NULL, overrideW, NULL);
1803 if (SUCCEEDED(hr))
1804 hr = IOpcPart_GetName(content_type->u.override.part, &uri);
1805 if (SUCCEEDED(hr))
1806 hr = IOpcPartUri_GetRawUri(uri, &name);
1807 if (SUCCEEDED(hr))
1808 hr = IXmlWriter_WriteAttributeString(writer, NULL, partnameW, NULL, name);
1809 if (SUCCEEDED(hr))
1810 hr = IOpcPart_GetContentType(content_type->u.override.part, &type);
1811 if (SUCCEEDED(hr))
1812 hr = IXmlWriter_WriteAttributeString(writer, NULL, contenttypeW, NULL, type);
1814 if (uri)
1815 IOpcPartUri_Release(uri);
1816 SysFreeString(name);
1817 CoTaskMemFree(type);
1819 IOpcPart_Release(content_type->u.override.part);
1821 if (SUCCEEDED(hr))
1822 hr = IXmlWriter_WriteEndElement(writer);
1824 list_remove(&content_type->entry);
1825 heap_free(content_type);
1828 if (SUCCEEDED(hr))
1829 hr = IXmlWriter_WriteEndDocument(writer);
1830 if (SUCCEEDED(hr))
1831 hr = IXmlWriter_Flush(writer);
1833 if (SUCCEEDED(hr))
1834 hr = compress_add_file(archive, contenttypesW, content, OPC_COMPRESSION_NORMAL);
1836 if (content)
1837 IStream_Release(content);
1839 return hr;
1842 static HRESULT opc_package_write_rel(IOpcRelationship *rel, IXmlWriter *writer)
1844 static const WCHAR relationshipW[] = {'R','e','l','a','t','i','o','n','s','h','i','p',0};
1845 static const WCHAR targetW[] = {'T','a','r','g','e','t',0};
1846 static const WCHAR typeW[] = {'T','y','p','e',0};
1847 static const WCHAR idW[] = {'I','d',0};
1848 BSTR target_uri;
1849 HRESULT hr;
1850 WCHAR *str;
1851 IUri *uri;
1853 if (FAILED(hr = IXmlWriter_WriteStartElement(writer, NULL, relationshipW, NULL)))
1854 return hr;
1856 if (FAILED(hr = IOpcRelationship_GetTargetUri(rel, &uri)))
1857 return hr;
1859 IUri_GetRawUri(uri, &target_uri);
1860 IUri_Release(uri);
1862 hr = IXmlWriter_WriteAttributeString(writer, NULL, targetW, NULL, target_uri);
1863 SysFreeString(target_uri);
1864 if (FAILED(hr))
1865 return hr;
1867 if (FAILED(hr = IOpcRelationship_GetId(rel, &str)))
1868 return hr;
1870 hr = IXmlWriter_WriteAttributeString(writer, NULL, idW, NULL, str);
1871 CoTaskMemFree(str);
1872 if (FAILED(hr))
1873 return hr;
1875 if (FAILED(hr = IOpcRelationship_GetRelationshipType(rel, &str)))
1876 return hr;
1878 hr = IXmlWriter_WriteAttributeString(writer, NULL, typeW, NULL, str);
1879 CoTaskMemFree(str);
1880 if (FAILED(hr))
1881 return hr;
1883 return IXmlWriter_WriteEndElement(writer);
1886 static HRESULT opc_package_write_rels(struct zip_archive *archive, IOpcRelationshipSet *rels,
1887 IOpcUri *uri, IXmlWriter *writer)
1889 static const WCHAR uriW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','o','p','e','n','x','m','l','f','o','r','m','a','t','s','.','o','r','g','/',
1890 'p','a','c','k','a','g','e','/','2','0','0','6','/','r','e','l','a','t','i','o','n','s','h','i','p','s',0};
1891 static const WCHAR relationshipsW[] = {'R','e','l','a','t','i','o','n','s','h','i','p','s',0};
1892 IOpcRelationshipEnumerator *enumerator;
1893 BSTR rels_part_uri = NULL;
1894 IOpcPartUri *rels_uri;
1895 IStream *content;
1896 BOOL has_next;
1897 HRESULT hr;
1899 if (FAILED(hr = IOpcRelationshipSet_GetEnumerator(rels, &enumerator)))
1900 return hr;
1902 hr = IOpcRelationshipEnumerator_MoveNext(enumerator, &has_next);
1903 if (!has_next)
1905 IOpcRelationshipEnumerator_Release(enumerator);
1906 return hr;
1909 if (FAILED(hr = CreateStreamOnHGlobal(NULL, TRUE, &content)))
1911 IOpcRelationshipEnumerator_Release(enumerator);
1912 return hr;
1915 hr = IXmlWriter_SetOutput(writer, (IUnknown *)content);
1916 if (SUCCEEDED(hr))
1917 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
1918 if (SUCCEEDED(hr))
1919 hr = IXmlWriter_WriteStartElement(writer, NULL, relationshipsW, uriW);
1921 while (has_next)
1923 IOpcRelationship *rel;
1925 if (FAILED(hr = IOpcRelationshipEnumerator_GetCurrent(enumerator, &rel)))
1926 break;
1928 hr = opc_package_write_rel(rel, writer);
1929 IOpcRelationship_Release(rel);
1930 if (FAILED(hr))
1931 break;
1933 IOpcRelationshipEnumerator_MoveNext(enumerator, &has_next);
1936 IOpcRelationshipEnumerator_Release(enumerator);
1938 if (SUCCEEDED(hr))
1939 hr = IXmlWriter_WriteEndDocument(writer);
1940 if (SUCCEEDED(hr))
1941 hr = IXmlWriter_Flush(writer);
1943 if (SUCCEEDED(hr))
1944 hr = IOpcUri_GetRelationshipsPartUri(uri, &rels_uri);
1945 if (SUCCEEDED(hr))
1946 hr = IOpcPartUri_GetRawUri(rels_uri, &rels_part_uri);
1947 if (SUCCEEDED(hr))
1949 /* Relationship part names always start with root '/', skip it. */
1950 hr = compress_add_file(archive, rels_part_uri + 1, content, OPC_COMPRESSION_NORMAL);
1953 SysFreeString(rels_part_uri);
1954 IStream_Release(content);
1956 return hr;
1959 static HRESULT opc_package_write_part(struct zip_archive *archive, IOpcPart *part, IXmlWriter *writer)
1961 OPC_COMPRESSION_OPTIONS options = OPC_COMPRESSION_NORMAL;
1962 IOpcRelationshipSet *rels = NULL;
1963 IStream *content = NULL;
1964 IOpcPartUri *name;
1965 BSTR uri = NULL;
1966 HRESULT hr;
1968 if (FAILED(hr = IOpcPart_GetName(part, &name)))
1969 return hr;
1971 hr = IOpcPartUri_GetRawUri(name, &uri);
1972 if (SUCCEEDED(hr))
1973 hr = IOpcPart_GetCompressionOptions(part, &options);
1974 if (SUCCEEDED(hr))
1975 hr = IOpcPart_GetContentStream(part, &content);
1976 if (SUCCEEDED(hr))
1978 /* Part names always start with root '/', skip it. */
1979 hr = compress_add_file(archive, uri + 1, content, options);
1981 if (SUCCEEDED(hr))
1982 hr = IOpcPart_GetRelationshipSet(part, &rels);
1983 if (SUCCEEDED(hr))
1984 hr = opc_package_write_rels(archive, rels, (IOpcUri *)name, writer);
1986 IOpcPartUri_Release(name);
1987 SysFreeString(uri);
1988 if (content)
1989 IStream_Release(content);
1990 if (rels)
1991 IOpcRelationshipSet_Release(rels);
1993 return hr;
1996 static HRESULT opc_package_write_parts(struct zip_archive *archive, IOpcPackage *package, IXmlWriter *writer)
1998 IOpcPartEnumerator *parts;
1999 IOpcPartSet *part_set;
2000 BOOL got_next;
2001 HRESULT hr;
2003 if (FAILED(hr = IOpcPackage_GetPartSet(package, &part_set)))
2004 return hr;
2006 hr = IOpcPartSet_GetEnumerator(part_set, &parts);
2007 IOpcPartSet_Release(part_set);
2008 if (FAILED(hr))
2009 return hr;
2011 while (IOpcPartEnumerator_MoveNext(parts, &got_next) == S_OK && got_next)
2013 IOpcPart *part;
2015 if (FAILED(hr = IOpcPartEnumerator_GetCurrent(parts, &part)))
2016 break;
2018 hr = opc_package_write_part(archive, part, writer);
2019 IOpcPart_Release(part);
2020 if (FAILED(hr))
2021 break;
2024 IOpcPartEnumerator_Release(parts);
2026 return hr;
2029 HRESULT opc_package_write(IOpcPackage *package, OPC_WRITE_FLAGS flags, IStream *stream)
2031 IOpcRelationshipSet *rels = NULL;
2032 struct zip_archive *archive;
2033 IOpcUri *uri = NULL;
2034 IXmlWriter *writer;
2035 HRESULT hr;
2037 if (flags != OPC_WRITE_FORCE_ZIP32)
2038 FIXME("Unsupported write flags %#x.\n", flags);
2040 if (FAILED(hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL)))
2041 return hr;
2043 if (FAILED(hr = compress_create_archive(stream, &archive)))
2045 IXmlWriter_Release(writer);
2046 return hr;
2049 /* [Content_Types].xml */
2050 hr = opc_package_write_contenttypes(package, archive, writer);
2051 /* Package relationships. */
2052 if (SUCCEEDED(hr))
2053 hr = IOpcPackage_GetRelationshipSet(package, &rels);
2054 if (SUCCEEDED(hr))
2055 hr = opc_root_uri_create(&uri);
2056 if (SUCCEEDED(hr))
2057 hr = opc_package_write_rels(archive, rels, uri, writer);
2058 /* Parts. */
2059 if (SUCCEEDED(hr))
2060 hr = opc_package_write_parts(archive, package, writer);
2062 if (rels)
2063 IOpcRelationshipSet_Release(rels);
2064 if (uri)
2065 IOpcUri_Release(uri);
2067 compress_finalize_archive(archive);
2068 IXmlWriter_Release(writer);
2070 return hr;