/************************************************************************** * WsWriteBody [webservices.@] */ HRESULT WINAPI WsWriteBody( WS_MESSAGE *handle, const WS_ELEMENT_DESCRIPTION *desc, WS_WRITE_OPTION option, const void *value, ULONG size, WS_ERROR *error ) { struct msg *msg = (struct msg *)handle; HRESULT hr; TRACE( "%p %p %08x %p %u %p\n", handle, desc, option, value, size, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!handle || !desc) return E_INVALIDARG; if (msg->state != WS_MESSAGE_STATE_WRITING) return WS_E_INVALID_OPERATION; if (desc->elementLocalName && (hr = WsWriteStartElement( msg->writer_body, NULL, desc->elementLocalName, desc->elementNs, NULL )) != S_OK) return hr; if ((hr = WsWriteType( msg->writer_body, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, desc->typeDescription, option, value, size, NULL )) != S_OK) return hr; if (desc->elementLocalName) hr = WsWriteEndElement( msg->writer_body, NULL ); return hr; }
static HRESULT write_envelope_start( struct msg *msg, WS_XML_WRITER *writer ) { static const char anonymous[] = "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous"; WS_XML_STRING prefix_s = {1, (BYTE *)"s"}, prefix_a = {1, (BYTE *)"a"}, body = {4, (BYTE *)"Body"}; WS_XML_STRING envelope = {8, (BYTE *)"Envelope"}, header = {6, (BYTE *)"Header"}; WS_XML_STRING msgid = {9, (BYTE *)"MessageID"}, replyto = {7, (BYTE *)"ReplyTo"}; WS_XML_STRING address = {7, (BYTE *)"Address"}, ns_env, ns_addr; WS_XML_UTF8_TEXT urn, addr; HRESULT hr; if ((hr = get_env_namespace( msg->version_env, &ns_env )) != S_OK) return hr; if ((hr = get_addr_namespace( msg->version_addr, &ns_addr )) != S_OK) return hr; if ((hr = WsWriteStartElement( writer, &prefix_s, &envelope, &ns_env, NULL )) != S_OK) return hr; if ((hr = WsWriteXmlnsAttribute( writer, &prefix_a, &ns_addr, FALSE, NULL )) != S_OK) return hr; if ((hr = WsWriteStartElement( writer, &prefix_s, &header, &ns_env, NULL )) != S_OK) return hr; if ((hr = WsWriteStartElement( writer, &prefix_a, &msgid, &ns_addr, NULL )) != S_OK) return hr; urn.text.textType = WS_XML_TEXT_TYPE_UNIQUE_ID; memcpy( &urn.value, &msg->id, sizeof(msg->id) ); if ((hr = WsWriteText( writer, &urn.text, NULL )) != S_OK) return hr; if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* </a:MessageID> */ if (msg->version_addr == WS_ADDRESSING_VERSION_0_9) { if ((hr = WsWriteStartElement( writer, &prefix_a, &replyto, &ns_addr, NULL )) != S_OK) return hr; if ((hr = WsWriteStartElement( writer, &prefix_a, &address, &ns_addr, NULL )) != S_OK) return hr; addr.text.textType = WS_XML_TEXT_TYPE_UTF8; addr.value.bytes = (BYTE *)anonymous; addr.value.length = sizeof(anonymous) - 1; if ((hr = WsWriteText( writer, &addr.text, NULL )) != S_OK) return hr; if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* </a:Address> */ if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* </a:ReplyTo> */ } if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* </s:Header> */ return WsWriteStartElement( writer, &prefix_s, &body, &ns_env, NULL ); /* <s:Body> */ }
// Reads the data and serializes it into the message. This function does custom serialization for the same // reason and with the same alrogithm as DeserializeAndWriteMessage. HRESULT CFileRepServer::ReadAndSendChunk( __in CRequest* request, __in long chunkSize, __in LONGLONG chunkPosition, __in HANDLE file) { PrintVerbose(L"Entering CFileRepServer::ReadAndSendChunk"); if (chunkSize < 0 || chunkPosition < 0) { PrintVerbose(L"Leaving CFileRepServer::ReadAndSendChunk"); return E_INVALIDARG; } HRESULT hr = S_OK; WS_XML_WRITER* writer = NULL; WS_MESSAGE* replyMessage = request->GetReplyMessage(); WS_MESSAGE* requestMessage = request->GetRequestMessage(); WS_ERROR* error = request->GetError(); WS_CHANNEL* channel = request->GetChannel(); BYTE* buf = NULL; LONG length = 0; // To avoid using too much memory we read and write the message in chunks. LONG bytesToRead = FILE_CHUNK; if (bytesToRead > chunkSize) { bytesToRead = chunkSize; } buf = (BYTE*)HeapAlloc(GetProcessHeap(), 0, bytesToRead); IfNullExit(buf); IfFailedExit(WsInitializeMessage(replyMessage, WS_BLANK_MESSAGE, requestMessage, error)); // Add the action header IfFailedExit(WsSetHeader( replyMessage, WS_ACTION_HEADER, WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_VALUE, &fileReplyAction, sizeof(fileReplyAction), error)); // Send the message headers IfFailedExit(WsWriteMessageStart(channel, replyMessage, NULL, error)); // Get writer to serialize message body IfFailedExit(WsGetMessageProperty(replyMessage, WS_MESSAGE_PROPERTY_BODY_WRITER, &writer, sizeof(writer), error)); // Write FileChunk start element. // This whole code block is the serialization equivalent of the desiralization code. IfFailedExit(WsWriteStartElement(writer, NULL, &fileChunkLocalName, &fileChunkNamespace, error)); // Write chunkPosition element IfFailedExit(WsWriteStartElement(writer, NULL, &chunkPositionLocalName, &fileChunkNamespace, error)); IfFailedExit(WsWriteValue(writer, WS_INT64_VALUE_TYPE, &chunkPosition, sizeof(chunkPosition), error)); IfFailedExit(WsWriteEndElement(writer, error)); // Write fileContent start element IfFailedExit(WsWriteStartElement(writer, NULL, &fileContentLocalName, &fileChunkNamespace, error)); // Like in the deserialization code, we read the file in multiple steps to avoid // having to have everything in memory at once. The message could potentially be // big so this is more efficient. for (;;) { ULONG bytesRead = 0; if (length + bytesToRead > chunkSize) { bytesToRead = chunkSize - length; } if (!ReadFile(file, buf, bytesToRead, &bytesRead, NULL)) { PrintError(L"File read error.", true); hr = HRESULT_FROM_WIN32(GetLastError()); EXIT_FUNCTION } if (0 == bytesRead) { // We reched the end of the file before filling the chunk. Send a partial chunk. break; } IfFailedExit(WsWriteBytes(writer, buf, bytesRead, error)); length += bytesRead; if (length == chunkSize) { // We filled the message break; } }
IfFailedExit(WsWriteBytes(writer, buf, bytesRead, error)); length += bytesRead; if (length == chunkSize) { // We filled the message break; } } // Write fileContent end element IfFailedExit(WsWriteEndElement(writer, error)); // Write error element IfFailedExit(WsWriteStartElement(writer, NULL, &errorLocalName, &fileChunkNamespace, error)); const WCHAR* noError = GlobalStrings::noError; IfFailedExit(WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL, WS_WRITE_REQUIRED_POINTER, &noError, sizeof(noError), error)); // Closing elements; IfFailedExit(WsWriteEndElement(writer, error)); IfFailedExit(WsWriteEndElement(writer, error)); IfFailedExit(WsWriteMessageEnd(channel, replyMessage, NULL, error));
// Main entry point int __cdecl wmain() { HRESULT hr = S_OK; WS_ERROR* error = NULL; WS_XML_WRITER* writer = NULL; WS_XML_READER* reader = NULL; WS_HEAP* heap = NULL; // Create an error object for storing rich error information hr = WsCreateError( NULL, 0, &error); if (FAILED(hr)) { goto Exit; } // Create a heap to store deserialized data hr = WsCreateHeap( /*maxSize*/ 2048, /*trimSize*/ 512, NULL, 0, &heap, error); if (FAILED(hr)) { goto Exit; } // Create an XML writer hr = WsCreateWriter( NULL, 0, &writer, error); if (FAILED(hr)) { goto Exit; } // Setup the output WS_XML_WRITER_BUFFER_OUTPUT bufferOutput; ZeroMemory(&bufferOutput, sizeof(bufferOutput)); bufferOutput.output.outputType = WS_XML_WRITER_OUTPUT_TYPE_BUFFER; // Setup the encoding WS_XML_WRITER_BINARY_ENCODING writerEncoding; ZeroMemory(&writerEncoding, sizeof(writerEncoding)); writerEncoding.encoding.encodingType = WS_XML_WRITER_ENCODING_TYPE_BINARY; writerEncoding.staticDictionary = &objectsDictionary.dictionary; writerEncoding.dynamicStringCallback = DynamicStringCallback; writerEncoding.dynamicStringCallbackState = NULL; // Setup the writer hr = WsSetOutput( writer, &writerEncoding.encoding, &bufferOutput.output, NULL, 0, error); if (FAILED(hr)) { goto Exit; } hr = WsWriteStartElement( writer, NULL, &objectsDictionary.objects, &objectsDictionary.ns, error); if (FAILED(hr)) { goto Exit; } // Write some xml using strings from all the dictionaries static const WS_XML_STRING* shapes[3] = { &shapeDictionary.triangle, &shapeDictionary.square, &shapeDictionary.circle }; static const WS_XML_STRING* colors[3] = { &colorDictionary.green, &colorDictionary.blue, &colorDictionary.red }; for (ULONG i = 0; i < 3; i++) { hr = WsWriteStartElement( writer, NULL, shapes[i], &objectsDictionary.ns, error); if (FAILED(hr)) { goto Exit; } hr = WsWriteStartAttribute( writer, NULL, &objectsDictionary.color, &objectsDictionary.ns, FALSE, error); if (FAILED(hr)) { goto Exit; } hr = WsWriteType( writer, WS_ATTRIBUTE_TYPE_MAPPING, WS_XML_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE, colors[i], sizeof(*colors[i]), error); if (FAILED(hr)) { goto Exit; } hr = WsWriteEndAttribute( writer, error); if (FAILED(hr)) { goto Exit; } hr = WsWriteEndElement( writer, error); if (FAILED(hr)) { goto Exit; } } hr = WsWriteEndElement( writer, error); if (FAILED(hr)) { goto Exit; } WS_BYTES bytes; hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &bytes, sizeof(bytes), error); if (FAILED(hr)) { goto Exit; } // Create an XML reader hr = WsCreateReader( NULL, 0, &reader, error); if (FAILED(hr)) { goto Exit; } // Setup the input WS_XML_READER_BUFFER_INPUT bufferInput; ZeroMemory(&bufferInput, sizeof(bufferInput)); bufferInput.input.inputType = WS_XML_READER_INPUT_TYPE_BUFFER; bufferInput.encodedData = bytes.bytes; bufferInput.encodedDataSize = bytes.length; // Setup the encoding WS_XML_READER_BINARY_ENCODING readerEncoding; ZeroMemory( &readerEncoding, sizeof(readerEncoding)); readerEncoding.encoding.encodingType = WS_XML_READER_ENCODING_TYPE_BINARY; readerEncoding.staticDictionary = &objectsDictionary.dictionary; readerEncoding.dynamicDictionary = &mergedDictionary.dictionary; // Setup the reader hr = WsSetInput( reader, &readerEncoding.encoding, &bufferInput.input, NULL, 0, error); if (FAILED(hr)) { goto Exit; } hr = WsReadToStartElement( reader, &objectsDictionary.objects, &objectsDictionary.ns, NULL, error); if (FAILED(hr)) { goto Exit; } hr = WsReadStartElement( reader, error); if (FAILED(hr)) { goto Exit; } for (;;) { BOOL found; hr = WsReadToStartElement( reader, NULL, NULL, &found, error); if (FAILED(hr)) { goto Exit; } if (!found) { break; } const WS_XML_NODE* node; hr = WsGetReaderNode( reader, &node, error); if (FAILED(hr)) { goto Exit; } const WS_XML_ELEMENT_NODE* elementNode = (WS_XML_ELEMENT_NODE*)node; printf("%.*s: ", elementNode->localName->length, elementNode->localName->bytes); ULONG index; hr = WsFindAttribute( reader, &objectsDictionary.color, &objectsDictionary.ns, TRUE, &index, error); if (FAILED(hr)) { goto Exit; } hr = WsReadStartAttribute( reader, index, error); if (FAILED(hr)) { goto Exit; } WS_XML_STRING color; hr = WsReadType( reader, WS_ATTRIBUTE_TYPE_MAPPING, WS_XML_STRING_TYPE, NULL, WS_READ_REQUIRED_VALUE, heap, &color, sizeof(color), error); if (FAILED(hr)) { goto Exit; } printf( "%.*s\n", color.length, color.bytes); hr = WsReadEndAttribute( reader, error); if (FAILED(hr)) { goto Exit; } hr = WsSkipNode( reader, error); if (FAILED(hr)) { goto Exit; } } hr = WsReadEndElement( reader, error); if (FAILED(hr)) { goto Exit; } Exit: if (FAILED(hr)) { // Print out the error PrintError(hr, error); } if (writer != NULL) { WsFreeWriter(writer); } if (reader != NULL) { WsFreeReader(reader); } if (heap != NULL) { WsFreeHeap(heap); } if (error != NULL) { WsFreeError(error); } fflush(stdout); return SUCCEEDED(hr) ? 0 : -1; }
// Main entry point int __cdecl wmain() { HRESULT hr = S_OK; WS_ERROR* error = NULL; WS_XML_BUFFER* xmlBuffer = NULL; WS_HEAP* heap = NULL; WS_XML_READER* xmlReader = NULL; WS_XML_WRITER* xmlWriter = NULL; PayloadBaseType* baseType = NULL; Payload1Type* payload1Type = NULL; static const WS_XML_STRING dataElement = WS_XML_STRING_VALUE("data"); static const WS_XML_STRING emptyNamespace = WS_XML_STRING_VALUE(""); // Create an error object for storing rich error information hr = WsCreateError( NULL, 0, &error); if (FAILED(hr)) { goto Exit; } // Create a heap to store deserialized data hr = WsCreateHeap( /*maxSize*/ 4096, /*trimSize*/ 512, NULL, 0, &heap, error); if (FAILED(hr)) { goto Exit; } // Create an XML reader hr = WsCreateReader( NULL, 0, &xmlReader, error); if (FAILED(hr)) { goto Exit; } // Create an XML writer hr = WsCreateWriter( NULL, 0, &xmlWriter, error); if (FAILED(hr)) { goto Exit; } // Create an XML buffer on the specified heap hr = WsCreateXmlBuffer( heap, NULL, 0, &xmlBuffer, error); if (FAILED(hr)) { goto Exit; } // Set the writer to output to the XML buffer hr = WsSetOutputToBuffer( xmlWriter, xmlBuffer, NULL, 0, error); if (FAILED(hr)) { goto Exit; } // Create a wrapper element for the two embedded elements hr = WsWriteStartElement( xmlWriter, NULL, &dataElement, &emptyNamespace, error); if (FAILED(hr)) { goto Exit; } baseType = new(std::nothrow) PayloadBaseType(); if (baseType == NULL) { goto Exit; } baseType->Id = 1; payload1Type = new(std::nothrow) Payload1Type(); if (payload1Type == NULL) { goto Exit; } payload1Type->Id = 2; payload1Type->BoolValue = FALSE; payload1Type->StringValue = L"hello world"; // Write the base type using the element description of the base type. // An xsi:type attribute will be added to the XML document for the element // indicating this is the base type. hr = WsWriteElement( xmlWriter, &DerivedType_xsd.globalElements.PayloadBase, WS_WRITE_REQUIRED_VALUE, baseType, sizeof(PayloadBaseType), error); if (FAILED(hr)) { goto Exit; } // Write the derived type using the element description of the base type. // An xsi:type attribute will be added to the XML document for the element // indicating this is the derived type. hr = WsWriteElement( xmlWriter, &DerivedType_xsd.globalElements.PayloadBase, WS_WRITE_REQUIRED_VALUE, payload1Type, sizeof(Payload1Type), error); if (FAILED(hr)) { goto Exit; } hr = WsWriteEndElement( xmlWriter, error); if (FAILED(hr)) { goto Exit; } // Flush writer so all XML content is put in the buffer hr = WsFlushWriter(xmlWriter, 0, NULL, error); if (FAILED(hr)) { goto Exit; } // Set the reader input to current position of XML buffer hr = WsSetInputToBuffer(xmlReader, xmlBuffer, NULL, 0, error); if (FAILED(hr)) { goto Exit; } // Read pass the wrapper element hr = WsReadToStartElement( xmlReader, &dataElement, &emptyNamespace, NULL, error); if (FAILED(hr)) { goto Exit; } hr = WsReadStartElement( xmlReader, error); if (FAILED(hr)) { goto Exit; } PayloadBaseType* outBaseType = NULL; // Read the first element using element description for the base // type. The type of returning structure is that of that base type. hr = WsReadElement( xmlReader, &DerivedType_xsd.globalElements.PayloadBase, WS_READ_REQUIRED_POINTER, heap, &outBaseType, sizeof(PayloadBaseType*), error); if (FAILED(hr)) { goto Exit; } PrintPayloadType(outBaseType); // Read the second element using element description for the base // type. The type of returning structure is that of the derived type. hr = WsReadElement( xmlReader, &DerivedType_xsd.globalElements.PayloadBase, WS_READ_REQUIRED_POINTER, heap, &outBaseType, sizeof(PayloadBaseType*), error); if (FAILED(hr)) { goto Exit; } PrintPayloadType(outBaseType); hr = WsReadEndElement( xmlReader, error); if (FAILED(hr)) { goto Exit; } Exit: if (FAILED(hr)) { // Print out the error PrintError(hr, error); } delete baseType; delete payload1Type; if (xmlReader != NULL) { WsFreeReader(xmlReader); } if (xmlWriter != NULL) { WsFreeWriter(xmlWriter); } if (error != NULL) { WsFreeError(error); } if (heap != NULL) { WsFreeHeap(heap); } fflush(stdout); return SUCCEEDED(hr) ? 0 : -1; }
// Main entry point int __cdecl wmain() { HRESULT hr = S_OK; WS_ERROR* error = NULL; WS_HEAP* heap = NULL; WS_XML_BUFFER* buffer = NULL; WS_XML_WRITER* writer = NULL; WS_XML_READER* reader = NULL; void* xml = NULL; ULONG xmlLength = 0; WS_XML_NODE_POSITION securityEndElementPosition; static const WS_XML_STRING soapNs = WS_XML_STRING_VALUE("http://schemas.xmlsoap.org/soap/envelope/"); static const WS_XML_STRING wsseNs = WS_XML_STRING_VALUE("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); static const WS_XML_STRING envelope = WS_XML_STRING_VALUE("Envelope"); static const WS_XML_STRING header = WS_XML_STRING_VALUE("Header"); static const WS_XML_STRING security = WS_XML_STRING_VALUE("Security"); static const WS_XML_STRING dsNs = WS_XML_STRING_VALUE("http://www.w3.org/2000/09/xmldsig#"); static const WS_XML_STRING signature = WS_XML_STRING_VALUE("Signature"); // Create an error object for storing rich error information hr = WsCreateError( NULL, 0, &error); if (FAILED(hr)) { goto Exit; } // Create a heap to store deserialized data hr = WsCreateHeap( /*maxSize*/ 2048, /*trimSize*/ 512, NULL, 0, &heap, error); if (FAILED(hr)) { goto Exit; } // Create an XML writer hr = WsCreateWriter( NULL, 0, &writer, error); if (FAILED(hr)) { goto Exit; } // Create an XML reader hr = WsCreateReader( NULL, 0, &reader, error); if (FAILED(hr)) { goto Exit; } // Create an XML buffer on the specified heap hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, error); if (FAILED(hr)) { goto Exit; } // Set the writer to output to the XML buffer hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, error); if (FAILED(hr)) { goto Exit; } // Write the envelope element hr = WsWriteStartElement(writer, NULL, &envelope, &soapNs, error); if (FAILED(hr)) { goto Exit; } // Write the header element hr = WsWriteStartElement(writer, NULL, &header, &soapNs, error); if (FAILED(hr)) { goto Exit; } // Write the security element hr = WsWriteStartElement(writer, NULL, &security, &wsseNs, error); if (FAILED(hr)) { goto Exit; } // Force the security element start tag to be written so the position obtained // is "after" the security element hr = WsWriteEndStartElement(writer, error); if (FAILED(hr)) { goto Exit; } hr = WsGetWriterPosition(writer, &securityEndElementPosition, error); if (FAILED(hr)) { goto Exit; } // Close the security element hr = WsWriteEndElement(writer, error); if (FAILED(hr)) { goto Exit; } // Close the header element hr = WsWriteEndElement(writer, error); if (FAILED(hr)) { goto Exit; } // Close the envelope element hr = WsWriteEndElement(writer, error); if (FAILED(hr)) { goto Exit; } // Move the write back hr = WsSetWriterPosition(writer, &securityEndElementPosition, error); if (FAILED(hr)) { goto Exit; } // Write the "signature" element hr = WsWriteStartElement(writer, NULL, &signature, &dsNs, error); if (FAILED(hr)) { goto Exit; } // Close the signature element hr = WsWriteEndElement(writer, error); if (FAILED(hr)) { goto Exit; } // Generate the bytes of the document ULONG indent = 4; WS_XML_WRITER_PROPERTY properties[1]; properties[0].id = WS_XML_WRITER_PROPERTY_INDENT; properties[0].value = &indent; properties[0].valueSize = sizeof(indent); hr = WsWriteXmlBufferToBytes(writer, buffer, NULL, properties, WsCountOf(properties), heap, &xml, &xmlLength, error); if (FAILED(hr)) { goto Exit; } printf("%.*s\n", xmlLength, (char*)xml); Exit: if (FAILED(hr)) { // Print out the error PrintError(hr, error); } if (writer != NULL) { WsFreeWriter(writer); } if (reader != NULL) { WsFreeReader(reader); } if (heap != NULL) { WsFreeHeap(heap); } if (error != NULL) { WsFreeError(error); } fflush(stdout); return SUCCEEDED(hr) ? 0 : -1; }