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
26 #include "wsdapi_internal.h"
27 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(wsdapi
);
32 static inline IWSDiscoveryPublisherImpl
*impl_from_IWSDiscoveryPublisher(IWSDiscoveryPublisher
*iface
)
34 return CONTAINING_RECORD(iface
, IWSDiscoveryPublisherImpl
, IWSDiscoveryPublisher_iface
);
37 static HRESULT WINAPI
IWSDiscoveryPublisherImpl_QueryInterface(IWSDiscoveryPublisher
*iface
, REFIID riid
, void **ppv
)
39 IWSDiscoveryPublisherImpl
*This
= impl_from_IWSDiscoveryPublisher(iface
);
41 TRACE("(%p, %s, %p)\n", This
, debugstr_guid(riid
), ppv
);
45 WARN("Invalid parameter\n");
51 if (IsEqualIID(riid
, &IID_IUnknown
) ||
52 IsEqualIID(riid
, &IID_IWSDiscoveryPublisher
))
54 *ppv
= &This
->IWSDiscoveryPublisher_iface
;
58 WARN("Unknown IID %s\n", debugstr_guid(riid
));
62 IUnknown_AddRef((IUnknown
*)*ppv
);
66 static ULONG WINAPI
IWSDiscoveryPublisherImpl_AddRef(IWSDiscoveryPublisher
*iface
)
68 IWSDiscoveryPublisherImpl
*This
= impl_from_IWSDiscoveryPublisher(iface
);
69 ULONG ref
= InterlockedIncrement(&This
->ref
);
71 TRACE("(%p) ref=%ld\n", This
, ref
);
75 static ULONG WINAPI
IWSDiscoveryPublisherImpl_Release(IWSDiscoveryPublisher
*iface
)
77 IWSDiscoveryPublisherImpl
*This
= impl_from_IWSDiscoveryPublisher(iface
);
78 ULONG ref
= InterlockedDecrement(&This
->ref
);
79 struct notificationSink
*sink
, *cursor
;
80 struct message_id
*msg_id
, *msg_id_cursor
;
82 TRACE("(%p) ref=%ld\n", This
, ref
);
86 terminate_networking(This
);
88 if (This
->xmlContext
!= NULL
)
90 IWSDXMLContext_Release(This
->xmlContext
);
93 LIST_FOR_EACH_ENTRY_SAFE(sink
, cursor
, &This
->notificationSinks
, struct notificationSink
, entry
)
95 IWSDiscoveryPublisherNotify_Release(sink
->notificationSink
);
96 list_remove(&sink
->entry
);
100 DeleteCriticalSection(&This
->notification_sink_critical_section
);
102 LIST_FOR_EACH_ENTRY_SAFE(msg_id
, msg_id_cursor
, &This
->message_ids
, struct message_id
, entry
)
105 list_remove(&msg_id
->entry
);
109 DeleteCriticalSection(&This
->message_ids_critical_section
);
116 static HRESULT WINAPI
IWSDiscoveryPublisherImpl_SetAddressFamily(IWSDiscoveryPublisher
*This
, DWORD dwAddressFamily
)
118 IWSDiscoveryPublisherImpl
*impl
= impl_from_IWSDiscoveryPublisher(This
);
120 TRACE("(%p, %ld)\n", This
, dwAddressFamily
);
122 /* Has the address family already been set? */
123 if (impl
->addressFamily
!= 0)
125 return STG_E_INVALIDFUNCTION
;
128 if ((dwAddressFamily
== WSDAPI_ADDRESSFAMILY_IPV4
) || (dwAddressFamily
== WSDAPI_ADDRESSFAMILY_IPV6
) ||
129 (dwAddressFamily
== (WSDAPI_ADDRESSFAMILY_IPV4
| WSDAPI_ADDRESSFAMILY_IPV6
)))
131 /* TODO: Check that the address family is supported by the system */
132 impl
->addressFamily
= dwAddressFamily
;
139 static HRESULT WINAPI
IWSDiscoveryPublisherImpl_RegisterNotificationSink(IWSDiscoveryPublisher
*This
, IWSDiscoveryPublisherNotify
*pSink
)
141 IWSDiscoveryPublisherImpl
*impl
= impl_from_IWSDiscoveryPublisher(This
);
142 struct notificationSink
*sink
;
144 TRACE("(%p, %p)\n", This
, pSink
);
151 sink
= calloc(1, sizeof(*sink
));
155 return E_OUTOFMEMORY
;
158 sink
->notificationSink
= pSink
;
159 IWSDiscoveryPublisherNotify_AddRef(pSink
);
161 EnterCriticalSection(&impl
->notification_sink_critical_section
);
162 list_add_tail(&impl
->notificationSinks
, &sink
->entry
);
163 LeaveCriticalSection(&impl
->notification_sink_critical_section
);
165 if ((!impl
->publisherStarted
) && (!init_networking(impl
)))
171 static HRESULT WINAPI
IWSDiscoveryPublisherImpl_UnRegisterNotificationSink(IWSDiscoveryPublisher
*This
, IWSDiscoveryPublisherNotify
*pSink
)
173 IWSDiscoveryPublisherImpl
*impl
= impl_from_IWSDiscoveryPublisher(This
);
174 struct notificationSink
*sink
;
176 TRACE("(%p, %p)\n", This
, pSink
);
183 EnterCriticalSection(&impl
->notification_sink_critical_section
);
185 LIST_FOR_EACH_ENTRY(sink
, &impl
->notificationSinks
, struct notificationSink
, entry
)
187 if (sink
->notificationSink
== pSink
)
189 IWSDiscoveryPublisherNotify_Release(pSink
);
190 list_remove(&sink
->entry
);
193 LeaveCriticalSection(&impl
->notification_sink_critical_section
);
198 LeaveCriticalSection(&impl
->notification_sink_critical_section
);
200 /* Notification sink is not registered */
204 static HRESULT WINAPI
IWSDiscoveryPublisherImpl_Publish(IWSDiscoveryPublisher
*This
, LPCWSTR pszId
, ULONGLONG ullMetadataVersion
, ULONGLONG ullInstanceId
,
205 ULONGLONG ullMessageNumber
, LPCWSTR pszSessionId
, const WSD_NAME_LIST
*pTypesList
,
206 const WSD_URI_LIST
*pScopesList
, const WSD_URI_LIST
*pXAddrsList
)
208 return IWSDiscoveryPublisher_PublishEx(This
, pszId
, ullMetadataVersion
, ullInstanceId
, ullMessageNumber
,
209 pszSessionId
, pTypesList
, pScopesList
, pXAddrsList
, NULL
, NULL
, NULL
, NULL
, NULL
);
212 static HRESULT WINAPI
IWSDiscoveryPublisherImpl_UnPublish(IWSDiscoveryPublisher
*This
, LPCWSTR pszId
, ULONGLONG ullInstanceId
, ULONGLONG ullMessageNumber
,
213 LPCWSTR pszSessionId
, const WSDXML_ELEMENT
*pAny
)
215 IWSDiscoveryPublisherImpl
*impl
= impl_from_IWSDiscoveryPublisher(This
);
217 TRACE("(%p, %s, %s, %s, %s, %p)\n", This
, debugstr_w(pszId
), wine_dbgstr_longlong(ullInstanceId
),
218 wine_dbgstr_longlong(ullMessageNumber
), debugstr_w(pszSessionId
), pAny
);
220 if ((!impl
->publisherStarted
) || (pszId
== NULL
) || (lstrlenW(pszId
) > WSD_MAX_TEXT_LENGTH
) ||
221 ((pszSessionId
!= NULL
) && (lstrlenW(pszSessionId
) > WSD_MAX_TEXT_LENGTH
)))
226 return send_bye_message(impl
, pszId
, ullInstanceId
, ullMessageNumber
, pszSessionId
, pAny
);
229 static HRESULT WINAPI
IWSDiscoveryPublisherImpl_MatchProbe(IWSDiscoveryPublisher
*This
, const WSD_SOAP_MESSAGE
*pProbeMessage
,
230 IWSDMessageParameters
*pMessageParameters
, LPCWSTR pszId
, ULONGLONG ullMetadataVersion
,
231 ULONGLONG ullInstanceId
, ULONGLONG ullMessageNumber
, LPCWSTR pszSessionId
,
232 const WSD_NAME_LIST
*pTypesList
, const WSD_URI_LIST
*pScopesList
,
233 const WSD_URI_LIST
*pXAddrsList
)
235 TRACE("(%p, %p, %p, %s, %s, %s, %s, %s, %p, %p, %p)\n", This
, pProbeMessage
, pMessageParameters
, debugstr_w(pszId
),
236 wine_dbgstr_longlong(ullMetadataVersion
), wine_dbgstr_longlong(ullInstanceId
), wine_dbgstr_longlong(ullMessageNumber
), debugstr_w(pszSessionId
),
237 pTypesList
, pScopesList
, pXAddrsList
);
239 return IWSDiscoveryPublisher_MatchProbeEx(This
, pProbeMessage
, pMessageParameters
, pszId
, ullMetadataVersion
,
240 ullInstanceId
, ullMessageNumber
, pszSessionId
, pTypesList
, pScopesList
, pXAddrsList
, NULL
, NULL
, NULL
, NULL
,
244 static HRESULT WINAPI
IWSDiscoveryPublisherImpl_MatchResolve(IWSDiscoveryPublisher
*This
, const WSD_SOAP_MESSAGE
*pResolveMessage
,
245 IWSDMessageParameters
*pMessageParameters
, LPCWSTR pszId
, ULONGLONG ullMetadataVersion
,
246 ULONGLONG ullInstanceId
, ULONGLONG ullMessageNumber
, LPCWSTR pszSessionId
,
247 const WSD_NAME_LIST
*pTypesList
, const WSD_URI_LIST
*pScopesList
,
248 const WSD_URI_LIST
*pXAddrsList
)
250 FIXME("(%p, %p, %p, %s, %s, %s, %s, %s, %p, %p, %p)\n", This
, pResolveMessage
, pMessageParameters
, debugstr_w(pszId
),
251 wine_dbgstr_longlong(ullMetadataVersion
), wine_dbgstr_longlong(ullInstanceId
), wine_dbgstr_longlong(ullMessageNumber
), debugstr_w(pszSessionId
),
252 pTypesList
, pScopesList
, pXAddrsList
);
257 static HRESULT WINAPI
IWSDiscoveryPublisherImpl_PublishEx(IWSDiscoveryPublisher
*This
, LPCWSTR pszId
, ULONGLONG ullMetadataVersion
,
258 ULONGLONG ullInstanceId
, ULONGLONG ullMessageNumber
, LPCWSTR pszSessionId
,
259 const WSD_NAME_LIST
*pTypesList
, const WSD_URI_LIST
*pScopesList
,
260 const WSD_URI_LIST
*pXAddrsList
, const WSDXML_ELEMENT
*pHeaderAny
,
261 const WSDXML_ELEMENT
*pReferenceParameterAny
, const WSDXML_ELEMENT
*pPolicyAny
,
262 const WSDXML_ELEMENT
*pEndpointReferenceAny
, const WSDXML_ELEMENT
*pAny
)
264 IWSDiscoveryPublisherImpl
*impl
= impl_from_IWSDiscoveryPublisher(This
);
266 TRACE("(%p, %s, %s, %s, %s, %s, %p, %p, %p, %p, %p, %p, %p, %p)\n", This
, debugstr_w(pszId
), wine_dbgstr_longlong(ullMetadataVersion
),
267 wine_dbgstr_longlong(ullInstanceId
), wine_dbgstr_longlong(ullMessageNumber
), debugstr_w(pszSessionId
), pTypesList
, pScopesList
, pXAddrsList
,
268 pHeaderAny
, pReferenceParameterAny
, pPolicyAny
, pEndpointReferenceAny
, pAny
);
270 if ((!impl
->publisherStarted
) || (pszId
== NULL
) || (lstrlenW(pszId
) > WSD_MAX_TEXT_LENGTH
) ||
271 ((pszSessionId
!= NULL
) && (lstrlenW(pszSessionId
) > WSD_MAX_TEXT_LENGTH
)))
276 return send_hello_message(impl
, pszId
, ullMetadataVersion
, ullInstanceId
, ullMessageNumber
, pszSessionId
,
277 pTypesList
, pScopesList
, pXAddrsList
, pHeaderAny
, pReferenceParameterAny
, pEndpointReferenceAny
, pAny
);
280 static BOOL
is_name_in_list(WSDXML_NAME
*name
, const WSD_NAME_LIST
*list
)
282 const WSD_NAME_LIST
*next
= list
;
286 if ((lstrcmpW(next
->Element
->LocalName
, name
->LocalName
) == 0) &&
287 (lstrcmpW(next
->Element
->Space
->PreferredPrefix
, name
->Space
->PreferredPrefix
) == 0))
298 static HRESULT WINAPI
IWSDiscoveryPublisherImpl_MatchProbeEx(IWSDiscoveryPublisher
*This
, const WSD_SOAP_MESSAGE
*pProbeMessage
,
299 IWSDMessageParameters
*pMessageParameters
, LPCWSTR pszId
, ULONGLONG ullMetadataVersion
,
300 ULONGLONG ullInstanceId
, ULONGLONG ullMessageNumber
, LPCWSTR pszSessionId
,
301 const WSD_NAME_LIST
*pTypesList
, const WSD_URI_LIST
*pScopesList
,
302 const WSD_URI_LIST
*pXAddrsList
, const WSDXML_ELEMENT
*pHeaderAny
,
303 const WSDXML_ELEMENT
*pReferenceParameterAny
, const WSDXML_ELEMENT
*pPolicyAny
,
304 const WSDXML_ELEMENT
*pEndpointReferenceAny
, const WSDXML_ELEMENT
*pAny
)
306 IWSDiscoveryPublisherImpl
*impl
= impl_from_IWSDiscoveryPublisher(This
);
307 WSD_NAME_LIST
*next_name
;
308 WSD_PROBE
*probe_msg
;
310 TRACE("(%p, %p, %p, %s, %s, %s, %s, %s, %p, %p, %p, %p, %p, %p, %p, %p)\n", This
, pProbeMessage
, pMessageParameters
, debugstr_w(pszId
),
311 wine_dbgstr_longlong(ullMetadataVersion
), wine_dbgstr_longlong(ullInstanceId
), wine_dbgstr_longlong(ullMessageNumber
), debugstr_w(pszSessionId
),
312 pTypesList
, pScopesList
, pXAddrsList
, pHeaderAny
, pReferenceParameterAny
, pPolicyAny
, pEndpointReferenceAny
, pAny
);
314 if (!impl
->publisherStarted
) return E_ABORT
;
316 if ((pszId
== NULL
) || (lstrlenW(pszId
) > WSD_MAX_TEXT_LENGTH
) ||
317 ((pszSessionId
!= NULL
) && (lstrlenW(pszSessionId
) > WSD_MAX_TEXT_LENGTH
)) || (pProbeMessage
== NULL
) ||
318 (pProbeMessage
->Body
== NULL
))
323 probe_msg
= (WSD_PROBE
*) pProbeMessage
->Body
;
324 next_name
= probe_msg
->Types
;
326 /* Verify that all names in the probe message are present in the types list */
327 while (next_name
!= NULL
)
329 /* If a name isn't present, return success; we simply don't send a Probe Match message */
330 if (!is_name_in_list(next_name
->Element
, pTypesList
)) return S_OK
;
332 next_name
= next_name
->Next
;
335 if ((probe_msg
->Scopes
!= NULL
) && (probe_msg
->Scopes
->Scopes
!= NULL
))
336 FIXME("Scopes matching currently unimplemented\n");
338 return send_probe_matches_message(impl
, pProbeMessage
, pMessageParameters
, pszId
, ullMetadataVersion
, ullInstanceId
,
339 ullMessageNumber
, pszSessionId
, pTypesList
, pScopesList
, pXAddrsList
, pHeaderAny
, pReferenceParameterAny
,
340 pEndpointReferenceAny
, pAny
);
343 static HRESULT WINAPI
IWSDiscoveryPublisherImpl_MatchResolveEx(IWSDiscoveryPublisher
*This
, const WSD_SOAP_MESSAGE
*pResolveMessage
,
344 IWSDMessageParameters
*pMessageParameters
, LPCWSTR pszId
, ULONGLONG ullMetadataVersion
,
345 ULONGLONG ullInstanceId
, ULONGLONG ullMessageNumber
, LPCWSTR pszSessionId
,
346 const WSD_NAME_LIST
*pTypesList
, const WSD_URI_LIST
*pScopesList
,
347 const WSD_URI_LIST
*pXAddrsList
, const WSDXML_ELEMENT
*pHeaderAny
,
348 const WSDXML_ELEMENT
*pReferenceParameterAny
, const WSDXML_ELEMENT
*pPolicyAny
,
349 const WSDXML_ELEMENT
*pEndpointReferenceAny
, const WSDXML_ELEMENT
*pAny
)
351 FIXME("(%p, %p, %p, %s, %s, %s, %s, %s, %p, %p, %p, %p, %p, %p, %p, %p)\n", This
, pResolveMessage
, pMessageParameters
, debugstr_w(pszId
),
352 wine_dbgstr_longlong(ullMetadataVersion
), wine_dbgstr_longlong(ullInstanceId
), wine_dbgstr_longlong(ullMessageNumber
), debugstr_w(pszSessionId
),
353 pTypesList
, pScopesList
, pXAddrsList
, pHeaderAny
, pReferenceParameterAny
, pPolicyAny
, pEndpointReferenceAny
, pAny
);
358 static HRESULT WINAPI
IWSDiscoveryPublisherImpl_RegisterScopeMatchingRule(IWSDiscoveryPublisher
*This
, IWSDScopeMatchingRule
*pScopeMatchingRule
)
360 FIXME("(%p, %p)\n", This
, pScopeMatchingRule
);
364 static HRESULT WINAPI
IWSDiscoveryPublisherImpl_UnRegisterScopeMatchingRule(IWSDiscoveryPublisher
*This
, IWSDScopeMatchingRule
*pScopeMatchingRule
)
366 FIXME("(%p, %p)\n", This
, pScopeMatchingRule
);
370 static HRESULT WINAPI
IWSDiscoveryPublisherImpl_GetXMLContext(IWSDiscoveryPublisher
*This
, IWSDXMLContext
**ppContext
)
372 IWSDiscoveryPublisherImpl
*impl
= impl_from_IWSDiscoveryPublisher(This
);
374 TRACE("%p, %p)\n", This
, ppContext
);
376 if (ppContext
== NULL
)
379 if (impl
->xmlContext
!= NULL
)
381 IWSDXMLContext_AddRef(impl
->xmlContext
);
384 *ppContext
= impl
->xmlContext
;
388 static const IWSDiscoveryPublisherVtbl publisher_vtbl
=
390 IWSDiscoveryPublisherImpl_QueryInterface
,
391 IWSDiscoveryPublisherImpl_AddRef
,
392 IWSDiscoveryPublisherImpl_Release
,
393 IWSDiscoveryPublisherImpl_SetAddressFamily
,
394 IWSDiscoveryPublisherImpl_RegisterNotificationSink
,
395 IWSDiscoveryPublisherImpl_UnRegisterNotificationSink
,
396 IWSDiscoveryPublisherImpl_Publish
,
397 IWSDiscoveryPublisherImpl_UnPublish
,
398 IWSDiscoveryPublisherImpl_MatchProbe
,
399 IWSDiscoveryPublisherImpl_MatchResolve
,
400 IWSDiscoveryPublisherImpl_PublishEx
,
401 IWSDiscoveryPublisherImpl_MatchProbeEx
,
402 IWSDiscoveryPublisherImpl_MatchResolveEx
,
403 IWSDiscoveryPublisherImpl_RegisterScopeMatchingRule
,
404 IWSDiscoveryPublisherImpl_UnRegisterScopeMatchingRule
,
405 IWSDiscoveryPublisherImpl_GetXMLContext
408 HRESULT WINAPI
WSDCreateDiscoveryPublisher(IWSDXMLContext
*pContext
, IWSDiscoveryPublisher
**ppPublisher
)
410 IWSDiscoveryPublisherImpl
*obj
;
413 TRACE("(%p, %p)\n", pContext
, ppPublisher
);
415 if (ppPublisher
== NULL
)
417 WARN("Invalid parameter: ppPublisher == NULL\n");
423 obj
= calloc(1, sizeof(*obj
));
427 WARN("Out of memory\n");
428 return E_OUTOFMEMORY
;
431 obj
->IWSDiscoveryPublisher_iface
.lpVtbl
= &publisher_vtbl
;
434 if (pContext
== NULL
)
436 ret
= WSDXMLCreateContext(&obj
->xmlContext
);
440 WARN("Unable to create XML context\n");
447 obj
->xmlContext
= pContext
;
448 IWSDXMLContext_AddRef(pContext
);
451 ret
= register_namespaces(obj
->xmlContext
);
455 WARN("Unable to register default namespaces\n");
461 InitializeCriticalSection(&obj
->notification_sink_critical_section
);
462 list_init(&obj
->notificationSinks
);
464 InitializeCriticalSection(&obj
->message_ids_critical_section
);
465 list_init(&obj
->message_ids
);
467 *ppPublisher
= &obj
->IWSDiscoveryPublisher_iface
;
468 TRACE("Returning iface %p\n", *ppPublisher
);
473 HRESULT WINAPI
WSDCreateDiscoveryProvider(IWSDXMLContext
*context
, IWSDiscoveryProvider
**provider
)
475 FIXME("(%p, %p) stub\n", context
, provider
);