(file) Return to wsbuf.c CVS log (file) (dir) Up to [OMI] / omi / protocol

   1 mike  1.1 /*
   2           **==============================================================================
   3           **
   4           ** Open Management Infrastructure (OMI)
   5           **
   6           ** Copyright (c) Microsoft Corporation
   7           ** 
   8           ** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
   9           ** use this file except in compliance with the License. You may obtain a copy 
  10           ** of the License at 
  11           **
  12           **     http://www.apache.org/licenses/LICENSE-2.0 
  13           **
  14           ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15           ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
  16           ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
  17           ** MERCHANTABLITY OR NON-INFRINGEMENT. 
  18           **
  19           ** See the Apache 2 License for the specific language governing permissions 
  20           ** and limitations under the License.
  21           **
  22 mike  1.1 **==============================================================================
  23           */
  24           
  25           #include <common.h>
  26           #include "wsbuf.h"
  27           #include <base/log.h>
  28           #include <base/result.h>
  29           #include <base/instance.h>
  30           #include <base/strings.h>
  31           #include <base/field.h>
  32           #include <base/messages.h>
  33           #include <base/helpers.h>
  34           #include <base/time.h>
  35           #include <base/io.h>
  36           #include <base/base64.h>
  37           
  38           #if defined(WSBUF_DISABLE_INLINING)
  39           # include "wsbufinline.h"
  40           #endif
  41           
  42           #define T MI_T
  43 mike  1.1 
  44           #if 0
  45           #define ENABLE_TRACING
  46           #endif
  47           
  48           #ifdef  ENABLE_TRACING
  49           #define PRINTF(a) printf a
  50           #else
  51           #define PRINTF(a)
  52           #endif
  53           
  54           #define XML_CR MI_T("\n")
  55           
  56           /*
  57           **==============================================================================
  58           **
  59           ** Local datatypes:
  60           **
  61           **==============================================================================
  62           */
  63           typedef struct _BUF_FaultItem
  64 mike  1.1 {
  65               const MI_Char* action;
  66               MI_Uint32 actionSize;
  67               const char* code; /* sender/receiver */
  68               const char* subCode; /* wsa:XXX */
  69               const char* defaultTest;
  70           }
  71           BUF_FaultItem;
  72           
  73           typedef struct _BUF_CIMErrorItem
  74           {
  75               WSBUF_FAULT_CODE faultCode;
  76               const MI_Char* description;
  77           } 
  78           BUF_CIMErrorItem;
  79           
  80           /*
  81           **==============================================================================
  82           **
  83           ** Forward declarations:
  84           **
  85 mike  1.1 **==============================================================================
  86           */
  87           static MI_Result _PackInstance(
  88               WSBuf* buf,
  89               const MI_Instance* instance,
  90               MI_Boolean (*filterProperty)(const MI_Char* name, void* data),
  91               void* filterPropertyData,
  92               const MI_ClassDecl* castToClassDecl,
  93               MI_Uint32 flags,
  94               MI_Boolean embedded);
  95           
  96           static MI_Result _PackEPR(
  97               WSBuf* buf,
  98               const MI_Instance* instance);
  99           
 100           /*
 101           **==============================================================================
 102           **
 103           ** Static data:
 104           **
 105           **==============================================================================
 106 mike  1.1 */
 107           
 108           static const BUF_FaultItem s_faults[] = {
 109               /* WSBUF_FAULT_INTERNAL_ERROR */
 110               {
 111                   LIT(MI_T("http://schemas.dmtf.org/wbem/wsman/1/wsman/fault")),
 112                   "SOAP-ENV:Receiver",
 113                   "wsman:InternalError",
 114                   "The service cannot comply with the request due to internal processing errors."
 115               },
 116               /* WSBUF_FAULT_NOT_SUPPORTED */
 117               {
 118                   LIT(MI_T("http://schemas.dmtf.org/wbem/wsman/1/wsman/fault")),
 119                   "SOAP-ENV:Sender",
 120                   "wsman:UnsupportedFeature",
 121                   "not supported"
 122               },
 123               /* WSBUF_FAULT_NOT_UNDERSTOOD */
 124               {
 125                   LIT(MI_T("http://schemas.xmlsoap.org/ws/2004/08/addressing/fault")),
 126                   "SOAP-ENV:MustUnderstand",
 127 mike  1.1         0,
 128                   "Header not understood"
 129               },
 130               /* WSBUF_FAULT_DESTINATION_UNREACHABLE */
 131               {
 132                   LIT(MI_T("http://schemas.xmlsoap.org/ws/2004/08/addressing/fault")),
 133                   "SOAP-ENV:Sender",
 134                   "wsa:DestinationUnreachable",
 135                   "No route can be determined to reach the destination role defined by the Addressing To header."
 136               },
 137               /* WSBUF_FAULT_ACCESS_DENIED */
 138               {
 139                   LIT(MI_T("http://schemas.dmtf.org/wbem/wsman/1/wsman/fault")),
 140                   "SOAP-ENV:Sender",
 141                   "wsman:AccessDenied",
 142                   "The sender was not authorized to access the resource."
 143               },
 144               /* WSBUF_FAULT_ENCODING_LIMIT */
 145               {
 146                   LIT(MI_T("http://schemas.dmtf.org/wbem/wsman/1/wsman/fault")),
 147                   "SOAP-ENV:Sender",
 148 mike  1.1         "wsman:EncodingLimit",
 149                   "An internal encoding limit was exceeded in a request or would be violated if the message were processed."
 150               }
 151           };
 152           
 153           static const BUF_CIMErrorItem   s_cimerrors[] = {
 154               /* MI_RESULT_OK = 0, */
 155               {
 156                   0,
 157                   0
 158               },
 159               /* MI_RESULT_FAILED = 1, */
 160               {
 161                   WSBUF_FAULT_INTERNAL_ERROR,
 162                   MI_T("CIM ERROR:FAILED: A general error occurred, not covered by a more specific error code.")
 163               },
 164           
 165               /* MI_RESULT_ACCESS_DENIED = 2, */
 166               {
 167                   WSBUF_FAULT_ACCESS_DENIED,
 168                   MI_T("CIM ERROR:ACCESS_DENIED: Access to a CIM resource is not available to the client.")
 169 mike  1.1     },
 170           
 171               /* MI_RESULT_INVALID_NAMESPACE = 3, */
 172               {
 173                   WSBUF_FAULT_DESTINATION_UNREACHABLE,
 174                   MI_T("CIM ERROR:INVALID_NAMESPACE: The target namespace does not exist.")
 175               },
 176           
 177               /* MI_RESULT_INVALID_PARAMETER  = 4,*/
 178               {
 179                   WSBUF_FAULT_INTERNAL_ERROR,
 180                   MI_T("CIM ERROR:INVALID_PARAMETER: One or more parameter values passed to the method are not valid.")
 181               },
 182           
 183               /* MI_RESULT_INVALID_CLASS = 5, */
 184               {
 185                   WSBUF_FAULT_DESTINATION_UNREACHABLE,
 186                   MI_T("CIM ERROR:INVALID_CLASS: The specified class does not exist.")
 187               },
 188           
 189               /* MI_RESULT_NOT_FOUND = 6,*/
 190 mike  1.1     {
 191                   WSBUF_FAULT_DESTINATION_UNREACHABLE,
 192                   MI_T("CIM ERROR:NOT_FOUND: The requested object cannot be found.")
 193               },
 194           
 195               /* MI_RESULT_NOT_SUPPORTED = 7, */
 196               {
 197                   WSBUF_FAULT_NOT_SUPPORTED,
 198                   MI_T("CIM ERROR:NOT_SUPPORTED: The requested operation is not supported.")
 199               }
 200           
 201           #if 0
 202               /* The operation cannot be invoked because the class has subclasses. */
 203               MI_RESULT_CLASS_HAS_CHILDREN = 8,
 204           
 205               /* The operation cannot be invoked because the class has instances. */
 206               MI_RESULT_CLASS_HAS_INSTANCES = 9,
 207           
 208               /* The operation cannot be invoked because the superclass does not exist. */
 209               MI_RESULT_INVALID_SUPERCLASS = 10,
 210           
 211 mike  1.1     /* The operation cannot be invoked because an object already exists. */
 212               MI_RESULT_ALREADY_EXISTS = 11,
 213           
 214               /* The specified property does not exist. */
 215               MI_RESULT_NO_SUCH_PROPERTY = 12,
 216           
 217               /* The value supplied is not compatible with the type. */
 218               MI_RESULT_TYPE_MISMATCH = 13,
 219           
 220               /* The query language is not recognized or supported. */
 221               MI_RESULT_QUERY_LANGUAGE_NOT_SUPPORTED = 14,
 222           
 223               /* The query is not valid for the specified query language. */
 224               MI_RESULT_INVALID_QUERY = 15,
 225           
 226               /* The extrinsic method cannot be invoked. */
 227               MI_RESULT_METHOD_NOT_AVAILABLE = 16,
 228           
 229               /* The specified extrinsic method does not exist. */
 230               MI_RESULT_METHOD_NOT_FOUND = 17,
 231           
 232 mike  1.1     /* The specified namespace is not empty. */
 233               MI_RESULT_NAMESPACE_NOT_EMPTY = 20,
 234           
 235               /* The enumeration identified by the specified context is invalid. */
 236               MI_RESULT_INVALID_ENUMERATION_CONTEXT = 21,
 237           
 238               /* The specified operation timeout is not supported by the CIM Server. */
 239               MI_RESULT_INVALID_OPERATION_TIMEOUT = 22,
 240           
 241               /* The Pull operation has been abandoned. */
 242               MI_RESULT_PULL_HAS_BEEN_ABANDONED = 23,
 243           
 244               /* The attempt to abandon a concurrent Pull operation failed. */
 245               MI_RESULT_PULL_CANNOT_BE_ABANDONED = 24,
 246           
 247               /* Using a filter in the enumeration is not supported by the CIM server. */
 248               MI_RESULT_FILTERED_ENUMERATION_NOT_SUPPORTED = 25,
 249           
 250               /* The CIM server does not support continuation on error. */
 251               MI_RESULT_CONTINUATION_ON_ERROR_NOT_SUPPORTED = 26,
 252           
 253 mike  1.1     /* The operation failed because server limits were exceeded. */
 254               MI_RESULT_SERVER_LIMITS_EXCEEDED = 27,
 255           
 256               /* The CIM server is shutting down and cannot process the operation. */
 257               MI_RESULT_SERVER_IS_SHUTTING_DOWN = 28
 258           #endif
 259           };
 260           
 261           /* Encodings for special XML characters */
 262           static const char* s_specialCharEncodings[128] =
 263           {
 264               "\004&#0;",
 265               "\004&#1;",
 266               "\004&#2;",
 267               "\004&#3;",
 268               "\004&#4;",
 269               "\004&#5;",
 270               "\004&#6;",
 271               "\004&#7;",
 272               "\004&#8;",
 273               "\004&#9;",
 274 mike  1.1     "\005&#10;",
 275               "\005&#11;",
 276               "\005&#12;",
 277               "\005&#13;",
 278               "\005&#14;",
 279               "\005&#15;",
 280               "\005&#16;",
 281               "\005&#17;",
 282               "\005&#18;",
 283               "\005&#19;",
 284               "\005&#20;",
 285               "\005&#21;",
 286               "\005&#22;",
 287               "\005&#23;",
 288               "\005&#24;",
 289               "\005&#25;",
 290               "\005&#26;",
 291               "\005&#27;",
 292               "\005&#28;",
 293               "\005&#29;",
 294               "\005&#30;",
 295 mike  1.1     "\005&#31;",
 296               "\001 ",
 297               "\001!",
 298               "\006&quot;",
 299               "\001#",
 300               "\001$",
 301               "\001%",
 302               "\005&amp;",
 303               "\006&apos;",
 304               "\001(",
 305               "\001)",
 306               "\001*",
 307               "\001+",
 308               "\001,",
 309               "\001-",
 310               "\001.",
 311               "\001/",
 312               "\0010",
 313               "\0011",
 314               "\0012",
 315               "\0013",
 316 mike  1.1     "\0014",
 317               "\0015",
 318               "\0016",
 319               "\0017",
 320               "\0018",
 321               "\0019",
 322               "\001:",
 323               "\001;",
 324               "\004&lt;",
 325               "\001=",
 326               "\004&gt;",
 327               "\001?",
 328               "\001@",
 329               "\001A",
 330               "\001B",
 331               "\001C",
 332               "\001D",
 333               "\001E",
 334               "\001F",
 335               "\001G",
 336               "\001H",
 337 mike  1.1     "\001I",
 338               "\001J",
 339               "\001K",
 340               "\001L",
 341               "\001M",
 342               "\001N",
 343               "\001O",
 344               "\001P",
 345               "\001Q",
 346               "\001R",
 347               "\001S",
 348               "\001T",
 349               "\001U",
 350               "\001V",
 351               "\001W",
 352               "\001X",
 353               "\001Y",
 354               "\001Z",
 355               "\001[",
 356               "\001\\",
 357               "\001]",
 358 mike  1.1     "\001^",
 359               "\001_",
 360               "\001`",
 361               "\001a",
 362               "\001b",
 363               "\001c",
 364               "\001d",
 365               "\001e",
 366               "\001f",
 367               "\001g",
 368               "\001h",
 369               "\001i",
 370               "\001j",
 371               "\001k",
 372               "\001l",
 373               "\001m",
 374               "\001n",
 375               "\001o",
 376               "\001p",
 377               "\001q",
 378               "\001r",
 379 mike  1.1     "\001s",
 380               "\001t",
 381               "\001u",
 382               "\001v",
 383               "\001w",
 384               "\001x",
 385               "\001y",
 386               "\001z",
 387               "\001{",
 388               "\001|",
 389               "\001}",
 390               "\001~",
 391               "\006&#127;",
 392           };
 393           
 394           /* This table idnetifies special XML characters. */
 395           static const char s_specialChars[256] =
 396           {
 397               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,
 398               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,
 399               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,
 400 mike  1.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,1,
 401               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,
 402               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,
 403               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,
 404               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,
 405           };
 406           
 407           /*
 408           **==============================================================================
 409           **
 410           ** Local definitions:
 411           **
 412           **==============================================================================
 413           */
 414           MI_INLINE MI_Boolean _Field_GetExists(
 415               const void* field, 
 416               MI_Type type)
 417           {
 418               return Field_GetExists((const Field*)field, type);
 419           }
 420           
 421 mike  1.1 static MI_Result _ReallocPage(
 422               WSBuf* buf,
 423               MI_Uint32 newSize)
 424           {
 425               Page* new_page;
 426           
 427               /* round up to next 1k */
 428           #define WSMAN_BUF_CAPACITY 1024
 429               newSize = ((newSize + WSMAN_BUF_CAPACITY) / WSMAN_BUF_CAPACITY)  * WSMAN_BUF_CAPACITY;
 430               new_page = (Page*)realloc(buf->page, sizeof(Page) + newSize);
 431           
 432               if (!new_page)
 433                   return MI_RESULT_FAILED;
 434           
 435               buf->page = new_page;
 436               buf->page->u.s.size = newSize;
 437               return MI_RESULT_OK;
 438           }
 439           
 440           #if 0
 441           #if (MI_CHAR_TYPE == 1)
 442 mike  1.1 #define FIRST_HIGH_SURROGATE  0xD800
 443           #define LAST_HIGH_SURROGATE   0xDBFF
 444           
 445           static void _UTF16toUTF8(
 446               MI_Char16 c,
 447               char* s)
 448           {
 449               static const MI_Uint8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
 450               MI_Uint8* tgt = (MI_Uint8*)s;
 451               MI_Uint32 numberOfBytes;
 452           
 453               /* not a valid single char */
 454               if (c >= FIRST_HIGH_SURROGATE
 455                   && c <= LAST_HIGH_SURROGATE)
 456               {
 457                   s[0] = '?';
 458                   s[1] = 0;
 459                   return;
 460               }
 461           
 462               if (c < 0x80)
 463 mike  1.1     {
 464                   numberOfBytes = 1;
 465               }
 466               else if (c < 0x800)
 467               {
 468                   numberOfBytes = 2;
 469               }
 470               else 
 471               {
 472                   numberOfBytes = 3;
 473               }
 474           
 475               tgt += numberOfBytes;
 476           
 477               switch (numberOfBytes)
 478               {
 479                   case 3:
 480                   *--tgt = (MI_Uint8)((c | 0x80) & 0xBF);
 481                   c >>= 6;
 482                   case 2:
 483                   *--tgt = (MI_Uint8)((c | 0x80) & 0xBF);
 484 mike  1.1         c >>= 6;
 485                   case 1:
 486                   *--tgt =  (MI_Uint8)(c | firstByteMark[numberOfBytes]);
 487               }
 488           }
 489           #endif
 490           #endif
 491           
 492           /*
 493           **==============================================================================
 494           **
 495           ** Public API:
 496           **
 497           **==============================================================================
 498           */
 499           MI_Result WSBuf_Init(
 500               WSBuf* buf,
 501               MI_Uint32 initialSize)
 502           {
 503               buf->page = (Page*)malloc(sizeof(Page) + initialSize);
 504               buf->position = 0;
 505 mike  1.1 
 506               if (!buf->page)
 507               {
 508                   return MI_RESULT_FAILED;
 509               }
 510           
 511               buf->page->u.s.size = initialSize;
 512               buf->page->u.s.next = 0;
 513               /* Put empty string inside */
 514               ((MI_Char*)(buf->page +1))[0] = 0;
 515               return MI_RESULT_OK;
 516           }
 517           
 518           MI_Result WSBuf_Destroy(
 519               WSBuf* buf)
 520           {
 521               if (buf->page)
 522                   free(buf->page);
 523           
 524               return MI_RESULT_OK;
 525           }
 526 mike  1.1 
 527           #if (MI_CHAR_TYPE == 1)
 528           Page* WSBuf_StealPage(
 529               WSBuf* buf)
 530           {
 531               Page* res = buf->page;
 532           
 533               if (!res)
 534                   return 0;
 535           
 536               buf->page = 0;
 537               res->u.s.size = buf->position;
 538               buf->position = 0;
 539           
 540               return res;
 541           }
 542           #else
 543           Page* WSBuf_StealPage(
 544               WSBuf* buf)
 545           {
 546           
 547 mike  1.1     if (!buf->page)
 548                   return 0;
 549           
 550               /* convert wchar_t to utf-8 
 551                   unfortunately, Windows does not support wchat -> utf8 conversion in crt */
 552           
 553               {
 554                   Page* res;
 555                   const MI_Char* text = ((MI_Char*)(buf->page +1));
 556                   int size = WideCharToMultiByte(CP_UTF8, 0, text, -1, NULL, 0, 0, NULL);
 557           
 558                   if (size == 0)
 559                       goto failed;
 560           
 561                   res = (Page*)malloc(sizeof(Page) + size);
 562           
 563                   if (!res)
 564                       goto failed;
 565           
 566                   if (WideCharToMultiByte(CP_UTF8, 0, text, -1, (char*)(res + 1), size, 0, NULL) == 0) 
 567                   {
 568 mike  1.1             free(res);
 569                       goto failed;
 570                   }
 571           
 572                   res->u.s.size = size - 1;
 573                   res->u.s.next = 0;
 574           
 575                   free(buf->page);
 576                   buf->page = 0;
 577                   buf->position = 0;
 578                   return res;
 579               }
 580           
 581           failed:
 582               free(buf->page);
 583               buf->page = 0;
 584               return 0;
 585           }
 586           #endif
 587           
 588           MI_Result WSBuf_AddUint32(
 589 mike  1.1     WSBuf* buf,
 590               MI_Uint32 x)
 591           {
 592               MI_Char tmp[12];
 593               size_t size;
 594               const MI_Char* s = Uint32ToZStr(tmp, x, &size);
 595               return WSBuf_AddLit(buf, s, (MI_Uint32)size);
 596           }
 597           
 598           MI_Result __WSBuf_AddLit(
 599               WSBuf* buf,
 600               const MI_Char* str,
 601               MI_Uint32 size)
 602           {
 603               MI_Uint32 n = (size + 1) * sizeof(MI_Char);
 604           
 605               /* Extend buffer (WSBuf_AddLit determined it was too small) */
 606               if (_ReallocPage(buf, n + buf->position) != MI_RESULT_OK)
 607                   return MI_RESULT_FAILED;
 608           
 609               /* Add string */
 610 mike  1.1     {
 611                   char* data = ((char*)(buf->page+1)) + buf->position;
 612                   memcpy( data, str, n - sizeof(MI_Char));
 613                   ((MI_Char*)data)[size] = 0;
 614           
 615                   buf->position += n - sizeof(MI_Char);
 616               }
 617           
 618               return MI_RESULT_OK;
 619           }
 620           
 621           /* Add string with proper xml encoding */
 622           MI_Result WSBuf_AddString(
 623               WSBuf* buf,
 624               const MI_Char* str)
 625           {
 626           #if (MI_CHAR_TYPE == 1)
 627               /* Process leading non-special characters in the hope that little will
 628                * be left over to be encoded the expensive way below this block.
 629                */
 630               {
 631 mike  1.1         const unsigned char* start = (const unsigned char*)str;
 632                   const unsigned char* p = start;
 633           
 634                   while (!s_specialChars[*p])
 635                       p++;
 636           
 637                   if (p != start)
 638                   {
 639                       if (WSBuf_AddLit(buf, (const char*)start, (MI_Uint32)(p - start)))
 640                           return MI_RESULT_FAILED;
 641           
 642                       str = (const char*)p;
 643                   }
 644           
 645                   if (!*str)
 646                       return MI_RESULT_OK;
 647               }
 648           #endif
 649           
 650               /* Now encode what remains (starting with first special char hit above) */
 651               {
 652 mike  1.1         /*MI_Uint32 size = (MI_Uint32)((MI_Strlen(str) + 1)*sizeof(MI_Char));*/
 653                   MI_Char* pos = (MI_Char*)(((char*)(buf->page +1)) + buf->position);
 654                   MI_Char* end = (MI_Char*)(((char*)(buf->page +1)) + buf->page->u.s.size);
 655           
 656                   /* Add reamingin characters (next character is special) */
 657                   while (*str)
 658                   {
 659                       const MI_Char* item;
 660                       size_t size_chars;
 661                       MI_Uint32 c = (MI_Uint32)(MI_Sint16)*str;
 662           
 663                       /* if c is ascii ?*/
 664                       if (c < 128)
 665                       {
 666                           /* First byte is the length */
 667                           item = s_specialCharEncodings[c] + 1;
 668                           size_chars = s_specialCharEncodings[c][0];
 669                       }
 670                       else
 671                       {
 672                           item = str;
 673 mike  1.1                 size_chars = 1;
 674                       }
 675           
 676                       /* Extend buffer if needed */
 677                       if ( (size_t)(end - pos) <= (size_chars + 1))
 678                       {
 679                           size_t current_pos = 
 680                               (pos - ((MI_Char*)(buf->page +1))) * sizeof(MI_Char);
 681           
 682                           if (_ReallocPage(buf, (MI_Uint32)(buf->page->u.s.size + size_chars * sizeof(MI_Char))) != MI_RESULT_OK)
 683                               return MI_RESULT_FAILED;
 684           
 685                           pos = (MI_Char*)(((char*)(buf->page +1)) + current_pos);
 686                           end = (MI_Char*)(((char*)(buf->page +1)) + buf->page->u.s.size);
 687                       }
 688           
 689                       if (1 == size_chars)
 690                           *pos = *item;
 691                       else
 692                           memcpy( pos, item, size_chars * sizeof(MI_Char));
 693           
 694 mike  1.1             pos += size_chars;
 695                       str++;
 696                   }
 697           
 698                   buf->position = (MI_Uint32)((pos - ((MI_Char*)(buf->page +1))) * sizeof(MI_Char));
 699           
 700                   /* put \0 at the end */
 701                   ((MI_Char*)(((char*)(buf->page +1)) + buf->position))[0] = 0;
 702           
 703                   return MI_RESULT_OK;
 704               }
 705           }
 706           
 707           #if (MI_CHAR_TYPE != 1)
 708           MI_Result WSBuf_AddCharStringNoEncoding(
 709               WSBuf* buf,
 710               const char* str)
 711           {
 712               return WSBuf_AddCharLit(buf, str, (MI_Uint32)strlen(str));
 713           }
 714           
 715 mike  1.1 MI_Result WSBuf_AddCharLit(
 716               WSBuf* buf,
 717               const char* str,
 718               MI_Uint32 size_)
 719           {
 720               MI_Uint32 size = (MI_Uint32)((size_ + 1)*sizeof(MI_Char));
 721           
 722               /* Extend buffer if needed */
 723               if (size + buf->position > buf->page->u.s.size &&
 724                   _ReallocPage(buf, size + buf->position) != MI_RESULT_OK)
 725                   return MI_RESULT_FAILED;
 726           
 727               {
 728                   MI_Char* data = (MI_Char*)(((char*)(buf->page +1)) + buf->position);
 729                   MI_Uint32 i;
 730           
 731                   for (i = 0; i < size_; i++)
 732                   {
 733                       *data++ = *str++;
 734                   }
 735                   buf->position += size - sizeof(MI_Char);
 736 mike  1.1     }
 737           
 738               return MI_RESULT_OK;
 739           }
 740           
 741           #endif
 742           
 743           /* Callback to tag writer:
 744               allows to write properties for both values/EPRs with the same routine */
 745           typedef MI_Result (*PropertyTagWriter)(
 746               WSBuf* buf,
 747               const MI_Char* name,
 748               MI_Boolean start);
 749           
 750           INLINE MI_Result PropertyTagWriter_PropStart(
 751               WSBuf* buf,
 752               const MI_Char* name)
 753           {
 754               MI_Uint32 n = (MI_Uint32)Zlen(name);
 755           
 756               if (MI_RESULT_OK != WSBuf_AddLit3(buf, '<', 'p', ':') ||
 757 mike  1.1         MI_RESULT_OK != WSBuf_AddLit(buf, name, n) ||
 758                   MI_RESULT_OK != WSBuf_AddLit1(buf,'>'))
 759               {
 760                   return MI_RESULT_FAILED;
 761               }
 762           
 763               return MI_RESULT_OK;
 764           }
 765           
 766           INLINE MI_Result PropertyTagWriter_PropEnd(
 767               WSBuf* buf,
 768               const MI_Char* name)
 769           {
 770               MI_Uint32 n = (MI_Uint32)Zlen(name);
 771           
 772               if (MI_RESULT_OK != WSBuf_AddLit4(buf, '<', '/', 'p', ':') || 
 773                   MI_RESULT_OK != WSBuf_AddLit(buf, name, n) ||
 774                   MI_RESULT_OK != WSBuf_AddLit2(buf, '>', '\n'))
 775               {
 776                   return MI_RESULT_FAILED;
 777               }
 778 mike  1.1 
 779               return MI_RESULT_OK;
 780           }
 781           
 782           static MI_Result PropertyTagWriter_Prop(
 783               WSBuf* buf,
 784               const MI_Char* name,
 785               MI_Boolean start)
 786           {
 787               if (start)
 788                   return PropertyTagWriter_PropStart(buf, name);
 789               else
 790                   return PropertyTagWriter_PropEnd(buf, name);
 791           }
 792           
 793           static MI_Result PropertyTagWriter_EPR(
 794               WSBuf* buf,
 795               const MI_Char* name,
 796               MI_Boolean start)
 797           {
 798               if (start)
 799 mike  1.1     {
 800                   if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("<wsman:Selector Name=\""))) ||
 801                       MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,name) ||
 802                       MI_RESULT_OK != WSBuf_AddLit2(buf, '"', '>')
 803                       )
 804                       return MI_RESULT_FAILED;
 805               }
 806               else
 807               {
 808                   if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wsman:Selector>") XML_CR)) 
 809                       )
 810                       return MI_RESULT_FAILED;
 811               }
 812           
 813               return MI_RESULT_OK;
 814           }
 815           
 816           static MI_Result _PackFieldNil(
 817               WSBuf* buf,
 818               const MI_Char* name)
 819           {
 820 mike  1.1     if ( MI_RESULT_OK != WSBuf_AddLit3(buf, '<', 'p', ':') ||
 821                   MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,name) ||
 822                   MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T(" xsi:nil=\"true\"/>") XML_CR)) )
 823                   return MI_RESULT_FAILED;
 824           
 825               return MI_RESULT_OK;
 826           }
 827           
 828           static int _Base64Callback(
 829               const char* data, 
 830               size_t size, 
 831               void* callbackData)
 832           {
 833               WSBuf* buf = callbackData;
 834               return WSBuf_AddLit(buf, data, size) == MI_RESULT_OK ? 0 : -1;
 835           }
 836           
 837           static MI_Result _PackFieldOctetString(
 838               WSBuf* buf,
 839               const MI_Char* name,
 840               const MI_Uint8* data,
 841 mike  1.1     size_t size)
 842           {
 843               /* Validate first 4 bytes which contain the length then remove them */
 844               {
 845                   size_t length = 0;
 846           
 847                   if (size < 4)
 848                       return MI_RESULT_FAILED;
 849           
 850                   length |= data[0] << 24;
 851                   length |= data[1] << 16;
 852                   length |= data[2] << 8;
 853                   length |= data[3];
 854           
 855                   if (length != size)
 856                       return MI_RESULT_FAILED;
 857           
 858                   data += 4;
 859                   size -= 4;
 860               }
 861           
 862 mike  1.1     if (WSBuf_AddLit3(buf, '<', 'p', ':') != MI_RESULT_OK)
 863                   return MI_RESULT_FAILED;
 864           
 865               if (WSBuf_AddStringNoEncoding(buf, name) != MI_RESULT_OK)
 866                   return MI_RESULT_FAILED;
 867           
 868               if (WSBuf_AddLit(buf,
 869                   LIT(MI_T(" xsi:type=\"cim:cimBase64Binary\">"))) != MI_RESULT_OK)
 870               {
 871                   return MI_RESULT_FAILED;
 872               }
 873           
 874               if (Base64Enc(data, size, _Base64Callback, buf) != 0)
 875                   return MI_RESULT_FAILED;
 876           
 877               if (PropertyTagWriter_PropEnd(buf, name) != MI_RESULT_OK)
 878                   return MI_RESULT_FAILED;
 879           
 880               return MI_RESULT_OK;
 881           }
 882           
 883 mike  1.1 static MI_Result _PackFieldString(
 884               WSBuf* buf,
 885               PropertyTagWriter writer,
 886               const MI_Char* name,
 887               const MI_Char* value)
 888           {
 889               if ( MI_RESULT_OK != writer(buf,name,MI_TRUE) ||
 890                   MI_RESULT_OK != WSBuf_AddString(buf,value) ||
 891                   MI_RESULT_OK != writer(buf,name,MI_FALSE)
 892                   )
 893                   return MI_RESULT_FAILED;
 894           
 895               return MI_RESULT_OK;
 896           }
 897           
 898           static MI_Result _PackFieldStringLit(
 899               WSBuf* buf,
 900               PropertyTagWriter writer,
 901               const MI_Char* name,
 902               const MI_Char* value,
 903               MI_Uint32 valueSize)
 904 mike  1.1 {
 905               if ( MI_RESULT_OK != writer(buf,name,MI_TRUE) ||
 906                   MI_RESULT_OK != WSBuf_AddLit(buf,value,valueSize) ||
 907                   MI_RESULT_OK != writer(buf,name,MI_FALSE)  
 908                   )
 909                   return MI_RESULT_FAILED;
 910           
 911               return MI_RESULT_OK;
 912           }
 913           
 914           static MI_Result _PackFieldEmbeddedInstance(
 915               WSBuf* buf,
 916               const MI_Char* name,
 917               const MI_Instance* value)
 918           {
 919               if ( MI_RESULT_OK != PropertyTagWriter_PropStart(buf,name) ||
 920                   MI_RESULT_OK != _PackInstance(buf,value,NULL,NULL,0,WSMAN_ObjectFlag,MI_TRUE) ||
 921                   MI_RESULT_OK != PropertyTagWriter_PropEnd(buf,name)  
 922                   )
 923                   return MI_RESULT_FAILED;
 924           
 925 mike  1.1     return MI_RESULT_OK;
 926           }
 927           
 928           static MI_Result _PackFieldRef(
 929               WSBuf* buf,
 930               const MI_Char* name,
 931               const MI_Instance* value)
 932           {
 933               if ( MI_RESULT_OK != PropertyTagWriter_PropStart(buf,name) ||
 934                   MI_RESULT_OK != _PackEPR(buf,value) ||
 935                   MI_RESULT_OK != PropertyTagWriter_PropEnd(buf,name)  
 936                   )
 937                   return MI_RESULT_FAILED;
 938           
 939               return MI_RESULT_OK;
 940           }
 941           
 942           static MI_Result _PackFieldUint32(
 943               WSBuf* buf,
 944               PropertyTagWriter writer,
 945               const MI_Char* name,
 946 mike  1.1     MI_Uint32 value)
 947           {
 948               MI_Char tmp[11];
 949               size_t size;
 950               const MI_Char* str = Uint32ToZStr(tmp, value, &size);
 951               return _PackFieldStringLit(buf,writer, name, str, (MI_Uint32)size);
 952           }
 953           
 954           static MI_Result _PackFieldUint64(
 955               WSBuf* buf,
 956               PropertyTagWriter writer,
 957               const MI_Char* name,
 958               MI_Uint64 value)
 959           {
 960               MI_Char tmp[21];
 961               size_t size;
 962               const MI_Char* str = Uint64ToZStr(tmp, value, &size);
 963               return _PackFieldStringLit(buf, writer, name, str, (MI_Uint32)size);
 964           }
 965           
 966           static MI_Result _PackFieldSint32(
 967 mike  1.1     WSBuf* buf,
 968               PropertyTagWriter writer,
 969               const MI_Char* name,
 970               MI_Sint32 value)
 971           {
 972               MI_Char s[24];
 973           
 974               MI_Sint32 size = Szprintf(s, MI_COUNT(s), MI_T("%d"), value);
 975               return _PackFieldStringLit(buf,writer,name,s,size);
 976           }
 977           
 978           static MI_Result _PackFieldSint64(
 979               WSBuf* buf,
 980               PropertyTagWriter writer,
 981               const MI_Char* name,
 982               MI_Sint64 value)
 983           {
 984               MI_Char s[24];
 985           
 986               MI_Sint32 size = Szprintf(s, MI_COUNT(s), SINT64_FMT_T, value);
 987               return _PackFieldStringLit(buf,writer,name,s,size);
 988 mike  1.1 }
 989           
 990           static MI_Result _PackFieldReal64(
 991               WSBuf* buf,
 992               PropertyTagWriter writer,
 993               const MI_Char* name,
 994               MI_Real64 value)
 995           {
 996               MI_Char s[24];
 997           
 998               MI_Sint32 size = Szprintf(s, MI_COUNT(s), MI_T("%g"), value);
 999               return _PackFieldStringLit(buf,writer,name,s,size);
1000           }
1001           
1002           static MI_Result _PackFieldDatetime(
1003               WSBuf* buf,
1004               PropertyTagWriter writer,
1005               const MI_Char* name,
1006               const MI_Datetime* p)
1007           {
1008               MI_Char tmp[64];
1009 mike  1.1     FormatWSManDatetime(p, tmp);
1010               return _PackFieldStringLit(buf, writer, name, tmp, (MI_Uint32)Zlen(tmp));
1011           }
1012           
1013           static MI_Result _PackValue(
1014               WSBuf* buf,
1015               PropertyTagWriter writer,
1016               const MI_Char* name,
1017               const void* field, 
1018               MI_Type type)
1019           {
1020               switch(type)
1021               {
1022                   case MI_BOOLEAN:
1023                   {
1024                       MI_Boolean* f = (MI_Boolean*)field;
1025           
1026                       if (*f)
1027                           return _PackFieldStringLit(buf,writer,name,LIT(MI_T("TRUE")));
1028                       else
1029                           return _PackFieldStringLit(buf,writer,name,LIT(MI_T("FALSE")));
1030 mike  1.1         }
1031                   case MI_UINT8:
1032                   {
1033                       MI_Uint8* f = (MI_Uint8*)field;
1034           
1035                       return _PackFieldUint32(buf,writer,name,*f);
1036                   }
1037                   case MI_UINT16:
1038                   {
1039                       MI_Uint16* f = (MI_Uint16*)field;
1040           
1041                       return _PackFieldUint32(buf,writer,name,*f);
1042                   }
1043                   case MI_UINT32:
1044                   {
1045                       MI_Uint32* f = (MI_Uint32*)field;
1046           
1047                       return _PackFieldUint32(buf,writer,name,*f);
1048                   }
1049                   case MI_UINT64:
1050                   {
1051 mike  1.1             MI_Uint64* f = (MI_Uint64*)field;
1052           
1053                       return _PackFieldUint64(buf,writer,name,*f);
1054                   }
1055                   case MI_SINT8:
1056                   {
1057                       MI_Sint8* f = (MI_Sint8*)field;
1058           
1059                       return _PackFieldSint32(buf,writer,name,*f);
1060                   }
1061                   case MI_SINT16:
1062                   {
1063                       MI_Sint16* f = (MI_Sint16*)field;
1064           
1065                       return _PackFieldSint32(buf,writer,name,*f);
1066                   }
1067                   case MI_SINT32:
1068                   {
1069                       MI_Sint32* f = (MI_Sint32*)field;
1070           
1071                       return _PackFieldSint32(buf,writer,name,*f);
1072 mike  1.1         }
1073                   case MI_SINT64:
1074                   {
1075                       MI_Sint64* f = (MI_Sint64*)field;
1076           
1077                       return _PackFieldSint64(buf,writer,name,*f);
1078                   }
1079                   case MI_REAL32:
1080                   {
1081                       MI_Real32* f = (MI_Real32*)field;
1082           
1083                       return _PackFieldReal64(buf,writer,name,*f);
1084                   }
1085                   case MI_REAL64:
1086                   {
1087                       MI_Real64* f = (MI_Real64*)field;
1088           
1089                       return _PackFieldReal64(buf,writer,name,*f);
1090                   }
1091                   case MI_DATETIME:
1092                   {
1093 mike  1.1             MI_Datetime* f = (MI_Datetime*)field;
1094           
1095                       return _PackFieldDatetime(buf,writer,name,&*f);
1096                   }
1097                   case MI_CHAR16:
1098                   {
1099                       MI_Char16* f = (MI_Char16*)field;
1100           #if 0
1101           #if (MI_CHAR_TYPE == 1)
1102                       char s[6];
1103                       memset(s,0,sizeof(s));
1104           
1105                       _UTF16toUTF8(*f,s);
1106           #else
1107                       /* whcar_t - 
1108                       steal page will translate it */
1109                       wchar_t s[2] = {0, 0};
1110           
1111                       s[0] = *f;
1112           #endif
1113           
1114 mike  1.1             /* ATTN: convert it to utf8 and encode as a string */
1115                       return _PackFieldString(buf,writer,name,s);
1116           #else
1117                       return _PackFieldUint32(buf,writer,name,(MI_Uint32)*f);
1118           #endif
1119                   }
1120                   case MI_INSTANCE:
1121                   {
1122                       MI_Instance** f = (MI_Instance**)field;
1123           
1124                       return _PackFieldEmbeddedInstance(buf,name,*f);
1125                   }
1126                   case MI_REFERENCE:
1127                   {
1128                       MI_Instance** f = (MI_Instance**)field;
1129           
1130                       return _PackFieldRef(buf,name,*f);
1131                   }
1132                   case MI_STRING:
1133                   {
1134                       MI_String* f = (MI_String*)field;
1135 mike  1.1 
1136                       return _PackFieldString(buf,writer,name,*f);
1137                   }
1138                   default:
1139                       break;
1140               }
1141           
1142               return MI_RESULT_OK;
1143           }
1144           
1145           static MI_Result _PackField(
1146               WSBuf* buf,
1147               PropertyTagWriter writer,
1148               const MI_Char* name,
1149               const void* field, 
1150               MI_Type type,
1151               MI_Boolean isOctetString)
1152           {
1153               /* Check if value is null */
1154               if (!_Field_GetExists(field, type))
1155                   return _PackFieldNil(buf, name);
1156 mike  1.1 
1157               /* Check if type is array:
1158                   Arrays are encoded the same way regular instances are 
1159                   with repeating instance as many times as many elements are in array */
1160               if (type & MI_ARRAY_BIT)
1161               {
1162                   if (isOctetString && type == MI_UINT8A)
1163                   {
1164                       MI_Uint8AField* f = (MI_Uint8AField*)field;
1165                       return _PackFieldOctetString(buf, name, f->value.data, 
1166                           f->value.size);
1167                   }
1168           
1169                   /* ATTN: STRING OctetString not handled! */
1170           
1171                   {
1172                       MI_ArrayField* f = (MI_ArrayField*)field;
1173                       MI_Uint32 i;
1174                       MI_Type stype = type & ~MI_ARRAY_BIT;
1175                       char* currentValue = (char*)f->value.data;
1176           
1177 mike  1.1             for (i = 0; i < f->value.size; i++)
1178                       {
1179                           if (_PackValue(
1180                               buf, 
1181                               writer, 
1182                               name, 
1183                               currentValue, 
1184                               stype) != MI_RESULT_OK)
1185                           {
1186                               return MI_RESULT_FAILED;
1187                           }
1188           
1189                           currentValue += Type_SizeOf(stype);
1190                       }
1191           
1192                       return MI_RESULT_OK;
1193                   }
1194               }
1195           
1196               return _PackValue(buf, writer, name, field, type);
1197           }
1198 mike  1.1 
1199           static MI_Result _PackEPR(
1200               WSBuf* buf,
1201               const MI_Instance* instance)
1202           {
1203               Instance* self = (Instance*)instance;
1204               const MI_ClassDecl* cd = self->classDecl;
1205               MI_Uint32 i;
1206           
1207               /* Put EPR header */
1208               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
1209                       MI_T("<wsa:ReferenceParameters>") XML_CR 
1210                       MI_T("<wsman:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/") )) ||
1211                   MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,cd->name) ||
1212                   MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wsman:ResourceURI>") XML_CR 
1213                       MI_T("<wsman:SelectorSet>") XML_CR )) )
1214                   return MI_RESULT_FAILED;
1215           
1216               /* namespace (if present)*/
1217               if (self->nameSpace)
1218               {
1219 mike  1.1     }
1220           
1221               /* Put properties */
1222               for ( i = 0; i < cd->numProperties; i++ )
1223               {
1224                   const MI_PropertyDecl* pd = cd->properties[i];
1225                   const void* value = (char*)self + pd->offset;
1226           
1227                   if ((pd->flags & MI_FLAG_KEY) == 0)
1228                       continue;
1229           
1230                   /* skip null values */
1231                   if (!_Field_GetExists(value,(MI_Type)pd->type))
1232                       continue;
1233           
1234                   if (_PackValue(
1235                       buf, 
1236                       PropertyTagWriter_EPR, 
1237                       pd->name, value, 
1238                       (MI_Type)pd->type) != MI_RESULT_OK)
1239                   {
1240 mike  1.1             return MI_RESULT_FAILED;
1241                   }
1242               }
1243           
1244               /* close EPR */
1245               if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wsman:SelectorSet>") XML_CR
1246                       MI_T("</wsa:ReferenceParameters>") XML_CR )) )
1247                   return MI_RESULT_FAILED;
1248           
1249               return MI_RESULT_OK;
1250           }
1251           
1252           static MI_Boolean TestOctetStringQualifier(
1253               const MI_PropertyDecl* pd)
1254           {
1255               size_t i;
1256           
1257               for (i = 0; i < pd->numQualifiers; i++)
1258               {
1259                   const MI_Qualifier* q = pd->qualifiers[i];
1260           
1261 mike  1.1         if (Zcasecmp(q->name, T("OctetString")) == 0 
1262                       && q->type == MI_BOOLEAN
1263                       && q->value)
1264                   {
1265                       return *((const MI_Boolean*)q->value);
1266                   }
1267               }
1268           
1269               return MI_FALSE;
1270           }
1271           
1272           static MI_Result _PackInstance(
1273               WSBuf* buf,
1274               const MI_Instance* instance,
1275               MI_Boolean (*filterProperty)(const MI_Char* name, void* data),
1276               void* filterPropertyData,
1277               const MI_ClassDecl* castToClassDecl,
1278               MI_Uint32 flags,
1279               MI_Boolean embedded)
1280           {
1281               Instance* self = (Instance*)instance;
1282 mike  1.1     const MI_ClassDecl* cd = castToClassDecl ? castToClassDecl : self->classDecl;
1283               MI_Uint32 i;
1284           
1285               /* Check for null arguments */
1286               if (!self || !buf)
1287                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1288           
1289               /* For Object & EPR, add <Item> tag */
1290               if ((flags & WSMAN_ObjectAndEPRFlag) == WSMAN_ObjectAndEPRFlag)
1291               {
1292                   if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("<wsman:Item>") XML_CR)))
1293                       return MI_RESULT_FAILED;
1294               }
1295           
1296               /* If object was requested */
1297               if ((flags & WSMAN_ObjectFlag) == WSMAN_ObjectFlag)
1298               {
1299                   /* Put classname */
1300                   if ( MI_RESULT_OK != WSBuf_AddLit3(buf, '<', 'p', ':') ||
1301                       MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,cd->name) ||
1302                       MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T(" xmlns:p=\"http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/"))) ||
1303 mike  1.1             MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,cd->name) ||
1304                       MI_RESULT_OK != WSBuf_AddLit2(buf, '"', '\n'))
1305                       return MI_RESULT_FAILED;
1306           
1307                   if (embedded)
1308                   {
1309                       if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T(" xsi:type=\""))) ||
1310                           MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,cd->name) ||
1311                           MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("_Type\"") XML_CR)))
1312                           return MI_RESULT_FAILED;
1313                   }
1314                   if ( MI_RESULT_OK != WSBuf_AddLit2(buf, '>', '\n'))
1315                       return MI_RESULT_FAILED;
1316           
1317                   /* Put properties */
1318                   for ( i = 0; i < cd->numProperties; i++ )
1319                   {
1320                       const MI_PropertyDecl* pd = cd->properties[i];
1321                       const void* value = (char*)self + pd->offset;
1322                       MI_Boolean isOctetString = MI_FALSE;
1323           
1324 mike  1.1             if (filterProperty && 
1325                           (*filterProperty)(pd->name, filterPropertyData))
1326                       {
1327                           continue;
1328                       }
1329           
1330                       /* Search for OctetString qualifier */
1331           
1332                       if (pd->type == MI_UINT8A || pd->type == MI_STRINGA)
1333                           isOctetString = TestOctetStringQualifier(pd);
1334           
1335                       /* Pack the field */
1336           
1337                       if (_PackField(
1338                           buf, 
1339                           PropertyTagWriter_Prop, 
1340                           pd->name, 
1341                           value, 
1342                           (MI_Type)pd->type,
1343                           isOctetString) != MI_RESULT_OK)
1344                       {
1345 mike  1.1                 return MI_RESULT_FAILED;
1346                       }
1347                   }
1348           
1349                   /* close class */
1350                   if ( MI_RESULT_OK != WSBuf_AddLit4(buf, '<', '/', 'p', ':') ||
1351                       MI_RESULT_OK != WSBuf_AddStringNoEncoding(buf,cd->name) ||
1352                       MI_RESULT_OK != WSBuf_AddLit2(buf, '>', '\n'))
1353                       return MI_RESULT_FAILED;
1354               }
1355           
1356               /* If EPR was requested */
1357               if ((flags & WSMAN_EPRFlag) == WSMAN_EPRFlag)
1358               {
1359                   if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("<wsa:EndpointReference>") XML_CR)) ||
1360                       MI_RESULT_OK != _PackEPR(buf,instance) ||
1361                       MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wsa:EndpointReference>") XML_CR)))
1362                       return MI_RESULT_FAILED;
1363               }
1364           
1365               /* If EPR was requested */
1366 mike  1.1     if ((flags & WSMAN_CreatedEPRFlag) == WSMAN_CreatedEPRFlag)
1367               {
1368                   if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("<wxf:ResourceCreated>") XML_CR)) ||
1369                       MI_RESULT_OK != _PackEPR(buf,instance) ||
1370                       MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wxf:ResourceCreated>") XML_CR)))
1371                       return MI_RESULT_FAILED;
1372               }
1373           
1374               /* For Object & EPR, add </Item> tag */
1375               if ((flags & WSMAN_ObjectAndEPRFlag) == WSMAN_ObjectAndEPRFlag)
1376               {
1377                   if ( MI_RESULT_OK != WSBuf_AddLit(buf,LIT(MI_T("</wsman:Item>") XML_CR)))
1378                       return MI_RESULT_FAILED;
1379               }
1380           
1381           
1382               return MI_RESULT_OK;
1383           }
1384           
1385           MI_Result WSBuf_InstanceToBuf(
1386               const MI_Instance* instance,
1387 mike  1.1     MI_Boolean (*filterProperty)(const MI_Char* name, void* data),
1388               void* filterPropertyData,
1389               const MI_ClassDecl* castToClassDecl,
1390               Batch* batch,
1391               MI_Uint32 flags,
1392               void** ptrOut,
1393               MI_Uint32* sizeOut)
1394           {
1395               WSBuf buf;
1396               MI_Result r;
1397               Page* page;
1398           
1399               r = WSBuf_Init(&buf,1024);
1400           
1401               if (MI_RESULT_OK != r)
1402                   return r;
1403           
1404               r = _PackInstance(&buf, instance, filterProperty, 
1405                   filterPropertyData, castToClassDecl, flags,MI_FALSE);
1406           
1407               if (MI_RESULT_OK != r)
1408 mike  1.1     {
1409                   WSBuf_Destroy(&buf);
1410                   return r;
1411               }
1412           
1413               page = WSBuf_StealPage(&buf);
1414               Batch_AttachPage(batch, page);
1415           
1416               *ptrOut = page + 1;
1417               *sizeOut = (MI_Uint32)page->u.s.size;
1418               return MI_RESULT_OK;
1419           }
1420           
1421           void WSBuf_GenerateMessageID(
1422               MI_Char msgID[WS_MSG_ID_SIZE])
1423           {
1424               //WS-Management qualifies the use of wsa:MessageID and wsa:RelatesTo as follows:
1425               //R5.4.6.4-1: The MessageID and RelatesTo URIs may be of any format, as long as they are valid
1426               //URIs according to RFC 3986. Two URIs are considered different even if the characters in the
1427               //URIs differ only by case.
1428               //The following two formats are endorsed by this specification. The first is considered a best
1429 mike  1.1     //practice because it is backed by RFC 4122:
1430               //urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
1431               //or
1432               //uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
1433               //In these formats, each x is an uppercase or lowercase hexadecimal digit (lowercase is required
1434               //by RFC 4122); there are no spaces or other tokens. The value may be a DCE-style universally
1435               //unique identifier (UUID) with provable uniqueness properties in this format, however, it is not
1436               //necessary to have provable uniqueness properties in the URIs used in the wsa:MessageID and
1437               //wsa:RelatesTo headers.
1438               //Regardless of format, the URI should not exceed the maximum defined in R13.1-6.
1439               //UUIDs have a numeric meaning as well as a string meaning, and this can lead to confusion. A UUID
1440               //in lowercase is a different URI from the same UUID in uppercase. This is because URIs are case1619
1441               //tive. If a UUID is converted to its decimal equivalent the case of the original characters is lost.
1442               //WS-Management works with the URI value itself, not the underlying decimal equivalent
1443               //representation. Services are free to interpret the URI in any way, but are not allowed to alter the case
1444               //usage when repeating the message or any of the MessageID values in subsequent messages.
1445               //The RFC 4122 requires the digits to be lowercase, which is the responsibility of the client. The service
1446               //simply processes the values as URI values and is not required to analyze the URI for correctness or
1447               //compliance. The service replicates the client usage in the wsa:RelatesTo reply header and is not
1448               //allowed to alter the case usage.
1449               //R5.4.6.4-2: The MessageID should be generated according to any algorithm that ensures that no
1450 mike  1.1     //two MessageIDs are repeated. Because the value is treated as case-sensitive (R5.4.6.4-1),
1451               //confusion can arise if the same value is reused differing only in case. As a result, the service shall
1452               //not create or employ MessageID values that differ only in case. For any message transmitted by
1453               //the service, the MessageID shall not be reused.
1454           
1455               static MI_Uint64  s1, s2;
1456           
1457               if (!s1)
1458                   Time_Now(&s1);
1459           
1460               s2++;
1461           
1462               /* ADC */
1463               if (!s2)
1464                   s1++;
1465           
1466               Szprintf(msgID, WS_MSG_ID_SIZE,
1467                   MI_T("uuid:%08X-%04X-%04X-%04X-%08X%04X"),
1468                   (MI_Uint32)(s1 & 0xFFFFFFFF),
1469                   (MI_Uint32)((s1 >> 32) & 0xFFFF),
1470                   (MI_Uint32)((s1 >> 48) & 0xFFFF),
1471 mike  1.1         (MI_Uint32)((s2 >> 48) & 0xFFFF),
1472                   (MI_Uint32)(s2 & 0xFFFFFFFF),
1473                   (MI_Uint32)((s2 >> 32) & 0xFFFF) );
1474           }
1475           
1476           MI_Result WSBuf_CreateSoapResponseHeader(
1477               WSBuf   *buf,
1478               const MI_Char*  action,
1479               MI_Uint32       actionSize,
1480               const char*     relatesTo)
1481           {
1482               MI_Char msgID[WS_MSG_ID_SIZE];
1483           
1484               /* Response header */
1485               if (MI_RESULT_OK != WSBuf_AddLit(buf, 
1486                   LIT(
1487                   MI_T("<SOAP-ENV:Envelope ")         
1488                   MI_T("xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\" ")
1489                   MI_T("xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\" ")
1490                   MI_T("xmlns:wsen=\"http://schemas.xmlsoap.org/ws/2004/09/enumeration\" ")
1491                   MI_T("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ")
1492 mike  1.1         MI_T("xmlns:wsmb=\"http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd\" ")
1493                   MI_T("xmlns:wsman=\"http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd\" ")
1494                   MI_T("xmlns:wxf=\"http://schemas.xmlsoap.org/ws/2004/09/transfer\" ")
1495                   MI_T("xmlns:xml=\"http://www.w3.org/XML/1998/namespace\" ")
1496                   MI_T("xmlns:wsmid=\"http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd\" >")
1497                   XML_CR
1498                   MI_T("<SOAP-ENV:Header>")                                                       XML_CR
1499                   MI_T("<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>")    XML_CR
1500                   MI_T("<wsa:Action>")))  )
1501               {
1502                   goto failed;
1503               }
1504           
1505               if (MI_RESULT_OK != WSBuf_AddLit(buf, action, actionSize))
1506                   goto failed;
1507           
1508               if (MI_RESULT_OK != WSBuf_AddLit(buf, 
1509                       LIT(MI_T("</wsa:Action>")           XML_CR
1510                       MI_T("<wsa:MessageID>" ))))
1511                   goto failed;
1512           
1513 mike  1.1     /* Generate new uniqueue msg id */
1514               WSBuf_GenerateMessageID(msgID);
1515           
1516               if (MI_RESULT_OK != WSBuf_AddLit(buf, msgID, WS_MSG_ID_SIZE - 1))
1517                   goto failed;
1518           
1519               if (MI_RESULT_OK != WSBuf_AddLit(buf,
1520                   LIT(MI_T("</wsa:MessageID>")    XML_CR)))
1521                   goto failed;
1522           
1523               if (relatesTo)
1524               {
1525                   if (MI_RESULT_OK != WSBuf_AddLit(buf,
1526                       LIT(MI_T("<wsa:RelatesTo>"))))
1527                       goto failed;
1528           
1529                   if (MI_RESULT_OK != WSBuf_AddCharStringNoEncoding(buf, relatesTo))
1530                       goto failed;
1531           
1532                   if (MI_RESULT_OK != WSBuf_AddLit(buf,
1533                       LIT(MI_T("</wsa:RelatesTo>")        XML_CR)))
1534 mike  1.1             goto failed;
1535               }
1536           
1537               return MI_RESULT_OK;
1538           
1539           failed:
1540               return MI_RESULT_FAILED;
1541           }
1542           
1543           
1544           
1545           Page* WSBuf_CreateFaultResponsePage(
1546               WSBUF_FAULT_CODE faultCode,
1547               const char* notUnderstoodTag,
1548               const char* requestMessageID,
1549               const MI_Char* descriptionText)
1550           {
1551               WSBuf   outBuf;
1552               const BUF_FaultItem* fault;
1553           
1554               if ( ((MI_Uint32)faultCode) >= MI_COUNT(s_faults))
1555 mike  1.1     {
1556                   fault = s_faults + 0; /* internal error */
1557               }
1558               else
1559               {
1560                   fault = s_faults + (MI_Uint32)faultCode;
1561               }
1562           
1563           
1564               /* prepare soap response with error */
1565               if (WSBuf_Init(&outBuf, 1024) != MI_RESULT_OK)
1566                   return 0;
1567           
1568               /* fault header */
1569               if (MI_RESULT_OK != WSBuf_CreateSoapResponseHeader(&outBuf,
1570                   fault->action, fault->actionSize, requestMessageID))
1571                   goto failed;
1572           
1573               if (notUnderstoodTag)
1574               {
1575                   if (MI_RESULT_OK != WSBuf_AddLit(&outBuf, 
1576 mike  1.1                 LIT(MI_T("<SOAP-ENV:NotUnderstood qname=\""))))
1577                       goto failed;
1578           
1579                   if (MI_RESULT_OK != WSBuf_AddCharStringNoEncoding(&outBuf, notUnderstoodTag ))
1580                       goto failed;
1581           
1582                   if (MI_RESULT_OK != WSBuf_AddLit3(&outBuf, '"', '/', '>'))
1583                       goto failed;
1584               }
1585           
1586               if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1587                   LIT(
1588                   MI_T("</SOAP-ENV:Header>")      XML_CR  XML_CR
1589                   MI_T("<SOAP-ENV:Body>")         XML_CR
1590                   MI_T("<SOAP-ENV:Fault>")        XML_CR
1591                   MI_T("<SOAP-ENV:Code>")         XML_CR
1592                   MI_T("<SOAP-ENV:Value>")))  )
1593                   goto failed;
1594           
1595               if (MI_RESULT_OK != WSBuf_AddCharStringNoEncoding(&outBuf, fault->code))
1596                   goto failed;
1597 mike  1.1         //SOAP-ENV:Sender
1598           
1599               if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1600                   LIT(MI_T("</SOAP-ENV:Value>")       XML_CR)))
1601                   goto failed;
1602           
1603               if (fault->subCode)
1604               {
1605                   if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1606                       LIT(MI_T("<SOAP-ENV:Subcode>")      XML_CR
1607                       MI_T("<SOAP-ENV:Value>"))))
1608                       goto failed;
1609           
1610                   if (MI_RESULT_OK != WSBuf_AddCharStringNoEncoding(&outBuf, fault->subCode))
1611                       goto failed;
1612           
1613                   if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1614                       LIT(MI_T("</SOAP-ENV:Value>")       XML_CR
1615                       MI_T("</SOAP-ENV:Subcode>")     XML_CR)))
1616                       goto failed;
1617               }
1618 mike  1.1 
1619               if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1620                   LIT(MI_T("</SOAP-ENV:Code>")        XML_CR
1621                   MI_T("<SOAP-ENV:Reason>")       XML_CR
1622                   MI_T("<SOAP-ENV:Text xml:lang=\"en-US\">"))))
1623                   goto failed;
1624           
1625               if ( descriptionText )
1626               {
1627                   if (MI_RESULT_OK != WSBuf_AddString(&outBuf, descriptionText))
1628                       goto failed;
1629               }
1630               else
1631               {
1632                   if (MI_RESULT_OK != WSBuf_AddCharStringNoEncoding(&outBuf, fault->defaultTest))
1633                       goto failed;
1634               }
1635           
1636               if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1637                   LIT( MI_T("</SOAP-ENV:Text>")      XML_CR
1638                   MI_T("</SOAP-ENV:Reason>")      XML_CR
1639 mike  1.1         MI_T("</SOAP-ENV:Fault>")       XML_CR
1640                   MI_T("</SOAP-ENV:Body>")        XML_CR
1641                   MI_T("</SOAP-ENV:Envelope>")    XML_CR)) )
1642                   goto failed;
1643           
1644           
1645               return WSBuf_StealPage(&outBuf);
1646           
1647           failed:
1648           
1649               WSBuf_Destroy(&outBuf);
1650               return 0;
1651           }
1652           
1653           Page* WSBuf_CreateReleaseResponsePage(
1654               const char* requestMessageID)
1655           {
1656               WSBuf   outBuf;
1657           
1658               /* prepare soap response with error */
1659               if (WSBuf_Init(&outBuf, 1024) != MI_RESULT_OK)
1660 mike  1.1         return 0;
1661           
1662               /* fault header */
1663               if (MI_RESULT_OK != WSBuf_CreateSoapResponseHeader(&outBuf,
1664                   LIT(MI_T("http://schemas.xmlsoap.org/ws/2004/09/enumeration/ReleaseResponse")), 
1665                   requestMessageID))
1666                   goto failed;
1667           
1668               if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1669                   LIT(
1670                   MI_T("</SOAP-ENV:Header>")      XML_CR  XML_CR
1671                   MI_T("<SOAP-ENV:Body/>")         XML_CR
1672                   MI_T("</SOAP-ENV:Envelope>")    XML_CR)) )
1673                   goto failed;
1674           
1675               return WSBuf_StealPage(&outBuf);
1676           
1677           failed:
1678           
1679               WSBuf_Destroy(&outBuf);
1680               return 0;
1681 mike  1.1 }
1682           
1683           WSBUF_FAULT_CODE    WSBuf_CIMErrorToWSFault(
1684               MI_Uint32       cimErrorCode,
1685               const MI_Char** description )
1686           {
1687               MI_Uint32 index = cimErrorCode < MI_COUNT(s_cimerrors) ? cimErrorCode : MI_RESULT_FAILED;
1688           
1689               if ( description )
1690                   *description = s_cimerrors[index].description;
1691           
1692               return s_cimerrors[index].faultCode;
1693           }

ViewCVS 0.9.2