Release 4.0.
[wine.git] / dlls / opcservices / uri.c
blob800ae34571e0372abc0b2bbf28b4d6da83726fdf
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"
25 #include "wine/debug.h"
26 #include "wine/unicode.h"
28 #include "opc_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(msopc);
32 static inline struct opc_uri *impl_from_IOpcPartUri(IOpcPartUri *iface)
34 return CONTAINING_RECORD(iface, struct opc_uri, IOpcPartUri_iface);
37 static HRESULT opc_source_uri_create(struct opc_uri *uri, IOpcUri **out);
39 static HRESULT WINAPI opc_uri_QueryInterface(IOpcPartUri *iface, REFIID iid, void **out)
41 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
43 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
45 if ((uri->is_part_uri && IsEqualIID(iid, &IID_IOpcPartUri)) ||
46 IsEqualIID(iid, &IID_IOpcUri) ||
47 IsEqualIID(iid, &IID_IUri) ||
48 IsEqualIID(iid, &IID_IUnknown))
50 *out = iface;
51 IOpcPartUri_AddRef(iface);
52 return S_OK;
55 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
56 return E_NOINTERFACE;
59 static ULONG WINAPI opc_uri_AddRef(IOpcPartUri *iface)
61 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
62 ULONG refcount = InterlockedIncrement(&uri->refcount);
64 TRACE("%p increasing refcount to %u.\n", iface, refcount);
66 return refcount;
69 static ULONG WINAPI opc_uri_Release(IOpcPartUri *iface)
71 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
72 ULONG refcount = InterlockedDecrement(&uri->refcount);
74 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
76 if (!refcount)
78 if (uri->rels_part_uri)
79 IUri_Release(uri->rels_part_uri);
80 if (uri->source_uri)
81 IOpcPartUri_Release(&uri->source_uri->IOpcPartUri_iface);
82 IUri_Release(uri->uri);
83 heap_free(uri);
86 return refcount;
89 static HRESULT WINAPI opc_uri_GetPropertyBSTR(IOpcPartUri *iface, Uri_PROPERTY property,
90 BSTR *value, DWORD flags)
92 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
94 TRACE("iface %p, property %d, value %p, flags %#x.\n", iface, property, value, flags);
96 return IUri_GetPropertyBSTR(uri->uri, property, value, flags);
99 static HRESULT WINAPI opc_uri_GetPropertyLength(IOpcPartUri *iface, Uri_PROPERTY property,
100 DWORD *length, DWORD flags)
102 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
104 TRACE("iface %p, property %d, length %p, flags %#x.\n", iface, property, length, flags);
106 return IUri_GetPropertyLength(uri->uri, property, length, flags);
109 static HRESULT WINAPI opc_uri_GetPropertyDWORD(IOpcPartUri *iface, Uri_PROPERTY property,
110 DWORD *value, DWORD flags)
112 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
114 TRACE("iface %p, property %d, value %p, flags %#x.\n", iface, property, value, flags);
116 return IUri_GetPropertyDWORD(uri->uri, property, value, flags);
119 static HRESULT WINAPI opc_uri_HasProperty(IOpcPartUri *iface, Uri_PROPERTY property,
120 BOOL *has_property)
122 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
124 TRACE("iface %p, property %d, has_property %p.\n", iface, property, has_property);
126 return IUri_HasProperty(uri->uri, property, has_property);
129 static HRESULT WINAPI opc_uri_GetAbsoluteUri(IOpcPartUri *iface, BSTR *value)
131 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
133 TRACE("iface %p, value %p.\n", iface, value);
135 return IUri_GetAbsoluteUri(uri->uri, value);
138 static HRESULT WINAPI opc_uri_GetAuthority(IOpcPartUri *iface, BSTR *value)
140 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
142 TRACE("iface %p, value %p.\n", iface, value);
144 return IUri_GetAuthority(uri->uri, value);
147 static HRESULT WINAPI opc_uri_GetDisplayUri(IOpcPartUri *iface, BSTR *value)
149 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
151 TRACE("iface %p, value %p.\n", iface, value);
153 return IUri_GetDisplayUri(uri->uri, value);
156 static HRESULT WINAPI opc_uri_GetDomain(IOpcPartUri *iface, BSTR *value)
158 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
160 TRACE("iface %p, value %p.\n", iface, value);
162 return IUri_GetDomain(uri->uri, value);
165 static HRESULT WINAPI opc_uri_GetExtension(IOpcPartUri *iface, BSTR *value)
167 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
169 TRACE("iface %p, value %p.\n", iface, value);
171 return IUri_GetExtension(uri->uri, value);
174 static HRESULT WINAPI opc_uri_GetFragment(IOpcPartUri *iface, BSTR *value)
176 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
178 TRACE("iface %p, value %p.\n", iface, value);
180 return IUri_GetFragment(uri->uri, value);
183 static HRESULT WINAPI opc_uri_GetHost(IOpcPartUri *iface, BSTR *value)
185 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
187 TRACE("iface %p, value %p.\n", iface, value);
189 return IUri_GetHost(uri->uri, value);
192 static HRESULT WINAPI opc_uri_GetPassword(IOpcPartUri *iface, BSTR *value)
194 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
196 TRACE("iface %p, value %p.\n", iface, value);
198 return IUri_GetPassword(uri->uri, value);
201 static HRESULT WINAPI opc_uri_GetPath(IOpcPartUri *iface, BSTR *value)
203 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
205 TRACE("iface %p, value %p.\n", iface, value);
207 return IUri_GetPath(uri->uri, value);
210 static HRESULT WINAPI opc_uri_GetPathAndQuery(IOpcPartUri *iface, BSTR *value)
212 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
214 TRACE("iface %p, value %p.\n", iface, value);
216 return IUri_GetPathAndQuery(uri->uri, value);
219 static HRESULT WINAPI opc_uri_GetQuery(IOpcPartUri *iface, BSTR *value)
221 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
223 TRACE("iface %p, value %p.\n", iface, value);
225 return IUri_GetQuery(uri->uri, value);
228 static HRESULT WINAPI opc_uri_GetRawUri(IOpcPartUri *iface, BSTR *value)
230 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
232 TRACE("iface %p, value %p.\n", iface, value);
234 return IUri_GetRawUri(uri->uri, value);
237 static HRESULT WINAPI opc_uri_GetSchemeName(IOpcPartUri *iface, BSTR *value)
239 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
241 TRACE("iface %p, value %p.\n", iface, value);
243 return IUri_GetSchemeName(uri->uri, value);
246 static HRESULT WINAPI opc_uri_GetUserInfo(IOpcPartUri *iface, BSTR *value)
248 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
250 TRACE("iface %p, value %p.\n", iface, value);
252 return IUri_GetUserInfo(uri->uri, value);
255 static HRESULT WINAPI opc_uri_GetUserName(IOpcPartUri *iface, BSTR *value)
257 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
259 TRACE("iface %p, value %p.\n", iface, value);
261 return IUri_GetUserName(uri->uri, value);
264 static HRESULT WINAPI opc_uri_GetHostType(IOpcPartUri *iface, DWORD *value)
266 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
268 TRACE("iface %p, value %p.\n", iface, value);
270 return IUri_GetHostType(uri->uri, value);
273 static HRESULT WINAPI opc_uri_GetPort(IOpcPartUri *iface, DWORD *value)
275 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
277 TRACE("iface %p, value %p.\n", iface, value);
279 return IUri_GetPort(uri->uri, value);
282 static HRESULT WINAPI opc_uri_GetScheme(IOpcPartUri *iface, DWORD *value)
284 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
286 TRACE("iface %p, value %p.\n", iface, value);
288 return IUri_GetScheme(uri->uri, value);
291 static HRESULT WINAPI opc_uri_GetZone(IOpcPartUri *iface, DWORD *value)
293 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
295 TRACE("iface %p, value %p.\n", iface, value);
297 return IUri_GetZone(uri->uri, value);
300 static HRESULT WINAPI opc_uri_GetProperties(IOpcPartUri *iface, DWORD *flags)
302 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
304 TRACE("iface %p, flags %p.\n", iface, flags);
306 return IUri_GetProperties(uri->uri, flags);
309 static HRESULT WINAPI opc_uri_IsEqual(IOpcPartUri *iface, IUri *comparand, BOOL *is_equal)
311 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
313 TRACE("iface %p, comparand %p, is_equal %p.\n", iface, comparand, is_equal);
315 if (!is_equal)
316 return E_POINTER;
318 if (!comparand)
320 if (uri->is_part_uri)
322 *is_equal = FALSE;
323 return S_OK;
326 return E_POINTER;
329 return IUri_IsEqual(comparand, uri->uri, is_equal);
332 static HRESULT WINAPI opc_uri_GetRelationshipsPartUri(IOpcPartUri *iface, IOpcPartUri **part_uri)
334 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
336 TRACE("iface %p, part_uri %p.\n", iface, part_uri);
338 if (!part_uri)
339 return E_POINTER;
341 if (!uri->rels_part_uri)
343 *part_uri = NULL;
344 return OPC_E_NONCONFORMING_URI;
347 return opc_part_uri_create(uri->rels_part_uri, uri, part_uri);
350 static HRESULT WINAPI opc_uri_GetRelativeUri(IOpcPartUri *iface, IOpcPartUri *part_uri,
351 IUri **relative_uri)
353 FIXME("iface %p, part_uri %p, relative_uri %p stub!\n", iface, part_uri, relative_uri);
355 return E_NOTIMPL;
358 static HRESULT WINAPI opc_uri_CombinePartUri(IOpcPartUri *iface, IUri *relative_uri, IOpcPartUri **combined)
360 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
361 IUri *combined_uri;
362 HRESULT hr;
364 TRACE("iface %p, relative_uri %p, combined %p.\n", iface, relative_uri, combined);
366 if (!combined)
367 return E_POINTER;
369 *combined = NULL;
371 if (!relative_uri)
372 return E_POINTER;
374 if (FAILED(hr = CoInternetCombineIUri(uri->uri, relative_uri, 0, &combined_uri, 0)))
375 return hr;
377 hr = opc_part_uri_create(combined_uri, NULL, combined);
378 IUri_Release(combined_uri);
379 return hr;
382 static HRESULT WINAPI opc_uri_ComparePartUri(IOpcPartUri *iface, IOpcPartUri *part_uri,
383 INT32 *result)
385 FIXME("iface %p, part_uri %p, result %p stub!\n", iface, part_uri, result);
387 return E_NOTIMPL;
390 static HRESULT WINAPI opc_uri_GetSourceUri(IOpcPartUri *iface, IOpcUri **source_uri)
392 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
394 TRACE("iface %p, source_uri %p.\n", iface, source_uri);
396 return opc_source_uri_create(uri, source_uri);
399 static HRESULT WINAPI opc_uri_IsRelationshipsPartUri(IOpcPartUri *iface, BOOL *result)
401 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
403 TRACE("iface %p, result %p.\n", iface, result);
405 if (!result)
406 return E_POINTER;
408 *result = !uri->rels_part_uri;
410 return S_OK;
413 static const IOpcPartUriVtbl opc_part_uri_vtbl =
415 opc_uri_QueryInterface,
416 opc_uri_AddRef,
417 opc_uri_Release,
418 opc_uri_GetPropertyBSTR,
419 opc_uri_GetPropertyLength,
420 opc_uri_GetPropertyDWORD,
421 opc_uri_HasProperty,
422 opc_uri_GetAbsoluteUri,
423 opc_uri_GetAuthority,
424 opc_uri_GetDisplayUri,
425 opc_uri_GetDomain,
426 opc_uri_GetExtension,
427 opc_uri_GetFragment,
428 opc_uri_GetHost,
429 opc_uri_GetPassword,
430 opc_uri_GetPath,
431 opc_uri_GetPathAndQuery,
432 opc_uri_GetQuery,
433 opc_uri_GetRawUri,
434 opc_uri_GetSchemeName,
435 opc_uri_GetUserInfo,
436 opc_uri_GetUserName,
437 opc_uri_GetHostType,
438 opc_uri_GetPort,
439 opc_uri_GetScheme,
440 opc_uri_GetZone,
441 opc_uri_GetProperties,
442 opc_uri_IsEqual,
443 opc_uri_GetRelationshipsPartUri,
444 opc_uri_GetRelativeUri,
445 opc_uri_CombinePartUri,
446 opc_uri_ComparePartUri,
447 opc_uri_GetSourceUri,
448 opc_uri_IsRelationshipsPartUri,
451 static IUri *opc_part_uri_get_rels_uri(IUri *uri)
453 static const WCHAR relsdirW[] = {'/','_','r','e','l','s',0};
454 static const WCHAR relsextW[] = {'.','r','e','l','s',0};
455 WCHAR *start = NULL, *end, *ret;
456 IUri *rels_uri;
457 HRESULT hr;
458 DWORD len;
459 BSTR path;
461 if (FAILED(IUri_GetPath(uri, &path)))
462 return NULL;
464 if (FAILED(IUri_GetPropertyLength(uri, Uri_PROPERTY_PATH, &len, 0)))
466 SysFreeString(path);
467 return NULL;
470 end = strrchrW(path, '/');
471 if (end && end >= path + ARRAY_SIZE(relsdirW) - 1)
472 start = end - ARRAY_SIZE(relsdirW) + 1;
473 if (!start)
474 start = end;
476 /* Test if it's already relationships uri. */
477 if (len > ARRAY_SIZE(relsextW))
479 if (!strcmpW(path + len - ARRAY_SIZE(relsextW) + 1, relsextW))
481 if (start && !memcmp(start, relsdirW, ARRAY_SIZE(relsdirW) - sizeof(WCHAR)))
483 SysFreeString(path);
484 return NULL;
489 ret = heap_alloc((len + ARRAY_SIZE(relsextW) + ARRAY_SIZE(relsdirW)) * sizeof(WCHAR));
490 if (!ret)
492 SysFreeString(path);
493 return NULL;
495 ret[0] = 0;
497 if (start != path)
499 memcpy(ret, path, (start - path) * sizeof(WCHAR));
500 ret[start - path] = 0;
503 strcatW(ret, relsdirW);
504 strcatW(ret, end);
505 strcatW(ret, relsextW);
507 if (FAILED(hr = CreateUri(ret, Uri_CREATE_ALLOW_RELATIVE, 0, &rels_uri)))
508 WARN("Failed to create rels uri, hr %#x.\n", hr);
509 heap_free(ret);
510 SysFreeString(path);
512 return rels_uri;
515 static HRESULT opc_part_uri_init(struct opc_uri *object, struct opc_uri *source_uri, BOOL is_part_uri, IUri *uri)
517 object->IOpcPartUri_iface.lpVtbl = &opc_part_uri_vtbl;
518 object->refcount = 1;
519 object->is_part_uri = is_part_uri;
520 object->uri = uri;
521 IUri_AddRef(object->uri);
522 object->rels_part_uri = opc_part_uri_get_rels_uri(object->uri);
523 object->source_uri = source_uri;
524 if (object->source_uri)
525 IOpcPartUri_AddRef(&object->source_uri->IOpcPartUri_iface);
527 return S_OK;
530 static HRESULT opc_source_uri_create(struct opc_uri *uri, IOpcUri **out)
532 struct opc_uri *obj;
533 HRESULT hr;
535 if (!out)
536 return E_POINTER;
538 *out = NULL;
540 if (!uri->source_uri)
541 return OPC_E_RELATIONSHIP_URI_REQUIRED;
543 if (!(obj = heap_alloc_zero(sizeof(*obj))))
544 return E_OUTOFMEMORY;
546 if (FAILED(hr = opc_part_uri_init(obj, NULL, uri->source_uri->is_part_uri, uri->source_uri->uri)))
548 WARN("Failed to init part uri, hr %#x.\n", hr);
549 heap_free(obj);
550 return hr;
553 *out = (IOpcUri *)&obj->IOpcPartUri_iface;
555 TRACE("Created source uri %p.\n", *out);
557 return S_OK;
560 HRESULT opc_part_uri_create(IUri *uri, struct opc_uri *source_uri, IOpcPartUri **out)
562 struct opc_uri *obj;
563 HRESULT hr;
565 if (!(obj = heap_alloc_zero(sizeof(*obj))))
566 return E_OUTOFMEMORY;
568 if (FAILED(hr = opc_part_uri_init(obj, source_uri, TRUE, uri)))
570 WARN("Failed to init part uri, hr %#x.\n", hr);
571 heap_free(obj);
572 return hr;
575 *out = &obj->IOpcPartUri_iface;
576 TRACE("Created part uri %p.\n", *out);
577 return S_OK;
580 HRESULT opc_root_uri_create(IOpcUri **out)
582 static const WCHAR rootW[] = {'/',0};
583 struct opc_uri *obj;
584 HRESULT hr;
585 IUri *uri;
587 *out = NULL;
589 if (!(obj = heap_alloc_zero(sizeof(*obj))))
590 return E_OUTOFMEMORY;
592 if (FAILED(hr = CreateUri(rootW, Uri_CREATE_ALLOW_RELATIVE, 0, &uri)))
594 WARN("Failed to create rels uri, hr %#x.\n", hr);
595 heap_free(obj);
596 return hr;
599 hr = opc_part_uri_init(obj, NULL, FALSE, uri);
600 IUri_Release(uri);
601 if (FAILED(hr))
603 WARN("Failed to init uri, hr %#x.\n", hr);
604 heap_free(uri);
605 return hr;
608 *out = (IOpcUri *)&obj->IOpcPartUri_iface;
609 TRACE("Created part uri %p.\n", *out);
610 return S_OK;