diff --git a/dlls/wsdapi/soap.c b/dlls/wsdapi/soap.c index abea33c488b..40edd154634 100644 --- a/dlls/wsdapi/soap.c +++ b/dlls/wsdapi/soap.c @@ -71,6 +71,13 @@ static const WCHAR relatesToString[] = { 'R','e','l','a','t','e','s','T','o', 0 static const WCHAR appSequenceString[] = { 'A','p','p','S','e','q','u','e','n','c','e', 0 }; static const WCHAR emptyString[] = { 0 }; +struct discovered_namespace +{ + struct list entry; + LPCWSTR prefix; + LPCWSTR uri; +}; + static char *wide_to_utf8(LPCWSTR wide_string, int *length) { char *new_string = NULL; @@ -252,6 +259,31 @@ static void populate_soap_header(WSD_SOAP_HEADER *header, LPCWSTR to, LPCWSTR ac /* TODO: Implement RelatesTo, ReplyTo, From, FaultTo */ } +static BOOL add_discovered_namespace(struct list *namespaces, WSDXML_NAMESPACE *discovered_ns) +{ + struct discovered_namespace *ns; + + LIST_FOR_EACH_ENTRY(ns, namespaces, struct discovered_namespace, entry) + { + if (lstrcmpW(ns->uri, discovered_ns->Uri) == 0) + return TRUE; /* Already added */ + } + + ns = WSDAllocateLinkedMemory(namespaces, sizeof(struct discovered_namespace)); + + if (ns == NULL) + return FALSE; + + ns->prefix = duplicate_string(ns, discovered_ns->PreferredPrefix); + ns->uri = duplicate_string(ns, discovered_ns->Uri); + + if ((ns->prefix == NULL) || (ns->uri == NULL)) + return FALSE; + + list_add_tail(namespaces, &ns->entry); + return TRUE; +} + static WSDXML_ELEMENT *create_soap_header_xml_elements(IWSDXMLContext *xml_context, WSD_SOAP_HEADER *header) { WSDXML_ELEMENT *header_element = NULL, *app_sequence_element = NULL; @@ -309,9 +341,10 @@ cleanup: static HRESULT create_soap_envelope(IWSDXMLContext *xml_context, WSD_SOAP_HEADER *header, WSDXML_ELEMENT *body_element, WS_HEAP **heap, char **output_xml, ULONG *xml_length, struct list *discovered_namespaces) { - WS_XML_STRING *actual_envelope_prefix = NULL, *envelope_uri_xmlstr = NULL; + WS_XML_STRING *actual_envelope_prefix = NULL, *envelope_uri_xmlstr = NULL, *tmp_prefix = NULL, *tmp_uri = NULL; WSDXML_NAMESPACE *addressing_ns = NULL, *discovery_ns = NULL, *envelope_ns = NULL; WSDXML_ELEMENT *header_element = NULL; + struct discovered_namespace *ns; WS_XML_BUFFER *buffer = NULL; WS_XML_WRITER *writer = NULL; WS_XML_STRING envelope; @@ -320,10 +353,13 @@ static HRESULT create_soap_envelope(IWSDXMLContext *xml_context, WSD_SOAP_HEADER /* Create the necessary XML prefixes */ if (FAILED(IWSDXMLContext_AddNamespace(xml_context, addressingNsUri, addressingPrefix, &addressing_ns))) goto cleanup; + if (!add_discovered_namespace(discovered_namespaces, addressing_ns)) goto cleanup; if (FAILED(IWSDXMLContext_AddNamespace(xml_context, discoveryNsUri, discoveryPrefix, &discovery_ns))) goto cleanup; + if (!add_discovered_namespace(discovered_namespaces, discovery_ns)) goto cleanup; if (FAILED(IWSDXMLContext_AddNamespace(xml_context, envelopeNsUri, envelopePrefix, &envelope_ns))) goto cleanup; + if (!add_discovered_namespace(discovered_namespaces, envelope_ns)) goto cleanup; envelope.bytes = envelopeString; envelope.length = sizeof(envelopeString) - 1; @@ -356,6 +392,23 @@ static HRESULT create_soap_envelope(IWSDXMLContext *xml_context, WSD_SOAP_HEADER ret = WsWriteStartElement(writer, actual_envelope_prefix, &envelope, envelope_uri_xmlstr, NULL); if (FAILED(ret)) goto cleanup; + LIST_FOR_EACH_ENTRY(ns, discovered_namespaces, struct discovered_namespace, entry) + { + tmp_prefix = populate_xml_string(ns->prefix); + tmp_uri = populate_xml_string(ns->uri); + + if ((tmp_prefix == NULL) || (tmp_uri == NULL)) goto cleanup; + + ret = WsWriteXmlnsAttribute(writer, tmp_prefix, tmp_uri, FALSE, NULL); + if (FAILED(ret)) goto cleanup; + + free_xml_string(tmp_prefix); + free_xml_string(tmp_uri); + } + + tmp_prefix = NULL; + tmp_uri = NULL; + /* Write the header */ if (!write_xml_element(header_element, writer)) goto cleanup; @@ -401,7 +454,7 @@ static HRESULT write_and_send_message(IWSDiscoveryPublisherImpl *impl, WSD_SOAP_ char *full_xml; HRESULT ret; - ret = create_soap_envelope(impl->xmlContext, header, NULL, &heap, &xml, &xml_length, NULL); + ret = create_soap_envelope(impl->xmlContext, header, NULL, &heap, &xml, &xml_length, discovered_namespaces); if (ret != S_OK) return ret; /* Prefix the XML header */ @@ -439,6 +492,7 @@ HRESULT send_hello_message(IWSDiscoveryPublisherImpl *impl, LPCWSTR id, ULONGLON const WSD_URI_LIST *xaddrs_list, const WSDXML_ELEMENT *hdr_any, const WSDXML_ELEMENT *ref_param_any, const WSDXML_ELEMENT *endpoint_ref_any, const WSDXML_ELEMENT *any) { + struct list *discoveredNamespaces = NULL; WSD_SOAP_HEADER soapHeader; WSD_APP_SEQUENCE sequence; WCHAR message_id[64]; @@ -450,13 +504,20 @@ HRESULT send_hello_message(IWSDiscoveryPublisherImpl *impl, LPCWSTR id, ULONGLON if (!create_guid(message_id)) goto cleanup; + discoveredNamespaces = WSDAllocateLinkedMemory(NULL, sizeof(struct list)); + if (!discoveredNamespaces) goto cleanup; + + list_init(discoveredNamespaces); + populate_soap_header(&soapHeader, discoveryTo, actionHello, message_id, &sequence, hdr_any); /* TODO: Populate message body */ /* Write and send the message */ - ret = write_and_send_message(impl, &soapHeader, NULL, NULL, NULL, APP_MAX_DELAY); + ret = write_and_send_message(impl, &soapHeader, NULL, discoveredNamespaces, NULL, APP_MAX_DELAY); cleanup: + WSDFreeLinkedMemory(discoveredNamespaces); + return ret; } diff --git a/dlls/wsdapi/tests/discovery.c b/dlls/wsdapi/tests/discovery.c index d81dcdc9360..563c33c7871 100644 --- a/dlls/wsdapi/tests/discovery.c +++ b/dlls/wsdapi/tests/discovery.c @@ -506,6 +506,7 @@ static void Publish_tests(void) messageStorage *msgStorage; WSADATA wsaData; BOOL messageOK; + BOOL hello_message_seen = FALSE; int ret, i; HRESULT rc; ULONG ref; @@ -595,8 +596,8 @@ static void Publish_tests(void) msg = msgStorage->messages[i]; messageOK = FALSE; - messageOK = (strstr(msg, "http://schemas.xmlsoap.org/ws/2005/04/discovery/Hello") != NULL); - messageOK = messageOK && (strstr(msg, endpointReferenceString) != NULL); + hello_message_seen = (strstr(msg, "http://schemas.xmlsoap.org/ws/2005/04/discovery/Hello") != NULL); + messageOK = hello_message_seen && (strstr(msg, endpointReferenceString) != NULL); messageOK = messageOK && (strstr(msg, "") != NULL); messageOK = messageOK && (strstr(msg, "1") != NULL); @@ -610,7 +611,8 @@ static void Publish_tests(void) heap_free(msgStorage); - todo_wine ok(messageOK == TRUE, "Hello message not received\n"); + ok(hello_message_seen == TRUE, "Hello message not received\n"); + todo_wine ok(messageOK == TRUE, "Hello message metadata not received\n"); after_publish_test: diff --git a/dlls/wsdapi/wsdapi_internal.h b/dlls/wsdapi/wsdapi_internal.h index 417eed91457..47dde6b2c98 100644 --- a/dlls/wsdapi/wsdapi_internal.h +++ b/dlls/wsdapi/wsdapi_internal.h @@ -62,4 +62,8 @@ HRESULT send_hello_message(IWSDiscoveryPublisherImpl *impl, LPCWSTR id, ULONGLON const WSD_URI_LIST *xaddrs_list, const WSDXML_ELEMENT *hdr_any, const WSDXML_ELEMENT *ref_param_any, const WSDXML_ELEMENT *endpoint_ref_any, const WSDXML_ELEMENT *any); +/* xml.c */ + +LPWSTR duplicate_string(void *parentMemoryBlock, LPCWSTR value); + #endif diff --git a/dlls/wsdapi/xml.c b/dlls/wsdapi/xml.c index 4d6319c36b4..fc02d8b2d47 100644 --- a/dlls/wsdapi/xml.c +++ b/dlls/wsdapi/xml.c @@ -27,7 +27,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wsdapi); -static LPWSTR duplicate_string(void *parentMemoryBlock, LPCWSTR value) +LPWSTR duplicate_string(void *parentMemoryBlock, LPCWSTR value) { int valueLen; LPWSTR dup;