widl: Always check the runtimeclass interfaces presence.
[wine/zf.git] / dlls / wsdapi / discovery.c
blobfcbdfef2ab205da3411e0fdbf0551706eae7658c
1 /*
2 * Web Services on Devices
4 * Copyright 2017 Owen Rudge for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #define COBJMACROS
24 #define INITGUID
26 #include "wsdapi_internal.h"
27 #include "wine/debug.h"
28 #include "wine/heap.h"
29 #include "guiddef.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(wsdapi);
33 static inline IWSDiscoveryPublisherImpl *impl_from_IWSDiscoveryPublisher(IWSDiscoveryPublisher *iface)
35 return CONTAINING_RECORD(iface, IWSDiscoveryPublisherImpl, IWSDiscoveryPublisher_iface);
38 static HRESULT WINAPI IWSDiscoveryPublisherImpl_QueryInterface(IWSDiscoveryPublisher *iface, REFIID riid, void **ppv)
40 IWSDiscoveryPublisherImpl *This = impl_from_IWSDiscoveryPublisher(iface);
42 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppv);
44 if (!ppv)
46 WARN("Invalid parameter\n");
47 return E_INVALIDARG;
50 *ppv = NULL;
52 if (IsEqualIID(riid, &IID_IUnknown) ||
53 IsEqualIID(riid, &IID_IWSDiscoveryPublisher))
55 *ppv = &This->IWSDiscoveryPublisher_iface;
57 else
59 WARN("Unknown IID %s\n", debugstr_guid(riid));
60 return E_NOINTERFACE;
63 IUnknown_AddRef((IUnknown*)*ppv);
64 return S_OK;
67 static ULONG WINAPI IWSDiscoveryPublisherImpl_AddRef(IWSDiscoveryPublisher *iface)
69 IWSDiscoveryPublisherImpl *This = impl_from_IWSDiscoveryPublisher(iface);
70 ULONG ref = InterlockedIncrement(&This->ref);
72 TRACE("(%p) ref=%d\n", This, ref);
73 return ref;
76 static ULONG WINAPI IWSDiscoveryPublisherImpl_Release(IWSDiscoveryPublisher *iface)
78 IWSDiscoveryPublisherImpl *This = impl_from_IWSDiscoveryPublisher(iface);
79 ULONG ref = InterlockedDecrement(&This->ref);
80 struct notificationSink *sink, *cursor;
81 struct message_id *msg_id, *msg_id_cursor;
83 TRACE("(%p) ref=%d\n", This, ref);
85 if (ref == 0)
87 terminate_networking(This);
89 if (This->xmlContext != NULL)
91 IWSDXMLContext_Release(This->xmlContext);
94 LIST_FOR_EACH_ENTRY_SAFE(sink, cursor, &This->notificationSinks, struct notificationSink, entry)
96 IWSDiscoveryPublisherNotify_Release(sink->notificationSink);
97 list_remove(&sink->entry);
98 HeapFree(GetProcessHeap(), 0, sink);
101 DeleteCriticalSection(&This->notification_sink_critical_section);
103 LIST_FOR_EACH_ENTRY_SAFE(msg_id, msg_id_cursor, &This->message_ids, struct message_id, entry)
105 heap_free(msg_id->id);
106 list_remove(&msg_id->entry);
107 heap_free(msg_id);
110 DeleteCriticalSection(&This->message_ids_critical_section);
111 HeapFree(GetProcessHeap(), 0, This);
114 return ref;
117 static HRESULT WINAPI IWSDiscoveryPublisherImpl_SetAddressFamily(IWSDiscoveryPublisher *This, DWORD dwAddressFamily)
119 IWSDiscoveryPublisherImpl *impl = impl_from_IWSDiscoveryPublisher(This);
121 TRACE("(%p, %d)\n", This, dwAddressFamily);
123 /* Has the address family already been set? */
124 if (impl->addressFamily != 0)
126 return STG_E_INVALIDFUNCTION;
129 if ((dwAddressFamily == WSDAPI_ADDRESSFAMILY_IPV4) || (dwAddressFamily == WSDAPI_ADDRESSFAMILY_IPV6) ||
130 (dwAddressFamily == (WSDAPI_ADDRESSFAMILY_IPV4 | WSDAPI_ADDRESSFAMILY_IPV6)))
132 /* TODO: Check that the address family is supported by the system */
133 impl->addressFamily = dwAddressFamily;
134 return S_OK;
137 return E_INVALIDARG;
140 static HRESULT WINAPI IWSDiscoveryPublisherImpl_RegisterNotificationSink(IWSDiscoveryPublisher *This, IWSDiscoveryPublisherNotify *pSink)
142 IWSDiscoveryPublisherImpl *impl = impl_from_IWSDiscoveryPublisher(This);
143 struct notificationSink *sink;
145 TRACE("(%p, %p)\n", This, pSink);
147 if (pSink == NULL)
149 return E_INVALIDARG;
152 sink = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*sink));
154 if (!sink)
156 return E_OUTOFMEMORY;
159 sink->notificationSink = pSink;
160 IWSDiscoveryPublisherNotify_AddRef(pSink);
162 EnterCriticalSection(&impl->notification_sink_critical_section);
163 list_add_tail(&impl->notificationSinks, &sink->entry);
164 LeaveCriticalSection(&impl->notification_sink_critical_section);
166 if ((!impl->publisherStarted) && (!init_networking(impl)))
167 return E_FAIL;
169 return S_OK;
172 static HRESULT WINAPI IWSDiscoveryPublisherImpl_UnRegisterNotificationSink(IWSDiscoveryPublisher *This, IWSDiscoveryPublisherNotify *pSink)
174 IWSDiscoveryPublisherImpl *impl = impl_from_IWSDiscoveryPublisher(This);
175 struct notificationSink *sink;
177 TRACE("(%p, %p)\n", This, pSink);
179 if (pSink == NULL)
181 return E_INVALIDARG;
184 EnterCriticalSection(&impl->notification_sink_critical_section);
186 LIST_FOR_EACH_ENTRY(sink, &impl->notificationSinks, struct notificationSink, entry)
188 if (sink->notificationSink == pSink)
190 IWSDiscoveryPublisherNotify_Release(pSink);
191 list_remove(&sink->entry);
192 HeapFree(GetProcessHeap(), 0, sink);
194 LeaveCriticalSection(&impl->notification_sink_critical_section);
195 return S_OK;
199 LeaveCriticalSection(&impl->notification_sink_critical_section);
201 /* Notification sink is not registered */
202 return E_FAIL;
205 static HRESULT WINAPI IWSDiscoveryPublisherImpl_Publish(IWSDiscoveryPublisher *This, LPCWSTR pszId, ULONGLONG ullMetadataVersion, ULONGLONG ullInstanceId,
206 ULONGLONG ullMessageNumber, LPCWSTR pszSessionId, const WSD_NAME_LIST *pTypesList,
207 const WSD_URI_LIST *pScopesList, const WSD_URI_LIST *pXAddrsList)
209 return IWSDiscoveryPublisher_PublishEx(This, pszId, ullMetadataVersion, ullInstanceId, ullMessageNumber,
210 pszSessionId, pTypesList, pScopesList, pXAddrsList, NULL, NULL, NULL, NULL, NULL);
213 static HRESULT WINAPI IWSDiscoveryPublisherImpl_UnPublish(IWSDiscoveryPublisher *This, LPCWSTR pszId, ULONGLONG ullInstanceId, ULONGLONG ullMessageNumber,
214 LPCWSTR pszSessionId, const WSDXML_ELEMENT *pAny)
216 IWSDiscoveryPublisherImpl *impl = impl_from_IWSDiscoveryPublisher(This);
218 TRACE("(%p, %s, %s, %s, %s, %p)\n", This, debugstr_w(pszId), wine_dbgstr_longlong(ullInstanceId),
219 wine_dbgstr_longlong(ullMessageNumber), debugstr_w(pszSessionId), pAny);
221 if ((!impl->publisherStarted) || (pszId == NULL) || (lstrlenW(pszId) > WSD_MAX_TEXT_LENGTH) ||
222 ((pszSessionId != NULL) && (lstrlenW(pszSessionId) > WSD_MAX_TEXT_LENGTH)))
224 return E_INVALIDARG;
227 return send_bye_message(impl, pszId, ullInstanceId, ullMessageNumber, pszSessionId, pAny);
230 static HRESULT WINAPI IWSDiscoveryPublisherImpl_MatchProbe(IWSDiscoveryPublisher *This, const WSD_SOAP_MESSAGE *pProbeMessage,
231 IWSDMessageParameters *pMessageParameters, LPCWSTR pszId, ULONGLONG ullMetadataVersion,
232 ULONGLONG ullInstanceId, ULONGLONG ullMessageNumber, LPCWSTR pszSessionId,
233 const WSD_NAME_LIST *pTypesList, const WSD_URI_LIST *pScopesList,
234 const WSD_URI_LIST *pXAddrsList)
236 TRACE("(%p, %p, %p, %s, %s, %s, %s, %s, %p, %p, %p)\n", This, pProbeMessage, pMessageParameters, debugstr_w(pszId),
237 wine_dbgstr_longlong(ullMetadataVersion), wine_dbgstr_longlong(ullInstanceId), wine_dbgstr_longlong(ullMessageNumber), debugstr_w(pszSessionId),
238 pTypesList, pScopesList, pXAddrsList);
240 return IWSDiscoveryPublisher_MatchProbeEx(This, pProbeMessage, pMessageParameters, pszId, ullMetadataVersion,
241 ullInstanceId, ullMessageNumber, pszSessionId, pTypesList, pScopesList, pXAddrsList, NULL, NULL, NULL, NULL,
242 NULL);
245 static HRESULT WINAPI IWSDiscoveryPublisherImpl_MatchResolve(IWSDiscoveryPublisher *This, const WSD_SOAP_MESSAGE *pResolveMessage,
246 IWSDMessageParameters *pMessageParameters, LPCWSTR pszId, ULONGLONG ullMetadataVersion,
247 ULONGLONG ullInstanceId, ULONGLONG ullMessageNumber, LPCWSTR pszSessionId,
248 const WSD_NAME_LIST *pTypesList, const WSD_URI_LIST *pScopesList,
249 const WSD_URI_LIST *pXAddrsList)
251 FIXME("(%p, %p, %p, %s, %s, %s, %s, %s, %p, %p, %p)\n", This, pResolveMessage, pMessageParameters, debugstr_w(pszId),
252 wine_dbgstr_longlong(ullMetadataVersion), wine_dbgstr_longlong(ullInstanceId), wine_dbgstr_longlong(ullMessageNumber), debugstr_w(pszSessionId),
253 pTypesList, pScopesList, pXAddrsList);
255 return E_NOTIMPL;
258 static HRESULT WINAPI IWSDiscoveryPublisherImpl_PublishEx(IWSDiscoveryPublisher *This, LPCWSTR pszId, ULONGLONG ullMetadataVersion,
259 ULONGLONG ullInstanceId, ULONGLONG ullMessageNumber, LPCWSTR pszSessionId,
260 const WSD_NAME_LIST *pTypesList, const WSD_URI_LIST *pScopesList,
261 const WSD_URI_LIST *pXAddrsList, const WSDXML_ELEMENT *pHeaderAny,
262 const WSDXML_ELEMENT *pReferenceParameterAny, const WSDXML_ELEMENT *pPolicyAny,
263 const WSDXML_ELEMENT *pEndpointReferenceAny, const WSDXML_ELEMENT *pAny)
265 IWSDiscoveryPublisherImpl *impl = impl_from_IWSDiscoveryPublisher(This);
267 TRACE("(%p, %s, %s, %s, %s, %s, %p, %p, %p, %p, %p, %p, %p, %p)\n", This, debugstr_w(pszId), wine_dbgstr_longlong(ullMetadataVersion),
268 wine_dbgstr_longlong(ullInstanceId), wine_dbgstr_longlong(ullMessageNumber), debugstr_w(pszSessionId), pTypesList, pScopesList, pXAddrsList,
269 pHeaderAny, pReferenceParameterAny, pPolicyAny, pEndpointReferenceAny, pAny);
271 if ((!impl->publisherStarted) || (pszId == NULL) || (lstrlenW(pszId) > WSD_MAX_TEXT_LENGTH) ||
272 ((pszSessionId != NULL) && (lstrlenW(pszSessionId) > WSD_MAX_TEXT_LENGTH)))
274 return E_INVALIDARG;
277 return send_hello_message(impl, pszId, ullMetadataVersion, ullInstanceId, ullMessageNumber, pszSessionId,
278 pTypesList, pScopesList, pXAddrsList, pHeaderAny, pReferenceParameterAny, pEndpointReferenceAny, pAny);
281 static BOOL is_name_in_list(WSDXML_NAME *name, const WSD_NAME_LIST *list)
283 const WSD_NAME_LIST *next = list;
285 while (next != NULL)
287 if ((lstrcmpW(next->Element->LocalName, name->LocalName) == 0) &&
288 (lstrcmpW(next->Element->Space->PreferredPrefix, name->Space->PreferredPrefix) == 0))
290 return TRUE;
293 next = next->Next;
296 return FALSE;
299 static HRESULT WINAPI IWSDiscoveryPublisherImpl_MatchProbeEx(IWSDiscoveryPublisher *This, const WSD_SOAP_MESSAGE *pProbeMessage,
300 IWSDMessageParameters *pMessageParameters, LPCWSTR pszId, ULONGLONG ullMetadataVersion,
301 ULONGLONG ullInstanceId, ULONGLONG ullMessageNumber, LPCWSTR pszSessionId,
302 const WSD_NAME_LIST *pTypesList, const WSD_URI_LIST *pScopesList,
303 const WSD_URI_LIST *pXAddrsList, const WSDXML_ELEMENT *pHeaderAny,
304 const WSDXML_ELEMENT *pReferenceParameterAny, const WSDXML_ELEMENT *pPolicyAny,
305 const WSDXML_ELEMENT *pEndpointReferenceAny, const WSDXML_ELEMENT *pAny)
307 IWSDiscoveryPublisherImpl *impl = impl_from_IWSDiscoveryPublisher(This);
308 WSD_NAME_LIST *next_name;
309 WSD_PROBE *probe_msg;
311 TRACE("(%p, %p, %p, %s, %s, %s, %s, %s, %p, %p, %p, %p, %p, %p, %p, %p)\n", This, pProbeMessage, pMessageParameters, debugstr_w(pszId),
312 wine_dbgstr_longlong(ullMetadataVersion), wine_dbgstr_longlong(ullInstanceId), wine_dbgstr_longlong(ullMessageNumber), debugstr_w(pszSessionId),
313 pTypesList, pScopesList, pXAddrsList, pHeaderAny, pReferenceParameterAny, pPolicyAny, pEndpointReferenceAny, pAny);
315 if (!impl->publisherStarted) return E_ABORT;
317 if ((pszId == NULL) || (lstrlenW(pszId) > WSD_MAX_TEXT_LENGTH) ||
318 ((pszSessionId != NULL) && (lstrlenW(pszSessionId) > WSD_MAX_TEXT_LENGTH)) || (pProbeMessage == NULL) ||
319 (pProbeMessage->Body == NULL))
321 return E_INVALIDARG;
324 probe_msg = (WSD_PROBE *) pProbeMessage->Body;
325 next_name = probe_msg->Types;
327 /* Verify that all names in the probe message are present in the types list */
328 while (next_name != NULL)
330 /* If a name isn't present, return success; we simply don't send a Probe Match message */
331 if (!is_name_in_list(next_name->Element, pTypesList)) return S_OK;
333 next_name = next_name->Next;
336 if ((probe_msg->Scopes != NULL) && (probe_msg->Scopes->Scopes != NULL))
337 FIXME("Scopes matching currently unimplemented\n");
339 return send_probe_matches_message(impl, pProbeMessage, pMessageParameters, pszId, ullMetadataVersion, ullInstanceId,
340 ullMessageNumber, pszSessionId, pTypesList, pScopesList, pXAddrsList, pHeaderAny, pReferenceParameterAny,
341 pEndpointReferenceAny, pAny);
344 static HRESULT WINAPI IWSDiscoveryPublisherImpl_MatchResolveEx(IWSDiscoveryPublisher *This, const WSD_SOAP_MESSAGE *pResolveMessage,
345 IWSDMessageParameters *pMessageParameters, LPCWSTR pszId, ULONGLONG ullMetadataVersion,
346 ULONGLONG ullInstanceId, ULONGLONG ullMessageNumber, LPCWSTR pszSessionId,
347 const WSD_NAME_LIST *pTypesList, const WSD_URI_LIST *pScopesList,
348 const WSD_URI_LIST *pXAddrsList, const WSDXML_ELEMENT *pHeaderAny,
349 const WSDXML_ELEMENT *pReferenceParameterAny, const WSDXML_ELEMENT *pPolicyAny,
350 const WSDXML_ELEMENT *pEndpointReferenceAny, const WSDXML_ELEMENT *pAny)
352 FIXME("(%p, %p, %p, %s, %s, %s, %s, %s, %p, %p, %p, %p, %p, %p, %p, %p)\n", This, pResolveMessage, pMessageParameters, debugstr_w(pszId),
353 wine_dbgstr_longlong(ullMetadataVersion), wine_dbgstr_longlong(ullInstanceId), wine_dbgstr_longlong(ullMessageNumber), debugstr_w(pszSessionId),
354 pTypesList, pScopesList, pXAddrsList, pHeaderAny, pReferenceParameterAny, pPolicyAny, pEndpointReferenceAny, pAny);
356 return E_NOTIMPL;
359 static HRESULT WINAPI IWSDiscoveryPublisherImpl_RegisterScopeMatchingRule(IWSDiscoveryPublisher *This, IWSDScopeMatchingRule *pScopeMatchingRule)
361 FIXME("(%p, %p)\n", This, pScopeMatchingRule);
362 return E_NOTIMPL;
365 static HRESULT WINAPI IWSDiscoveryPublisherImpl_UnRegisterScopeMatchingRule(IWSDiscoveryPublisher *This, IWSDScopeMatchingRule *pScopeMatchingRule)
367 FIXME("(%p, %p)\n", This, pScopeMatchingRule);
368 return E_NOTIMPL;
371 static HRESULT WINAPI IWSDiscoveryPublisherImpl_GetXMLContext(IWSDiscoveryPublisher *This, IWSDXMLContext **ppContext)
373 IWSDiscoveryPublisherImpl *impl = impl_from_IWSDiscoveryPublisher(This);
375 TRACE("%p, %p)\n", This, ppContext);
377 if (ppContext == NULL)
378 return E_INVALIDARG;
380 if (impl->xmlContext != NULL)
382 IWSDXMLContext_AddRef(impl->xmlContext);
385 *ppContext = impl->xmlContext;
386 return S_OK;
389 static const IWSDiscoveryPublisherVtbl publisher_vtbl =
391 IWSDiscoveryPublisherImpl_QueryInterface,
392 IWSDiscoveryPublisherImpl_AddRef,
393 IWSDiscoveryPublisherImpl_Release,
394 IWSDiscoveryPublisherImpl_SetAddressFamily,
395 IWSDiscoveryPublisherImpl_RegisterNotificationSink,
396 IWSDiscoveryPublisherImpl_UnRegisterNotificationSink,
397 IWSDiscoveryPublisherImpl_Publish,
398 IWSDiscoveryPublisherImpl_UnPublish,
399 IWSDiscoveryPublisherImpl_MatchProbe,
400 IWSDiscoveryPublisherImpl_MatchResolve,
401 IWSDiscoveryPublisherImpl_PublishEx,
402 IWSDiscoveryPublisherImpl_MatchProbeEx,
403 IWSDiscoveryPublisherImpl_MatchResolveEx,
404 IWSDiscoveryPublisherImpl_RegisterScopeMatchingRule,
405 IWSDiscoveryPublisherImpl_UnRegisterScopeMatchingRule,
406 IWSDiscoveryPublisherImpl_GetXMLContext
409 HRESULT WINAPI WSDCreateDiscoveryPublisher(IWSDXMLContext *pContext, IWSDiscoveryPublisher **ppPublisher)
411 IWSDiscoveryPublisherImpl *obj;
412 HRESULT ret;
414 TRACE("(%p, %p)\n", pContext, ppPublisher);
416 if (ppPublisher == NULL)
418 WARN("Invalid parameter: ppPublisher == NULL\n");
419 return E_POINTER;
422 *ppPublisher = NULL;
424 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*obj));
426 if (!obj)
428 WARN("Out of memory\n");
429 return E_OUTOFMEMORY;
432 obj->IWSDiscoveryPublisher_iface.lpVtbl = &publisher_vtbl;
433 obj->ref = 1;
435 if (pContext == NULL)
437 ret = WSDXMLCreateContext(&obj->xmlContext);
439 if (FAILED(ret))
441 WARN("Unable to create XML context\n");
442 heap_free(obj);
443 return ret;
446 else
448 obj->xmlContext = pContext;
449 IWSDXMLContext_AddRef(pContext);
452 ret = register_namespaces(obj->xmlContext);
454 if (FAILED(ret))
456 WARN("Unable to register default namespaces\n");
457 heap_free(obj);
459 return ret;
462 InitializeCriticalSection(&obj->notification_sink_critical_section);
463 list_init(&obj->notificationSinks);
465 InitializeCriticalSection(&obj->message_ids_critical_section);
466 list_init(&obj->message_ids);
468 *ppPublisher = &obj->IWSDiscoveryPublisher_iface;
469 TRACE("Returning iface %p\n", *ppPublisher);
471 return S_OK;