ntoskrnl/tests: Test the contents of the user IO_STATUS_BLOCK.
[wine/zf.git] / dlls / opcservices / uri.c
blob5cba14aa78bc3f5727f76edd97c2787ab5a988b9
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"
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))
49 *out = iface;
50 IOpcPartUri_AddRef(iface);
51 return S_OK;
54 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
55 return E_NOINTERFACE;
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 increasing refcount to %u.\n", iface, refcount);
65 return 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 decreasing refcount to %u.\n", iface, refcount);
75 if (!refcount)
77 if (uri->rels_part_uri)
78 IUri_Release(uri->rels_part_uri);
79 if (uri->source_uri)
80 IOpcPartUri_Release(&uri->source_uri->IOpcPartUri_iface);
81 IUri_Release(uri->uri);
82 heap_free(uri);
85 return refcount;
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 %#x.\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 %#x.\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 %#x.\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,
119 BOOL *has_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);
314 if (!is_equal)
315 return E_POINTER;
317 if (!comparand)
319 if (uri->is_part_uri)
321 *is_equal = FALSE;
322 return S_OK;
325 return E_POINTER;
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);
337 if (!part_uri)
338 return E_POINTER;
340 if (!uri->rels_part_uri)
342 *part_uri = NULL;
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,
350 IUri **relative_uri)
352 FIXME("iface %p, part_uri %p, relative_uri %p stub!\n", iface, part_uri, relative_uri);
354 return E_NOTIMPL;
357 static HRESULT WINAPI opc_uri_CombinePartUri(IOpcPartUri *iface, IUri *relative_uri, IOpcPartUri **combined)
359 struct opc_uri *uri = impl_from_IOpcPartUri(iface);
360 IUri *combined_uri;
361 HRESULT hr;
363 TRACE("iface %p, relative_uri %p, combined %p.\n", iface, relative_uri, combined);
365 if (!combined)
366 return E_POINTER;
368 *combined = NULL;
370 if (!relative_uri)
371 return E_POINTER;
373 if (FAILED(hr = CoInternetCombineIUri(uri->uri, relative_uri, 0, &combined_uri, 0)))
374 return hr;
376 hr = opc_part_uri_create(combined_uri, NULL, combined);
377 IUri_Release(combined_uri);
378 return hr;
381 static HRESULT WINAPI opc_uri_ComparePartUri(IOpcPartUri *iface, IOpcPartUri *part_uri,
382 INT32 *result)
384 FIXME("iface %p, part_uri %p, result %p stub!\n", iface, part_uri, result);
386 return E_NOTIMPL;
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);
404 if (!result)
405 return E_POINTER;
407 *result = !uri->rels_part_uri;
409 return S_OK;
412 static const IOpcPartUriVtbl opc_part_uri_vtbl =
414 opc_uri_QueryInterface,
415 opc_uri_AddRef,
416 opc_uri_Release,
417 opc_uri_GetPropertyBSTR,
418 opc_uri_GetPropertyLength,
419 opc_uri_GetPropertyDWORD,
420 opc_uri_HasProperty,
421 opc_uri_GetAbsoluteUri,
422 opc_uri_GetAuthority,
423 opc_uri_GetDisplayUri,
424 opc_uri_GetDomain,
425 opc_uri_GetExtension,
426 opc_uri_GetFragment,
427 opc_uri_GetHost,
428 opc_uri_GetPassword,
429 opc_uri_GetPath,
430 opc_uri_GetPathAndQuery,
431 opc_uri_GetQuery,
432 opc_uri_GetRawUri,
433 opc_uri_GetSchemeName,
434 opc_uri_GetUserInfo,
435 opc_uri_GetUserName,
436 opc_uri_GetHostType,
437 opc_uri_GetPort,
438 opc_uri_GetScheme,
439 opc_uri_GetZone,
440 opc_uri_GetProperties,
441 opc_uri_IsEqual,
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;
455 IUri *rels_uri;
456 HRESULT hr;
457 DWORD len;
458 BSTR path;
460 if (FAILED(IUri_GetPath(uri, &path)))
461 return NULL;
463 if (FAILED(IUri_GetPropertyLength(uri, Uri_PROPERTY_PATH, &len, 0)))
465 SysFreeString(path);
466 return NULL;
469 end = wcsrchr(path, '/');
470 if (end && end >= path + ARRAY_SIZE(relsdirW) - 1)
471 start = end - ARRAY_SIZE(relsdirW) + 1;
472 if (!start)
473 start = end;
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)))
482 SysFreeString(path);
483 return NULL;
488 ret = heap_alloc((len + ARRAY_SIZE(relsextW) + ARRAY_SIZE(relsdirW)) * sizeof(WCHAR));
489 if (!ret)
491 SysFreeString(path);
492 return NULL;
494 ret[0] = 0;
496 if (start != path)
498 memcpy(ret, path, (start - path) * sizeof(WCHAR));
499 ret[start - path] = 0;
502 lstrcatW(ret, relsdirW);
503 lstrcatW(ret, end);
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 %#x.\n", hr);
508 heap_free(ret);
509 SysFreeString(path);
511 return rels_uri;
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;
519 object->uri = 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);
526 return S_OK;
529 static HRESULT opc_source_uri_create(struct opc_uri *uri, IOpcUri **out)
531 struct opc_uri *obj;
532 HRESULT hr;
534 if (!out)
535 return E_POINTER;
537 *out = NULL;
539 if (!uri->source_uri)
540 return OPC_E_RELATIONSHIP_URI_REQUIRED;
542 if (!(obj = heap_alloc_zero(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 %#x.\n", hr);
548 heap_free(obj);
549 return hr;
552 *out = (IOpcUri *)&obj->IOpcPartUri_iface;
554 TRACE("Created source uri %p.\n", *out);
556 return S_OK;
559 HRESULT opc_part_uri_create(IUri *uri, struct opc_uri *source_uri, IOpcPartUri **out)
561 struct opc_uri *obj;
562 HRESULT hr;
564 if (!(obj = heap_alloc_zero(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 %#x.\n", hr);
570 heap_free(obj);
571 return hr;
574 *out = &obj->IOpcPartUri_iface;
575 TRACE("Created part uri %p.\n", *out);
576 return S_OK;
579 HRESULT opc_root_uri_create(IOpcUri **out)
581 struct opc_uri *obj;
582 HRESULT hr;
583 IUri *uri;
585 *out = NULL;
587 if (!(obj = heap_alloc_zero(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 %#x.\n", hr);
593 heap_free(obj);
594 return hr;
597 hr = opc_part_uri_init(obj, NULL, FALSE, uri);
598 IUri_Release(uri);
599 if (FAILED(hr))
601 WARN("Failed to init uri, hr %#x.\n", hr);
602 heap_free(uri);
603 return hr;
606 *out = (IOpcUri *)&obj->IOpcPartUri_iface;
607 TRACE("Created part uri %p.\n", *out);
608 return S_OK;