/*
**==============================================================================
**
** Open Management Infrastructure (OMI)
**
** Copyright (c) Microsoft Corporation
**
** Licensed under the Apache License, Version 2.0 (the "License"); you may not
** use this file except in compliance with the License. You may obtain a copy
** of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
** MERCHANTABLITY OR NON-INFRINGEMENT.
**
** See the Apache 2 License for the specific language governing permissions
** and limitations under the License.
**
**==============================================================================
*/
#include <common.h>
#include "wsmanbuffer.h"
#include <base/log.h>
#include <base/result.h>
#include <base/instance.h>
#include <base/strings.h>
#include <base/field.h>
#include <base/messages.h>
#include <base/helpers.h>
#include <base/time.h>
#include <base/io.h>
#define T MI_T
#if 0
#define ENABLE_TRACING
#endif
#ifdef ENABLE_TRACING
#define PRINTF(a) printf a
#else
#define PRINTF(a)
#endif
#define XML_CR MI_T("\n")
/*
**==============================================================================
**
** Local datatypes:
**
**==============================================================================
*/
typedef struct _BUF_FaultItem
{
const MI_Char* action;
MI_Uint32 actionSize;
const char* code; /* sender/receiver */
const char* subCode; /* wsa:XXX */
const char* defaultTest;
}
BUF_FaultItem;
typedef struct _BUF_CIMErrorItem
{
WSBUF_FAULT_CODE faultCode;
const MI_Char* description;
}
BUF_CIMErrorItem;
typedef struct _Char_Encoding
{
const MI_Char* str;
MI_Uint32 size;
}
Char_Encoding;
/*
**==============================================================================
**
** Forward declarations:
**
**==============================================================================
*/
static MI_Result _PackInstance(
WS_Buffer* buf,
const MI_Instance* instance,
MI_Boolean (*filterProperty)(const MI_Char* name, void* data),
void* filterPropertyData,
const MI_ClassDecl* castToClassDecl,
MI_Uint32 flags,
MI_Boolean embedded);
static MI_Result _PackEPR(
WS_Buffer* buf,
const MI_Instance* instance);
/*
**==============================================================================
**
** Static data:
**
**==============================================================================
*/
static const BUF_FaultItem s_faults[] = {
/* WSBUF_FAULT_INTERNAL_ERROR */
{
LIT(MI_T("http://schemas.dmtf.org/wbem/wsman/1/wsman/fault")),
"SOAP-ENV:Receiver",
"wsman:InternalError",
"The service cannot comply with the request due to internal processing errors."
},
/* WSBUF_FAULT_NOT_SUPPORTED */
{
LIT(MI_T("http://schemas.dmtf.org/wbem/wsman/1/wsman/fault")),
"SOAP-ENV:Sender",
"wsman:UnsupportedFeature",
"not supported"
},
/* WSBUF_FAULT_NOT_UNDERSTOOD */
{
LIT(MI_T("http://schemas.xmlsoap.org/ws/2004/08/addressing/fault")),
"SOAP-ENV:MustUnderstand",
0,
"Header not understood"
},
/* WSBUF_FAULT_DESTINATION_UNREACHABLE */
{
LIT(MI_T("http://schemas.xmlsoap.org/ws/2004/08/addressing/fault")),
"SOAP-ENV:Sender",
"wsa:DestinationUnreachable",
"No route can be determined to reach the destination role defined by the Addressing To header."
},
/* WSBUF_FAULT_ACCESS_DENIED */
{
LIT(MI_T("http://schemas.dmtf.org/wbem/wsman/1/wsman/fault")),
"SOAP-ENV:Sender",
"wsman:AccessDenied",
"The sender was not authorized to access the resource."
},
/* WSBUF_FAULT_ENCODING_LIMIT */
{
LIT(MI_T("http://schemas.dmtf.org/wbem/wsman/1/wsman/fault")),
"SOAP-ENV:Sender",
"wsman:EncodingLimit",
"An internal encoding limit was exceeded in a request or would be violated if the message were processed."
}
};
static const BUF_CIMErrorItem s_cimerrors[] = {
/* MI_RESULT_OK = 0, */
{
0,
0
},
/* MI_RESULT_FAILED = 1, */
{
WSBUF_FAULT_INTERNAL_ERROR,
MI_T("CIM ERROR:FAILED: A general error occurred, not covered by a more specific error code.")
},
/* MI_RESULT_ACCESS_DENIED = 2, */
{
WSBUF_FAULT_ACCESS_DENIED,
MI_T("CIM ERROR:ACCESS_DENIED: Access to a CIM resource is not available to the client.")
},
/* MI_RESULT_INVALID_NAMESPACE = 3, */
{
WSBUF_FAULT_DESTINATION_UNREACHABLE,
MI_T("CIM ERROR:INVALID_NAMESPACE: The target namespace does not exist.")
},
/* MI_RESULT_INVALID_PARAMETER = 4,*/
{
WSBUF_FAULT_INTERNAL_ERROR,
MI_T("CIM ERROR:INVALID_PARAMETER: One or more parameter values passed to the method are not valid.")
},
/* MI_RESULT_INVALID_CLASS = 5, */
{
WSBUF_FAULT_DESTINATION_UNREACHABLE,
MI_T("CIM ERROR:INVALID_CLASS: The specified class does not exist.")
},
/* MI_RESULT_NOT_FOUND = 6,*/
{
WSBUF_FAULT_DESTINATION_UNREACHABLE,
MI_T("CIM ERROR:NOT_FOUND: The requested object cannot be found.")
},
/* MI_RESULT_NOT_SUPPORTED = 7, */
{
WSBUF_FAULT_NOT_SUPPORTED,
MI_T("CIM ERROR:NOT_SUPPORTED: The requested operation is not supported.")
}
#if 0
/* The operation cannot be invoked because the class has subclasses. */
MI_RESULT_CLASS_HAS_CHILDREN = 8,
/* The operation cannot be invoked because the class has instances. */
MI_RESULT_CLASS_HAS_INSTANCES = 9,
/* The operation cannot be invoked because the superclass does not exist. */
MI_RESULT_INVALID_SUPERCLASS = 10,
/* The operation cannot be invoked because an object already exists. */
MI_RESULT_ALREADY_EXISTS = 11,
/* The specified property does not exist. */
MI_RESULT_NO_SUCH_PROPERTY = 12,
/* The value supplied is not compatible with the type. */
MI_RESULT_TYPE_MISMATCH = 13,
/* The query language is not recognized or supported. */
MI_RESULT_QUERY_LANGUAGE_NOT_SUPPORTED = 14,
/* The query is not valid for the specified query language. */
MI_RESULT_INVALID_QUERY = 15,
/* The extrinsic method cannot be invoked. */
MI_RESULT_METHOD_NOT_AVAILABLE = 16,
/* The specified extrinsic method does not exist. */
MI_RESULT_METHOD_NOT_FOUND = 17,
/* The specified namespace is not empty. */
MI_RESULT_NAMESPACE_NOT_EMPTY = 20,
/* The enumeration identified by the specified context is invalid. */
MI_RESULT_INVALID_ENUMERATION_CONTEXT = 21,
/* The specified operation timeout is not supported by the CIM Server. */
MI_RESULT_INVALID_OPERATION_TIMEOUT = 22,
/* The Pull operation has been abandoned. */
MI_RESULT_PULL_HAS_BEEN_ABANDONED = 23,
/* The attempt to abandon a concurrent Pull operation failed. */
MI_RESULT_PULL_CANNOT_BE_ABANDONED = 24,
/* Using a filter in the enumeration is not supported by the CIM server. */
MI_RESULT_FILTERED_ENUMERATION_NOT_SUPPORTED = 25,
/* The CIM server does not support continuation on error. */
MI_RESULT_CONTINUATION_ON_ERROR_NOT_SUPPORTED = 26,
/* The operation failed because server limits were exceeded. */
MI_RESULT_SERVER_LIMITS_EXCEEDED = 27,
/* The CIM server is shutting down and cannot process the operation. */
MI_RESULT_SERVER_IS_SHUTTING_DOWN = 28
#endif
};
// Defines encodings of special characters. Just use a 7-bit ASCII character
// as an index into this array to retrieve its string encoding and encoding
// length in bytes.
static const Char_Encoding s_encodedChars127[128] =
{
{LIT(MI_T("�"))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T("	"))},
{LIT(MI_T(" "))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(" "))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(""))},
{LIT(MI_T(" "))},
{LIT(MI_T("!"))},
{LIT(MI_T("""))},
{LIT(MI_T("#"))},
{LIT(MI_T("$"))},
{LIT(MI_T("%"))},
{LIT(MI_T("&"))},
{LIT(MI_T("'"))},
{LIT(MI_T("("))},
{LIT(MI_T(")"))},
{LIT(MI_T("*"))},
{LIT(MI_T("+"))},
{LIT(MI_T(","))},
{LIT(MI_T("-"))},
{LIT(MI_T("."))},
{LIT(MI_T("/"))},
{LIT(MI_T("0"))},
{LIT(MI_T("1"))},
{LIT(MI_T("2"))},
{LIT(MI_T("3"))},
{LIT(MI_T("4"))},
{LIT(MI_T("5"))},
{LIT(MI_T("6"))},
{LIT(MI_T("7"))},
{LIT(MI_T("8"))},
{LIT(MI_T("9"))},
{LIT(MI_T(":"))},
{LIT(MI_T(";"))},
{LIT(MI_T("<"))},
{LIT(MI_T("="))},
{LIT(MI_T(">"))},
{LIT(MI_T("?"))},
{LIT(MI_T("@"))},
{LIT(MI_T("A"))},
{LIT(MI_T("B"))},
{LIT(MI_T("C"))},
{LIT(MI_T("D"))},
{LIT(MI_T("E"))},
{LIT(MI_T("F"))},
{LIT(MI_T("G"))},
{LIT(MI_T("H"))},
{LIT(MI_T("I"))},
{LIT(MI_T("J"))},
{LIT(MI_T("K"))},
{LIT(MI_T("L"))},
{LIT(MI_T("M"))},
{LIT(MI_T("N"))},
{LIT(MI_T("O"))},
{LIT(MI_T("P"))},
{LIT(MI_T("Q"))},
{LIT(MI_T("R"))},
{LIT(MI_T("S"))},
{LIT(MI_T("T"))},
{LIT(MI_T("U"))},
{LIT(MI_T("V"))},
{LIT(MI_T("W"))},
{LIT(MI_T("X"))},
{LIT(MI_T("Y"))},
{LIT(MI_T("Z"))},
{LIT(MI_T("["))},
{LIT(MI_T("\\"))},
{LIT(MI_T("]"))},
{LIT(MI_T("^"))},
{LIT(MI_T("_"))},
{LIT(MI_T("`"))},
{LIT(MI_T("a"))},
{LIT(MI_T("b"))},
{LIT(MI_T("c"))},
{LIT(MI_T("d"))},
{LIT(MI_T("e"))},
{LIT(MI_T("f"))},
{LIT(MI_T("g"))},
{LIT(MI_T("h"))},
{LIT(MI_T("i"))},
{LIT(MI_T("j"))},
{LIT(MI_T("k"))},
{LIT(MI_T("l"))},
{LIT(MI_T("m"))},
{LIT(MI_T("n"))},
{LIT(MI_T("o"))},
{LIT(MI_T("p"))},
{LIT(MI_T("q"))},
{LIT(MI_T("r"))},
{LIT(MI_T("s"))},
{LIT(MI_T("t"))},
{LIT(MI_T("u"))},
{LIT(MI_T("v"))},
{LIT(MI_T("w"))},
{LIT(MI_T("x"))},
{LIT(MI_T("y"))},
{LIT(MI_T("z"))},
{LIT(MI_T("{"))},
{LIT(MI_T("|"))},
{LIT(MI_T("}"))},
{LIT(MI_T("~"))},
{LIT(MI_T(""))}
};
/* Table used to identify special characters */
static const char s_specialChars[256] =
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
};
/*
**==============================================================================
**
** Local definitions:
**
**==============================================================================
*/
MI_INLINE MI_Boolean _Field_GetExists(
const void* field,
MI_Type type)
{
return Field_GetExists((const Field*)field, type);
}
static MI_Result _ReallocPage(
WS_Buffer* buf,
MI_Uint32 newSize)
{
Page* new_page;
/* round up to next 1k */
#define WSMAN_BUF_CAPACITY 1024
newSize = ((newSize + WSMAN_BUF_CAPACITY) / WSMAN_BUF_CAPACITY) * WSMAN_BUF_CAPACITY;
new_page = (Page*)realloc(buf->page, sizeof(Page) + newSize);
if (!new_page)
return MI_RESULT_FAILED;
buf->page = new_page;
buf->page->u.s.size = newSize;
return MI_RESULT_OK;
}
#if 0
#if (MI_CHAR_TYPE == 1)
#define FIRST_HIGH_SURROGATE 0xD800
#define LAST_HIGH_SURROGATE 0xDBFF
static void _UTF16toUTF8(
MI_Char16 c,
char* s)
{
static const MI_Uint8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
MI_Uint8* tgt = (MI_Uint8*)s;
MI_Uint32 numberOfBytes;
/* not a valid single char */
if (c >= FIRST_HIGH_SURROGATE
&& c <= LAST_HIGH_SURROGATE)
{
s[0] = '?';
s[1] = 0;
return;
}
if (c < 0x80)
{
numberOfBytes = 1;
}
else if (c < 0x800)
{
numberOfBytes = 2;
}
else
{
numberOfBytes = 3;
}
tgt += numberOfBytes;
switch (numberOfBytes)
{
case 3:
*--tgt = (MI_Uint8)((c | 0x80) & 0xBF);
c >>= 6;
case 2:
*--tgt = (MI_Uint8)((c | 0x80) & 0xBF);
c >>= 6;
case 1:
*--tgt = (MI_Uint8)(c | firstByteMark[numberOfBytes]);
}
}
#endif
#endif
/*
**==============================================================================
**
** Public API:
**
**==============================================================================
*/
MI_Result WSBuf_Init(
WS_Buffer* buf,
MI_Uint32 initialSize)
{
buf->page = (Page*)malloc(sizeof(Page) + initialSize);
buf->position = 0;
if (!buf->page)
{
return MI_RESULT_FAILED;
}
buf->page->u.s.size = initialSize;
buf->page->u.s.next = 0;
/* Put empty string inside */
((MI_Char*)(buf->page +1))[0] = 0;
return MI_RESULT_OK;
}
MI_Result WSBuf_Destroy(
WS_Buffer* buf)
{
if (buf->page)
free(buf->page);
return MI_RESULT_OK;
}
#if (MI_CHAR_TYPE == 1)
Page* WSBuf_StealPage(
WS_Buffer* buf)
{
Page* res = buf->page;
if (!res)
return 0;
buf->page = 0;
res->u.s.size = buf->position;
buf->position = 0;
return res;
}
#else
Page* WSBuf_StealPage(
WS_Buffer* buf)
{
if (!buf->page)
return 0;
/* convert wchar_t to utf-8
unfortunately, Windows does not support wchat -> utf8 conversion in crt */
{
Page* res;
const MI_Char* text = ((MI_Char*)(buf->page +1));
int size = WideCharToMultiByte(CP_UTF8, 0, text, -1, NULL, 0, 0, NULL);
if (size == 0)
goto failed;
res = (Page*)malloc(sizeof(Page) + size);
if (!res)
goto failed;
if (WideCharToMultiByte(CP_UTF8, 0, text, -1, (char*)(res + 1), size, 0, NULL) == 0)
{
free(res);
goto failed;
}
res->u.s.size = size - 1;
res->u.s.next = 0;
free(buf->page);
buf->page = 0;
buf->position = 0;
return res;
}
failed:
free(buf->page);
buf->page = 0;
return 0;
}
#endif
MI_Result WSBuf_AddUint32(
WS_Buffer* buf,
MI_Uint32 x)
{
MI_Char tmp[12];
size_t size;
const MI_Char* s = Uint32ToZStr(tmp, x, &size);
return WSBuf_AddLit(buf, s, (MI_Uint32)size);
}
MI_Result __WSBuf_AddLit(
WS_Buffer* buf,
const MI_Char* str,
MI_Uint32 size)
{
MI_Uint32 n = (size + 1) * sizeof(MI_Char);
/* Extend buffer (WSBuf_AddLit determined it was too small) */
if (_ReallocPage(buf, n + buf->position) != MI_RESULT_OK)
return MI_RESULT_FAILED;
/* Add string */
{
char* data = ((char*)(buf->page+1)) + buf->position;
memcpy( data, str, n - sizeof(MI_Char));
((MI_Char*)data)[size] = 0;
buf->position += n - sizeof(MI_Char);
}
return MI_RESULT_OK;
}
/* Add string with proper xml encoding */
MI_Result WSBuf_AddString(
WS_Buffer* buf,
const MI_Char* str)
{
#if (MI_CHAR_TYPE == 1)
/* Process leading non-special characters in the hope that little will
* be left over to be encoded the expensive way below this block.
*/
{
const unsigned char* start = (const unsigned char*)str;
const unsigned char* p = start;
while (!s_specialChars[*p])
p++;
if (p != start)
{
if (WSBuf_AddLit(buf, (const char*)start, (MI_Uint32)(p - start)))
return MI_RESULT_FAILED;
str = (const char*)p;
}
if (!*str)
return MI_RESULT_OK;
}
#endif
/* Now encode what remains (starting with first special char hit above) */
{
/*MI_Uint32 size = (MI_Uint32)((MI_Strlen(str) + 1)*sizeof(MI_Char));*/
MI_Char* pos = (MI_Char*)(((char*)(buf->page +1)) + buf->position);
MI_Char* end = (MI_Char*)(((char*)(buf->page +1)) + buf->page->u.s.size);
/* Add reamingin characters (next character is special) */
while (*str)
{
const MI_Char* item;
size_t size_chars;
MI_Uint32 c = (MI_Uint32)(MI_Sint16)*str;
/* if c is ascii ?*/
if (c < 128)
{
item = s_encodedChars127[c].str;
size_chars = s_encodedChars127[c].size;
}
else
{
item = str;
size_chars = 1;
}
/* Extend buffer if needed */
if ( (size_t)(end - pos) <= (size_chars + 1))
{
size_t current_pos =
(pos - ((MI_Char*)(buf->page +1))) * sizeof(MI_Char);
if (_ReallocPage(buf, (MI_Uint32)(buf->page->u.s.size + size_chars * sizeof(MI_Char))) != MI_RESULT_OK)
return MI_RESULT_FAILED;
pos = (MI_Char*)(((char*)(buf->page +1)) + current_pos);
end = (MI_Char*)(((char*)(buf->page +1)) + buf->page->u.s.size);
}
if (1 == size_chars)
*pos = *item;
else
memcpy( pos, item, size_chars * sizeof(MI_Char));
pos += size_chars;
str++;
}
buf->position = (MI_Uint32)((pos - ((MI_Char*)(buf->page +1))) * sizeof(MI_Char));
/* put \0 at the end */
((MI_Char*)(((char*)(buf->page +1)) + buf->position))[0] = 0;
return MI_RESULT_OK;
}
}
#if (MI_CHAR_TYPE != 1)
MI_Result WSBuf_AddCharStringNoEncoding(
WS_Buffer* buf,
const char* str)
{
return WSBuf_AddCharLit(buf, str, (MI_Uint32)strlen(str));
}
MI_Result WSBuf_AddCharLit(
WS_Buffer* buf,
const char* str,
MI_Uint32 size_)
{
MI_Uint32 size = (MI_Uint32)((size_ + 1)*sizeof(MI_Char));
/* Extend buffer if needed */
if (size + buf->position > buf->page->u.s.size &&
_ReallocPage(buf, size + buf->position) != MI_RESULT_OK)
return MI_RESULT_FAILED;
{
MI_Char* data = (MI_Char*)(((char*)(buf->page +1)) + buf->position);
MI_Uint32 i;
for (i = 0; i < size_; i++)
{
*data++ = *str++;
}
buf->position += size - sizeof(MI_Char);
}
return MI_RESULT_OK;
}
#endif
/* Callback to tag writer:
allows to write properties for both values/EPRs with the same routine */
typedef MI_Result (*PropertyTagWriter)(
WS_Buffer* buf,
const MI_Char* name,
MI_Boolean start);
INLINE MI_Result PropertyTagWriter_PropStart(
WS_Buffer* buf,
const MI_Char* name)
{
MI_Uint32 n = (MI_Uint32)Zlen(name);
if (MI_RESULT_OK != WSBuf_AddLit3(buf, '<', 'p', ':') ||
MI_RESULT_OK != WSBuf_AddLit(buf, name, n) ||
MI_RESULT_OK != WSBuf_AddLit1(buf,'>'))
{
return MI_RESULT_FAILED;
}
return MI_RESULT_OK;
}
INLINE MI_Result PropertyTagWriter_PropEnd(
WS_Buffer* buf,
const MI_Char* name)
{
MI_Uint32 n = (MI_Uint32)Zlen(name);
if (MI_RESULT_OK != WSBuf_AddLit4(buf, '<', '/', 'p', ':') ||
MI_RESULT_OK != WSBuf_AddLit(buf, name, n) ||
MI_RESULT_OK != WSBuf_AddLit2(buf, '>', '\n'))
{
return MI_RESULT_FAILED;
}
return MI_RESULT_OK;
}
static MI_Result PropertyTagWriter_Prop(
WS_Buffer* buf,
const MI_Char* name,
MI_Boolean start)
{
if (start)
return PropertyTagWriter_PropStart(buf, name);
else
return PropertyTagWriter_PropEnd(buf, name);
}
static MI_Result PropertyTagWriter_EPR(
WS_Buffer* buf,
const MI_Char* name,
MI_Boolean start)
{
if (start)
{
if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("<wsman:Selector Name=\""))) ||
MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,name) ||
MI_RESULT_OK != WSBuf_AddLit2(buf, '"', '>')
)
return MI_RESULT_FAILED;
}
else
{
if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wsman:Selector>") XML_CR))
)
return MI_RESULT_FAILED;
}
return MI_RESULT_OK;
}
static MI_Result _PackFieldNil(
WS_Buffer* buf,
const MI_Char* name)
{
if ( MI_RESULT_OK != WSBuf_AddLit3(buf, '<', 'p', ':') ||
MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,name) ||
MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T(" xsi:nil=\"true\"/>") XML_CR)) )
return MI_RESULT_FAILED;
return MI_RESULT_OK;
}
static MI_Result _PackFieldString(
WS_Buffer* buf,
PropertyTagWriter writer,
const MI_Char* name,
const MI_Char* value)
{
if ( MI_RESULT_OK != writer(buf,name,MI_TRUE) ||
MI_RESULT_OK != WSBuf_AddString(buf,value) ||
MI_RESULT_OK != writer(buf,name,MI_FALSE)
)
return MI_RESULT_FAILED;
return MI_RESULT_OK;
}
static MI_Result _PackFieldStringLit(
WS_Buffer* buf,
PropertyTagWriter writer,
const MI_Char* name,
const MI_Char* value,
MI_Uint32 valueSize)
{
if ( MI_RESULT_OK != writer(buf,name,MI_TRUE) ||
MI_RESULT_OK != WSBuf_AddLit(buf,value,valueSize) ||
MI_RESULT_OK != writer(buf,name,MI_FALSE)
)
return MI_RESULT_FAILED;
return MI_RESULT_OK;
}
static MI_Result _PackFieldEmbeddedInstance(
WS_Buffer* buf,
const MI_Char* name,
const MI_Instance* value)
{
if ( MI_RESULT_OK != PropertyTagWriter_PropStart(buf,name) ||
MI_RESULT_OK != _PackInstance(buf,value,NULL,NULL,0,WSMAN_ObjectFlag,MI_TRUE) ||
MI_RESULT_OK != PropertyTagWriter_PropEnd(buf,name)
)
return MI_RESULT_FAILED;
return MI_RESULT_OK;
}
static MI_Result _PackFieldRef(
WS_Buffer* buf,
const MI_Char* name,
const MI_Instance* value)
{
if ( MI_RESULT_OK != PropertyTagWriter_PropStart(buf,name) ||
MI_RESULT_OK != _PackEPR(buf,value) ||
MI_RESULT_OK != PropertyTagWriter_PropEnd(buf,name)
)
return MI_RESULT_FAILED;
return MI_RESULT_OK;
}
static MI_Result _PackFieldUint32(
WS_Buffer* buf,
PropertyTagWriter writer,
const MI_Char* name,
MI_Uint32 value)
{
MI_Char tmp[11];
size_t size;
const MI_Char* str = Uint32ToZStr(tmp, value, &size);
return _PackFieldStringLit(buf,writer, name, str, (MI_Uint32)size);
}
static MI_Result _PackFieldUint64(
WS_Buffer* buf,
PropertyTagWriter writer,
const MI_Char* name,
MI_Uint64 value)
{
MI_Char tmp[21];
size_t size;
const MI_Char* str = Uint64ToZStr(tmp, value, &size);
return _PackFieldStringLit(buf, writer, name, str, (MI_Uint32)size);
}
static MI_Result _PackFieldSint32(
WS_Buffer* buf,
PropertyTagWriter writer,
const MI_Char* name,
MI_Sint32 value)
{
MI_Char s[24];
MI_Sint32 size = Szprintf(s, MI_COUNT(s), MI_T("%d"), value);
return _PackFieldStringLit(buf,writer,name,s,size);
}
static MI_Result _PackFieldSint64(
WS_Buffer* buf,
PropertyTagWriter writer,
const MI_Char* name,
MI_Sint64 value)
{
MI_Char s[24];
MI_Sint32 size = Szprintf(s, MI_COUNT(s), SINT64_FMT_T, value);
return _PackFieldStringLit(buf,writer,name,s,size);
}
static MI_Result _PackFieldReal64(
WS_Buffer* buf,
PropertyTagWriter writer,
const MI_Char* name,
MI_Real64 value)
{
MI_Char s[24];
MI_Sint32 size = Szprintf(s, MI_COUNT(s), MI_T("%g"), value);
return _PackFieldStringLit(buf,writer,name,s,size);
}
static MI_Result _PackFieldDatetime(
WS_Buffer* buf,
PropertyTagWriter writer,
const MI_Char* name,
const MI_Datetime* p)
{
MI_Char tmp[64];
FormatWSManDatetime(p, tmp);
return _PackFieldStringLit(buf, writer, name, tmp, (MI_Uint32)Zlen(tmp));
}
static MI_Result _PackValue(
WS_Buffer* buf,
PropertyTagWriter writer,
const MI_Char* name,
const void* field,
MI_Type type)
{
switch(type)
{
case MI_BOOLEAN:
{
MI_Boolean* f = (MI_Boolean*)field;
if (*f)
return _PackFieldStringLit(buf,writer,name,LIT(MI_T("TRUE")));
else
return _PackFieldStringLit(buf,writer,name,LIT(MI_T("FALSE")));
}
case MI_UINT8:
{
MI_Uint8* f = (MI_Uint8*)field;
return _PackFieldUint32(buf,writer,name,*f);
}
case MI_UINT16:
{
MI_Uint16* f = (MI_Uint16*)field;
return _PackFieldUint32(buf,writer,name,*f);
}
case MI_UINT32:
{
MI_Uint32* f = (MI_Uint32*)field;
return _PackFieldUint32(buf,writer,name,*f);
}
case MI_UINT64:
{
MI_Uint64* f = (MI_Uint64*)field;
return _PackFieldUint64(buf,writer,name,*f);
}
case MI_SINT8:
{
MI_Sint8* f = (MI_Sint8*)field;
return _PackFieldSint32(buf,writer,name,*f);
}
case MI_SINT16:
{
MI_Sint16* f = (MI_Sint16*)field;
return _PackFieldSint32(buf,writer,name,*f);
}
case MI_SINT32:
{
MI_Sint32* f = (MI_Sint32*)field;
return _PackFieldSint32(buf,writer,name,*f);
}
case MI_SINT64:
{
MI_Sint64* f = (MI_Sint64*)field;
return _PackFieldSint64(buf,writer,name,*f);
}
case MI_REAL32:
{
MI_Real32* f = (MI_Real32*)field;
return _PackFieldReal64(buf,writer,name,*f);
}
case MI_REAL64:
{
MI_Real64* f = (MI_Real64*)field;
return _PackFieldReal64(buf,writer,name,*f);
}
case MI_DATETIME:
{
MI_Datetime* f = (MI_Datetime*)field;
return _PackFieldDatetime(buf,writer,name,&*f);
}
case MI_CHAR16:
{
MI_Char16* f = (MI_Char16*)field;
#if 0
#if (MI_CHAR_TYPE == 1)
char s[6];
memset(s,0,sizeof(s));
_UTF16toUTF8(*f,s);
#else
/* whcar_t -
steal page will translate it */
wchar_t s[2] = {0, 0};
s[0] = *f;
#endif
/* ATTN: convert it to utf8 and encode as a string */
return _PackFieldString(buf,writer,name,s);
#else
return _PackFieldUint32(buf,writer,name,(MI_Uint32)*f);
#endif
}
case MI_INSTANCE:
{
MI_Instance** f = (MI_Instance**)field;
return _PackFieldEmbeddedInstance(buf,name,*f);
}
case MI_REFERENCE:
{
MI_Instance** f = (MI_Instance**)field;
return _PackFieldRef(buf,name,*f);
}
case MI_STRING:
{
MI_String* f = (MI_String*)field;
return _PackFieldString(buf,writer,name,*f);
}
default:
break;
}
return MI_RESULT_OK;
}
static MI_Result _PackField(
WS_Buffer* buf,
PropertyTagWriter writer,
const MI_Char* name,
const void* field,
MI_Type type)
{
/* Check if value is null */
if (!_Field_GetExists(field, type))
return _PackFieldNil(buf, name);
/* Check if type is array:
Arrays are encoded the same way regular instances are
with repeating instance as many times as many elements are in array */
if (type & MI_ARRAY_BIT)
{
MI_ArrayField* f = (MI_ArrayField*)field;
MI_Uint32 i;
MI_Type stype = type & ~MI_ARRAY_BIT;
char* currentValue = (char*)f->value.data;
for (i = 0; i < f->value.size; i++)
{
if (MI_RESULT_OK != _PackValue(buf,writer,name,currentValue,stype))
return MI_RESULT_FAILED;
currentValue += Type_SizeOf(stype);
}
return MI_RESULT_OK;
}
return _PackValue(buf,writer,name,field,type);
}
static MI_Result _PackEPR(
WS_Buffer* buf,
const MI_Instance* instance)
{
Instance* self = (Instance*)instance;
const MI_ClassDecl* cd = self->classDecl;
MI_Uint32 i;
/* Put EPR header */
if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>") XML_CR
MI_T("<wsa:ReferenceParameters>") XML_CR
MI_T("<wsman:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/") )) ||
MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,cd->name) ||
MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wsman:ResourceURI>") XML_CR
MI_T("<wsman:SelectorSet>") XML_CR )) )
return MI_RESULT_FAILED;
/* namespace (if present)*/
if (self->nameSpace)
{
}
/* Put properties */
for ( i = 0; i < cd->numProperties; i++ )
{
const MI_PropertyDecl* pd = cd->properties[i];
const void* value = (char*)self + pd->offset;
if ((pd->flags & MI_FLAG_KEY) == 0)
continue;
/* skip null values */
if (!_Field_GetExists(value,(MI_Type)pd->type))
continue;
if (MI_RESULT_OK != _PackValue(buf, PropertyTagWriter_EPR, pd->name, value, (MI_Type)pd->type))
return MI_RESULT_FAILED;
}
/* close EPR */
if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wsman:SelectorSet>") XML_CR
MI_T("</wsa:ReferenceParameters>") XML_CR )) )
return MI_RESULT_FAILED;
return MI_RESULT_OK;
}
static MI_Result _PackInstance(
WS_Buffer* buf,
const MI_Instance* instance,
MI_Boolean (*filterProperty)(const MI_Char* name, void* data),
void* filterPropertyData,
const MI_ClassDecl* castToClassDecl,
MI_Uint32 flags,
MI_Boolean embedded)
{
Instance* self = (Instance*)instance;
const MI_ClassDecl* cd = castToClassDecl ? castToClassDecl : self->classDecl;
MI_Uint32 i;
/* Check for null arguments */
if (!self || !buf)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* For Object & EPR, add <Item> tag */
if ((flags & WSMAN_ObjectAndEPRFlag) == WSMAN_ObjectAndEPRFlag)
{
if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("<wsman:Item>") XML_CR)))
return MI_RESULT_FAILED;
}
/* If object was requested */
if ((flags & WSMAN_ObjectFlag) == WSMAN_ObjectFlag)
{
/* Put classname */
if ( MI_RESULT_OK != WSBuf_AddLit3(buf, '<', 'p', ':') ||
MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,cd->name) ||
MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T(" xmlns:p=\"http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/"))) ||
MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,cd->name) ||
MI_RESULT_OK != WSBuf_AddLit2(buf, '"', '\n'))
return MI_RESULT_FAILED;
if (embedded)
{
if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T(" xsi:type=\""))) ||
MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,cd->name) ||
MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("_Type\"") XML_CR)))
return MI_RESULT_FAILED;
}
if ( MI_RESULT_OK != WSBuf_AddLit2(buf, '>', '\n'))
return MI_RESULT_FAILED;
/* Put properties */
for ( i = 0; i < cd->numProperties; i++ )
{
const MI_PropertyDecl* pd = cd->properties[i];
const void* value = (char*)self + pd->offset;
if (filterProperty && (*filterProperty)(pd->name, filterPropertyData))
continue;
if (MI_RESULT_OK != _PackField(buf, PropertyTagWriter_Prop, pd->name, value, (MI_Type)pd->type))
return MI_RESULT_FAILED;
}
/* close class */
if ( MI_RESULT_OK != WSBuf_AddLit4(buf, '<', '/', 'p', ':') ||
MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,cd->name) ||
MI_RESULT_OK != WSBuf_AddLit2(buf, '>', '\n'))
return MI_RESULT_FAILED;
}
/* If EPR was requested */
if ((flags & WSMAN_EPRFlag) == WSMAN_EPRFlag)
{
if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("<wsa:EndpointReference>") XML_CR)) ||
MI_RESULT_OK != _PackEPR(buf,instance) ||
MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wsa:EndpointReference>") XML_CR)))
return MI_RESULT_FAILED;
}
/* If EPR was requested */
if ((flags & WSMAN_CreatedEPRFlag) == WSMAN_CreatedEPRFlag)
{
if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("<wxf:ResourceCreated>") XML_CR)) ||
MI_RESULT_OK != _PackEPR(buf,instance) ||
MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wxf:ResourceCreated>") XML_CR)))
return MI_RESULT_FAILED;
}
/* For Object & EPR, add </Item> tag */
if ((flags & WSMAN_ObjectAndEPRFlag) == WSMAN_ObjectAndEPRFlag)
{
if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wsman:Item>") XML_CR)))
return MI_RESULT_FAILED;
}
return MI_RESULT_OK;
}
MI_Result WSBuf_InstanceToBuf(
const MI_Instance* instance,
MI_Boolean (*filterProperty)(const MI_Char* name, void* data),
void* filterPropertyData,
const MI_ClassDecl* castToClassDecl,
Batch* batch,
MI_Uint32 flags,
void** ptrOut,
MI_Uint32* sizeOut)
{
WS_Buffer buf;
MI_Result r;
Page* page;
r = WSBuf_Init(&buf,1024);
if (MI_RESULT_OK != r)
return r;
r = _PackInstance(&buf, instance, filterProperty,
filterPropertyData, castToClassDecl, flags,MI_FALSE);
if (MI_RESULT_OK != r)
{
WSBuf_Destroy(&buf);
return r;
}
page = WSBuf_StealPage(&buf);
Batch_AttachPage(batch, page);
*ptrOut = page + 1;
*sizeOut = (MI_Uint32)page->u.s.size;
return MI_RESULT_OK;
}
void WSBuf_GenerateMessageID(
MI_Char msgID[WS_MSG_ID_SIZE])
{
//WS-Management qualifies the use of wsa:MessageID and wsa:RelatesTo as follows:
//R5.4.6.4-1: The MessageID and RelatesTo URIs may be of any format, as long as they are valid
//URIs according to RFC 3986. Two URIs are considered different even if the characters in the
//URIs differ only by case.
//The following two formats are endorsed by this specification. The first is considered a best
//practice because it is backed by RFC 4122:
//urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
//or
//uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
//In these formats, each x is an uppercase or lowercase hexadecimal digit (lowercase is required
//by RFC 4122); there are no spaces or other tokens. The value may be a DCE-style universally
//unique identifier (UUID) with provable uniqueness properties in this format, however, it is not
//necessary to have provable uniqueness properties in the URIs used in the wsa:MessageID and
//wsa:RelatesTo headers.
//Regardless of format, the URI should not exceed the maximum defined in R13.1-6.
//UUIDs have a numeric meaning as well as a string meaning, and this can lead to confusion. A UUID
//in lowercase is a different URI from the same UUID in uppercase. This is because URIs are case1619
//tive. If a UUID is converted to its decimal equivalent the case of the original characters is lost.
//WS-Management works with the URI value itself, not the underlying decimal equivalent
//representation. Services are free to interpret the URI in any way, but are not allowed to alter the case
//usage when repeating the message or any of the MessageID values in subsequent messages.
//The RFC 4122 requires the digits to be lowercase, which is the responsibility of the client. The service
//simply processes the values as URI values and is not required to analyze the URI for correctness or
//compliance. The service replicates the client usage in the wsa:RelatesTo reply header and is not
//allowed to alter the case usage.
//R5.4.6.4-2: The MessageID should be generated according to any algorithm that ensures that no
//two MessageIDs are repeated. Because the value is treated as case-sensitive (R5.4.6.4-1),
//confusion can arise if the same value is reused differing only in case. As a result, the service shall
//not create or employ MessageID values that differ only in case. For any message transmitted by
//the service, the MessageID shall not be reused.
static MI_Uint64 s1, s2;
if (!s1)
Time_Now(&s1);
s2++;
/* ADC */
if (!s2)
s1++;
Szprintf(msgID, WS_MSG_ID_SIZE,
MI_T("uuid:%08X-%04X-%04X-%04X-%08X%04X"),
(MI_Uint32)(s1 & 0xFFFFFFFF),
(MI_Uint32)((s1 >> 32) & 0xFFFF),
(MI_Uint32)((s1 >> 48) & 0xFFFF),
(MI_Uint32)((s2 >> 48) & 0xFFFF),
(MI_Uint32)(s2 & 0xFFFFFFFF),
(MI_Uint32)((s2 >> 32) & 0xFFFF) );
}
MI_Result WSBuf_CreateSoapResponseHeader(
WS_Buffer *buf,
const MI_Char* action,
MI_Uint32 actionSize,
const char* relatesTo)
{
MI_Char msgID[WS_MSG_ID_SIZE];
/* Response header */
if (MI_RESULT_OK != WSBuf_AddLit(buf,
LIT(
MI_T("<SOAP-ENV:Envelope ")
MI_T("xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\" ")
MI_T("xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\" ")
MI_T("xmlns:wsen=\"http://schemas.xmlsoap.org/ws/2004/09/enumeration\" ")
MI_T("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ")
MI_T("xmlns:wsmb=\"http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd\" ")
MI_T("xmlns:wsman=\"http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd\" ")
MI_T("xmlns:wxf=\"http://schemas.xmlsoap.org/ws/2004/09/transfer\" ")
MI_T("xmlns:xml=\"http://www.w3.org/XML/1998/namespace\" ")
MI_T("xmlns:wsmid=\"http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd\" >")
XML_CR
MI_T("<SOAP-ENV:Header>") XML_CR
MI_T("<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>") XML_CR
MI_T("<wsa:Action>"))) )
{
goto failed;
}
if (MI_RESULT_OK != WSBuf_AddLit(buf, action, actionSize))
goto failed;
if (MI_RESULT_OK != WSBuf_AddLit(buf,
LIT(MI_T("</wsa:Action>") XML_CR
MI_T("<wsa:MessageID>" ))))
goto failed;
/* Generate new uniqueue msg id */
WSBuf_GenerateMessageID(msgID);
if (MI_RESULT_OK != WSBuf_AddLit(buf, msgID, WS_MSG_ID_SIZE - 1))
goto failed;
if (MI_RESULT_OK != WSBuf_AddLit(buf,
LIT(MI_T("</wsa:MessageID>") XML_CR)))
goto failed;
if (relatesTo)
{
if (MI_RESULT_OK != WSBuf_AddLit(buf,
LIT(MI_T("<wsa:RelatesTo>"))))
goto failed;
if (MI_RESULT_OK != WSBuf_AddCharStringNoEncoding(buf, relatesTo))
goto failed;
if (MI_RESULT_OK != WSBuf_AddLit(buf,
LIT(MI_T("</wsa:RelatesTo>") XML_CR)))
goto failed;
}
return MI_RESULT_OK;
failed:
return MI_RESULT_FAILED;
}
Page* WSBuf_CreateFaultResponsePage(
WSBUF_FAULT_CODE faultCode,
const char* notUnderstoodTag,
const char* requestMessageID,
const MI_Char* descriptionText)
{
WS_Buffer outBuf;
const BUF_FaultItem* fault;
if ( ((MI_Uint32)faultCode) >= MI_COUNT(s_faults))
{
fault = s_faults + 0; /* internal error */
}
else
{
fault = s_faults + (MI_Uint32)faultCode;
}
/* prepare soap response with error */
if (WSBuf_Init(&outBuf, 1024) != MI_RESULT_OK)
return 0;
/* fault header */
if (MI_RESULT_OK != WSBuf_CreateSoapResponseHeader(&outBuf,
fault->action, fault->actionSize, requestMessageID))
goto failed;
if (notUnderstoodTag)
{
if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
LIT(MI_T("<SOAP-ENV:NotUnderstood qname=\""))))
goto failed;
if (MI_RESULT_OK != WSBuf_AddCharStringNoEncoding(&outBuf, notUnderstoodTag ))
goto failed;
if (MI_RESULT_OK != WSBuf_AddLit3(&outBuf, '"', '/', '>'))
goto failed;
}
if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
LIT(
MI_T("</SOAP-ENV:Header>") XML_CR XML_CR
MI_T("<SOAP-ENV:Body>") XML_CR
MI_T("<SOAP-ENV:Fault>") XML_CR
MI_T("<SOAP-ENV:Code>") XML_CR
MI_T("<SOAP-ENV:Value>"))) )
goto failed;
if (MI_RESULT_OK != WSBuf_AddCharStringNoEncoding(&outBuf, fault->code))
goto failed;
//SOAP-ENV:Sender
if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
LIT(MI_T("</SOAP-ENV:Value>") XML_CR)))
goto failed;
if (fault->subCode)
{
if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
LIT(MI_T("<SOAP-ENV:Subcode>") XML_CR
MI_T("<SOAP-ENV:Value>"))))
goto failed;
if (MI_RESULT_OK != WSBuf_AddCharStringNoEncoding(&outBuf, fault->subCode))
goto failed;
if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
LIT(MI_T("</SOAP-ENV:Value>") XML_CR
MI_T("</SOAP-ENV:Subcode>") XML_CR)))
goto failed;
}
if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
LIT(MI_T("</SOAP-ENV:Code>") XML_CR
MI_T("<SOAP-ENV:Reason>") XML_CR
MI_T("<SOAP-ENV:Text xml:lang=\"en-US\">"))))
goto failed;
if ( descriptionText )
{
if (MI_RESULT_OK != WSBuf_AddString(&outBuf, descriptionText))
goto failed;
}
else
{
if (MI_RESULT_OK != WSBuf_AddCharStringNoEncoding(&outBuf, fault->defaultTest))
goto failed;
}
if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
LIT( MI_T("</SOAP-ENV:Text>") XML_CR
MI_T("</SOAP-ENV:Reason>") XML_CR
MI_T("</SOAP-ENV:Fault>") XML_CR
MI_T("</SOAP-ENV:Body>") XML_CR
MI_T("</SOAP-ENV:Envelope>") XML_CR)) )
goto failed;
return WSBuf_StealPage(&outBuf);
failed:
WSBuf_Destroy(&outBuf);
return 0;
}
Page* WSBuf_CreateReleaseResponsePage(
const char* requestMessageID)
{
WS_Buffer outBuf;
/* prepare soap response with error */
if (WSBuf_Init(&outBuf, 1024) != MI_RESULT_OK)
return 0;
/* fault header */
if (MI_RESULT_OK != WSBuf_CreateSoapResponseHeader(&outBuf,
LIT(MI_T("http://schemas.xmlsoap.org/ws/2004/09/enumeration/ReleaseResponse")),
requestMessageID))
goto failed;
if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
LIT(
MI_T("</SOAP-ENV:Header>") XML_CR XML_CR
MI_T("<SOAP-ENV:Body/>") XML_CR
MI_T("</SOAP-ENV:Envelope>") XML_CR)) )
goto failed;
return WSBuf_StealPage(&outBuf);
failed:
WSBuf_Destroy(&outBuf);
return 0;
}
WSBUF_FAULT_CODE WSBuf_CIMErrorToWSFault(
MI_Uint32 cimErrorCode,
const MI_Char** description )
{
MI_Uint32 index = cimErrorCode < MI_COUNT(s_cimerrors) ? cimErrorCode : MI_RESULT_FAILED;
if ( description )
*description = s_cimerrors[index].description;
return s_cimerrors[index].faultCode;
}