(file) Return to wsman.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 <assert.h>
  26           #include "wsman.h"
  27           #include "wsmanbuffer.h"
  28           #include "wsmanparser.h"
  29           #include "http.h"
  30           #include <base/time.h>
  31           #include <xml/xml.h>
  32           #include <base/log.h>
  33           #include <base/result.h>
  34           #include <base/strings.h>
  35           #include <base/user.h>
  36           #include <base/io.h>
  37           #include <base/base.h>
  38           
  39           #include "wstags.h"
  40           
  41           #define T MI_T
  42           #define CR    MI_T("\n")
  43 mike  1.1 
  44           /*
  45           **==============================================================================
  46           **
  47           ** Local definitions:
  48           **
  49           **==============================================================================
  50           */
  51           /* Maximum wsman envelope size */
  52           #define WSMAN_MAX_ENVELOPE_SIZE     (128 * 1024)
  53           
  54           /* aproximate repsonse header size */
  55           #define WSMAN_APROX_ENUM_RESP_HEADER_SIZE     1024
  56           
  57           static const MI_Uint32 _MAGIC = 0x1CF2BCB7;
  58           
  59           
  60           /************************************************************************\
  61           *   Local definitions
  62           \************************************************************************/
  63           
  64 mike  1.1 typedef struct _WSMAN_ConnectionData    WSMAN_ConnectionData;
  65           typedef struct _WSMAN_EnumerateContext  WSMAN_EnumerateContext;
  66           
  67           /* These tags are used as magic numbers as well as to distinguish connection data strucutre from enumeration context */
  68           #define DATA_TAG_CONNECTION_DATA        0x17CDDC11
  69           #define DATA_TAG_ENUMERATION_CONTEXT    0xAB70900D
  70           
  71           /* Maximum number of enumeration contexts stored at the same time 
  72               effectively limits number of concurent enumerations */
  73           #define WSMAN_MAX_ENUM_CONTEXTS     64
  74           
  75           struct _WSMAN
  76           {
  77               MI_Uint32 magic;
  78               WSMANCallback callback;
  79               void* callbackData;
  80               Http* http;
  81               Selector* selector;
  82           
  83               /* configurable options */
  84               WSMAN_Options options;
  85 mike  1.1 
  86               /* Array of enumeration contexts:
  87                   each 'pull' will look for corresponding context
  88               */
  89               WSMAN_EnumerateContext* enumerateContexts[WSMAN_MAX_ENUM_CONTEXTS];
  90           
  91               /* Cached xml parser with all namespaces registered */
  92               XML xml;
  93           };
  94           
  95           /* Represents state of connection including buffers, unsent packets, states etc */
  96           struct _WSMAN_ConnectionData
  97           {
  98               /* Since message's data can point to either ConnectionData or EnumerationContext, 
  99                   both strucutres need some generic base property - tag;
 100                   in addition, tag used as magic number */
 101               MI_Uint32   tag;
 102           
 103               /* Link to http layer */
 104               void*   httpConnectionHandle;
 105           
 106 mike  1.1     /* Requestor information */
 107               uid_t uid;
 108               gid_t gid;
 109           
 110               /* Attributes of the request */
 111               WSMAN_WSHeader  wsheader;
 112               union
 113               {
 114                   /* Actual type is defined by wsheader.rqtAction field */
 115                    WSMAN_WSEnumeratePullBody wsenumpullbody;
 116               }
 117               u;
 118           
 119               /* Request page (buffer for most pointers inside header/body structures) */
 120               Page*   page;
 121           
 122               /* for single-instance repsonses, we keep mesage until result received to avoid 
 123                   conflicts with keep-alive enabled */
 124               PostInstanceMsg* single_message;
 125           
 126               /* Number of consumers of this structure: 
 127 mike  1.1         connected client, outstanding request to the provider and timer */
 128               MI_Uint32   refcounter;
 129           
 130               /* response data */
 131               /* only valid for enumerate/pull requests */
 132               MI_Uint32   enumerateContextID;
 133           
 134               /* flag indicates that response was not sent yet to the client */
 135               MI_Boolean  outstandingRequest;
 136           };
 137           
 138           /* Enumeration context:
 139               'derived' from socket Handler, so it can subscribe for timeouts */
 140           
 141           struct _WSMAN_EnumerateContext
 142           {
 143               /* Since message's data can point to either ConnectionData or EnumerationContext, 
 144                   both strucutres need some generic base property - tag;
 145                   in addition, tag used as magic number */
 146               MI_Uint32   tag;
 147           
 148 mike  1.1     /* based member - can be added to 'selector' for timeout support */
 149               Handler     base;
 150           
 151               /* response data */
 152               /* Linked list of messages to send */
 153               PostInstanceMsg* head;
 154               PostInstanceMsg* tail;
 155           
 156               /* Total size of all instances in response queue */
 157               MI_Uint32   totalResponseSize;
 158           
 159               /* NUmber of messages in repsonse queue */
 160               MI_Uint32   totalResponses;
 161           
 162               /* Number of consumers of this structure: 
 163                  reference from enum-context-list in WSMAN, outstanding request to the provider and timer */
 164               MI_Uint32   refcounter;
 165           
 166               /* lower 16 bits is aninxed in self->enumerateContexts, upper 16 bits are random data (for validation) */
 167               MI_Uint32   enumerationContextID;
 168               MI_Result   finalResult;
 169 mike  1.1     /* indicates that 'Result' recevied form provider and stored in finalResult */
 170               MI_Boolean  enumerationCompleted;
 171               /* Indicates that context has expired (either by timer or by Release request)
 172               and all repsonses form the provider has to be ignored */
 173               MI_Boolean  expired;
 174           
 175               /* pointer to current active connection - either Enumerate or Pull request */
 176               WSMAN_ConnectionData*   activeConnection;
 177           };
 178           
 179           /* forward declarations */
 180           static void _CD_Release(
 181               WSMAN_ConnectionData* selfConnectionData);
 182           
 183           static void _SendEnumPullResponse(
 184               WSMAN* self,
 185               WSMAN_EnumerateContext* selfEC);
 186           
 187           static MI_Boolean _ProcessEnumResponse(
 188               WSMAN* self,
 189               WSMAN_EnumerateContext* selfEC,
 190 mike  1.1     MI_Boolean attachingPullRequest);
 191           
 192           static void _WSMAN_ReleaseEnumerateContext(
 193               WSMAN* self,
 194               MI_Uint32   enumerationContextID);
 195           
 196           /************************************************************************\
 197           *   Helper funcitons
 198           \************************************************************************/
 199           /* Converts Enumeration mode into "Message" struct flag */
 200           MI_INLINE   MI_Uint32 _convertWSMANtoMsgEnumerationMode(
 201               MI_Uint32 enumerationMode )
 202           {
 203               if (WSMANTAG_ENUM_MODE_EPR == enumerationMode)
 204                   return WSMAN_EPRFlag;
 205           
 206               if (WSMANTAG_ENUM_MODE_OBJECT_AND_EPR == enumerationMode)
 207                   return WSMAN_ObjectAndEPRFlag;
 208           
 209               return WSMAN_ObjectFlag;
 210           }
 211 mike  1.1 
 212           /************************************************************************\
 213           *   Enumeration Context operations
 214           \************************************************************************/
 215           static void _EC_ReleaseAllMessages(
 216               WSMAN_EnumerateContext* self)
 217           {
 218               /* Delete all queued messages*/
 219               while (self->head)
 220               {
 221                   PostInstanceMsg* msg = self->head;
 222           
 223                   List_Remove(
 224                       (ListElem**)&self->head, 
 225                       (ListElem**)&self->tail, 
 226                       (ListElem*)msg);
 227                   PostInstanceMsg_Release(msg);
 228               }
 229               self->totalResponses = 0;
 230               self->totalResponseSize = 0;
 231           }
 232 mike  1.1 
 233           static void _EC_SetActiveConnection(
 234               WSMAN_EnumerateContext* self,
 235               WSMAN_ConnectionData* selfCD)
 236           {
 237               if (self->activeConnection)
 238                   _CD_Release(self->activeConnection);
 239           
 240               self->activeConnection = selfCD;
 241               if (self->activeConnection)
 242               {
 243                   self->activeConnection->refcounter++;
 244                   self->activeConnection->enumerateContextID = self->enumerationContextID;
 245               }
 246           }
 247           
 248           static void _EC_Release(
 249               WSMAN_EnumerateContext* self,
 250               MI_Boolean freeAllMessages)
 251           {
 252               if (--self->refcounter == 0)
 253 mike  1.1     {
 254                   /* Delete all queued messages*/
 255                   _EC_ReleaseAllMessages(self);
 256           
 257                   /* release active connection (if exist) */
 258                   _EC_SetActiveConnection(self, 0);
 259           
 260           #ifdef CONFIG_ENABLE_DEBUG
 261                   /* invalidate struct */
 262                   memset(self, 0xcd, sizeof(*self));
 263           #endif
 264                   free(self);
 265               }
 266               else if (freeAllMessages)
 267               {
 268                   /* Delete all queued messages*/
 269                   _EC_ReleaseAllMessages(self);
 270               }
 271           }
 272           
 273           static MI_Boolean _EC_TimeoutCallback(
 274 mike  1.1     Selector* sel,
 275               Handler* handler,
 276               MI_Uint32 mask, 
 277               MI_Uint64 currentTimeUsec)
 278           {
 279               /* since 'base' is not the first member in EC struct,
 280                   adjust pointer as appropriate */
 281               WSMAN_EnumerateContext* self = (WSMAN_EnumerateContext*)
 282                   (((char*)handler) - offsetof(WSMAN_EnumerateContext, base));
 283           
 284               MI_UNUSED(sel);
 285               MI_UNUSED(currentTimeUsec);
 286           
 287               if (mask & SELECTOR_TIMEOUT)
 288               {
 289                   /* remove context only from wsman list; selector will remove it automatically, 
 290                       once 'false' returned */
 291                   _WSMAN_ReleaseEnumerateContext(
 292                       (WSMAN*)self->base.data, self->enumerationContextID);
 293           
 294                   /* once 'false' returned, selector will remove handler,
 295 mike  1.1             so actual handling happens in next 'if' */
 296                   return MI_FALSE;
 297               }
 298           
 299               if (mask & (SELECTOR_REMOVE | SELECTOR_DESTROY))
 300               {
 301                   _EC_Release(self, MI_TRUE);
 302               }
 303           
 304               return MI_TRUE;
 305           }
 306           
 307           /************************************************************************\
 308           *   WSman operations
 309           \************************************************************************/
 310           static WSMAN_EnumerateContext* _WSMAN_AllocateEnumContext(
 311               WSMAN* self)
 312           {
 313               MI_Uint32   enumerationContextID;
 314               WSMAN_EnumerateContext* enumContext;
 315           
 316 mike  1.1     /* Find empty slot */
 317               for (enumerationContextID = 0; enumerationContextID < MI_COUNT(self->enumerateContexts); enumerationContextID++)
 318               {
 319                   if (!self->enumerateContexts[enumerationContextID])
 320                       break;
 321               }
 322           
 323               if (MI_COUNT(self->enumerateContexts) == enumerationContextID)
 324               {
 325                   LOGW((T("Cannot allocate new enumerate context - too many concurrent enumerations") ));
 326                   return 0;   /* no more slots available */
 327               }
 328           
 329               enumContext = (WSMAN_EnumerateContext*)calloc(1, sizeof(WSMAN_EnumerateContext));
 330           
 331               if (!enumContext)
 332                   return 0;
 333           
 334               /* Store reference to a new context */
 335               self->enumerateContexts[enumerationContextID] = enumContext;
 336           
 337 mike  1.1     /* set tag/magic */
 338               enumContext->tag = DATA_TAG_ENUMERATION_CONTEXT;
 339           
 340               /* Add random data to the context-id */
 341               enumerationContextID |= (rand() & 0xFFFF) << 16;
 342               enumContext->enumerationContextID = enumerationContextID;
 343           
 344               /* set ref-counter to 1, since it's referred by enumerateContexts array now */
 345               enumContext->refcounter = 1;
 346               return enumContext;
 347           }
 348           
 349           static WSMAN_EnumerateContext* _WSMAN_FindEnumContext(
 350               WSMAN* self,
 351               MI_Uint32   enumerationContextID)
 352           {
 353               MI_Uint32 index = enumerationContextID & 0xFFFF;
 354           
 355               /* ATTN: add logging here! */
 356               /* verify that context exist and has the same id as required */
 357               if (index < MI_COUNT(self->enumerateContexts) &&
 358 mike  1.1         self->enumerateContexts[index] &&
 359                   self->enumerateContexts[index]->enumerationContextID == enumerationContextID)
 360                   return self->enumerateContexts[index];
 361           
 362               return 0;
 363           }
 364           
 365           
 366           static void _WSMAN_ReleaseEnumerateContext(
 367               WSMAN* self,
 368               MI_Uint32   enumerationContextID)
 369           {
 370               MI_Uint32 index = enumerationContextID & 0xFFFF;
 371           
 372               if (index < MI_COUNT(self->enumerateContexts) &&
 373                   self->enumerateContexts[index] &&
 374                   self->enumerateContexts[index]->enumerationContextID == enumerationContextID)
 375               {
 376                   /* mark handler for removing:
 377                       we cannot remove it directly since we are inside selector's callback;
 378                       settign time to current will trigger timeout/context removal */
 379 mike  1.1         MI_Uint64 currentTimeUsec = 0;
 380           
 381                   Time_Now(&currentTimeUsec);
 382                   self->enumerateContexts[index]->base.fireTimeoutAt = currentTimeUsec;
 383                   self->enumerateContexts[index]->expired = MI_TRUE;
 384           
 385                   /* dec-ref context: note: it can still be alive if porvider has outstanding request */
 386                   _EC_Release(self->enumerateContexts[index], MI_FALSE);
 387                   self->enumerateContexts[index] = 0;
 388               }
 389           }
 390           
 391           static void _WSMAN_ReleaseAllEnumerateContexts(
 392               WSMAN* self)
 393           {
 394               MI_Uint32 index;
 395           
 396               for (index = 0; index < MI_COUNT(self->enumerateContexts); index++ )
 397               {
 398                   if (self->enumerateContexts[index])
 399                   {
 400 mike  1.1             /* delete timer if was set */
 401                       Selector_RemoveHandler(self->selector, &self->enumerateContexts[index]->base);
 402           
 403                       /* dec-ref context: note: it can still be alive if porvider has outstanding request */
 404                       _EC_Release(self->enumerateContexts[index], MI_FALSE);
 405                       self->enumerateContexts[index] = 0;
 406                   }
 407               }
 408           }
 409           
 410           static void _WSMAN_SetUpdateTimer(
 411               WSMAN* self,
 412               WSMAN_EnumerateContext* selfEC)
 413           {
 414               /* check if timer was already added */
 415               if (!selfEC->base.fireTimeoutAt)
 416               {
 417                   /* add timer - first time called */
 418                   selfEC->base.sock = INVALID_SOCK;
 419                   selfEC->base.data = self;
 420                   selfEC->base.callback = _EC_TimeoutCallback;
 421 mike  1.1 
 422                   /* increment counter - will be decremented in callback/remove */
 423                   if (MI_RESULT_OK == Selector_AddHandler(self->selector, &selfEC->base))
 424                       selfEC->refcounter++;
 425               }
 426           
 427               /* extend time */
 428               {
 429                   MI_Uint64 currentTimeUsec = 0;
 430           
 431                   if (MI_RESULT_OK == Time_Now(&currentTimeUsec))
 432                   {
 433                       selfEC->base.fireTimeoutAt = 
 434                           currentTimeUsec + self->options.timeoutEnumContextUsec;
 435                   }
 436               }
 437           }
 438           
 439           /************************************************************************\
 440           *   connection data operations
 441           \************************************************************************/
 442 mike  1.1 MI_INLINE void _CD_SetPage(
 443               WSMAN_ConnectionData* selfConnectionData,
 444               Page*   page)
 445           {
 446               if (selfConnectionData->page)
 447                   free(selfConnectionData->page);
 448           
 449               selfConnectionData->page = page;
 450           }
 451           
 452           MI_INLINE void _CD_SetSingleMessage(
 453               WSMAN_ConnectionData* selfConnectionData,
 454               PostInstanceMsg* single_message)
 455           {
 456               if (selfConnectionData->single_message)
 457                   PostInstanceMsg_Release(selfConnectionData->single_message);
 458           
 459               selfConnectionData->single_message = single_message;
 460           
 461               if (selfConnectionData->single_message)
 462                   Message_AddRef(&selfConnectionData->single_message->base);
 463 mike  1.1 }
 464           
 465           static void _CD_Cleanup(
 466               WSMAN_ConnectionData* selfConnectionData)
 467           {
 468               _CD_SetPage(selfConnectionData, 0);
 469               _CD_SetSingleMessage(selfConnectionData, 0);
 470           
 471               /* free allocated instance/batch */
 472               if (selfConnectionData->wsheader.instanceBatch)
 473               {
 474                   /* destroying batch takes care of instance and instanceBatch members */
 475                   Batch_Destroy(selfConnectionData->wsheader.instanceBatch);
 476                   selfConnectionData->wsheader.instanceBatch = 0;
 477                   selfConnectionData->wsheader.instance = 0;
 478               }
 479               memset(&selfConnectionData->wsheader, 0, sizeof(selfConnectionData->wsheader));
 480           }
 481           
 482           static void _CD_Release(
 483               WSMAN_ConnectionData* selfConnectionData)
 484 mike  1.1 {
 485               if (--selfConnectionData->refcounter == 0)
 486               {
 487                   _CD_Cleanup(selfConnectionData);
 488           
 489                   free(selfConnectionData);
 490               }
 491           }
 492           
 493           
 494           static void _SendFaultResponse(
 495               Http* http,
 496               WSMAN_ConnectionData* selfCD,
 497               WSBUF_FAULT_CODE faultCode,
 498               const MI_Char* descriptionText)
 499           {
 500               Page* responsePage = WSBuf_CreateFaultResponsePage(
 501                   faultCode,
 502                   selfCD->wsheader.unknownMandatoryTag,
 503                   selfCD->wsheader.rqtMessageID,
 504                   descriptionText);
 505 mike  1.1         
 506               //printf("\n\n%s\n\n", (char*)(responsePage+1));
 507           
 508               Http_SendResponse(http, selfCD->httpConnectionHandle,
 509                   HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR, 
 510                   &responsePage);
 511           
 512               selfCD->outstandingRequest = MI_FALSE;
 513           
 514               if (responsePage)
 515                   free(responsePage);
 516           }
 517           
 518           static void _SendReleaseResponse(
 519               WSMAN* self,
 520               WSMAN_ConnectionData* selfCD)
 521           {
 522               Page* responsePage = WSBuf_CreateReleaseResponsePage(
 523                   selfCD->wsheader.rqtMessageID);
 524                   
 525               //printf("\n\n%s\n\n", (char*)(responsePage+1));
 526 mike  1.1 
 527               Http_SendResponse(self->http, selfCD->httpConnectionHandle,
 528                   HTTP_ERROR_CODE_OK, 
 529                   &responsePage);
 530           
 531               selfCD->outstandingRequest = MI_FALSE;
 532           
 533               if (responsePage)
 534                   free(responsePage);
 535           }
 536           
 537           
 538           
 539           static int _ValidateHeader(
 540               Http* http,
 541               WSMAN_ConnectionData* selfCD)
 542           {
 543               if (selfCD->wsheader.unknownMandatoryTag)
 544               {
 545                   _SendFaultResponse(http, selfCD, WSBUF_FAULT_NOT_UNDERSTOOD, 0);
 546                   return -1;
 547 mike  1.1     }
 548           
 549               //DSP0226
 550               //1756 R6.2-4: Services should reject any MaxEnvelopeSize value less than 8192 octets. This number
 551               //1757 is the safe minimum in which faults can be reliably encoded for all character sets. If the requested
 552               //1758 size is less than this, the service should return a wsman:EncodingLimit fault with the following
 553               //1759 detail code:
 554               //1760 http://schemas.dmtf.org/wbem/wsman/1/wsman/faultDetail/MinimumEnvelopeLimit
 555           
 556               if (selfCD->wsheader.maxEnvelopeSize != 0 &&
 557                   selfCD->wsheader.maxEnvelopeSize < 8192)
 558               {
 559                   LOGW_CHAR(("wsman: requested envelope size (%d) is too small; "
 560                       "expected at least 8K", (int)selfCD->wsheader.maxEnvelopeSize));
 561           
 562                   _SendFaultResponse(http, selfCD, WSBUF_FAULT_ENCODING_LIMIT, 0);
 563                   return -1;
 564               }
 565           
 566               /* Limit envelope size to server's max */
 567               if (selfCD->wsheader.maxEnvelopeSize == 0 ||
 568 mike  1.1         selfCD->wsheader.maxEnvelopeSize > WSMAN_MAX_ENVELOPE_SIZE)
 569               {
 570                   selfCD->wsheader.maxEnvelopeSize = WSMAN_MAX_ENVELOPE_SIZE;
 571               }
 572           
 573               /* verify action for invoke */
 574               if (selfCD->wsheader.foundAction &&
 575                   0 == selfCD->wsheader.rqtAction &&
 576                   (!selfCD->wsheader.rqtClassname || !selfCD->wsheader.rqtMethod))
 577               {
 578                   LOGW_CHAR(("wsman: unknown custom action"));
 579           
 580                   _SendFaultResponse(http, selfCD, WSBUF_FAULT_NOT_SUPPORTED, 
 581                       T("unknown custom action"));
 582                   return -1;
 583               }
 584           
 585               return 0;
 586           }
 587           
 588           static int _ValidateEnumerateRequest(
 589 mike  1.1     Http* http,
 590               WSMAN_ConnectionData* selfCD)
 591           {
 592               /* If it has reference params, it must be an association request */
 593               MI_Instance* referenceParameters = 
 594                   selfCD->u.wsenumpullbody.associationFilter.referenceParameters;
 595           
 596               if (referenceParameters)
 597               {
 598                   selfCD->wsheader.rqtNamespace = referenceParameters->nameSpace;
 599                   selfCD->wsheader.rqtClassname = referenceParameters->classDecl->name;
 600               }
 601               else if (!selfCD->wsheader.rqtClassname || !selfCD->wsheader.rqtNamespace)
 602               {
 603                   LOGW_CHAR(("wsman: mandatory parameters (className, namespace) "
 604                       "are missing for enumerate request"));
 605           
 606                   _SendFaultResponse(
 607                       http, 
 608                       selfCD, 
 609                       WSBUF_FAULT_INTERNAL_ERROR, 
 610 mike  1.1             T("mandatory parameters (className, namespace) "
 611                           "are missing for enumerate request"));
 612                   return -1;
 613               }
 614           
 615               //R8.2.3; DSP226
 616               //wsmen:Enumerate/wsman:MaxElements
 617               //(optional) indicates the maximum number of items the consumer is willing to accept in the
 618               //EnumerateResponse
 619               //It plays the same role as wsmen:Pull/wsmen:MaxElements. When this element is absent, its
 620               //implied value is 1.
 621               if (!selfCD->u.wsenumpullbody.maxElements)
 622                   selfCD->u.wsenumpullbody.maxElements = 1;
 623           
 624               // if enumeration mode is not specified, use 'Objects'
 625               if (selfCD->u.wsenumpullbody.enumerationMode == 0)
 626                   selfCD->u.wsenumpullbody.enumerationMode = WSMANTAG_ENUM_MODE_OBJECT;
 627           
 628               return 0;
 629           }
 630           
 631 mike  1.1 static int _ValidatePullRequest(
 632               Http* http,
 633               WSMAN_ConnectionData* selfCD)
 634           {
 635               MI_UNUSED(http);
 636               //R8.2.3; DSP226
 637               //wsmen:Enumerate/wsman:MaxElements
 638               //(optional) indicates the maximum number of items the consumer is willing to accept in the
 639               //EnumerateResponse
 640               //It plays the same role as wsmen:Pull/wsmen:MaxElements. When this element is absent, its
 641               //implied value is 1.
 642               if (!selfCD->u.wsenumpullbody.maxElements)
 643                   selfCD->u.wsenumpullbody.maxElements = 1;
 644           
 645               return 0;
 646           }
 647           
 648           static void _ProcessEnumerateRequest(
 649               Http* http,
 650               void* httpConnectionHandle,
 651               WSMAN* self,
 652 mike  1.1     WSMAN_ConnectionData* selfCD)
 653           {
 654               EnumerateInstancesReq* msg;
 655               WSMAN_EnumerateContext* enumContext;
 656           
 657               /* create EnumerateContext */
 658               enumContext = _WSMAN_AllocateEnumContext(self);
 659           
 660               if (!enumContext)
 661               {
 662                   Http_SendErrorResponse(http, httpConnectionHandle, HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
 663                   selfCD->outstandingRequest = MI_FALSE;
 664                   return;
 665               }
 666           
 667               /* link new context to current EnumRequest */
 668               _EC_SetActiveConnection(enumContext, selfCD);
 669           
 670           
 671               // Create new request.
 672               msg = EnumerateInstancesReq_New(/*_NextMsgID()*/ 1, 
 673 mike  1.1         WSMANFlag | _convertWSMANtoMsgEnumerationMode(selfCD->u.wsenumpullbody.enumerationMode));
 674           
 675               if (!msg)
 676               {
 677                   _WSMAN_ReleaseEnumerateContext(self, enumContext->enumerationContextID);
 678                   selfCD->enumerateContextID = 0;
 679                   Http_SendErrorResponse(http, httpConnectionHandle, HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
 680                   selfCD->outstandingRequest = MI_FALSE;
 681                   return;
 682               }
 683           
 684               /* In case when client does not support optimized enumeration,
 685                   send empty Enum-response with correct enumerate context */
 686               if (!selfCD->u.wsenumpullbody.allowOptimization)
 687               {   
 688                   _SendEnumPullResponse(self, enumContext);
 689                   _EC_SetActiveConnection(enumContext, 0);
 690                   _WSMAN_SetUpdateTimer(self, enumContext);
 691               }
 692           
 693               msg->nameSpace = Batch_Strdup2(msg->base.batch, selfCD->wsheader.rqtNamespace);
 694 mike  1.1     msg->className = Batch_Strdup2(msg->base.batch, selfCD->wsheader.rqtClassname);
 695               msg->deepInheritance = (selfCD->u.wsenumpullbody.polymorphismMode != WSMANTAG_ENUM_POLYMORPHISM_MODE_NONE);
 696               msg->basePropertiesOnly = (selfCD->u.wsenumpullbody.polymorphismMode == WSMANTAG_ENUM_POLYMORPHISM_MODE_EXCLUDE_PROPS);
 697           
 698               /* Set the query related fields */
 699               {
 700                   if (selfCD->u.wsenumpullbody.dialect)
 701                       msg->queryLanguage = Batch_Strdup2(msg->base.batch, selfCD->u.wsenumpullbody.dialect);
 702           
 703                   if (selfCD->u.wsenumpullbody.filter)
 704                       msg->queryExpression = Batch_Strdup2(msg->base.batch, selfCD->u.wsenumpullbody.filter);
 705               }
 706           
 707               msg->base.uid = selfCD->uid;
 708               msg->base.gid = selfCD->gid;
 709           
 710               /* attach client id */
 711               msg->base.clientID = PtrToUint64(enumContext);
 712           
 713               /* increment counter to keep it alive until provider replies */
 714               enumContext->refcounter++;
 715 mike  1.1 
 716               (*self->callback)(self, &msg->base, self->callbackData);
 717           
 718               EnumerateInstancesReq_Release(msg);
 719           }
 720           
 721           static void _ProcessAssociatorsRequest(
 722               Http* http,
 723               void* httpConnectionHandle,
 724               WSMAN* self,
 725               WSMAN_ConnectionData* selfCD)
 726           {
 727               AssociatorsOfReq* msg;
 728               WSMAN_EnumerateContext* enumContext;
 729               MI_Uint32 enumerationMode;
 730           
 731           
 732               /* create EnumerateContext */
 733               enumContext = _WSMAN_AllocateEnumContext(self);
 734           
 735               if (!enumContext)
 736 mike  1.1     {
 737                   Http_SendErrorResponse(
 738                       http, 
 739                       httpConnectionHandle, 
 740                       HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
 741                   selfCD->outstandingRequest = MI_FALSE;
 742                   return;
 743               }
 744           
 745               /* link new context to current EnumRequest */
 746               _EC_SetActiveConnection(enumContext, selfCD);
 747           
 748               /* Extract teh enumeration mode */
 749               enumerationMode = _convertWSMANtoMsgEnumerationMode(
 750                   selfCD->u.wsenumpullbody.enumerationMode);
 751           
 752               /* Create new request. */
 753               msg = AssociatorsOfReq_New(
 754                   /*_NextMsgID()*/ 1, 
 755                   WSMANFlag | enumerationMode);
 756           
 757 mike  1.1     if (!msg)
 758               {
 759                   _WSMAN_ReleaseEnumerateContext(self, enumContext->enumerationContextID);
 760                   selfCD->enumerateContextID = 0;
 761                   Http_SendErrorResponse(
 762                       http, 
 763                       httpConnectionHandle, 
 764                       HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
 765                   selfCD->outstandingRequest = MI_FALSE;
 766                   return;
 767               }
 768           
 769               /* In case when client does not support optimized enumeration,
 770                *  send empty Enum-response with correct enumerate context 
 771                */
 772               if (!selfCD->u.wsenumpullbody.allowOptimization)
 773               {
 774                   _SendEnumPullResponse(self, enumContext);
 775                   _EC_SetActiveConnection(enumContext, 0);
 776                   _WSMAN_SetUpdateTimer(self, enumContext);
 777               }
 778 mike  1.1 
 779               msg->nameSpace = Batch_Strdup2(
 780                   msg->base.batch, 
 781                   selfCD->wsheader.rqtNamespace);
 782           
 783               msg->className = Batch_Strdup2(
 784                   msg->base.batch, 
 785                   selfCD->wsheader.rqtClassname);
 786           
 787               msg->base.uid = selfCD->uid;
 788               msg->base.gid = selfCD->gid;
 789           
 790               /* Set messages fileds from association filter */
 791               {
 792                   WSMAN_AssociationFilter* filter = 
 793                       &selfCD->u.wsenumpullbody.associationFilter;
 794           
 795                   msg->instance = filter->referenceParameters;
 796                   msg->assocClass = filter->associationClassName;
 797                   msg->resultClass = filter->resultClassName;
 798                   msg->role = filter->role;
 799 mike  1.1         msg->resultRole = filter->resultRole;
 800               }
 801           
 802               /* attach client id */
 803               msg->base.clientID = PtrToUint64(enumContext);
 804           
 805               /* increment counter to keep it alive until provider replies */
 806               enumContext->refcounter++;
 807           
 808               (*self->callback)(self, &msg->base, self->callbackData);
 809           
 810               AssociatorsOfReq_Release(msg);
 811           }
 812           
 813           static void _ProcessPullRequest(
 814               Http* http,
 815               WSMAN* self,
 816               WSMAN_ConnectionData* selfCD)
 817           {
 818               WSMAN_EnumerateContext* enumContext;
 819           
 820 mike  1.1     /* find EnumerateContext */
 821               enumContext = _WSMAN_FindEnumContext(self, selfCD->u.wsenumpullbody.enumerationContextID);
 822           
 823               if (!enumContext)
 824               {
 825                   _SendFaultResponse(http, selfCD, WSBUF_FAULT_DESTINATION_UNREACHABLE, T("Enumeration context not found"));
 826                   return;
 827               }
 828           
 829               /* link new context to the request */
 830               _EC_SetActiveConnection(enumContext, selfCD);
 831           
 832               _ProcessEnumResponse(self, enumContext, MI_TRUE);
 833           
 834           }
 835           
 836           static void _ProcessReleaseRequest(
 837               Http* http,
 838               WSMAN* self,
 839               WSMAN_ConnectionData* selfCD)
 840           {
 841 mike  1.1     WSMAN_EnumerateContext* enumContext;
 842           
 843               /* find EnumerateContext */
 844               enumContext = _WSMAN_FindEnumContext(self, selfCD->u.wsenumpullbody.enumerationContextID);
 845           
 846               if (!enumContext)
 847               {
 848                   _SendFaultResponse(http, selfCD, WSBUF_FAULT_DESTINATION_UNREACHABLE, T("Enumeration context not found"));
 849                   return;
 850               }
 851           
 852               /* Remove context from the list */
 853               _WSMAN_ReleaseEnumerateContext(self, enumContext->enumerationContextID);
 854           
 855               _SendReleaseResponse(self, selfCD);
 856           }
 857           
 858           static void _ParseValidateProcessEnumerateRequest(
 859               Http* http,
 860               void* httpConnectionHandle,
 861               WSMAN* self,
 862 mike  1.1     WSMAN_ConnectionData* selfCD,
 863               XML*    xml)
 864           {
 865               /* ATTN: only used if enumeration contains an association filter. Find
 866                * some way to prevent creation in that case.
 867                */
 868           
 869               if (!selfCD->wsheader.instanceBatch)
 870               {
 871                   selfCD->wsheader.instanceBatch = Batch_New(BATCH_MAX_PAGES);
 872               }
 873           
 874               /* Parse enumerate request/body */
 875               if (WS_ParseEnumerateBody(
 876                   xml, 
 877                   &selfCD->wsheader.instanceBatch, 
 878                   &selfCD->u.wsenumpullbody) != 0)
 879               {
 880                   LOGW_CHAR(("wsman: unable to parse incoming xml/ enumerate request body"));
 881                   Http_SendErrorResponse(http, httpConnectionHandle, HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
 882                   selfCD->outstandingRequest = MI_FALSE;
 883 mike  1.1         return;
 884               }
 885           
 886               /* Validate enumerate request body */
 887               if (_ValidateEnumerateRequest(http, selfCD) != 0)
 888               {
 889                   /* appropriate error code was already sent to the client */
 890                   return;
 891               }
 892           
 893               /* Process reqest */
 894           
 895               if (selfCD->u.wsenumpullbody.foundAssociationFilter)
 896               {
 897                   _ProcessAssociatorsRequest(http,httpConnectionHandle,self,selfCD);
 898               }
 899               else
 900               {
 901                   _ProcessEnumerateRequest(http,httpConnectionHandle,self,selfCD);
 902               }
 903           }
 904 mike  1.1 
 905           static void _ParseValidateProcessInvokeRequest(
 906               Http* http,
 907               void* httpConnectionHandle,
 908               WSMAN* self,
 909               WSMAN_ConnectionData* selfCD,
 910               XML*    xml)
 911           {
 912               InvokeReq* msg = 0;
 913           
 914               /* if instance was created from batch, re-use exisintg batch to allocate message */
 915               if (selfCD->wsheader.instanceBatch)
 916               {
 917                   /* Allocate heap space for message */
 918                   msg = Batch_GetClear(selfCD->wsheader.instanceBatch, sizeof(InvokeReq));
 919           
 920                   if (!msg)
 921                       goto failed;
 922           
 923                   /* Set the tag */
 924                   msg->base.tag = InvokeReqTag;
 925 mike  1.1 
 926                   /* Set the message id and flags */
 927                   msg->base.msgID = 1;
 928                   msg->base.flags = WSMANFlag | WSMAN_ObjectFlag;
 929           
 930                   /* ref-counter is set to 1, to balance NewMessage/Release Message pair*/
 931                   msg->base.refCounter = 1;
 932           
 933                   /* Copy batch onto message (released by delete method) */
 934                   msg->base.batch = selfCD->wsheader.instanceBatch;
 935           
 936                   msg->instance = selfCD->wsheader.instance;
 937                   selfCD->wsheader.instanceBatch = 0;
 938                   selfCD->wsheader.instance = 0;
 939               }
 940               else
 941                   msg = InvokeReq_New(1, WSMANFlag | WSMAN_ObjectFlag);
 942           
 943               if (!msg)
 944                   goto failed;
 945           
 946 mike  1.1     /* Parse invoke request/body */
 947               if (WS_ParseInvokeBody(xml, msg->base.batch, &msg->instanceParams) != 0)
 948                   goto failed;
 949           
 950               /* Extract/set relevant parameters */
 951               if (selfCD->wsheader.rqtNamespace)
 952                   msg->nameSpace = Batch_Strdup2(msg->base.batch, selfCD->wsheader.rqtNamespace);
 953           
 954               msg->className = Batch_Strdup2(msg->base.batch, selfCD->wsheader.rqtClassname);
 955               msg->function = Batch_Strdup2(msg->base.batch, selfCD->wsheader.rqtMethod);
 956           
 957               /* attach client id */
 958               msg->base.clientID = PtrToUint64(selfCD);
 959               msg->base.uid = selfCD->uid;
 960               msg->base.gid = selfCD->gid;
 961           
 962               /* increment counter to keep it alive until provider replies */
 963               selfCD->refcounter++;
 964           
 965               (*self->callback)(self, &msg->base, self->callbackData);
 966           
 967 mike  1.1     InvokeReq_Release(msg);
 968               return;
 969           
 970           failed:
 971               LOGW_CHAR(("wsman: unable to process invoke request"));
 972               Http_SendErrorResponse(http, httpConnectionHandle, HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
 973               selfCD->outstandingRequest = MI_FALSE;
 974           
 975               if (msg)
 976                   InvokeReq_Release(msg);
 977           }
 978           
 979           static void _ParseValidateProcessGetRequest(
 980               Http* http,
 981               void* httpConnectionHandle,
 982               WSMAN* self,
 983               WSMAN_ConnectionData* selfCD,
 984               XML*    xml)
 985           {
 986               GetInstanceReq* msg = 0;
 987           
 988 mike  1.1     MI_UNUSED(xml);
 989           
 990               /* Check if instance name parameter was specified */
 991               if (!selfCD->wsheader.instance || !selfCD->wsheader.instanceBatch)
 992               {
 993                   LOGW_CHAR(("wsman: get-instance: instance name parameter is missing"));
 994                   _SendFaultResponse(http, selfCD, WSBUF_FAULT_INTERNAL_ERROR, T("get-instance: instance name parameter is missing"));
 995           
 996                   selfCD->outstandingRequest = MI_FALSE;
 997                   return;
 998               }
 999           
1000               /* if instance was created from batch, re-use exisintg batch to allocate message */
1001               /* Allocate heap space for message */
1002               msg = Batch_GetClear(selfCD->wsheader.instanceBatch, sizeof(GetInstanceReq));
1003           
1004               if (!msg)
1005                   goto failed;
1006           
1007               /* Set the tag */
1008               msg->base.tag = GetInstanceReqTag;
1009 mike  1.1 
1010               /* Set the message id and flags */
1011               msg->base.msgID = 1;
1012               msg->base.flags = WSMANFlag | WSMAN_ObjectFlag;
1013           
1014               /* ref-counter is set to 1, to balance NewMessage/Release Message pair*/
1015               msg->base.refCounter = 1;
1016           
1017               /* Copy batch into message (released by delete method) */
1018               msg->base.batch = selfCD->wsheader.instanceBatch;
1019           
1020               msg->instanceName = selfCD->wsheader.instance;
1021           
1022               /* clear batch/instance fields in header structure */
1023               selfCD->wsheader.instanceBatch = 0;
1024               selfCD->wsheader.instance = 0;
1025           
1026               /* Skip parsing get-request/body - assumed to be empty */
1027           
1028               /* Extract/set relevant parameters */
1029               if (selfCD->wsheader.rqtNamespace)
1030 mike  1.1         msg->nameSpace = Batch_Strdup2(msg->base.batch, selfCD->wsheader.rqtNamespace);
1031           
1032               /* attach client id */
1033               msg->base.clientID = PtrToUint64(selfCD);
1034               msg->base.uid = selfCD->uid;
1035               msg->base.gid = selfCD->gid;
1036           
1037               /* increment counter to keep it alive until provider replies */
1038               selfCD->refcounter++;
1039           
1040               (*self->callback)(self, &msg->base, self->callbackData);
1041           
1042               GetInstanceReq_Release(msg);
1043               return;
1044           
1045           failed:
1046               LOGW_CHAR(("wsman: unable to process get-instance request"));
1047               Http_SendErrorResponse(http, httpConnectionHandle, HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
1048               selfCD->outstandingRequest = MI_FALSE;
1049           
1050               if (msg)
1051 mike  1.1         GetInstanceReq_Release(msg);
1052           }
1053           
1054           static void _ParseValidateProcessPutRequest(
1055               Http* http,
1056               void* httpConnectionHandle,
1057               WSMAN* self,
1058               WSMAN_ConnectionData* selfCD,
1059               XML*    xml)
1060           {
1061               ModifyInstanceReq* msg = 0;
1062           
1063               MI_UNUSED(xml);
1064           
1065               /* Check if instance name parameter was specified */
1066               if (!selfCD->wsheader.instance || !selfCD->wsheader.instanceBatch)
1067               {
1068                   LOGW_CHAR(("wsman: Put-instance: instance name parameter is missing"));
1069                   _SendFaultResponse(http, selfCD, WSBUF_FAULT_INTERNAL_ERROR, T("Put-instance: instance name parameter is missing"));
1070           
1071                   selfCD->outstandingRequest = MI_FALSE;
1072 mike  1.1         return;
1073               }
1074           
1075               /* if instance was created from batch, re-use exisintg batch to allocate message */
1076               /* Allocate heap space for message */
1077               msg = Batch_GetClear(selfCD->wsheader.instanceBatch, sizeof(ModifyInstanceReq));
1078           
1079               if (!msg)
1080                   goto failed;
1081           
1082               /* Set the tag */
1083               msg->base.tag = ModifyInstanceReqTag;
1084           
1085               /* Set the message id and flags */
1086               msg->base.msgID = 1;
1087               msg->base.flags = WSMANFlag | WSMAN_ObjectFlag;
1088           
1089               /* ref-counter is set to 1, to balance NewMessage/Release Message pair*/
1090               msg->base.refCounter = 1;
1091           
1092               /* Copy batch into message (released by delete method) */
1093 mike  1.1     msg->base.batch = selfCD->wsheader.instanceBatch;
1094               msg->instance = selfCD->wsheader.instance;
1095           
1096               /* clear batch/instance fields in header structure */
1097               selfCD->wsheader.instanceBatch = 0;
1098               selfCD->wsheader.instance = 0;
1099           
1100               /* re-use 'create' parser to parse 'Modify' request/body */
1101               if (WS_ParseCreateBody(xml, msg->base.batch, &msg->instance) != 0)
1102                   goto failed;
1103           
1104               /* Extract/set relevant parameters */
1105               if (selfCD->wsheader.rqtNamespace)
1106                   msg->nameSpace = Batch_Strdup2(msg->base.batch, selfCD->wsheader.rqtNamespace);
1107           
1108               /* attach client id */
1109               msg->base.clientID = PtrToUint64(selfCD);
1110               msg->base.uid = selfCD->uid;
1111               msg->base.gid = selfCD->gid;
1112           
1113               /* increment counter to keep it alive until provider replies */
1114 mike  1.1     selfCD->refcounter++;
1115           
1116               (*self->callback)(self, &msg->base, self->callbackData);
1117           
1118               ModifyInstanceReq_Release(msg);
1119               return;
1120           
1121           failed:
1122               LOGW_CHAR(("wsman: unable to process Put-instance request"));
1123               Http_SendErrorResponse(http, httpConnectionHandle, HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
1124               selfCD->outstandingRequest = MI_FALSE;
1125           
1126               if (msg)
1127                   ModifyInstanceReq_Release(msg);
1128           }
1129           
1130           static void _ParseValidateProcessDeleteRequest(
1131               Http* http,
1132               void* httpConnectionHandle,
1133               WSMAN* self,
1134               WSMAN_ConnectionData* selfCD,
1135 mike  1.1     XML*    xml)
1136           {
1137               DeleteInstanceReq* msg = 0;
1138           
1139               MI_UNUSED(xml);
1140           
1141               /* Check if instance name parameter was specified */
1142               if (!selfCD->wsheader.instance || !selfCD->wsheader.instanceBatch)
1143               {
1144                   LOGW_CHAR(("wsman: delete-instance: instance name parameter is missing"));
1145                   _SendFaultResponse(http, selfCD, WSBUF_FAULT_INTERNAL_ERROR, T("delete-instance: instance name parameter is missing"));
1146           
1147                   selfCD->outstandingRequest = MI_FALSE;
1148                   return;
1149               }
1150           
1151               /* if instance was created from batch, re-use exisintg batch to allocate message */
1152               /* Allocate heap space for message */
1153               msg = Batch_GetClear(selfCD->wsheader.instanceBatch, sizeof(DeleteInstanceReq));
1154           
1155               if (!msg)
1156 mike  1.1         goto failed;
1157           
1158               /* Set the tag */
1159               msg->base.tag = DeleteInstanceReqTag;
1160           
1161               /* Set the message id and flags */
1162               msg->base.msgID = 1;
1163               msg->base.flags = WSMANFlag | WSMAN_ObjectFlag;
1164           
1165               /* ref-counter is set to 1, to balance NewMessage/Release Message pair*/
1166               msg->base.refCounter = 1;
1167           
1168               /* Copy batch into message (released by delete method) */
1169               msg->base.batch = selfCD->wsheader.instanceBatch;
1170           
1171               msg->instanceName = selfCD->wsheader.instance;
1172           
1173               /* clear batch/instance fields in header structure */
1174               selfCD->wsheader.instanceBatch = 0;
1175               selfCD->wsheader.instance = 0;
1176           
1177 mike  1.1     /* Skip parsing Delete-request/body - assumed to be empty */
1178           
1179               /* Extract/set relevant parameters */
1180               if (selfCD->wsheader.rqtNamespace)
1181                   msg->nameSpace = Batch_Strdup2(msg->base.batch, selfCD->wsheader.rqtNamespace);
1182           
1183               /* attach client id */
1184               msg->base.clientID = PtrToUint64(selfCD);
1185               msg->base.uid = selfCD->uid;
1186               msg->base.gid = selfCD->gid;
1187           
1188               /* increment counter to keep it alive until provider replies */
1189               selfCD->refcounter++;
1190           
1191               (*self->callback)(self, &msg->base, self->callbackData);
1192           
1193               DeleteInstanceReq_Release(msg);
1194               return;
1195           
1196           failed:
1197               LOGW_CHAR(("wsman: unable to process delete-instance request"));
1198 mike  1.1     Http_SendErrorResponse(http, httpConnectionHandle, HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
1199               selfCD->outstandingRequest = MI_FALSE;
1200           
1201               if (msg)
1202                   DeleteInstanceReq_Release(msg);
1203           }
1204           
1205           static void _ParseValidateProcessCreateRequest(
1206               Http* http,
1207               void* httpConnectionHandle,
1208               WSMAN* self,
1209               WSMAN_ConnectionData* selfCD,
1210               XML*    xml)
1211           {
1212               CreateInstanceReq* msg = 0;
1213           
1214                msg = CreateInstanceReq_New(1, WSMANFlag | WSMAN_CreatedEPRFlag);
1215           
1216               if (!msg)
1217                   goto failed;
1218           
1219 mike  1.1     /* Parse create request/body */
1220               if (WS_ParseCreateBody(xml, msg->base.batch, &msg->instance) != 0)
1221                   goto failed;
1222           
1223               /* Extract/set relevant parameters */
1224               if (selfCD->wsheader.rqtNamespace)
1225                   msg->nameSpace = Batch_Strdup2(msg->base.batch, selfCD->wsheader.rqtNamespace);
1226           
1227               /* attach client id */
1228               msg->base.clientID = PtrToUint64(selfCD);
1229               msg->base.uid = selfCD->uid;
1230               msg->base.gid = selfCD->gid;
1231           
1232               /* increment counter to keep it alive until provider replies */
1233               selfCD->refcounter++;
1234           
1235               (*self->callback)(self, &msg->base, self->callbackData);
1236           
1237               CreateInstanceReq_Release(msg);
1238               return;
1239           
1240 mike  1.1 failed:
1241               LOGW_CHAR(("wsman: unable to process Create request"));
1242               Http_SendErrorResponse(http, httpConnectionHandle, HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
1243               selfCD->outstandingRequest = MI_FALSE;
1244           
1245               if (msg)
1246                   CreateInstanceReq_Release(msg);
1247           }
1248           
1249           static void _ParseValidateProcessPullRequest(
1250               Http* http,
1251               void* httpConnectionHandle,
1252               WSMAN* self,
1253               WSMAN_ConnectionData* selfCD,
1254               XML*    xml)
1255           {
1256               /* Parse pull request/body */
1257               if (WS_ParsePullBody(xml, &selfCD->u.wsenumpullbody) != 0)
1258               {
1259                   LOGW_CHAR(("wsman: unable to parse incoming xml/ Pull request body"));
1260                   Http_SendErrorResponse(http, httpConnectionHandle, HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
1261 mike  1.1         selfCD->outstandingRequest = MI_FALSE;
1262                   return;
1263               }
1264           
1265               /* Validate enumerate request body */
1266               if (_ValidatePullRequest(http, selfCD) != 0)
1267               {
1268                   /* appropriate error code was already sent to the client */
1269                   return;
1270               }
1271           
1272               /* Process reqest */
1273               _ProcessPullRequest(http,self,selfCD);
1274           }
1275           
1276           static void _ParseValidateProcessReleaseRequest(
1277               Http* http,
1278               void* httpConnectionHandle,
1279               WSMAN* self,
1280               WSMAN_ConnectionData* selfCD,
1281               XML*    xml)
1282 mike  1.1 {
1283               /* Parse pull request/body */
1284               if (WS_ParseReleaseBody(xml, &selfCD->u.wsenumpullbody) != 0)
1285               {
1286                   LOGW_CHAR(("wsman: unable to parse incoming xml/ Release request body"));
1287                   Http_SendErrorResponse(http, httpConnectionHandle, HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
1288                   selfCD->outstandingRequest = MI_FALSE;
1289                   return;
1290               }
1291           
1292               /* Validate enumerate request body */
1293               /* no validation needed */
1294           
1295               /* Process reqest */
1296               _ProcessReleaseRequest(http,self,selfCD);
1297           }
1298           
1299           static void _SendIdentifyResponse(
1300               WSMAN* self,
1301               WSMAN_ConnectionData* selfCD)
1302           {
1303 mike  1.1     WS_Buffer out;
1304               Page* responsePage = 0;
1305           #   define MSG \
1306               "<soap:Envelope " \
1307               "xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" " \
1308               "xmlns:wsmid=\"http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd\">" CR \
1309               "<soap:Header/>" CR \
1310               "<soap:Body>" CR \
1311               "<soap:IdentifyResponse>" CR \
1312               "<wsmid:ProtocolVersion>" \
1313                 "http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" \
1314               "</wsmid:ProtocolVersion>" CR \
1315               "<wsmid:ProductVendor>" \
1316                 CONFIG_FULLPRODUCT \
1317               "</wsmid:ProductVendor>" CR \
1318               "<wsmid:ProductVersion>" \
1319                 CONFIG_VERSION \
1320               "</wsmid:ProductVersion>" CR \
1321               "<wsmid:SecurityProfiles>" CR \
1322               "<wsmid:SecurityProfileName>" \
1323               "http://schemas.dmtf.org/wbem/wsman/1/wsman/secprofile/https/basic" \
1324 mike  1.1     "</wsmid:SecurityProfileName>" CR \
1325               "</wsmid:SecurityProfiles>" CR \
1326               "</soap:IdentifyResponse>" CR \
1327               "</soap:Body>" CR \
1328               "</soap:Envelope>" CR
1329           
1330               if (WSBuf_Init(&out, 1024) != MI_RESULT_OK)
1331               {
1332                   goto failed;
1333               }
1334           
1335               if (WSBuf_AddLit(&out, LIT(MSG)) != MI_RESULT_OK)
1336               {
1337                   goto failed;
1338               }
1339           
1340               responsePage = WSBuf_StealPage(&out);
1341           
1342               if (!responsePage)
1343                   goto failed;
1344           
1345 mike  1.1     if (self->options.enableTracing)
1346               {
1347                   printf("%s\n\n", (char*)(responsePage+1));
1348               }
1349           
1350               Http_SendResponse(
1351                   self->http, 
1352                   selfCD->httpConnectionHandle, 
1353                   HTTP_ERROR_CODE_OK, 
1354                   &responsePage);
1355           
1356               selfCD->outstandingRequest = MI_FALSE;
1357           
1358               if (responsePage)
1359                   free(responsePage);
1360           
1361               return;
1362           
1363           failed:
1364               WSBuf_Destroy(&out);
1365               Http_SendErrorResponse(
1366 mike  1.1         self->http, 
1367                   selfCD->httpConnectionHandle, 
1368                   HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
1369               selfCD->outstandingRequest = MI_FALSE;
1370           }
1371           
1372           static void _HandleIdentifyRequest(
1373               Http* http,
1374               void* httpConnectionHandle,
1375               WSMAN* self,
1376               WSMAN_ConnectionData* selfCD,
1377               XML* xml)
1378           {
1379               /* Parse pull request/body */
1380               if (WS_ParseIdentifyBody(xml) != 0)
1381               {
1382                   LOGW_CHAR(("wsman: found neither Action or Identify"));
1383                   Http_SendErrorResponse(http, httpConnectionHandle, 
1384                       HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
1385                   selfCD->outstandingRequest = MI_FALSE;
1386                   return;
1387 mike  1.1     }
1388           
1389               _SendIdentifyResponse(self, selfCD);
1390           }
1391           
1392           /************************************************************************\
1393           *   Dispatcher calls processing
1394           \************************************************************************/
1395           
1396           static void _EC_GetMessageSubset(
1397               WSMAN_EnumerateContext* selfEC,
1398               WSMAN_ConnectionData* selfCD,
1399               PostInstanceMsg** subsetEnd,
1400               MI_Uint32*  totalSize)
1401           {
1402               MI_Uint32 count = 0;
1403               *totalSize = 0;
1404               *subsetEnd = selfEC->head;
1405           
1406               while (*subsetEnd)
1407               {
1408 mike  1.1         if (count + 1 > selfCD->u.wsenumpullbody.maxElements ||
1409                       (*totalSize) + (*subsetEnd)->packedInstanceSize + WSMAN_APROX_ENUM_RESP_HEADER_SIZE > selfCD->wsheader.maxEnvelopeSize)
1410                       break;
1411           
1412                   (*totalSize) += (*subsetEnd)->packedInstanceSize;
1413                   count++;
1414                   (*subsetEnd) = (PostInstanceMsg*)(*subsetEnd)->base.next;
1415               }
1416           }
1417           
1418           /* Sends as many instances as posisble (based on envelope-size and instance counter) */
1419           static void _SendEnumPullResponse(
1420               WSMAN* self,
1421               WSMAN_EnumerateContext* selfEC)
1422           {
1423               WS_Buffer   outBufHeader, outBufTrailer;
1424               Page*       responsePageCombined = 0;
1425               Page*       responsePageHeader = 0;
1426               Page*       responsePageTrailer = 0;
1427               MI_Uint32       totalSize, messagesSize = 0;
1428               WSMAN_ConnectionData* selfCD = selfEC->activeConnection;
1429 mike  1.1     PostInstanceMsg* subsetEnd = 0;
1430               MI_Boolean      endOfSequence = selfEC->enumerationCompleted;
1431           
1432           
1433               /* Get message subset based on envelope size/ maxElements */
1434               _EC_GetMessageSubset(selfEC, selfCD, &subsetEnd, &messagesSize);
1435           
1436               /* validate if all mesages can be sent */
1437               if (endOfSequence && subsetEnd)
1438               {
1439                   endOfSequence = MI_FALSE;
1440               }
1441           
1442               /* check if we can put at least one message in response */
1443               if (NULL != selfEC->head &&
1444                   subsetEnd == selfEC->head)
1445               {
1446                   LOGW_CHAR(("wsman: max-envelope is too small even for one message; message size %d", 
1447                       (int)subsetEnd->packedInstanceSize ));
1448                   _SendFaultResponse(self->http, selfCD, WSBUF_FAULT_ENCODING_LIMIT, T("insufficient envelope size for instance transferring"));
1449                   /* Note: leaving context 'as is' so advanced client can increase packet size and re-try */
1450 mike  1.1         return;
1451               }
1452           
1453               /* Create EnumResponse */
1454               if (WSBuf_Init(&outBufHeader, WSMAN_APROX_ENUM_RESP_HEADER_SIZE) != MI_RESULT_OK)
1455               {
1456                   outBufTrailer.page = 0;
1457                   goto failed;
1458               }
1459           
1460               if (WSBuf_Init(&outBufTrailer, 256) != MI_RESULT_OK)
1461                   goto failed;
1462           
1463               /* prepare response header */
1464               if (selfCD->wsheader.rqtAction == WSMANTAG_ACTION_ENUMERATE)
1465               {
1466                   if (MI_RESULT_OK != WSBuf_CreateSoapResponseHeader(&outBufHeader,
1467                       LIT(T("http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse")), selfCD->wsheader.rqtMessageID))
1468                       goto failed;
1469               }
1470               else
1471 mike  1.1     {
1472                   if (MI_RESULT_OK != WSBuf_CreateSoapResponseHeader(&outBufHeader,
1473                       LIT(T("http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse")), selfCD->wsheader.rqtMessageID))
1474                       goto failed;
1475               }
1476           
1477               if (MI_RESULT_OK != WSBuf_AddLit(&outBufHeader,
1478                   LIT(T("</SOAP-ENV:Header>")
1479                   T("<SOAP-ENV:Body>"))))
1480                   goto failed;
1481           
1482               if (selfCD->wsheader.rqtAction == WSMANTAG_ACTION_ENUMERATE)
1483               {
1484                   if (MI_RESULT_OK != WSBuf_AddLit(&outBufHeader,
1485                       LIT(T("<wsen:EnumerateResponse>"))))
1486                       goto failed;
1487               }
1488               else
1489               {
1490                   if (MI_RESULT_OK != WSBuf_AddLit(&outBufHeader,
1491                       LIT(T("<wsen:PullResponse>"))))
1492 mike  1.1             goto failed;
1493               }
1494           
1495               if (MI_RESULT_OK != WSBuf_AddLit(&outBufHeader,
1496                   LIT(T("<wsen:EnumerationContext>"))))
1497                   goto failed;
1498           
1499               if (MI_RESULT_OK != WSBuf_AddUint32(&outBufHeader,selfEC->enumerationContextID))
1500                   goto failed;
1501           
1502               if (MI_RESULT_OK != WSBuf_AddLit(&outBufHeader,
1503                   LIT(T("</wsen:EnumerationContext>"))))
1504                   goto failed;
1505           
1506               if (selfCD->wsheader.rqtAction == WSMANTAG_ACTION_ENUMERATE)
1507               {
1508                   if (MI_RESULT_OK != WSBuf_AddLit(&outBufHeader,
1509                       LIT(T("<wsman:Items>"))))
1510                       goto failed;
1511               }
1512               else
1513 mike  1.1     {
1514                   if (MI_RESULT_OK != WSBuf_AddLit(&outBufHeader,
1515                       LIT(T("<wsen:Items>"))))
1516                       goto failed;
1517               }
1518           
1519           
1520           
1521               /* trailer */
1522               if (selfCD->wsheader.rqtAction == WSMANTAG_ACTION_ENUMERATE)
1523               {
1524                   if (MI_RESULT_OK != WSBuf_AddLit(&outBufTrailer,
1525                       LIT(T("</wsman:Items>"))))
1526                       goto failed;
1527               }
1528               else
1529               {
1530                   if (MI_RESULT_OK != WSBuf_AddLit(&outBufTrailer,
1531                       LIT(T("</wsen:Items>"))))
1532                       goto failed;
1533               }
1534 mike  1.1 
1535               if (endOfSequence)
1536               {
1537                   if (selfCD->wsheader.rqtAction == WSMANTAG_ACTION_ENUMERATE)
1538                   {
1539                       if (MI_RESULT_OK != WSBuf_AddLit(&outBufTrailer,
1540                           LIT(T("<wsman:EndOfSequence/>"))))
1541                           goto failed;
1542                   }
1543                   else
1544                   {
1545                       if (MI_RESULT_OK != WSBuf_AddLit(&outBufTrailer,
1546                           LIT(T("<wsen:EndOfSequence/>"))))
1547                           goto failed;
1548                   }
1549               }
1550           
1551               if (selfCD->wsheader.rqtAction == WSMANTAG_ACTION_ENUMERATE)
1552               {
1553                   if (MI_RESULT_OK != WSBuf_AddLit(&outBufTrailer,
1554                       LIT(T("</wsen:EnumerateResponse>"))))
1555 mike  1.1             goto failed;
1556               }
1557               else
1558               {
1559                   if (MI_RESULT_OK != WSBuf_AddLit(&outBufTrailer,
1560                       LIT(T("</wsen:PullResponse>"))))
1561                       goto failed;
1562               }
1563               if (MI_RESULT_OK != WSBuf_AddLit(&outBufTrailer,
1564                   LIT(T("</SOAP-ENV:Body>")
1565                   T("</SOAP-ENV:Envelope>"))))
1566                   goto failed;
1567           
1568               /* all together */
1569               responsePageHeader = WSBuf_StealPage(&outBufHeader);
1570               responsePageTrailer = WSBuf_StealPage(&outBufTrailer);
1571           
1572               if (!responsePageTrailer || !responsePageHeader)
1573                   goto failed;
1574           
1575               /* calculate size */
1576 mike  1.1     totalSize = (MI_Uint32)(responsePageHeader->u.s.size + responsePageTrailer->u.s.size) + messagesSize;
1577           
1578               responsePageCombined = (Page*)malloc(sizeof(Page) + totalSize + 1);
1579           
1580               if (!responsePageCombined)
1581                   goto failed;
1582           
1583               {
1584                   char* data = (char*) (responsePageCombined + 1);
1585                   data[totalSize] = 0;
1586           
1587                   memcpy(data, responsePageHeader+1, responsePageHeader->u.s.size);
1588                   data += responsePageHeader->u.s.size;
1589           
1590                   {
1591                       PostInstanceMsg* msg = selfEC->head;
1592                       while (msg != subsetEnd)
1593                       {
1594                           PostInstanceMsg* next = (PostInstanceMsg*)msg->base.next;
1595           
1596                           memcpy(data, msg->packedInstancePtr, msg->packedInstanceSize);
1597 mike  1.1                 data += msg->packedInstanceSize;
1598           
1599                           /* remove message from the list */
1600                           selfEC->totalResponses--;
1601                           selfEC->totalResponseSize -= msg->packedInstanceSize;
1602                           List_Remove(
1603                               (ListElem**)&selfEC->head, 
1604                               (ListElem**)&selfEC->tail, 
1605                               (ListElem*)msg);
1606                           PostInstanceMsg_Release(msg);
1607           
1608                           msg = next;
1609                       }
1610                   }
1611           
1612                   memcpy(data, responsePageTrailer+1, responsePageTrailer->u.s.size);
1613                   data += responsePageTrailer->u.s.size;
1614           
1615                   responsePageCombined->u.s.size = totalSize;
1616                   responsePageCombined->u.s.next = 0;
1617               }
1618 mike  1.1 
1619               free(responsePageHeader); responsePageHeader = 0;
1620               free(responsePageTrailer); responsePageTrailer = 0;
1621           
1622               /* Trace the response XML */
1623           
1624               if (self->options.enableTracing)
1625               {
1626                   printf("%s\n\n", (char*)(responsePageCombined+1));
1627               }
1628           
1629               /*{
1630                   FILE* f = Fopen("out_test.xml", "a");
1631                   fwrite((char*)(responsePageCombined+1), 1, (size_t)responsePageCombined->u.s.size, f);
1632                   fclose(f);
1633               }*/
1634           
1635               Http_SendResponse(
1636                   self->http, 
1637                   selfCD->httpConnectionHandle, 
1638                   HTTP_ERROR_CODE_OK, 
1639 mike  1.1         &responsePageCombined);
1640           
1641               selfCD->outstandingRequest = MI_FALSE;
1642           
1643               if (responsePageCombined)
1644                   free(responsePageCombined);
1645           
1646               return;
1647           
1648           failed:
1649               WSBuf_Destroy(&outBufHeader);
1650               WSBuf_Destroy(&outBufTrailer);
1651               if (responsePageCombined) free(responsePageCombined);
1652               if (responsePageHeader) free(responsePageHeader);
1653               if (responsePageTrailer) free(responsePageTrailer);
1654           
1655               _EC_ReleaseAllMessages(selfEC);
1656               Http_SendErrorResponse(self->http, selfCD->httpConnectionHandle, HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
1657               selfCD->outstandingRequest = MI_FALSE;
1658           }
1659           
1660 mike  1.1 static void _SendInvokeResponse(
1661               WSMAN* self,
1662               WSMAN_ConnectionData* selfCD,
1663               PostInstanceMsg* message)
1664           {
1665               WS_Buffer   outBuf;
1666               Page*       responsePage = 0;
1667               MI_Char*    action = 0;
1668               MI_Uint32   actionLen;
1669           
1670               /* create action */
1671               actionLen = (MI_Uint32)(7 /* http:// */ +
1672                   27 /* "/wbem/wscim/1/cim-schema/2/" */ +
1673                   1 /* / between cn/meth */ +
1674                   1 /* \0 at the end */ +
1675                   strlen(selfCD->wsheader.rqtServer) +
1676                   strlen(selfCD->wsheader.rqtClassname) +
1677                   strlen(selfCD->wsheader.rqtMethod));
1678           
1679               action = (MI_Char*)malloc(actionLen * sizeof(MI_Char));
1680           
1681 mike  1.1     if (!action)
1682                   goto failed;
1683           
1684           #if (MI_CHAR_TYPE == 1)
1685               //Snprintf(action, actionLen, T("http://%s/wbem/wscim/1/cim-schema/2/%s/%s"),
1686               //    selfCD->wsheader.rqtServer, selfCD->wsheader.rqtClassname, selfCD->wsheader.rqtMethod);
1687               {
1688                   MI_Uint32 size;
1689                   action[0] = 0;
1690                   size = Strlcat(action, "http://", actionLen);
1691                   size += Strlcat(action + size, selfCD->wsheader.rqtServer, actionLen - size);
1692                   size += Strlcat(action + size, "/wbem/wscim/1/cim-schema/2/", actionLen - size);
1693                   size += Strlcat(action + size, selfCD->wsheader.rqtClassname, actionLen - size);
1694                   size += Strlcat(action + size, "/", actionLen - size);
1695                   size += Strlcat(action + size, selfCD->wsheader.rqtMethod, actionLen - size);
1696           
1697                   assert(size == (actionLen-1));
1698               }
1699           #else
1700               Szprintf(action, actionLen, T("http://%S/wbem/wscim/1/cim-schema/2/%S/%S"),
1701                   selfCD->wsheader.rqtServer, selfCD->wsheader.rqtClassname, selfCD->wsheader.rqtMethod);
1702 mike  1.1 #endif
1703           
1704               actionLen--;
1705           
1706               /* Create EnumResponse */
1707               if (WSBuf_Init(&outBuf, WSMAN_APROX_ENUM_RESP_HEADER_SIZE + message->packedInstanceSize) != MI_RESULT_OK)
1708                   goto failed;
1709           
1710               /* prepare response header */
1711               if (MI_RESULT_OK != WSBuf_CreateSoapResponseHeader(&outBuf,
1712                   action, actionLen, selfCD->wsheader.rqtMessageID))
1713                   goto failed;
1714           
1715               if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1716                   LIT(T("</SOAP-ENV:Header>")
1717                   T("<SOAP-ENV:Body>")
1718                   T("<n1:ExecuteCommand_OUTPUT xmlns:n1=\"")
1719                   )))
1720                   goto failed;
1721           
1722               if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1723 mike  1.1         action, actionLen))
1724                   goto failed;
1725           
1726               if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1727                   LIT(T("\">"))))
1728                   goto failed;
1729           
1730           
1731               if (MI_RESULT_OK != WSBuf_AddCharLit(&outBuf,
1732                   message->packedInstancePtr, message->packedInstanceSize))
1733                   goto failed;
1734           
1735               /* trailer */
1736               if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1737                   LIT(
1738                   T("</n1:ExecuteCommand_OUTPUT>")
1739                   T("</SOAP-ENV:Body>")
1740                   T("</SOAP-ENV:Envelope>"))))
1741                   goto failed;
1742           
1743               /* all together */
1744 mike  1.1     responsePage = WSBuf_StealPage(&outBuf);
1745           
1746               if (!responsePage)
1747                   goto failed;
1748           
1749               /* Trace the response XML */
1750           
1751               if (self->options.enableTracing)
1752               {
1753                   printf("%s\n\n", (char*)(responsePage+1));
1754               }
1755           
1756               /*{
1757                   FILE* f = Fopen("out_test.xml", "a");
1758                   fwrite((char*)(responsePageCombined+1), 1, (size_t)responsePageCombined->u.s.size, f);
1759                   fclose(f);
1760               }*/
1761           
1762               Http_SendResponse(
1763                   self->http, 
1764                   selfCD->httpConnectionHandle, 
1765 mike  1.1         HTTP_ERROR_CODE_OK, 
1766                   &responsePage);
1767           
1768               /* indicate that response was sent */
1769               selfCD->outstandingRequest = MI_FALSE;
1770           
1771               if (responsePage)
1772                   free(responsePage);
1773           
1774               if (action) 
1775                   free(action);
1776           
1777               return;
1778           
1779           failed:
1780               WSBuf_Destroy(&outBuf);
1781               if (responsePage) free(responsePage);
1782               if (action) free(action);
1783           
1784               Http_SendErrorResponse(self->http, selfCD->httpConnectionHandle, HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
1785           
1786 mike  1.1     /* indicate that response was sent */
1787               selfCD->outstandingRequest = MI_FALSE;
1788           }
1789           
1790           static void _SendSingleInstanceResponse(
1791               WSMAN* self,
1792               WSMAN_ConnectionData* selfCD,
1793               PostInstanceMsg* message,
1794               const MI_Char* action,
1795               MI_Uint32 actionSize)
1796           {
1797               WS_Buffer   outBuf;
1798               Page*       responsePage = 0;
1799           
1800               if (WSBuf_Init(&outBuf, WSMAN_APROX_ENUM_RESP_HEADER_SIZE + message->packedInstanceSize) != MI_RESULT_OK)
1801                   goto failed;
1802           
1803               if (MI_RESULT_OK != WSBuf_CreateSoapResponseHeader(&outBuf,
1804                   action, actionSize, selfCD->wsheader.rqtMessageID))
1805                   goto failed;
1806           
1807 mike  1.1     if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1808                   LIT(T("</SOAP-ENV:Header>")
1809                   T("<SOAP-ENV:Body>")
1810                   )))
1811                   goto failed;
1812           
1813           
1814               if (MI_RESULT_OK != WSBuf_AddCharLit(&outBuf,
1815                   message->packedInstancePtr, message->packedInstanceSize))
1816                   goto failed;
1817           
1818               /* trailer */
1819               if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1820                   LIT(
1821                   T("</SOAP-ENV:Body>")
1822                   T("</SOAP-ENV:Envelope>"))))
1823                   goto failed;
1824           
1825               /* all together */
1826               responsePage = WSBuf_StealPage(&outBuf);
1827           
1828 mike  1.1     if (!responsePage)
1829                   goto failed;
1830           
1831               /* Trace the response XML */
1832           
1833               if (self->options.enableTracing)
1834               {
1835                   printf("%s\n\n", (char*)(responsePage+1));
1836               }
1837           
1838               /* {
1839                   FILE* f = Fopen("out_test.xml", "a");
1840                   fwrite((char*)(responsePage+1), 1, (size_t)responsePage->u.s.size, f);
1841                   fclose(f);
1842               } */
1843           
1844               Http_SendResponse(
1845                   self->http, 
1846                   selfCD->httpConnectionHandle, 
1847                   HTTP_ERROR_CODE_OK, 
1848                   &responsePage);
1849 mike  1.1 
1850               /* indicate that response was sent */
1851               selfCD->outstandingRequest = MI_FALSE;
1852           
1853               if (responsePage)
1854                   free(responsePage);
1855           
1856               return;
1857           
1858           failed:
1859               WSBuf_Destroy(&outBuf);
1860               if (responsePage) free(responsePage);
1861           
1862               Http_SendErrorResponse(self->http, selfCD->httpConnectionHandle, HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
1863           
1864               /* indicate that response was sent */
1865               selfCD->outstandingRequest = MI_FALSE;
1866           }
1867           
1868           static void _SendDeleteInstanceResponse(
1869               WSMAN* self,
1870 mike  1.1     WSMAN_ConnectionData* selfCD)
1871           {
1872               WS_Buffer   outBuf;
1873               Page*       responsePage = 0;
1874           
1875               if (WSBuf_Init(&outBuf, WSMAN_APROX_ENUM_RESP_HEADER_SIZE) != MI_RESULT_OK)
1876                   goto failed;
1877           
1878               if (MI_RESULT_OK != WSBuf_CreateSoapResponseHeader(&outBuf,
1879                   LIT(T("http://schemas.xmlsoap.org/ws/2004/09/transfer/DeleteResponse")), selfCD->wsheader.rqtMessageID))
1880                   goto failed;
1881           
1882               if (MI_RESULT_OK != WSBuf_AddLit(&outBuf,
1883                   LIT(T("</SOAP-ENV:Header>")
1884                   T("<SOAP-ENV:Body/>")
1885                   T("</SOAP-ENV:Envelope>")
1886                   )))
1887                   goto failed;
1888           
1889               /* all together */
1890               responsePage = WSBuf_StealPage(&outBuf);
1891 mike  1.1 
1892               if (!responsePage)
1893                   goto failed;
1894           
1895               /* Trace the response XML */
1896           
1897               if (self->options.enableTracing)
1898               {
1899                   printf("%s\n\n", (char*)(responsePage+1));
1900               }
1901           
1902               /*{
1903                   FILE* f = Fopen("out_test.xml", "a");
1904                   fwrite((char*)(responsePageCombined+1), 1, (size_t)responsePageCombined->u.s.size, f);
1905                   fclose(f);
1906               }*/
1907           
1908               Http_SendResponse(
1909                   self->http, 
1910                   selfCD->httpConnectionHandle, 
1911                   HTTP_ERROR_CODE_OK, 
1912 mike  1.1         &responsePage);
1913           
1914               /* indicate that response was sent */
1915               selfCD->outstandingRequest = MI_FALSE;
1916           
1917               if (responsePage)
1918                   free(responsePage);
1919           
1920               return;
1921           
1922           failed:
1923               WSBuf_Destroy(&outBuf);
1924               if (responsePage) free(responsePage);
1925           
1926               Http_SendErrorResponse(self->http, selfCD->httpConnectionHandle, HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
1927           
1928               /* indicate that response was sent */
1929               selfCD->outstandingRequest = MI_FALSE;
1930           }
1931           
1932           static void _SendErrorResponse(
1933 mike  1.1     WSMAN* self,
1934               WSMAN_ConnectionData* selfCD, 
1935               MI_Result result)
1936           {
1937               WSBUF_FAULT_CODE faultCode;
1938               const MI_Char* description = 0;
1939           
1940               faultCode = WSBuf_CIMErrorToWSFault(result, &description);
1941           
1942               /* ATTN! consume text from cim_error if supplied */
1943               _SendFaultResponse(self->http, selfCD, faultCode, description);
1944           }
1945           
1946           
1947           /* Function processes backlog in enumeration context;
1948               returns true if message was sent to active connection;
1949               once last repsonse is sent, it deletes context */
1950           static MI_Boolean _ProcessEnumResponse(
1951               WSMAN* self,
1952               WSMAN_EnumerateContext* selfEC,
1953               MI_Boolean attachingPullRequest)
1954 mike  1.1 {
1955               /* do we have connected cleint to send response to? */
1956               if (!selfEC->activeConnection)
1957                   return MI_FALSE;
1958           
1959               if (selfEC->enumerationCompleted && selfEC->finalResult != MI_RESULT_OK)
1960               {
1961                   _SendErrorResponse(self, selfEC->activeConnection, selfEC->finalResult);
1962           
1963                   /* release context */
1964                   _EC_SetActiveConnection(selfEC, 0);
1965                   _WSMAN_ReleaseEnumerateContext(self, selfEC->enumerationContextID);
1966                   selfEC = 0;
1967                   return MI_TRUE;
1968               }
1969           
1970               /* Check if partial response has to be sent (or enumeration is completed) */
1971               /* Update: send anything that is available once client re-connects with pull */
1972               /* Send resposne now if:
1973                   - enumeration is complete
1974                   - queue has enough instances to fill entire packet (by size or number)
1975 mike  1.1         - pull request arrives. Normally, network is lsower than providers,
1976                       so once client returns with next pull request, lets send all messages
1977                       we have in queue
1978                   - server is stressed (too many instances)
1979               */
1980               if (selfEC->enumerationCompleted ||
1981                   WSMAN_APROX_ENUM_RESP_HEADER_SIZE + selfEC->totalResponseSize > selfEC->activeConnection->wsheader.maxEnvelopeSize ||
1982                   selfEC->totalResponses >= selfEC->activeConnection->u.wsenumpullbody.maxElements ||
1983                   (attachingPullRequest && selfEC->head) ||
1984                   (Selector_IsStressed(self->selector) && selfEC->head)
1985                   )
1986               //if (selfEC->enumerationCompleted || selfEC->head)
1987               {
1988                   //LOGW_CHAR(("processing responses %d", selfEC->totalResponses));
1989           
1990                   _SendEnumPullResponse(self, selfEC);
1991                   _EC_SetActiveConnection(selfEC, 0);
1992               }
1993           
1994               /* release context if last message was sent */
1995               if (selfEC->enumerationCompleted && !selfEC->head)
1996 mike  1.1     {
1997                   _EC_SetActiveConnection(selfEC, 0);
1998                   _WSMAN_ReleaseEnumerateContext(self, selfEC->enumerationContextID);
1999                   selfEC = 0;
2000               }
2001               else
2002               {
2003                   /* set/update timer */
2004                   _WSMAN_SetUpdateTimer(self, selfEC);
2005               }
2006           
2007               return MI_TRUE;
2008           }
2009           
2010           static void _ProcessResultEnumerationContext(
2011               WSMAN* self,
2012               WSMAN_EnumerateContext* selfEC,
2013               PostResultMsg* message )
2014           {
2015               /* mark context as 'completed' */
2016               selfEC->enumerationCompleted = MI_TRUE;
2017 mike  1.1     selfEC->finalResult = message->result;
2018               //ATTN!: process error text/messages
2019           
2020               _ProcessEnumResponse(self, selfEC, MI_FALSE);
2021           
2022               /* release context */
2023               _EC_Release(selfEC, MI_FALSE);
2024           }
2025           
2026           
2027           static void _ProcessInstanceResponse(
2028               WSMAN* self,
2029               WSMAN_ConnectionData* selfCD,
2030               PostInstanceMsg* message)
2031           {
2032               /* send appropriate response */
2033               switch (selfCD->wsheader.rqtAction)
2034               {
2035               case 0: /* since invoke does not have strict URI, we got it as 'undefined' */
2036                   _SendInvokeResponse(self, selfCD, message);
2037                   break;
2038 mike  1.1 
2039               case WSMANTAG_ACTION_GET:
2040                   _SendSingleInstanceResponse(self, selfCD, message, LIT(T("http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse")));
2041                   break;
2042           
2043               case WSMANTAG_ACTION_PUT:
2044                   _SendSingleInstanceResponse(self, selfCD, message, LIT(T("http://schemas.xmlsoap.org/ws/2004/09/transfer/PutResponse")));
2045                   break;
2046           
2047               case WSMANTAG_ACTION_CREATE:
2048                   _SendSingleInstanceResponse(self, selfCD, message, LIT(T("http://schemas.xmlsoap.org/ws/2004/09/transfer/CreateResponse")));
2049                   break;
2050           
2051               default:
2052                   /* unexpected */
2053                   _SendFaultResponse(
2054                       self->http, 
2055                       selfCD, 
2056                       WSBUF_FAULT_INTERNAL_ERROR, 
2057                       T("unexpected internal state"));
2058                   break;
2059 mike  1.1     }
2060               selfCD->outstandingRequest = MI_FALSE;
2061           }
2062           
2063           static void _ProcessResultConnectionData(
2064               WSMAN* self,
2065               WSMAN_ConnectionData* selfCD,
2066               PostResultMsg* message )
2067           {
2068               /* if response was not sent yet, send it now (error probably) */
2069               if (selfCD->outstandingRequest)
2070               {
2071                   if (selfCD->single_message)
2072                   {
2073                       _ProcessInstanceResponse(self, selfCD, selfCD->single_message);
2074                   }
2075                   else if (MI_RESULT_OK == message->result &&
2076                       WSMANTAG_ACTION_DELETE == selfCD->wsheader.rqtAction)
2077                   {
2078                       _SendDeleteInstanceResponse(self, selfCD);
2079                   }
2080 mike  1.1         else
2081                   {
2082                       _SendErrorResponse(self, selfCD, message->result);
2083                   }
2084           
2085                   selfCD->outstandingRequest = MI_FALSE;
2086               }
2087           
2088               /* release connection data */
2089               _CD_Release(selfCD);
2090           }
2091           
2092           static void _ProcessInstanceConnectionData(
2093               WSMAN* self,
2094               WSMAN_ConnectionData* selfCD,
2095               PostInstanceMsg* message)
2096           {
2097               MI_UNUSED(self);
2098           
2099               /* Ignore expired contexts */
2100               if (!selfCD->outstandingRequest)
2101 mike  1.1         return;
2102           
2103               _CD_SetSingleMessage(selfCD, message);
2104           }
2105           
2106           static void _ProcessInstanceEnumerationContext(
2107               WSMAN* self,
2108               WSMAN_EnumerateContext* selfEC,
2109               PostInstanceMsg* message )
2110           {
2111               /* Ignore expired contexts */
2112               if (selfEC->expired)
2113                   return;
2114           
2115               /* add-ref message to keep it alive */
2116               Message_AddRef( &message->base);
2117           
2118               /* Add it to the list to process when result is posted */
2119               List_Append(
2120                   (ListElem**)&selfEC->head, 
2121                   (ListElem**)&selfEC->tail, 
2122 mike  1.1         (ListElem*)message);
2123           
2124               /* Increment total instance size */
2125               selfEC->totalResponseSize += message->packedInstanceSize;
2126           
2127               /* Increment total number of responses */
2128               selfEC->totalResponses++;
2129           
2130               /* Check if we need to send response to the client */
2131               _ProcessEnumResponse(self, selfEC, MI_FALSE);
2132           }
2133           
2134           /* HTTP callbacks */
2135           static void _HttpCallbackOnNewConnection(
2136               Http* http,
2137               void* callbackData,
2138               void* httpConnectionHandle,
2139               void** connectionData)
2140           {
2141               WSMAN_ConnectionData* selfConnectionData;
2142               MI_UNUSED(http);
2143 mike  1.1     MI_UNUSED(callbackData);
2144           
2145               selfConnectionData = (WSMAN_ConnectionData*)calloc(1, sizeof(WSMAN_ConnectionData));
2146           
2147               if (!selfConnectionData)
2148                   return /*MI_RESULT_FAILED*/;
2149           
2150               selfConnectionData->httpConnectionHandle = httpConnectionHandle;
2151               selfConnectionData->refcounter = 1;
2152               selfConnectionData->tag = DATA_TAG_CONNECTION_DATA;
2153               *connectionData = selfConnectionData;
2154           }
2155           
2156           static void _HttpCallbackOnCloseConnection(
2157               Http* http,
2158               void* callbackData,
2159               void* connectionData)
2160           {
2161               MI_UNUSED(http);
2162               MI_UNUSED(callbackData);
2163           
2164 mike  1.1     if (connectionData)
2165               {
2166                   WSMAN_ConnectionData* selfConnectionData = (WSMAN_ConnectionData*)connectionData;
2167                   selfConnectionData->httpConnectionHandle = 0;
2168                   selfConnectionData->outstandingRequest = MI_FALSE;
2169           
2170                   _CD_Release(selfConnectionData);
2171               }
2172           }
2173           
2174           static void _HttpCallbackOnRequest(
2175               Http* http,
2176               void* callbackData,
2177               void* connectionData,
2178               void* httpConnectionHandle,
2179               const HttpHeaders* headers,
2180               Page** page)
2181           {
2182               WSMAN_ConnectionData* selfCD = (WSMAN_ConnectionData*)connectionData;
2183               WSMAN* self = (WSMAN*)callbackData;
2184               XML     xml = self->xml;
2185 mike  1.1 
2186               /* Trace the request XML */
2187           
2188               if (self->options.enableTracing)
2189               {
2190                   printf("%s\n\n", (const char*)((*page)+1));
2191               }
2192           
2193               /* Cleanup connection data, since it may still store allocated pointers 
2194                   from previous operation */
2195               _CD_Cleanup(selfCD);
2196           
2197               /* Verify content type */
2198               if ( !headers->contentType ||
2199                   (Strcasecmp(headers->contentType,"application/soap+xml") != 0 &&
2200                       Strcasecmp(headers->contentType,"text/xml") != 0))
2201               {
2202                   LOGW_CHAR(("wsman: invalid/missing content type in request [%s]", (const char*)((*page)+1) ));
2203                   Http_SendErrorResponse(http, httpConnectionHandle, HTTP_ERROR_CODE_BAD_REQUEST);
2204                   return;
2205               }
2206 mike  1.1 
2207               if (headers->charset &&
2208                   Strcasecmp(headers->charset,"utf-8") != 0)
2209               {
2210                   LOGW_CHAR(("wsman: charset is not supported [%s]", MI_GET_SAFE_PRINTF_STRING(headers->charset) ));
2211                   _SendFaultResponse(http, selfCD, WSBUF_FAULT_ENCODING_LIMIT, T("only utf 8 is supported"));
2212                   return;
2213               }
2214           
2215               if (!headers->username || !headers->password ||
2216                   0 != AuthenticateUser(headers->username, headers->password))
2217               {
2218                   LOGW_CHAR(("wsman: authentication failed for user [%s]", MI_GET_SAFE_PRINTF_STRING(headers->username) ));
2219                   Http_SendErrorResponse(http, httpConnectionHandle, HTTP_ERROR_CODE_UNAUTHORIZED);
2220                   return;
2221               }
2222           
2223               if (0 != LookupUser(headers->username, &selfCD->uid, &selfCD->gid))
2224               {
2225                   LOGW_CHAR(("wsman: get user [%s] uid/gid", MI_GET_SAFE_PRINTF_STRING(headers->username) ));
2226                   Http_SendErrorResponse(http, httpConnectionHandle, HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
2227 mike  1.1         return;
2228               }
2229           
2230               XML_SetText(&xml, (char*)((*page)+1) );
2231           
2232               /* Parse header */
2233               if (WS_ParseSoapEnvelope(&xml) != 0 || 
2234                   WS_ParseWSHeader(&xml, &selfCD->wsheader) != 0 ||
2235                   xml.status)
2236               {
2237                   LOGW_CHAR(("wsman: unable to parse incoming xml [%s] ", (const char*)((*page)+1) ));
2238                   Http_SendErrorResponse(http, httpConnectionHandle, HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR);
2239                   return;
2240               }
2241           
2242               /* Validate header */
2243               if (_ValidateHeader(http, selfCD) != 0)
2244               {
2245                   return;
2246               }
2247           
2248 mike  1.1     /* See if this is a Identify request */
2249           
2250               if (!selfCD->wsheader.foundAction)
2251               {
2252                   _HandleIdentifyRequest(
2253                       http, 
2254                       httpConnectionHandle, 
2255                       self, 
2256                       selfCD,
2257                       &xml);
2258                   return;
2259               }
2260           
2261               /* keep reference to the page to keep xml object/ cached strings like msgID valid */
2262               _CD_SetPage(selfCD, *page);
2263               *page = 0;
2264           
2265               selfCD->outstandingRequest = MI_TRUE;
2266           
2267               /* Parse body and send request to the dispatcher */
2268               switch (selfCD->wsheader.rqtAction)
2269 mike  1.1     {
2270                   case WSMANTAG_ACTION_ENUMERATE:
2271                   {
2272                       _ParseValidateProcessEnumerateRequest(http, httpConnectionHandle, self, selfCD, &xml);
2273                       break;
2274                   }
2275                   case WSMANTAG_ACTION_PULL:
2276                   {
2277                       _ParseValidateProcessPullRequest(http, httpConnectionHandle, self, selfCD, &xml);
2278                       break;
2279                   }
2280                   case WSMANTAG_ACTION_RELEASE:
2281                   {
2282                       _ParseValidateProcessReleaseRequest(http, httpConnectionHandle, self, selfCD, &xml);
2283                       break;
2284                   }
2285                   case WSMANTAG_ACTION_GET:
2286                   {
2287                       _ParseValidateProcessGetRequest(http, httpConnectionHandle, self, selfCD, &xml);
2288                       break;
2289                   }
2290 mike  1.1         case WSMANTAG_ACTION_PUT:
2291                   {
2292                       _ParseValidateProcessPutRequest(http, httpConnectionHandle, self, selfCD, &xml);
2293                       break;
2294                   }
2295                   case WSMANTAG_ACTION_DELETE:
2296                   {
2297                       _ParseValidateProcessDeleteRequest(http, httpConnectionHandle, self, selfCD, &xml);
2298                       break;
2299                   }
2300                   case WSMANTAG_ACTION_CREATE:
2301                   {
2302                       _ParseValidateProcessCreateRequest(http, httpConnectionHandle, self, selfCD, &xml);
2303                       break;
2304                   }
2305                   case 0: /* since invoke does not have strict URI, we got it as 'undefined' */
2306                   {
2307                       _ParseValidateProcessInvokeRequest(http, httpConnectionHandle, self, selfCD, &xml);
2308                       break;
2309                   }
2310                   default:
2311 mike  1.1         {
2312                       /* unsupported action */
2313                       LOGW_CHAR(("wsman: unsupported action [%d] ", selfCD->wsheader.rqtAction ));
2314                       _SendFaultResponse(http, selfCD, WSBUF_FAULT_NOT_SUPPORTED, 0);
2315                       selfCD->outstandingRequest = MI_FALSE;
2316                       break;
2317                   }
2318               }
2319           }
2320           
2321           /*
2322           **==============================================================================
2323           **
2324           ** Public definitions:
2325           **
2326           **==============================================================================
2327           */
2328           MI_Result WSMAN_New_Listener(
2329               WSMAN** selfOut,
2330               Selector* selector, /*optional, maybe NULL*/
2331               unsigned short http_port,   /* 0 to disable */
2332 mike  1.1     unsigned short https_port,  /* 0 to disable */
2333               WSMANCallback callback,
2334               void* callbackData)
2335           {
2336               WSMAN* self;
2337               MI_Result r;
2338           
2339               /* Check parameters */
2340               if (!selfOut)
2341                   return MI_RESULT_INVALID_PARAMETER;
2342           
2343               /* Clear output parameter */
2344               *selfOut = NULL;
2345           
2346               /* Allocate structure */
2347               {
2348                   self = (WSMAN*)calloc(1, sizeof(WSMAN));
2349           
2350                   if (!self)
2351                       return MI_RESULT_FAILED;
2352               }
2353 mike  1.1 
2354               /* Save the callback and callbackData */
2355               self->callback = callback;
2356               self->callbackData = callbackData;
2357           
2358               /*ATTN! slector can be null!*/
2359               self->selector = selector;
2360           
2361               /* options */
2362               {
2363                   WSMAN_Options options = DEFAULT_WSMAN_OPTIONS;
2364           
2365                   self->options = options;
2366               }
2367           
2368               /* Set the magic number */
2369               self->magic = _MAGIC;
2370           
2371               /* create a server */
2372               r = Http_New_Server(
2373                   &self->http, selector, http_port, https_port,
2374 mike  1.1         _HttpCallbackOnNewConnection,
2375                   _HttpCallbackOnCloseConnection,
2376                   _HttpCallbackOnRequest, self);
2377           
2378               if (MI_RESULT_OK != r)
2379               {
2380                   WSMAN_Delete(self);
2381                   return r;
2382               }
2383           
2384               /* Initialize xml parser */
2385               XML_Init(&self->xml);
2386           
2387               XML_RegisterNameSpace(&self->xml, 's', 
2388                   "http://www.w3.org/2003/05/soap-envelope");
2389           
2390               XML_RegisterNameSpace(&self->xml, 'a', 
2391                   "http://schemas.xmlsoap.org/ws/2004/08/addressing");
2392           
2393               XML_RegisterNameSpace(&self->xml, 'w', 
2394                   "http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd");
2395 mike  1.1 
2396               XML_RegisterNameSpace(&self->xml, 'n', 
2397                   "http://schemas.xmlsoap.org/ws/2004/09/enumeration");
2398           
2399               XML_RegisterNameSpace(&self->xml, 'b', 
2400                   "http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd");
2401           
2402               XML_RegisterNameSpace(&self->xml, 'p', 
2403                   "http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd");
2404           
2405               XML_RegisterNameSpace(&self->xml, 'i',
2406                   "http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd");
2407           
2408               *selfOut = self;
2409           
2410               return MI_RESULT_OK;
2411           }
2412           
2413           MI_Result WSMAN_Delete(
2414               WSMAN* self)
2415           {
2416 mike  1.1     /* Check parameters */
2417               if (!self)
2418                   return MI_RESULT_INVALID_PARAMETER;
2419           
2420               /* Check magic number */
2421               if (self->magic != _MAGIC)
2422                   return MI_RESULT_INVALID_PARAMETER;
2423           
2424               Http_Delete(self->http);
2425           
2426               /* clear all outstanding contexts */
2427               _WSMAN_ReleaseAllEnumerateContexts(self);
2428           
2429               /* Clear magic number */
2430               self->magic = 0xDDDDDDDD;
2431           
2432               /* Free self pointer */
2433               free(self);
2434           
2435               return MI_RESULT_OK;
2436           }
2437 mike  1.1 
2438           MI_Result WSMAN_Run(
2439               WSMAN* self,
2440               MI_Uint64 timeoutUsec)
2441           {
2442               /* Run the selector */
2443               return Http_Run(self->http, timeoutUsec);
2444           }
2445           
2446           static MI_Result _SendIN_IO_thread(
2447               void* self_,
2448               Message* message)
2449           {
2450               WSMAN* self = (WSMAN*)self_;
2451               WSMAN_ConnectionData* selfCD = 0;
2452               WSMAN_EnumerateContext* selfEC = 0;
2453           
2454               /* check params */
2455               if (!self || !message )
2456                   return MI_RESULT_INVALID_PARAMETER;
2457           
2458 mike  1.1     if (self->magic != _MAGIC)
2459               {
2460                   LOGW((T("_SendIN_IO_thread: invalid magic!") ));
2461                   return MI_RESULT_INVALID_PARAMETER;
2462               }
2463           
2464               /* find where to send it */
2465               selfCD = (WSMAN_ConnectionData*)Uint64ToPtr(message->clientID);
2466               selfEC = (WSMAN_EnumerateContext*)Uint64ToPtr(message->clientID);
2467           
2468               if (selfCD && selfCD->tag != DATA_TAG_CONNECTION_DATA)
2469               {
2470                   selfCD = 0;
2471               }
2472               if (selfEC && selfEC->tag != DATA_TAG_ENUMERATION_CONTEXT)
2473               {
2474                   selfEC = 0;
2475               }
2476               if (!selfCD && !selfEC)
2477               {
2478                   LOGW((T("_SendIN_IO_thread: clientID!") ));
2479 mike  1.1         return MI_RESULT_INVALID_PARAMETER;
2480               }
2481           
2482               /* ATTN! validate handler */
2483           
2484               /* Process response message */
2485               switch (message->tag)
2486               {
2487               case PostResultMsgTag:
2488                   if (selfCD)
2489                       _ProcessResultConnectionData(self, selfCD, (PostResultMsg*)message );
2490                   else
2491                       _ProcessResultEnumerationContext(self, selfEC, (PostResultMsg*)message );
2492           
2493                   break;
2494           
2495               case PostInstanceMsgTag:
2496                   if (selfCD)
2497                       _ProcessInstanceConnectionData(self, selfCD, (PostInstanceMsg*)message );
2498                   else
2499                       _ProcessInstanceEnumerationContext(self, selfEC, (PostInstanceMsg*)message );
2500 mike  1.1 
2501                   break;
2502           
2503               default:
2504                   LOGW((T("wsman: _SendIN_IO_thread: unexpected message tag %d"), message->tag ));
2505                   return MI_RESULT_INVALID_PARAMETER;
2506               }
2507           
2508               return MI_RESULT_OK;
2509           }
2510           
2511           /* Signature must not have return type so we created this wrapper */
2512           static void _SendIN_IO_thread_wrapper(void* self, Message* message)
2513           {
2514               MI_Result r;
2515               r = _SendIN_IO_thread(self, message);
2516           
2517               /* ATTN: log failed result? */
2518           }
2519           
2520           
2521 mike  1.1 MI_Result WSMAN_Send(
2522               WSMAN* self,
2523               Message* message)
2524           {
2525               return Selector_CallInIOThread(
2526                   self->selector, _SendIN_IO_thread_wrapper, self, message );
2527           }
2528           
2529           MI_Result WSMAN_SetOptions(
2530               WSMAN* self,
2531               const WSMAN_Options* options)
2532           {
2533               /* check params */
2534               if (!self || !options)
2535                   return MI_RESULT_INVALID_PARAMETER;
2536           
2537               /* Check magic number */
2538               if (self->magic != _MAGIC)
2539               {
2540                   LOGW((T("invalid magic!") ));
2541                   return MI_RESULT_INVALID_PARAMETER;
2542 mike  1.1     }
2543           
2544               self->options = *options;
2545               return MI_RESULT_OK;
2546           }

ViewCVS 0.9.2