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"
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
))
51 IOpcPartUri_AddRef(iface
);
55 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
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
);
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
);
78 if (uri
->rels_part_uri
)
79 IUri_Release(uri
->rels_part_uri
);
81 IOpcPartUri_Release(&uri
->source_uri
->IOpcPartUri_iface
);
82 IUri_Release(uri
->uri
);
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
,
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
);
320 if (uri
->is_part_uri
)
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
);
341 if (!uri
->rels_part_uri
)
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
,
353 FIXME("iface %p, part_uri %p, relative_uri %p stub!\n", iface
, part_uri
, relative_uri
);
358 static HRESULT WINAPI
opc_uri_CombinePartUri(IOpcPartUri
*iface
, IUri
*relative_uri
, IOpcPartUri
**combined
)
360 struct opc_uri
*uri
= impl_from_IOpcPartUri(iface
);
364 TRACE("iface %p, relative_uri %p, combined %p.\n", iface
, relative_uri
, combined
);
374 if (FAILED(hr
= CoInternetCombineIUri(uri
->uri
, relative_uri
, 0, &combined_uri
, 0)))
377 hr
= opc_part_uri_create(combined_uri
, NULL
, combined
);
378 IUri_Release(combined_uri
);
382 static HRESULT WINAPI
opc_uri_ComparePartUri(IOpcPartUri
*iface
, IOpcPartUri
*part_uri
,
385 FIXME("iface %p, part_uri %p, result %p stub!\n", iface
, part_uri
, result
);
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
);
408 *result
= !uri
->rels_part_uri
;
413 static const IOpcPartUriVtbl opc_part_uri_vtbl
=
415 opc_uri_QueryInterface
,
418 opc_uri_GetPropertyBSTR
,
419 opc_uri_GetPropertyLength
,
420 opc_uri_GetPropertyDWORD
,
422 opc_uri_GetAbsoluteUri
,
423 opc_uri_GetAuthority
,
424 opc_uri_GetDisplayUri
,
426 opc_uri_GetExtension
,
431 opc_uri_GetPathAndQuery
,
434 opc_uri_GetSchemeName
,
441 opc_uri_GetProperties
,
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
;
461 if (FAILED(IUri_GetPath(uri
, &path
)))
464 if (FAILED(IUri_GetPropertyLength(uri
, Uri_PROPERTY_PATH
, &len
, 0)))
470 end
= strrchrW(path
, '/');
471 if (end
&& end
>= path
+ ARRAY_SIZE(relsdirW
) - 1)
472 start
= end
- ARRAY_SIZE(relsdirW
) + 1;
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
)))
489 ret
= heap_alloc((len
+ ARRAY_SIZE(relsextW
) + ARRAY_SIZE(relsdirW
)) * sizeof(WCHAR
));
499 memcpy(ret
, path
, (start
- path
) * sizeof(WCHAR
));
500 ret
[start
- path
] = 0;
503 strcatW(ret
, relsdirW
);
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
);
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
;
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
);
530 static HRESULT
opc_source_uri_create(struct opc_uri
*uri
, IOpcUri
**out
)
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
);
553 *out
= (IOpcUri
*)&obj
->IOpcPartUri_iface
;
555 TRACE("Created source uri %p.\n", *out
);
560 HRESULT
opc_part_uri_create(IUri
*uri
, struct opc_uri
*source_uri
, IOpcPartUri
**out
)
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
);
575 *out
= &obj
->IOpcPartUri_iface
;
576 TRACE("Created part uri %p.\n", *out
);
580 HRESULT
opc_root_uri_create(IOpcUri
**out
)
582 static const WCHAR rootW
[] = {'/',0};
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
);
599 hr
= opc_part_uri_init(obj
, NULL
, FALSE
, uri
);
603 WARN("Failed to init uri, hr %#x.\n", hr
);
608 *out
= (IOpcUri
*)&obj
->IOpcPartUri_iface
;
609 TRACE("Created part uri %p.\n", *out
);