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"
28 #include "wine/heap.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
);
46 WARN("Invalid parameter\n");
52 if (IsEqualIID(riid
, &IID_IUnknown
) ||
53 IsEqualIID(riid
, &IID_IWSDiscoveryPublisher
))
55 *ppv
= &This
->IWSDiscoveryPublisher_iface
;
59 WARN("Unknown IID %s\n", debugstr_guid(riid
));
63 IUnknown_AddRef((IUnknown
*)*ppv
);
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
);
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
);
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
);
110 DeleteCriticalSection(&This
->message_ids_critical_section
);
111 HeapFree(GetProcessHeap(), 0, This
);
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
;
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
);
152 sink
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*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
)))
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
);
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
);
199 LeaveCriticalSection(&impl
->notification_sink_critical_section
);
201 /* Notification sink is not registered */
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
)))
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
,
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
);
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
)))
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
;
287 if ((lstrcmpW(next
->Element
->LocalName
, name
->LocalName
) == 0) &&
288 (lstrcmpW(next
->Element
->Space
->PreferredPrefix
, name
->Space
->PreferredPrefix
) == 0))
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
))
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
);
359 static HRESULT WINAPI
IWSDiscoveryPublisherImpl_RegisterScopeMatchingRule(IWSDiscoveryPublisher
*This
, IWSDScopeMatchingRule
*pScopeMatchingRule
)
361 FIXME("(%p, %p)\n", This
, pScopeMatchingRule
);
365 static HRESULT WINAPI
IWSDiscoveryPublisherImpl_UnRegisterScopeMatchingRule(IWSDiscoveryPublisher
*This
, IWSDScopeMatchingRule
*pScopeMatchingRule
)
367 FIXME("(%p, %p)\n", This
, pScopeMatchingRule
);
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
)
380 if (impl
->xmlContext
!= NULL
)
382 IWSDXMLContext_AddRef(impl
->xmlContext
);
385 *ppContext
= impl
->xmlContext
;
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
;
414 TRACE("(%p, %p)\n", pContext
, ppPublisher
);
416 if (ppPublisher
== NULL
)
418 WARN("Invalid parameter: ppPublisher == NULL\n");
424 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*obj
));
428 WARN("Out of memory\n");
429 return E_OUTOFMEMORY
;
432 obj
->IWSDiscoveryPublisher_iface
.lpVtbl
= &publisher_vtbl
;
435 if (pContext
== NULL
)
437 ret
= WSDXMLCreateContext(&obj
->xmlContext
);
441 WARN("Unable to create XML context\n");
448 obj
->xmlContext
= pContext
;
449 IWSDXMLContext_AddRef(pContext
);
452 ret
= register_namespaces(obj
->xmlContext
);
456 WARN("Unable to register default namespaces\n");
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
);