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
25 #include "wine/debug.h"
27 #include "opc_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(msopc
);
31 static inline struct opc_uri
*impl_from_IOpcPartUri(IOpcPartUri
*iface
)
33 return CONTAINING_RECORD(iface
, struct opc_uri
, IOpcPartUri_iface
);
36 static HRESULT
opc_source_uri_create(struct opc_uri
*uri
, IOpcUri
**out
);
38 static HRESULT WINAPI
opc_uri_QueryInterface(IOpcPartUri
*iface
, REFIID iid
, void **out
)
40 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
42 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
44 if ((uri
->is_part_uri
&& IsEqualIID(iid
, &IID_IOpcPartUri
)) ||
45 IsEqualIID(iid
, &IID_IOpcUri
) ||
46 IsEqualIID(iid
, &IID_IUri
) ||
47 IsEqualIID(iid
, &IID_IUnknown
))
50 IOpcPartUri_AddRef(iface
);
54 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
58 static ULONG WINAPI
opc_uri_AddRef(IOpcPartUri
*iface
)
60 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
61 ULONG refcount
= InterlockedIncrement(&uri
->refcount
);
63 TRACE("%p, refcount %lu.\n", iface
, refcount
);
68 static ULONG WINAPI
opc_uri_Release(IOpcPartUri
*iface
)
70 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
71 ULONG refcount
= InterlockedDecrement(&uri
->refcount
);
73 TRACE("%p, refcount %lu.\n", iface
, refcount
);
77 if (uri
->rels_part_uri
)
78 IUri_Release(uri
->rels_part_uri
);
80 IOpcPartUri_Release(&uri
->source_uri
->IOpcPartUri_iface
);
81 IUri_Release(uri
->uri
);
88 static HRESULT WINAPI
opc_uri_GetPropertyBSTR(IOpcPartUri
*iface
, Uri_PROPERTY property
,
89 BSTR
*value
, DWORD flags
)
91 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
93 TRACE("iface %p, property %d, value %p, flags %#lx.\n", iface
, property
, value
, flags
);
95 return IUri_GetPropertyBSTR(uri
->uri
, property
, value
, flags
);
98 static HRESULT WINAPI
opc_uri_GetPropertyLength(IOpcPartUri
*iface
, Uri_PROPERTY property
,
99 DWORD
*length
, DWORD flags
)
101 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
103 TRACE("iface %p, property %d, length %p, flags %#lx.\n", iface
, property
, length
, flags
);
105 return IUri_GetPropertyLength(uri
->uri
, property
, length
, flags
);
108 static HRESULT WINAPI
opc_uri_GetPropertyDWORD(IOpcPartUri
*iface
, Uri_PROPERTY property
,
109 DWORD
*value
, DWORD flags
)
111 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
113 TRACE("iface %p, property %d, value %p, flags %#lx.\n", iface
, property
, value
, flags
);
115 return IUri_GetPropertyDWORD(uri
->uri
, property
, value
, flags
);
118 static HRESULT WINAPI
opc_uri_HasProperty(IOpcPartUri
*iface
, Uri_PROPERTY property
,
121 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
123 TRACE("iface %p, property %d, has_property %p.\n", iface
, property
, has_property
);
125 return IUri_HasProperty(uri
->uri
, property
, has_property
);
128 static HRESULT WINAPI
opc_uri_GetAbsoluteUri(IOpcPartUri
*iface
, BSTR
*value
)
130 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
132 TRACE("iface %p, value %p.\n", iface
, value
);
134 return IUri_GetAbsoluteUri(uri
->uri
, value
);
137 static HRESULT WINAPI
opc_uri_GetAuthority(IOpcPartUri
*iface
, BSTR
*value
)
139 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
141 TRACE("iface %p, value %p.\n", iface
, value
);
143 return IUri_GetAuthority(uri
->uri
, value
);
146 static HRESULT WINAPI
opc_uri_GetDisplayUri(IOpcPartUri
*iface
, BSTR
*value
)
148 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
150 TRACE("iface %p, value %p.\n", iface
, value
);
152 return IUri_GetDisplayUri(uri
->uri
, value
);
155 static HRESULT WINAPI
opc_uri_GetDomain(IOpcPartUri
*iface
, BSTR
*value
)
157 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
159 TRACE("iface %p, value %p.\n", iface
, value
);
161 return IUri_GetDomain(uri
->uri
, value
);
164 static HRESULT WINAPI
opc_uri_GetExtension(IOpcPartUri
*iface
, BSTR
*value
)
166 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
168 TRACE("iface %p, value %p.\n", iface
, value
);
170 return IUri_GetExtension(uri
->uri
, value
);
173 static HRESULT WINAPI
opc_uri_GetFragment(IOpcPartUri
*iface
, BSTR
*value
)
175 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
177 TRACE("iface %p, value %p.\n", iface
, value
);
179 return IUri_GetFragment(uri
->uri
, value
);
182 static HRESULT WINAPI
opc_uri_GetHost(IOpcPartUri
*iface
, BSTR
*value
)
184 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
186 TRACE("iface %p, value %p.\n", iface
, value
);
188 return IUri_GetHost(uri
->uri
, value
);
191 static HRESULT WINAPI
opc_uri_GetPassword(IOpcPartUri
*iface
, BSTR
*value
)
193 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
195 TRACE("iface %p, value %p.\n", iface
, value
);
197 return IUri_GetPassword(uri
->uri
, value
);
200 static HRESULT WINAPI
opc_uri_GetPath(IOpcPartUri
*iface
, BSTR
*value
)
202 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
204 TRACE("iface %p, value %p.\n", iface
, value
);
206 return IUri_GetPath(uri
->uri
, value
);
209 static HRESULT WINAPI
opc_uri_GetPathAndQuery(IOpcPartUri
*iface
, BSTR
*value
)
211 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
213 TRACE("iface %p, value %p.\n", iface
, value
);
215 return IUri_GetPathAndQuery(uri
->uri
, value
);
218 static HRESULT WINAPI
opc_uri_GetQuery(IOpcPartUri
*iface
, BSTR
*value
)
220 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
222 TRACE("iface %p, value %p.\n", iface
, value
);
224 return IUri_GetQuery(uri
->uri
, value
);
227 static HRESULT WINAPI
opc_uri_GetRawUri(IOpcPartUri
*iface
, BSTR
*value
)
229 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
231 TRACE("iface %p, value %p.\n", iface
, value
);
233 return IUri_GetRawUri(uri
->uri
, value
);
236 static HRESULT WINAPI
opc_uri_GetSchemeName(IOpcPartUri
*iface
, BSTR
*value
)
238 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
240 TRACE("iface %p, value %p.\n", iface
, value
);
242 return IUri_GetSchemeName(uri
->uri
, value
);
245 static HRESULT WINAPI
opc_uri_GetUserInfo(IOpcPartUri
*iface
, BSTR
*value
)
247 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
249 TRACE("iface %p, value %p.\n", iface
, value
);
251 return IUri_GetUserInfo(uri
->uri
, value
);
254 static HRESULT WINAPI
opc_uri_GetUserName(IOpcPartUri
*iface
, BSTR
*value
)
256 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
258 TRACE("iface %p, value %p.\n", iface
, value
);
260 return IUri_GetUserName(uri
->uri
, value
);
263 static HRESULT WINAPI
opc_uri_GetHostType(IOpcPartUri
*iface
, DWORD
*value
)
265 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
267 TRACE("iface %p, value %p.\n", iface
, value
);
269 return IUri_GetHostType(uri
->uri
, value
);
272 static HRESULT WINAPI
opc_uri_GetPort(IOpcPartUri
*iface
, DWORD
*value
)
274 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
276 TRACE("iface %p, value %p.\n", iface
, value
);
278 return IUri_GetPort(uri
->uri
, value
);
281 static HRESULT WINAPI
opc_uri_GetScheme(IOpcPartUri
*iface
, DWORD
*value
)
283 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
285 TRACE("iface %p, value %p.\n", iface
, value
);
287 return IUri_GetScheme(uri
->uri
, value
);
290 static HRESULT WINAPI
opc_uri_GetZone(IOpcPartUri
*iface
, DWORD
*value
)
292 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
294 TRACE("iface %p, value %p.\n", iface
, value
);
296 return IUri_GetZone(uri
->uri
, value
);
299 static HRESULT WINAPI
opc_uri_GetProperties(IOpcPartUri
*iface
, DWORD
*flags
)
301 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
303 TRACE("iface %p, flags %p.\n", iface
, flags
);
305 return IUri_GetProperties(uri
->uri
, flags
);
308 static HRESULT WINAPI
opc_uri_IsEqual(IOpcPartUri
*iface
, IUri
*comparand
, BOOL
*is_equal
)
310 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
312 TRACE("iface %p, comparand %p, is_equal %p.\n", iface
, comparand
, is_equal
);
319 if (uri
->is_part_uri
)
328 return IUri_IsEqual(comparand
, uri
->uri
, is_equal
);
331 static HRESULT WINAPI
opc_uri_GetRelationshipsPartUri(IOpcPartUri
*iface
, IOpcPartUri
**part_uri
)
333 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
335 TRACE("iface %p, part_uri %p.\n", iface
, part_uri
);
340 if (!uri
->rels_part_uri
)
343 return OPC_E_NONCONFORMING_URI
;
346 return opc_part_uri_create(uri
->rels_part_uri
, uri
, part_uri
);
349 static HRESULT WINAPI
opc_uri_GetRelativeUri(IOpcPartUri
*iface
, IOpcPartUri
*part_uri
,
352 FIXME("iface %p, part_uri %p, relative_uri %p stub!\n", iface
, part_uri
, relative_uri
);
357 static HRESULT WINAPI
opc_uri_CombinePartUri(IOpcPartUri
*iface
, IUri
*relative_uri
, IOpcPartUri
**combined
)
359 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
363 TRACE("iface %p, relative_uri %p, combined %p.\n", iface
, relative_uri
, combined
);
373 if (FAILED(hr
= CoInternetCombineIUri(uri
->uri
, relative_uri
, 0, &combined_uri
, 0)))
376 hr
= opc_part_uri_create(combined_uri
, NULL
, combined
);
377 IUri_Release(combined_uri
);
381 static HRESULT WINAPI
opc_uri_ComparePartUri(IOpcPartUri
*iface
, IOpcPartUri
*part_uri
,
384 FIXME("iface %p, part_uri %p, result %p stub!\n", iface
, part_uri
, result
);
389 static HRESULT WINAPI
opc_uri_GetSourceUri(IOpcPartUri
*iface
, IOpcUri
**source_uri
)
391 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
393 TRACE("iface %p, source_uri %p.\n", iface
, source_uri
);
395 return opc_source_uri_create(uri
, source_uri
);
398 static HRESULT WINAPI
opc_uri_IsRelationshipsPartUri(IOpcPartUri
*iface
, BOOL
*result
)
400 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
402 TRACE("iface %p, result %p.\n", iface
, result
);
407 *result
= !uri
->rels_part_uri
;
412 static const IOpcPartUriVtbl opc_part_uri_vtbl
=
414 opc_uri_QueryInterface
,
417 opc_uri_GetPropertyBSTR
,
418 opc_uri_GetPropertyLength
,
419 opc_uri_GetPropertyDWORD
,
421 opc_uri_GetAbsoluteUri
,
422 opc_uri_GetAuthority
,
423 opc_uri_GetDisplayUri
,
425 opc_uri_GetExtension
,
430 opc_uri_GetPathAndQuery
,
433 opc_uri_GetSchemeName
,
440 opc_uri_GetProperties
,
442 opc_uri_GetRelationshipsPartUri
,
443 opc_uri_GetRelativeUri
,
444 opc_uri_CombinePartUri
,
445 opc_uri_ComparePartUri
,
446 opc_uri_GetSourceUri
,
447 opc_uri_IsRelationshipsPartUri
,
450 static IUri
*opc_part_uri_get_rels_uri(IUri
*uri
)
452 static const WCHAR relsdirW
[] = L
"/_rels";
453 static const WCHAR relsextW
[] = L
".rels";
454 WCHAR
*start
= NULL
, *end
, *ret
;
460 if (FAILED(IUri_GetPath(uri
, &path
)))
463 if (FAILED(IUri_GetPropertyLength(uri
, Uri_PROPERTY_PATH
, &len
, 0)))
469 end
= wcsrchr(path
, '/');
470 if (end
&& end
>= path
+ ARRAY_SIZE(relsdirW
) - 1)
471 start
= end
- ARRAY_SIZE(relsdirW
) + 1;
475 /* Test if it's already relationships uri. */
476 if (len
> ARRAY_SIZE(relsextW
))
478 if (!wcscmp(path
+ len
- ARRAY_SIZE(relsextW
) + 1, relsextW
))
480 if (start
&& !memcmp(start
, relsdirW
, ARRAY_SIZE(relsdirW
) - sizeof(WCHAR
)))
488 ret
= malloc((len
+ ARRAY_SIZE(relsextW
) + ARRAY_SIZE(relsdirW
)) * sizeof(WCHAR
));
498 memcpy(ret
, path
, (start
- path
) * sizeof(WCHAR
));
499 ret
[start
- path
] = 0;
502 lstrcatW(ret
, relsdirW
);
504 lstrcatW(ret
, relsextW
);
506 if (FAILED(hr
= CreateUri(ret
, Uri_CREATE_ALLOW_RELATIVE
, 0, &rels_uri
)))
507 WARN("Failed to create rels uri, hr %#lx.\n", hr
);
514 static HRESULT
opc_part_uri_init(struct opc_uri
*object
, struct opc_uri
*source_uri
, BOOL is_part_uri
, IUri
*uri
)
516 object
->IOpcPartUri_iface
.lpVtbl
= &opc_part_uri_vtbl
;
517 object
->refcount
= 1;
518 object
->is_part_uri
= is_part_uri
;
520 IUri_AddRef(object
->uri
);
521 object
->rels_part_uri
= opc_part_uri_get_rels_uri(object
->uri
);
522 object
->source_uri
= source_uri
;
523 if (object
->source_uri
)
524 IOpcPartUri_AddRef(&object
->source_uri
->IOpcPartUri_iface
);
529 static HRESULT
opc_source_uri_create(struct opc_uri
*uri
, IOpcUri
**out
)
539 if (!uri
->source_uri
)
540 return OPC_E_RELATIONSHIP_URI_REQUIRED
;
542 if (!(obj
= calloc(1, sizeof(*obj
))))
543 return E_OUTOFMEMORY
;
545 if (FAILED(hr
= opc_part_uri_init(obj
, NULL
, uri
->source_uri
->is_part_uri
, uri
->source_uri
->uri
)))
547 WARN("Failed to init part uri, hr %#lx.\n", hr
);
552 *out
= (IOpcUri
*)&obj
->IOpcPartUri_iface
;
554 TRACE("Created source uri %p.\n", *out
);
559 HRESULT
opc_part_uri_create(IUri
*uri
, struct opc_uri
*source_uri
, IOpcPartUri
**out
)
564 if (!(obj
= calloc(1, sizeof(*obj
))))
565 return E_OUTOFMEMORY
;
567 if (FAILED(hr
= opc_part_uri_init(obj
, source_uri
, TRUE
, uri
)))
569 WARN("Failed to init part uri, hr %#lx.\n", hr
);
574 *out
= &obj
->IOpcPartUri_iface
;
575 TRACE("Created part uri %p.\n", *out
);
579 HRESULT
opc_root_uri_create(IOpcUri
**out
)
587 if (!(obj
= calloc(1, sizeof(*obj
))))
588 return E_OUTOFMEMORY
;
590 if (FAILED(hr
= CreateUri(L
"/", Uri_CREATE_ALLOW_RELATIVE
, 0, &uri
)))
592 WARN("Failed to create rels uri, hr %#lx.\n", hr
);
597 hr
= opc_part_uri_init(obj
, NULL
, FALSE
, uri
);
601 WARN("Failed to init uri, hr %#lx.\n", hr
);
606 *out
= (IOpcUri
*)&obj
->IOpcPartUri_iface
;
607 TRACE("Created part uri %p.\n", *out
);