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

   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 krisbash 1.4 #include <pal/strings.h>
  26              #include <pal/format.h>
  27 mike     1.1 #include <base/messages.h>
  28 krisbash 1.4 #include <base/Strand.h>
  29 mike     1.1 #include <base/log.h>
  30              #include <base/paths.h>
  31 krisbash 1.4 #include <pal/hashmap.h>
  32              #include <base/naming.h>
  33 mike     1.1 #include <wql/wql.h>
  34              #include "disp.h"
  35 krisbash 1.4 #include <omi_error/errorutil.h>
  36 mike     1.1 
  37 krisbash 1.4 /*
  38              **==============================================================================
  39              */
  40              
  41              #define DISPENUMPARENT_STRANDAUX_ENUMDONE      0
  42              
  43              STRAND_DEBUGNAME1( DispEnumParent, EnumDone );
  44              STRAND_DEBUGNAME( DispEnumEntry );
  45 mike     1.1 
  46              /*
  47              **==============================================================================
  48              **
  49 mike     1.2 ** ClassName hash implementation
  50              **
  51              **==============================================================================
  52              */
  53              
  54              typedef struct _ClassNameBucket /* derives from HashBucket */
  55              {
  56                  struct _ClassNameBucket* next;
  57 krisbash 1.4     ZChar* key;
  58 mike     1.2 }
  59              ClassNameBucket;
  60              
  61              static size_t ClassNameHash(
  62                  const HashBucket* bucket_)
  63              {
  64                  /* Note: this algorithm has a poor distribution */
  65                  ClassNameBucket* bucket = (ClassNameBucket*)bucket_;
  66                  size_t h = 0;
  67 krisbash 1.4     ZChar* key = bucket->key;
  68 mike     1.2 
  69                  while (*key)
  70                  {
  71                      h += 5 * *key++;
  72                  }
  73              
  74                  return h;
  75              }
  76              
  77              static int ClassNameEqual(
  78                  const HashBucket* bucket1_,
  79                  const HashBucket* bucket2_)
  80              {
  81                  ClassNameBucket* bucket1 = (ClassNameBucket*)bucket1_;
  82                  ClassNameBucket* bucket2 = (ClassNameBucket*)bucket2_;
  83 krisbash 1.4     return Tcscasecmp(bucket1->key, bucket2->key) == 0;
  84 mike     1.2 }
  85              
  86              static void ClassNameRelease(
  87                  HashBucket* bucket_)
  88              {
  89                  ClassNameBucket* bucket = (ClassNameBucket*)bucket_;
  90              
  91 krisbash 1.4     PAL_Free(bucket->key);
  92                  PAL_Free(bucket);
  93 mike     1.2 }
  94              
  95              /*
  96              **==============================================================================
  97              **
  98 krisbash 1.4 ** Local definitions
  99 mike     1.1 **
 100              **==============================================================================
 101              */
 102              
 103 krisbash 1.4 typedef struct _DispEnumParent
 104              {
 105                  StrandMany              strand;
 106                  Disp*                   disp;
 107                  RequestMsg*             baseRequest;
 108                  MI_Result               result;
 109                  MI_Boolean              done;
 110              }
 111              DispEnumParent;
 112              
 113              typedef struct _EnumEntry EnumEntry;
 114              
 115              struct _EnumEntry
 116              {
 117                  StrandEntry             strand;
 118                  const ZChar*            className;
 119                  EnumEntry*              next;       // Links the entries that are about to be dispatched
 120                                                      // We cannot use list on StrandMany as that one can get modify in the meantime 
 121                                                      // as the interactions are being dinamically closed themselves
 122                                                      // (that is why that list requires to be in the strand to use it)
 123              };
 124 krisbash 1.4 
 125              MI_INLINE void _DispEnumParent_Delete(
 126                  _In_ DispEnumParent* self)
 127              {
 128                  trace_DispDeleteInteraction(self);
 129                  Message_Release( &self->baseRequest->base );
 130                  StrandMany_Delete(&self->strand);
 131              }
 132              
 133              // interaction is already opened, we can have left the Strand or not indicated by leftStrand
 134              static void _SendErrorResponse_Opened(
 135                  _Inout_ InteractionOpenParams* interactionParams, 
 136                  _In_ DispEnumParent* self,
 137                  _In_ MI_Result r,
 138                  MI_Boolean leftStrand
 139                  )
 140 mike     1.1 {
 141 krisbash 1.4     PostResultMsg* openResp = PostResultMsg_NewAndSerialize( &self->baseRequest->base, NULL, NULL, MI_RESULT_TYPE_MI, r);
 142 mike     1.1 
 143 krisbash 1.4     if( openResp )
 144                  {
 145                      if( leftStrand )
 146                      {
 147                          StrandMany_SchedulePost( &self->strand, &openResp->base );
 148                          StrandMany_ScheduleClose( &self->strand ); 
 149                      }
 150                      else
 151                      {
 152                          Strand_Post( &self->strand.strand, &openResp->base );
 153                          Strand_Close( &self->strand.strand ); 
 154                          Strand_Leave( &self->strand.strand );
 155                      }
 156                      PostResultMsg_Release(openResp);
 157                  }
 158                  else
 159                  {
 160                      // delete the object directly
 161                      _DispEnumParent_Delete( self );
 162                      
 163                      interactionParams->msg = NULL;  // Null this out since we have already sent an Ack
 164 krisbash 1.4         interactionParams->origin= NULL;  // Null this out since we have already left origin strand
 165                      Strand_FailOpenWithResult(interactionParams, r, PostResultMsg_NewAndSerialize);
 166                  }
 167              }
 168 mike     1.1 
 169 krisbash 1.4 static void _DispEnumParent__SendLastResponse(
 170                  _In_ DispEnumParent* interaction
 171                  )
 172              {
 173                  PostResultMsg* resp;
 174 mike     1.1 
 175 krisbash 1.4     resp = PostResultMsg_NewAndSerialize(&interaction->baseRequest->base, NULL, NULL, MI_RESULT_TYPE_MI, interaction->result);
 176                  if( resp )
 177                  {
 178                      Strand_Post( &interaction->strand.strand, &resp->base );
 179                      Message_Release(&resp->base);
 180                  }
 181 mike     1.1 
 182 krisbash 1.4     Strand_Close( &interaction->strand.strand ); 
 183              }
 184 mike     1.1 
 185 krisbash 1.4 static void _DispEnumParent_Transport_Post( _In_ Strand* self_, _In_ Message* msg)
 186              {
 187                  DEBUG_ASSERT( MI_FALSE );  // we dont expect any additional messages at this point
 188 mike     1.1 }
 189              
 190 krisbash 1.4 static void _DispEnumParent_Transport_PostControl( _In_ Strand* self, _In_ Message* msg)
 191 mike     1.1 {
 192 krisbash 1.4     DEBUG_ASSERT( MI_FALSE );  // not used yet
 193 mike     1.1 }
 194              
 195 krisbash 1.4 static void _DispEnumParent_Transport_Cancel( _In_ Strand* self)
 196 mike     1.1 {
 197 krisbash 1.4     // not used yet
 198 mike     1.1 }
 199              
 200 krisbash 1.4 static void _DispEnumParent_Finished( _In_ Strand* self_)
 201 mike     1.1 {
 202 krisbash 1.4     DispEnumParent* self = (DispEnumParent*)StrandMany_FromStrand(self_);
 203                  _DispEnumParent_Delete( self );
 204 mike     1.1 }
 205              
 206 krisbash 1.4 //DISPENUMPARENT_STRANDAUX_ENUMDONE
 207              static void _DispEnumParent_EnumDone( _In_ Strand* self_)
 208 mike     1.1 {
 209 krisbash 1.4     DispEnumParent* self = (DispEnumParent*)StrandMany_FromStrand(self_);
 210 mike     1.1 
 211 krisbash 1.4     trace_DispEnumDone(self, self->strand.numEntries, self->result );
 212              
 213                  self->done = MI_TRUE;
 214                  
 215                  if( 0 == self->strand.numEntries )
 216 mike     1.1     {
 217 krisbash 1.4         _DispEnumParent__SendLastResponse( self );
 218 mike     1.1     }
 219              }
 220              
 221 krisbash 1.4 /*
 222                  This object manages a a "Parent" enumeration on the dispatcher level.
 223                  Enumerations in this context include also Associations and References.
 224                  The dispatcher converts that parent enumertion coming from the client
 225                  into several actual child enumerations that can go to the same or different providers
 226                  for each of those child enumerations a "EnumEntry" object (see more info below) will be 
 227                  created and attached to this Parent enumeration using the one-to-many 
 228                  strand interface (StrandMany).
 229              
 230                  Behavior:
 231                  - Post and PostControl are not used yet as no secondary messages after
 232                     initial request are issued currently
 233                  - Cancel is also not implememented as Cancelation e2e is not implemented
 234                  - Shutdown: 
 235                     once all the child enumerations have been issued DISPENUMPARENT_STRANDAUX_ENUMDONE
 236                     is scheduled on the parent, what in turn set the done flag to true and sends the last response 
 237                     (final result) to the transport. That would happen if all the enumerations ran in the same thread 
 238                     as by that point all of them would have completed. However if one or more enumerations
 239                     are run in the own thread (by the provider or out-of-proc) then may not be completed
 240                     at that point and then the sending of last response and shutdown will occur once
 241                     the last enumeration is closed and deleted and the parent is notified on
 242 krisbash 1.4        _DispEnumParent_Entry_Deleted (implemented below on the internal FT)
 243              
 244                  Internal interface and unique features:
 245                  - When a message is sent internally (from EnumEntry) it is just sent pass
 246                     thru to the transport EXCEPT if it is a PostResultMsg as in that case the result
 247                     is just stored internally (if it is not success) as we are only returning one single
 248                     result to the parent interaction (managed on _DispEnumParent_Entry_Post below)
 249              */
 250              static StrandFT _DispEnumParent_TransportFT = { 
 251                  _DispEnumParent_Transport_Post, 
 252                  _DispEnumParent_Transport_PostControl, 
 253                  NULL, 
 254                  _DispEnumParent_Transport_Cancel, 
 255                  NULL,
 256                  _DispEnumParent_Finished,
 257                  NULL,
 258                  _DispEnumParent_EnumDone,
 259                  NULL,
 260                  NULL,
 261                  NULL,
 262                  NULL };
 263 krisbash 1.4 
 264              static void _DispEnumEntry_Provider_PostControl( _In_ Strand* self, _In_ Message* msg)
 265              {
 266                  DEBUG_ASSERT( MI_FALSE );  // not used yet
 267              }
 268 mike     1.1 
 269 krisbash 1.4 static void _DispEnumEntry_Provider_Close( _In_ Strand* self )
 270 mike     1.1 {
 271 krisbash 1.4     if(!self->info.thisClosedOther)
 272 mike     1.1     {
 273 krisbash 1.4         // Just close back
 274                      Strand_Close( self );
 275 mike     1.1     }
 276              }
 277              
 278 krisbash 1.4 /*
 279                  This object manages the interaction wich each particular provider enumeration
 280                  that a parent provider is divided into (see more info above on _DispEnumParent_TransportFT)
 281 mike     1.1 
 282 krisbash 1.4     Behavior:
 283                  - PostControl is not used yet
 284                  - Posts are just passed pass thru (and acks are managed by StrandMany)
 285                  - Shutdown: once the provider side closes the interaction this object closes the
 286                     interaction back what will trigger automatically deletion of the object
 287              */
 288              static StrandFT _DispEnumEntry_ProviderFT = { 
 289                  NULL, 
 290                  _DispEnumEntry_Provider_PostControl, 
 291                  NULL, 
 292                  NULL, 
 293                  _DispEnumEntry_Provider_Close,
 294                  NULL,
 295                  NULL,
 296                  NULL,
 297                  NULL,
 298                  NULL,
 299                  NULL,
 300                  NULL };
 301                  
 302              static void _DispEnumParent_Entry_Deleted( _In_ StrandMany* self_ )
 303 mike     1.1 {
 304 krisbash 1.4     DispEnumParent* self = (DispEnumParent*)self_;
 305 mike     1.1 
 306 krisbash 1.4     DEBUG_ASSERT( NULL != self );
 307 mike     1.1 
 308 krisbash 1.4     trace_DispEntryDeleted(self, self->strand.numEntries, self->done );
 309 mike     1.1 
 310 krisbash 1.4     if( self->done && 0 == self->strand.numEntries )
 311                  {
 312                      _DispEnumParent__SendLastResponse( self );
 313 mike     1.1     }
 314              }
 315              
 316 krisbash 1.4 static void _DispEnumParent_Entry_Post( _In_ StrandMany* self_, _In_ Message* msg)
 317 mike     1.1 {
 318 krisbash 1.4     DispEnumParent* self = (DispEnumParent*)self_;
 319 mike     1.1 
 320 krisbash 1.4     DEBUG_ASSERT( NULL != self );
 321                  
 322                  trace_DispPostingMessage( self->strand.strand.info.interaction.other, self_);
 323 mike     1.1 
 324 krisbash 1.4     if( PostResultMsgTag == msg->tag )
 325 mike     1.1     {
 326 krisbash 1.4         PostResultMsg* rsp = (PostResultMsg*)msg;
 327 mike     1.1 
 328 krisbash 1.4         if( MI_RESULT_OK != rsp->result && MI_RESULT_OK == self->result )
 329 mike     1.1         {
 330 krisbash 1.4             self->result = rsp->result;
 331 mike     1.1         }
 332              
 333 krisbash 1.4         // This is not posted here
 334                  }
 335                  else
 336                  {
 337                      Strand_Post( &self->strand.strand, msg );
 338 mike     1.1     }
 339              }
 340              
 341 krisbash 1.4 // used for enums, associators, references and subcriptions
 342              static StrandManyInternalFT _DispEnumParent_InternalFT = { 
 343                  NULL,
 344                  _DispEnumParent_Entry_Deleted,
 345                  _DispEnumParent_Entry_Post, 
 346                  NULL, 
 347                  NULL, 
 348                  NULL, 
 349                  NULL,
 350                  NULL,
 351                  NULL,
 352                  NULL };
 353                      
 354              static MI_Result _DispatchEnumerateInstancesReq(
 355                  _In_ Disp* disp,
 356                  _In_ EnumerateInstancesReq* request,
 357                  _In_ const ZChar* className, 
 358                  _In_opt_ EnumEntry* enumEntry,
 359                  _In_opt_ InteractionOpenParams* interactionParams )
 360 mike     1.1 {
 361 krisbash 1.4     const ProvRegEntry* provEntry;
 362                  MI_Result result;
 363                  EnumerateInstancesReq* msg;
 364                  AgentMgr_OpenCallbackData openCallbackData;
 365 mike     1.1 
 366 krisbash 1.4     DEBUG_ASSERT( NULL != className );
 367                  
 368                  /* Attempt to find a provider for this class */
 369                  provEntry = ProvReg_FindProviderForClass(&disp->provreg, 
 370                      request->nameSpace, className, &result );
 371 mike     1.1 
 372 krisbash 1.4     if (!provEntry)
 373                  {
 374                      return MI_RESULT_NOT_SUPPORTED;
 375                  }
 376 mike     1.1 
 377 krisbash 1.4     /* Create new request to send to provider */
 378                  msg = EnumerateInstancesReq_New(request->base.base.operationId, request->base.base.flags);
 379                  if( NULL == msg )
 380                  {
 381                      trace_DispatchEnumerateInstancesReq_OutOfMemory();
 382                      return MI_RESULT_SERVER_LIMITS_EXCEEDED;
 383                  }
 384                  
 385                  msg->base.options = request->base.options;
 386                  AuthInfo_Copy( &msg->base.authInfo, &request->base.authInfo );
 387                  msg->nameSpace = Batch_Tcsdup(msg->base.base.batch, request->nameSpace);
 388                  msg->className = Batch_Tcsdup(msg->base.base.batch, className);
 389                  msg->base.userAgent = request->base.userAgent;
 390 mike     1.1 
 391 krisbash 1.4     if (!msg->nameSpace || !msg->className)
 392 mike     1.1     {
 393 krisbash 1.4         goto OutOfMemory;
 394 mike     1.1     }
 395              
 396 krisbash 1.4     /* Clone the query fields (if any) */
 397                  if (request->queryLanguage)
 398 mike     1.1     {
 399 krisbash 1.4         msg->queryLanguage = Batch_Tcsdup(msg->base.base.batch, request->queryLanguage);
 400                      if (!msg->queryLanguage)
 401                      {
 402                          goto OutOfMemory;
 403                      }
 404 mike     1.1     }
 405              
 406 krisbash 1.4     if( request->queryExpression )
 407 mike     1.1     {
 408 krisbash 1.4         msg->queryExpression = Batch_Tcsdup(msg->base.base.batch,request->queryExpression);
 409                      if (!msg->queryExpression)
 410 mike     1.1         {
 411 krisbash 1.4             goto OutOfMemory;
 412 mike     1.1         }
 413                  }
 414 krisbash 1.4     
 415                  /* Save request's class name to allow provmgr pack back only base properties */
 416                  if( request->basePropertiesOnly )
 417 mike     1.1     {
 418 krisbash 1.4         msg->requestClassName = Batch_Tcsdup(msg->base.base.batch, request->className);
 419                      if (!msg->requestClassName)
 420                      {
 421                          goto OutOfMemory;
 422                      }
 423 mike     1.1     }
 424              
 425 krisbash 1.4     openCallbackData.self = &disp->agentmgr;
 426                  openCallbackData.proventry = provEntry;
 427                  
 428                  if( NULL != enumEntry )
 429                  {
 430                      trace_DispatchEnumDispInteraction(tcs(className));
 431 mike     1.1 
 432 krisbash 1.4         /* Send the request to provider manager */
 433                      Strand_Open( &enumEntry->strand.strand, AgentMgr_OpenCallback, &openCallbackData, &msg->base.base, MI_TRUE );
 434                  }
 435                  else
 436 mike     1.1     {
 437 krisbash 1.4         DEBUG_ASSERT( NULL != interactionParams );
 438                      
 439                      // send it directly to AgentMgr
 440                      interactionParams->callbackData = &openCallbackData;
 441                      interactionParams->msg = &request->base.base;
 442                      
 443                      trace_DispatchEnumDirectly(tcs(className));
 444                      
 445                      AgentMgr_OpenCallback( interactionParams );
 446 mike     1.1     }
 447              
 448                  /* Release the original message */
 449                  EnumerateInstancesReq_Release(msg);
 450              
 451 krisbash 1.4     return MI_RESULT_OK;
 452 mike     1.1 
 453 krisbash 1.4 OutOfMemory:
 454                  trace_DispatchEnumerateInstancesReq_OutOfMemory();
 455                  EnumerateInstancesReq_Release(msg);
 456                  
 457                  return MI_RESULT_SERVER_LIMITS_EXCEEDED;
 458 mike     1.1 }
 459              
 460 krisbash 1.4 // Also used for References
 461 mike     1.1 static MI_Boolean _DispatchAssocReq(
 462 krisbash 1.4     _In_ Disp* disp,
 463                  _In_ AssociationsOfReq* req,
 464                  _In_ EnumEntry* enumEntry,
 465                  MessageTag tag )
 466 mike     1.1 {
 467                  const ProvRegEntry* entry;
 468 krisbash 1.4     AssociationsOfReq* msg;
 469                  const ZChar* className = enumEntry->className;
 470                  MI_Result result;
 471                  AgentMgr_OpenCallbackData openCallbackData;
 472 mike     1.2 
 473 mike     1.1     /* Attempt to find a provider for this class */
 474 krisbash 1.4     entry = ProvReg_FindProviderForClass(&disp->provreg, 
 475                      req->nameSpace, className, &result );
 476              
 477                  if (!entry)
 478 mike     1.1     {
 479 krisbash 1.4         trace__DispatchAssocReq_OutOfMemory();
 480                      return MI_FALSE;
 481 mike     1.1     }
 482              
 483                  /* Create new request to send to provider */
 484 krisbash 1.4     msg = AssociationsOfReq_New(req->base.base.operationId, req->base.base.flags, tag);
 485                  msg->base.options = req->base.options;
 486                  AuthInfo_Copy( &msg->base.authInfo, &req->base.authInfo );
 487 mike     1.1     /* original request will be kept for the request duration, so perform shallow copy only */
 488                  msg->nameSpace = req->nameSpace;
 489                  msg->assocClass = req->assocClass;
 490                  msg->resultClass = req->resultClass;
 491                  msg->role = req->role;
 492                  msg->resultRole = req->resultRole;
 493                  msg->instance = req->instance;
 494                  msg->packedInstancePtr = req->packedInstancePtr;
 495                  msg->packedInstanceSize = req->packedInstanceSize;
 496 krisbash 1.4     msg->base.userAgent = req->base.userAgent;
 497 mike     1.1 
 498 krisbash 1.4     msg->className = Batch_Tcsdup(msg->base.base.batch, className);
 499 mike     1.1 
 500 krisbash 1.4     trace_DispatchAssoc(tcs(className));
 501                   
 502                  /* Send the request to provider manager */
 503                  openCallbackData.self = &disp->agentmgr;
 504                  openCallbackData.proventry = entry;
 505                  Strand_Open( &enumEntry->strand.strand, AgentMgr_OpenCallback, &openCallbackData, &msg->base.base, MI_TRUE );
 506 mike     1.1 
 507 krisbash 1.4     /* Release the original message */
 508                  AssociationsOfReq_Release(msg);
 509 mike     1.1 
 510 krisbash 1.4     return MI_TRUE;
 511              }
 512 mike     1.1 
 513 krisbash 1.4 DispEnumParent* _DispEnumParent_New(
 514                  _In_ Disp*                  disp,
 515                  _In_ InteractionOpenParams* interactionParams )
 516              {
 517                  DispEnumParent* self;
 518              
 519                  self = (DispEnumParent*)StrandMany_New(
 520                              STRAND_DEBUG( DispEnumParent )
 521                              &_DispEnumParent_TransportFT,
 522                              &_DispEnumParent_InternalFT, 
 523                              sizeof( DispEnumParent ),
 524                              STRAND_FLAG_ENTERSTRAND,
 525                              interactionParams,
 526                              1,
 527                              NULL,
 528                              NULL,
 529                              NULL);
 530 mike     1.1 
 531 krisbash 1.4     if(self)
 532 mike     1.1     {
 533 krisbash 1.4         RequestMsg* req = (RequestMsg*)interactionParams->msg;
 534                      DEBUG_ASSERT( NULL != req );
 535 mike     1.1         
 536 krisbash 1.4         Message_AddRef( &req->base );
 537                      self->baseRequest = req;
 538              
 539                      self->disp = disp;
 540                      self->result = MI_RESULT_OK;
 541              
 542                      // As soon as we accept the open we can send the open msg ack
 543                      Strand_Ack( &self->strand.strand );
 544 mike     1.1     }
 545 krisbash 1.4     
 546                  return self;
 547 mike     1.1 }
 548              
 549 krisbash 1.4 static MI_Result _HandleGetInstanceReq(
 550                  _In_ Disp* self,
 551                  _Inout_ InteractionOpenParams* interactionParams, 
 552                  _In_ GetInstanceReq* req)
 553 mike     1.1 {
 554                  MI_Result r;
 555 krisbash 1.4     const ProvRegEntry* reg;
 556 mike     1.1 
 557 krisbash 1.4     /* Validate input parameters */
 558                  if (!req->instanceName || !req->nameSpace)
 559                      return MI_RESULT_INVALID_PARAMETER;
 560 mike     1.1 
 561 krisbash 1.4     // Find a provider for this class.
 562                  reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace, 
 563                      req->instanceName->classDecl->name, &r );
 564 mike     1.1 
 565 krisbash 1.4     if (!reg)
 566                  {
 567                      trace_NoProviderForClass(
 568                          req->nameSpace,
 569                          req->instanceName->classDecl->name);
 570                      goto sendErrorBack;
 571                  }
 572 mike     1.1 
 573 krisbash 1.4     // Send the request to provider manager.
 574                  r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, reg);
 575 mike     1.1 
 576                  if (r != MI_RESULT_OK)
 577                  {
 578 krisbash 1.4         trace_AgentMgrHandleRequestForNS(
 579                          req->nameSpace);
 580                      goto sendErrorBack;
 581 mike     1.1     }
 582              
 583 krisbash 1.4     return MI_RESULT_OK;
 584 mike     1.1 
 585 krisbash 1.4 sendErrorBack:
 586                  // Just abort creating any interaction at all
 587                  return r;
 588 mike     1.1 }
 589              
 590 krisbash 1.4 static MI_Result _HandleGetClassReq(
 591                  _In_ Disp* self,
 592                  _Inout_ InteractionOpenParams* interactionParams,     
 593                  _In_ GetClassReq* req)
 594 mike     1.1 {
 595 krisbash 1.4     MI_Result r;
 596                  const ProvRegEntry* reg;
 597                  ProvRegEntry freg;
 598 mike     1.1     ProvRegPosition pos;
 599              
 600                  /* Validate input parameters */
 601                  if (!req->className || !req->nameSpace)
 602                      return MI_RESULT_INVALID_PARAMETER;
 603              
 604 krisbash 1.4     // client must specify classname for GetClass request
 605                  if(Tcscmp(req->className, PAL_T("*")) == 0)
 606                      return MI_RESULT_INVALID_CLASS;
 607 mike     1.1 
 608 krisbash 1.4     memset( &freg, 0, sizeof(freg) );
 609 mike     1.1 
 610 krisbash 1.4     // Find a provider for this class.
 611                  reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace, 
 612                      req->className, &r );
 613 mike     1.1 
 614 krisbash 1.4     if (!reg)
 615 mike     1.1     {
 616 krisbash 1.4         if(MI_RESULT_INVALID_CLASS == r)
 617 mike     1.1         {
 618 krisbash 1.4             /* Checking if the requested class is a base class of an implemented class */
 619 mike     1.1             r = ProvReg_BeginClasses(&self->provreg, req->nameSpace, 
 620 krisbash 1.4                     req->className, MI_TRUE, &pos, MI_FALSE);
 621 mike     1.1 
 622 krisbash 1.4             if(MI_RESULT_INVALID_CLASS == r)
 623 mike     1.1             {
 624 krisbash 1.4                 /* Checking if the requested class is an extraclass (Class without key property or Class with key property but not part of any 
 625                                  class heirarchy of an implemented class.)
 626                                  Class with valid providerFT is called as an implemented class */
 627              
 628                              /* In extra classes inheritance tree a namespace node is created only if there is at least one extra class in the namespace.
 629                                  So namespace node need not exist in extra classes inheritance tree even for valid namespace */
 630                              r = ProvReg_BeginClasses(&self->provreg, req->nameSpace, 
 631                                      req->className, MI_TRUE, &pos, MI_TRUE);
 632 mike     1.1 
 633 krisbash 1.4                 if(MI_RESULT_INVALID_NAMESPACE == r)
 634                                  r = MI_RESULT_INVALID_CLASS;
 635 mike     1.1             }
 636 krisbash 1.4             if (MI_RESULT_OK == r)
 637 mike     1.1             {
 638 krisbash 1.4                 DEBUG_ASSERT(pos.start != NULL);
 639                              MapRegPositionValuesToRegEntry(&freg, &pos);
 640                              freg.nameSpace = req->nameSpace;
 641                              freg.nameSpaceHash = Hash(req->nameSpace);
 642 mike     1.1             }
 643                      }
 644 krisbash 1.4         
 645                      if (MI_RESULT_OK != r)
 646 mike     1.1         {
 647 krisbash 1.4             trace_NoProviderForClass(
 648                              req->nameSpace,
 649                              req->className);
 650                          goto sendErrorBack;
 651 mike     1.1         }
 652                  }
 653 krisbash 1.4     else
 654 mike     1.1     {
 655 krisbash 1.4         freg = *reg;
 656 mike     1.1     }
 657              
 658                  // Send the request to provider manager.
 659 krisbash 1.4     r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, &freg);
 660 mike     1.1 
 661                  if (r != MI_RESULT_OK)
 662                  {
 663 krisbash 1.4         trace_AgentMgrHandleRequestForNS(
 664                          req->nameSpace);
 665 mike     1.1         goto sendErrorBack;
 666                  }
 667              
 668                  return MI_RESULT_OK;
 669              
 670              sendErrorBack:
 671 krisbash 1.4     // Just abort creating any interaction at all
 672                  return r;
 673 mike     1.1 }
 674              
 675              static MI_Result _HandleCreateInstanceReq(
 676 krisbash 1.4     _In_ Disp* self,
 677                  _Inout_ InteractionOpenParams* interactionParams, 
 678                  _In_ CreateInstanceReq* req)
 679 mike     1.1 {
 680                  MI_Result r;
 681                  const ProvRegEntry* reg;
 682              
 683                  /* Validate input parameters */
 684                  if (!req->instance || !req->nameSpace)
 685                      return MI_RESULT_INVALID_PARAMETER;
 686              
 687                  // Find a provider for this class.
 688                  reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace, 
 689 krisbash 1.4         req->instance->classDecl->name, &r );
 690 mike     1.1 
 691                  if (!reg)
 692                  {
 693 krisbash 1.4         trace_NoProviderForClass(
 694                          req->nameSpace, 
 695                          req->instance->classDecl->name);
 696 mike     1.1         goto sendErrorBack;
 697                  }
 698              
 699                  // Send the request to provider manager.
 700 krisbash 1.4     r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, reg);
 701 mike     1.1 
 702                  if (r != MI_RESULT_OK)
 703                  {
 704 krisbash 1.4         trace_AgentMgrHandleRequestForNS(
 705                          req->nameSpace);
 706 mike     1.1         goto sendErrorBack;
 707                  }
 708              
 709                  return MI_RESULT_OK;
 710              
 711              sendErrorBack:
 712 krisbash 1.4     // Just abort creating any interaction at all
 713                  return r;
 714 mike     1.1 }
 715              
 716              static MI_Result _HandleModifyInstanceReq(
 717 krisbash 1.4     _In_ Disp* self,
 718                  _Inout_ InteractionOpenParams* interactionParams, 
 719                  _In_ ModifyInstanceReq* req)
 720 mike     1.1 {
 721                  MI_Result r;
 722                  const ProvRegEntry* reg;
 723              
 724                  /* Validate input parameters */
 725                  if (!req->instance || !req->nameSpace)
 726                      return MI_RESULT_INVALID_PARAMETER;
 727              
 728                  // Find a provider for this class.
 729                  reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace, 
 730 krisbash 1.4         req->instance->classDecl->name, &r );
 731 mike     1.1 
 732                  if (!reg)
 733                  {
 734 krisbash 1.4         trace_NoProviderForClass(
 735                          req->nameSpace, 
 736                          req->instance->classDecl->name);
 737 mike     1.1         goto sendErrorBack;
 738                  }
 739              
 740                  // Send the request to provider manager.
 741 krisbash 1.4     r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, reg);
 742 mike     1.1 
 743                  if (r != MI_RESULT_OK)
 744                  {
 745 krisbash 1.4         trace_AgentMgrHandleRequestForNS(
 746                          req->nameSpace);
 747 mike     1.1         goto sendErrorBack;
 748                  }
 749              
 750                  return MI_RESULT_OK;
 751              
 752              sendErrorBack:
 753 krisbash 1.4     // Just abort creating any interaction at all
 754                  return r;
 755 mike     1.1 }
 756              
 757              static MI_Result _HandleDeleteInstanceReq(
 758 krisbash 1.4     _In_ Disp* self,
 759                  _Inout_ InteractionOpenParams* interactionParams, 
 760                  _In_ DeleteInstanceReq* req)
 761 mike     1.1 {
 762                  MI_Result r;
 763                  const ProvRegEntry* reg;
 764              
 765                  /* Validate input parameters */
 766                  if (!req->instanceName || !req->nameSpace)
 767                      return MI_RESULT_INVALID_PARAMETER;
 768              
 769                  // Find a provider for this class.
 770                  reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace, 
 771 krisbash 1.4         req->instanceName->classDecl->name, &r);
 772 mike     1.1 
 773                  if (!reg)
 774                  {
 775 krisbash 1.4         trace_NoProviderForClass(
 776                          req->nameSpace, 
 777                          req->instanceName->classDecl->name);
 778 mike     1.1         goto sendErrorBack;
 779                  }
 780              
 781                  // Send the request to provider manager.
 782 krisbash 1.4     r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, reg);
 783 mike     1.1 
 784                  if (r != MI_RESULT_OK)
 785                  {
 786 krisbash 1.4         trace_AgentMgrHandleRequestForNS(
 787                          req->nameSpace);
 788 mike     1.1         goto sendErrorBack;
 789                  }
 790              
 791                  return MI_RESULT_OK;
 792              
 793              sendErrorBack:
 794 krisbash 1.4     // Just abort creating any interaction at all
 795                  return r;
 796 mike     1.1 }
 797              
 798 krisbash 1.4 static MI_Result _HandleInvokeReq(
 799                  _In_ Disp* self,
 800                  _Inout_ InteractionOpenParams* interactionParams, 
 801                  _In_ InvokeReq* req)
 802 mike     1.1 {
 803                  MI_Result r;
 804 krisbash 1.4     const ProvRegEntry* reg;
 805                  MI_ConstString cn = 0;
 806 mike     1.1 
 807                  /* Validate input parameters */
 808 krisbash 1.4     if (!req->nameSpace)
 809 mike     1.1         return MI_RESULT_INVALID_PARAMETER;
 810              
 811 krisbash 1.4     if (req->className)
 812                      cn = req->className;
 813                  else if (req->instance)
 814                      cn = req->instance->classDecl->name;
 815 mike     1.1 
 816 krisbash 1.4     if (!cn)
 817                  {
 818                      r = MI_RESULT_INVALID_CLASS;
 819                      trace_ClassNameIsExpectedForInvoke();
 820                      goto sendErrorBack;
 821                  }
 822 mike     1.1 
 823              
 824 krisbash 1.4     // Find a provider for this class.
 825                  reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace, cn, &r);
 826 mike     1.1 
 827 krisbash 1.4     if (!reg)
 828                  {
 829                      trace_FoundNoProvider(
 830                          cn);
 831 mike     1.1         goto sendErrorBack;
 832 krisbash 1.4     }
 833 mike     1.1 
 834                  // Send the request to provider manager.
 835 krisbash 1.4     r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, reg);
 836 mike     1.1 
 837                  if (r != MI_RESULT_OK)
 838                  {
 839 krisbash 1.4         trace_AgentMgrHandleRequestForNS(
 840                          req->nameSpace);
 841 mike     1.1         goto sendErrorBack;
 842                  }
 843              
 844                  return MI_RESULT_OK;
 845              
 846              sendErrorBack:
 847 krisbash 1.4     // Just abort creating any interaction at all
 848                  return r;
 849 mike     1.1 }
 850              
 851 krisbash 1.4 static MI_Result _HandleEnumerateInstancesReq(
 852                  _In_ Disp* self,
 853                  _Inout_ InteractionOpenParams* interactionParams, 
 854                  _In_ EnumerateInstancesReq* req)
 855 mike     1.1 {
 856 krisbash 1.4     MI_Result r = MI_RESULT_FAILED;
 857                  MI_Boolean sentOk = MI_FALSE;
 858                  WQL_Dialect dialect;
 859                  DispEnumParent* enumInteraction;
 860                  EnumEntry* enumEntry;
 861                  EnumEntry* enumEntryHead = NULL;
 862 mike     1.1 
 863                  /* Validate input parameters */
 864                  if (!req->nameSpace)
 865                      return MI_RESULT_INVALID_PARAMETER;
 866              
 867 krisbash 1.4     /* Precompile the query */
 868                  if (req->queryLanguage || req->queryExpression)
 869                  {
 870                      /* Fail if either query language or expression is missing */
 871                      if (!req->queryLanguage || !req->queryExpression)
 872                      {
 873                          trace_QueryLanguageOrExpressionMissing();
 874                          return MI_RESULT_INVALID_QUERY;
 875                      }
 876              
 877                      /* Reject non-WQL queries */
 878                      if (Tcscasecmp(req->queryLanguage, MI_QUERY_DIALECT_WQL) == 0)
 879                      {
 880                          dialect = WQL_DIALECT_WQL;
 881                      }
 882                      else if (Tcscasecmp(req->queryLanguage, MI_QUERY_DIALECT_CQL) == 0)
 883                      {
 884                          dialect = WQL_DIALECT_CQL;
 885                      }
 886                      else
 887                      {
 888 krisbash 1.4             trace_UnsupportedQueryLanguage(tcs(req->queryLanguage));
 889                          return MI_RESULT_QUERY_LANGUAGE_NOT_SUPPORTED;
 890                      }
 891              
 892                      /* Compile the query */
 893                      {
 894                          req->wql = WQL_Parse(req->queryExpression, req->base.base.batch,
 895                              dialect);
 896              
 897                          if (!req->wql)
 898                          {
 899                              trace_InvalidQueryExpression(tcs(req->queryExpression));
 900                              return MI_RESULT_INVALID_QUERY;
 901                          }
 902                      }
 903              
 904                      /* WQL queries from WinRM pass '*' as the class name */
 905              
 906                      if (!req->className || (Tcscmp(req->className, PAL_T("*")) == 0))
 907                      {
 908                          req->className = req->wql->className;
 909 krisbash 1.4         }
 910 mike     1.1 
 911 krisbash 1.4         /* Verify that the query classname matches the enumeration classname */
 912                      if (Tcscmp(req->wql->className, req->className) != 0)
 913                      {
 914                          trace_QueryEnumClassnameMismatch(
 915                              tcs(req->wql->className), tcs(req->className));
 916                          return MI_RESULT_INVALID_QUERY;
 917                      }
 918                  }
 919                  else if (!req->className)
 920 mike     1.1     {
 921 krisbash 1.4         trace_EnumHasNoClassname();
 922                      return MI_RESULT_INVALID_PARAMETER;
 923 mike     1.1     }
 924              
 925 krisbash 1.4     if (req->deepInheritance)
 926                  {
 927                      ProvRegPosition pos;
 928                      EnumEntry* enumEntryPrev;
 929                      
 930                      /* create the interaction that will keep track of results from providers */
 931                      enumInteraction = _DispEnumParent_New(
 932                                          self,
 933                                          interactionParams);
 934                      if (!enumInteraction)
 935                      {
 936                          trace_Disp_ErrorInteractionAlloc();
 937                          return MI_RESULT_FAILED;
 938                      }
 939              
 940                      /* Send to direct name */
 941                      /* Start by sending to direct name */
 942                      enumEntry = (EnumEntry*)StrandEntry_New( STRAND_DEBUG( DispEnumEntry ) 
 943                                                                  &enumInteraction->strand, 
 944                                                                  &_DispEnumEntry_ProviderFT, 
 945                                                                  sizeof(EnumEntry), 
 946 krisbash 1.4                                                     STRAND_FLAG_ENTERSTRAND, 
 947                                                                  NULL);
 948                      if( NULL == enumEntry )
 949                      {
 950                          trace_Disp_ErrorEnumEntryAlloc();
 951                          goto sendErrorBack_Opened;
 952                      }
 953                      r = StrandMany_AddEntry( &enumEntry->strand );
 954                      if( MI_RESULT_OK != r )
 955                      {
 956                          StrandEntry_DeleteNoAdded( &enumEntry->strand );
 957                          goto sendErrorBack_Opened;
 958                      }
 959                      enumEntry->className = req->className;
 960                      enumEntryHead = enumEntry;
 961                      enumEntryPrev = enumEntry;
 962              
 963                      /* Begin enumeration of classes for this request */
 964                      {
 965                          r = ProvReg_BeginClasses(&self->provreg, req->nameSpace, 
 966                              req->className, MI_TRUE, &pos, MI_FALSE);
 967 krisbash 1.4 
 968                          if (MI_RESULT_OK != r)
 969                          {
 970                              {
 971                                  /* Checking if the class is in extra classes to return appropriate error */
 972                                  MI_Result result;
 973                                  result = ProvReg_BeginClasses(&self->provreg, req->nameSpace, 
 974                                                  req->className, MI_TRUE, &pos, MI_TRUE);
 975                                  if(MI_RESULT_OK == result)
 976                                  {
 977                                      ProvReg_EndClasses(&pos);
 978                                      r = MI_RESULT_NOT_SUPPORTED;
 979                                      goto sendErrorBack_Opened;
 980                                  }
 981                              }
 982                              trace_ProvReg_BeginClasses_Failed( 
 983                                  r, tcs(Result_ToString(r)));
 984                          
 985                              trace_DispEnum_UnknownClass(
 986                                  tcs(req->nameSpace), tcs(req->className));
 987              
 988 krisbash 1.4                 /* send error back to caller */
 989                              goto sendErrorBack_Opened;
 990                          }
 991                      }
 992              
 993                      /* While more classes */
 994                      for (;;)
 995                      {
 996                          const ZChar* derived = NULL;
 997                          MI_Boolean done;
 998              
 999                          r = ProvReg_NextClass(&pos, &derived, &done);
1000              
1001                          if (done)
1002                              break;
1003              
1004                          if (MI_RESULT_OK != r)
1005                          {
1006                              trace_ProvReg_NextClass_Failed(
1007                                  r, tcs(Result_ToString(r)));
1008                      
1009 krisbash 1.4                 trace_DispEnum_UnknownClass(
1010                                  tcs(req->nameSpace), tcs(req->className));
1011                      
1012                              /* send error back to caller */
1013                              goto sendErrorBack_Opened;
1014                          }
1015              
1016                          enumEntry = (EnumEntry*)StrandEntry_New( STRAND_DEBUG( DispEnumEntry ) 
1017                                                                      &enumInteraction->strand, 
1018                                                                      &_DispEnumEntry_ProviderFT, 
1019                                                                      sizeof(EnumEntry), 
1020                                                                      STRAND_FLAG_ENTERSTRAND, 
1021                                                                      NULL);
1022                          if( NULL == enumEntry )
1023                          {
1024                              trace_Disp_ErrorEnumEntryAlloc();
1025                              goto sendErrorBack_Opened;
1026                          }
1027                          
1028                          r = StrandMany_AddEntry( &enumEntry->strand );
1029                          if( MI_RESULT_OK != r )
1030 krisbash 1.4             {
1031                              trace_Disp_ErrorAddEntry();
1032                              StrandEntry_DeleteNoAdded( &enumEntry->strand );
1033                              goto sendErrorBack_Opened;
1034                          }
1035              
1036                          // Use the original message batch, it will not be deleted until enumInteraction (who holds a ref to the message) is deleted
1037                          enumEntry->className = Batch_Tcsdup(req->base.base.batch, derived);
1038                          enumEntry->next = NULL;
1039                          enumEntryPrev->next = enumEntry;
1040                          enumEntryPrev = enumEntry;
1041                      }
1042              
1043                      /* Finalize enumeration */
1044                      {
1045                          r = ProvReg_EndClasses(&pos);
1046              
1047                          if (MI_RESULT_OK != r)
1048                          {
1049                              trace_ProvReg_EndClasses_Failed(
1050                                  r, tcs(Result_ToString(r)));
1051 krisbash 1.4                 /* send error back to caller */
1052                              goto sendErrorBack_Opened;
1053                          }
1054                      }
1055              
1056                      Strand_Leave( &enumInteraction->strand.strand );
1057 mike     1.1 
1058 krisbash 1.4         // Now go thru the added entries and dispatch the interactions
1059                      enumEntry = enumEntryHead;
1060                      while( NULL != enumEntry )
1061                      {
1062                          // Move to the next one before the object can be deleted by itself or by delete below
1063                          enumEntryPrev = enumEntry;
1064                          enumEntry = enumEntry->next;
1065                          if( _DispatchEnumerateInstancesReq(self, req, enumEntryPrev->className, enumEntryPrev, NULL) == MI_RESULT_OK)
1066                          {
1067                              sentOk = MI_TRUE;
1068                          }
1069                          else
1070                          {
1071                              StrandEntry_Delete( &enumEntryPrev->strand );
1072                          }
1073                      }
1074                      enumEntryHead = NULL;
1075                          
1076                      /* Fail if no provider was found for request */
1077                      if (!sentOk)
1078                      {        
1079 krisbash 1.4             trace_FoundNoProvider(
1080                              req->className);
1081                          r = MI_RESULT_NOT_SUPPORTED;
1082                          goto sendErrorBack_Opened;
1083                      }
1084 mike     1.1 
1085 krisbash 1.4         StrandMany_ScheduleAux(&enumInteraction->strand,DISPENUMPARENT_STRANDAUX_ENUMDONE);
1086                  } /* if deep*/
1087                  else
1088 mike     1.1     {
1089 krisbash 1.4         /* Checking to see if the requested className is valid */
1090                      ProvRegPosition pos;
1091                      r = ProvReg_BeginClasses(&self->provreg, req->nameSpace, 
1092                          req->className, MI_TRUE, &pos, MI_FALSE);
1093              
1094                      if (MI_RESULT_OK != r)
1095                      {
1096                          /* Checking if the class is in extra classes to return appropriate error */
1097                          MI_Result result;
1098                          result = ProvReg_BeginClasses(&self->provreg, req->nameSpace, 
1099                                          req->className, MI_TRUE, &pos, MI_TRUE);
1100                          if(MI_RESULT_OK == result)
1101                          {
1102                              r = MI_RESULT_NOT_SUPPORTED;
1103                              ProvReg_EndClasses(&pos);
1104                          }
1105                          return r;
1106                      }
1107                      else
1108                      {
1109                          ProvReg_EndClasses(&pos);
1110 krisbash 1.4         }
1111              
1112                      // no need to create new interaction
1113                      return _DispatchEnumerateInstancesReq(self, req, req->className, NULL, interactionParams);
1114 mike     1.1     }
1115              
1116 krisbash 1.4     return MI_RESULT_OK;
1117 mike     1.1 
1118 krisbash 1.4 sendErrorBack_Opened:
1119                  // Delete not dispatched entries 
1120                  enumEntry = enumEntryHead;
1121                  while( NULL != enumEntry )
1122 mike     1.1     {
1123 krisbash 1.4         StrandEntry_Delete( &enumEntry->strand );
1124                      enumEntry = enumEntry->next;
1125 mike     1.1     }
1126 krisbash 1.4     
1127                  // send error back to caller 
1128                  _SendErrorResponse_Opened(interactionParams, enumInteraction, r, MI_FALSE ); 
1129 mike     1.1     return MI_RESULT_OK;
1130              }
1131              
1132              static MI_Result _HandleAssociatorsOfReq(
1133 krisbash 1.4     _In_ Disp* self,
1134                  _Inout_ InteractionOpenParams* interactionParams, 
1135                  _In_ AssociationsOfReq* req)
1136 mike     1.1 {
1137 krisbash 1.4     int res;
1138                  MI_Result r = MI_RESULT_FAILED;
1139 mike     1.1     MI_ConstString cn = 0;
1140                  ProvRegAssocPosition pos;
1141                  MI_Boolean sentOk = MI_FALSE;
1142 krisbash 1.4     HashMap classNames;
1143                  DispEnumParent* enumInteraction;
1144                  EnumEntry* enumEntry;
1145                  EnumEntry* enumEntryHead = NULL;
1146                  EnumEntry* enumEntryPrev = NULL;
1147 mike     1.2 
1148                  /* Create a hash table of class names */
1149              
1150 krisbash 1.4     res = HashMap_Init(
1151 mike     1.2         &classNames, 
1152                      64, 
1153                      ClassNameHash, 
1154                      ClassNameEqual, 
1155                      ClassNameRelease);
1156              
1157 krisbash 1.4     if (res != 0)
1158 mike     1.2         return MI_RESULT_FAILED;
1159 mike     1.1 
1160                  /* Validate input parameters */
1161                  if (!req->instance || !req->nameSpace)
1162                      return MI_RESULT_INVALID_PARAMETER;
1163              
1164 krisbash 1.4     /* create the interaction that will keep track of results from providers */
1165                  enumInteraction = _DispEnumParent_New(
1166                                      self,
1167                                      interactionParams);
1168                  if (!enumInteraction)
1169                  {
1170                      trace_Disp_ErrorInteractionAlloc();
1171                      HashMap_Destroy(&classNames);
1172 mike     1.1         return MI_RESULT_FAILED;
1173 krisbash 1.4     }
1174 mike     1.1     
1175                  r = ProvReg_BeginAssocClasses(&self->provreg, req->nameSpace, 
1176                      req->instance->classDecl->name,
1177                      req->assocClass, req->resultClass, &pos);
1178              
1179                  if (MI_RESULT_OK != r)
1180                  {
1181 krisbash 1.4         trace_ProvReg_BeginAssocClasses_Failed(r, tcs(Result_ToString(r)));
1182 mike     1.1 
1183                      /* send error back to caller */
1184 krisbash 1.4         goto sendErrorBack_Opened;
1185 mike     1.1     }
1186              
1187 mike     1.2     /* ATTN: there is a bug in the provider registration tree causing
1188                   * the association provider to be called twice. To avoid this for now,
1189                   * we maintain a hash table of already dispatched classes.
1190                   */
1191              
1192 mike     1.1     /* While more classes */
1193                  for (;;)
1194                  {
1195                      MI_Boolean done;
1196                      r = ProvReg_NextAssocClass(&pos, &cn, &done);
1197              
1198                      if (done)
1199                          break;
1200              
1201                      if (MI_RESULT_OK != r)
1202                      {
1203 krisbash 1.4             trace_ProvReg_NextAssocClass_Failed(r, tcs(Result_ToString(r)));
1204                          
1205 mike     1.1             /* send error back to caller */
1206 krisbash 1.4             goto sendErrorBack_Opened;
1207 mike     1.1         }
1208              
1209 mike     1.2         /* Check whether this class has been dispatched */
1210                      {
1211                          ClassNameBucket bucket;
1212 krisbash 1.4             bucket.key = (ZChar*)cn;
1213 mike     1.2 
1214 krisbash 1.4             if (!HashMap_Find(&classNames, (const HashBucket*)&bucket))
1215 mike     1.2             {
1216 krisbash 1.4                 enumEntry = (EnumEntry*)StrandEntry_New( STRAND_DEBUG( DispEnumEntry ) 
1217                                                                          &enumInteraction->strand, 
1218                                                                          &_DispEnumEntry_ProviderFT, 
1219                                                                          sizeof(EnumEntry), 
1220                                                                          STRAND_FLAG_ENTERSTRAND, 
1221                                                                          NULL);
1222                              if( NULL == enumEntry )
1223                              {
1224                                  trace_Disp_ErrorEnumEntryAlloc();
1225                                  goto sendErrorBack_Opened;
1226                              }
1227                              
1228                              r = StrandMany_AddEntry( &enumEntry->strand );
1229                              if( MI_RESULT_OK != r )
1230                              {
1231                                  trace_Disp_ErrorAddEntry();
1232                                  StrandEntry_DeleteNoAdded( &enumEntry->strand );
1233                                  goto sendErrorBack_Opened;
1234                              }
1235                              
1236                              // Use the original message batch, it will not be deleted until enumInteraction (who holds a ref to the message) is deleted
1237 krisbash 1.4                 enumEntry->className = Batch_Tcsdup(req->base.base.batch, cn);
1238                              enumEntry->next = NULL;
1239                              if( NULL == enumEntryHead )
1240                              {
1241                                  enumEntryHead = enumEntry;
1242                              }
1243                              else
1244                              {
1245                                  enumEntryPrev->next = enumEntry;
1246                              }
1247                              enumEntryPrev = enumEntry;
1248 mike     1.2 
1249                              {
1250 krisbash 1.4                     ClassNameBucket* bucket = (ClassNameBucket*)PAL_Calloc(
1251 mike     1.2                         1, sizeof(ClassNameBucket));
1252              
1253                                  if (!bucket)
1254                                  {
1255                                      r = MI_RESULT_FAILED;
1256 krisbash 1.4                         goto sendErrorBack_Opened;
1257 mike     1.2                     }
1258              
1259 krisbash 1.4                     bucket->key = PAL_Tcsdup(cn);
1260 mike     1.2 
1261 krisbash 1.4                     if (HashMap_Insert(&classNames, (HashBucket*)bucket) != 0)
1262 mike     1.2                     {
1263                                      r = MI_RESULT_FAILED;
1264 krisbash 1.4                         goto sendErrorBack_Opened;
1265 mike     1.2                     }
1266                              }
1267                          }
1268                      }
1269 mike     1.1     }
1270              
1271                  /* Finalize enumeration */
1272                  {
1273                      r = ProvReg_EndAssocClasses(&pos);
1274              
1275                      if (MI_RESULT_OK != r)
1276                      {
1277 krisbash 1.4             trace_ProvReg_EndAssocClasses_Failed(r, tcs(Result_ToString(r)));
1278                          
1279 mike     1.1             /* send error back to caller */
1280 krisbash 1.4             goto sendErrorBack_Opened;
1281 mike     1.1         }
1282                  }
1283              
1284 krisbash 1.4     Strand_Leave( &enumInteraction->strand.strand );
1285                  
1286                  // Now go thru the added entries and dispatch the interactions
1287                  enumEntry = enumEntryHead;
1288                  while( NULL != enumEntry )
1289                  {
1290                      // Move to the next one before the object can be deleted by itself or by delete below
1291                      enumEntryPrev = enumEntry;
1292                      enumEntry = enumEntry->next;
1293                      if (_DispatchAssocReq(self, req, enumEntryPrev, AssociatorsOfReqTag))
1294                      {
1295                          sentOk = MI_TRUE;
1296                      }
1297                      else
1298                      {
1299                          StrandEntry_Delete( &enumEntryPrev->strand );
1300                      }
1301                  }
1302                  enumEntryHead = NULL;
1303                      
1304                  HashMap_Destroy(&classNames);
1305 krisbash 1.4         
1306 mike     1.1     /* Fail if no provider was found for request */
1307                  if (!sentOk)
1308                  {
1309 krisbash 1.4         trace_FoundNoProvider(
1310                          tcs(req->instance->classDecl->name));
1311                      _SendErrorResponse_Opened(interactionParams, enumInteraction, MI_RESULT_NOT_SUPPORTED, MI_TRUE );
1312                      return MI_RESULT_OK;
1313 mike     1.1     }
1314              
1315 krisbash 1.4     StrandMany_ScheduleAux(&enumInteraction->strand,DISPENUMPARENT_STRANDAUX_ENUMDONE);
1316                  return MI_RESULT_OK;
1317              
1318              sendErrorBack_Opened:
1319                  HashMap_Destroy(&classNames);
1320                  // Delete not dispatched entries 
1321                  enumEntry = enumEntryHead;
1322                  while( NULL != enumEntry )
1323                  {
1324                      StrandEntry_Delete( &enumEntry->strand );
1325                      enumEntry = enumEntry->next;
1326 mike     1.1     }
1327 krisbash 1.4     
1328                  // send error back to caller 
1329                  _SendErrorResponse_Opened(interactionParams, enumInteraction, r, MI_FALSE );
1330 mike     1.1     return MI_RESULT_OK;
1331              }
1332              
1333              static MI_Result _HandleReferencesOfReq(
1334 krisbash 1.4     _In_ Disp* self,
1335                  _Inout_ InteractionOpenParams* interactionParams, 
1336                  _In_ AssociationsOfReq* req)
1337 mike     1.1 {
1338 krisbash 1.4     MI_Result r = MI_RESULT_FAILED;
1339 mike     1.1     MI_ConstString cn = 0;
1340                  ProvRegAssocPosition pos;
1341                  MI_Boolean sentOk = MI_FALSE;
1342 krisbash 1.4     DispEnumParent* enumInteraction;
1343                  EnumEntry* enumEntry;
1344                  EnumEntry* enumEntryHead = NULL;
1345                  EnumEntry* enumEntryPrev = NULL;
1346 mike     1.1 
1347                  /* Validate input parameters */
1348                  if (!req->instance || !req->nameSpace)
1349                      return MI_RESULT_INVALID_PARAMETER;
1350              
1351 krisbash 1.4     /* create the interaction that will keep track of results from providers */
1352                  enumInteraction = _DispEnumParent_New(
1353                                          self,
1354                                          interactionParams);
1355                  if (!enumInteraction)
1356                  {
1357                      trace_Disp_ErrorInteractionAlloc();
1358 mike     1.1         return MI_RESULT_FAILED;
1359 krisbash 1.4     }
1360 mike     1.1 
1361 krisbash 1.4     /* resultClass parameter of ReferencesOf operation contains association class name.
1362                    Here using req->resultClass for passing assocClassName to ProvReg_BeginAssocClasses function */
1363 mike     1.1     r = ProvReg_BeginAssocClasses(&self->provreg, req->nameSpace, 
1364                      req->instance->classDecl->name,
1365 krisbash 1.4         req->resultClass, 0, &pos);
1366 mike     1.1 
1367                  if (MI_RESULT_OK != r)
1368                  {
1369 krisbash 1.4         trace_ProvReg_BeginAssocClasses_Failed(r, tcs(Result_ToString(r)));
1370 mike     1.1 
1371                      /* send error back to caller */
1372 krisbash 1.4         goto sendErrorBack_Opened;
1373 mike     1.1     }
1374              
1375                  /* While more classes */
1376                  for (;;)
1377                  {
1378                      MI_Boolean done;
1379                      r = ProvReg_NextAssocClass(&pos, &cn, &done);
1380              
1381                      if (done)
1382                          break;
1383              
1384                      if (MI_RESULT_OK != r)
1385                      {
1386 krisbash 1.4             trace_ProvReg_NextAssocClass_Failed(r, tcs(Result_ToString(r)));
1387                          
1388 mike     1.1             /* send error back to caller */
1389 krisbash 1.4             goto sendErrorBack_Opened;
1390 mike     1.1         }
1391              
1392 krisbash 1.4         enumEntry = (EnumEntry*)StrandEntry_New( STRAND_DEBUG( DispEnumEntry ) 
1393                                                                  &enumInteraction->strand, 
1394                                                                  &_DispEnumEntry_ProviderFT, 
1395                                                                  sizeof(EnumEntry), 
1396                                                                  STRAND_FLAG_ENTERSTRAND, 
1397                                                                  NULL);
1398                      if( NULL == enumEntry )
1399                      {
1400                          trace_Disp_ErrorEnumEntryAlloc();
1401                          goto sendErrorBack_Opened;
1402                      }
1403                      
1404                      r = StrandMany_AddEntry( &enumEntry->strand );
1405                      if( MI_RESULT_OK != r )
1406                      {
1407                          trace_Disp_ErrorAddEntry();
1408                          StrandEntry_DeleteNoAdded( &enumEntry->strand );
1409                          goto sendErrorBack_Opened;
1410                      }
1411                      
1412                      // Use the original message batch, it will not be deleted until enumInteraction (who holds a ref to the message) is deleted
1413 krisbash 1.4         enumEntry->className = Batch_Tcsdup(req->base.base.batch, cn);
1414                      enumEntry->next = NULL;
1415                      if( NULL == enumEntryHead )
1416                      {
1417                          enumEntryHead = enumEntry;
1418                      }
1419                      else
1420                      {
1421                          enumEntryPrev->next = enumEntry;
1422                      }
1423                      enumEntryPrev = enumEntry;
1424 mike     1.1     }
1425              
1426                  /* Finalize enumeration */
1427                  {
1428                      r = ProvReg_EndAssocClasses(&pos);
1429              
1430                      if (MI_RESULT_OK != r)
1431                      {
1432 krisbash 1.4             trace_ProvReg_EndAssocClasses_Failed(r, tcs(Result_ToString(r)));
1433                          
1434 mike     1.1             /* send error back to caller */
1435 krisbash 1.4             goto sendErrorBack_Opened;
1436 mike     1.1         }
1437                  }
1438              
1439 krisbash 1.4     Strand_Leave( &enumInteraction->strand.strand );
1440                  
1441                  // Now go thru the added entries and dispatch the interactions
1442                  enumEntry = enumEntryHead;
1443                  while( NULL != enumEntry )
1444                  {
1445                      // Move to the next one before the object can be deleted by itself or by delete below
1446                      enumEntryPrev = enumEntry;
1447                      enumEntry = enumEntry->next;
1448                      if (_DispatchAssocReq(self, req, enumEntryPrev, ReferencesOfReqTag))
1449                      {
1450                          sentOk = MI_TRUE;
1451                      }
1452                      else
1453                      {
1454                          StrandEntry_Delete( &enumEntryPrev->strand );
1455                      }
1456                  }
1457                  enumEntryHead = NULL;
1458                      
1459 mike     1.1     /* Fail if no provider was found for request */
1460                  if (!sentOk)
1461                  {
1462 krisbash 1.4         trace_FoundNoProvider(
1463                          tcs(req->instance->classDecl->name));
1464                      _SendErrorResponse_Opened(interactionParams, enumInteraction, MI_RESULT_NOT_SUPPORTED, MI_TRUE );
1465                      return MI_RESULT_OK;
1466 mike     1.1     }
1467              
1468 krisbash 1.4     StrandMany_ScheduleAux(&enumInteraction->strand,DISPENUMPARENT_STRANDAUX_ENUMDONE);
1469                  return MI_RESULT_OK;
1470              
1471              sendErrorBack_Opened:
1472                  // Delete not dispatched entries 
1473                  enumEntry = enumEntryHead;
1474                  while( NULL != enumEntry )
1475                  {
1476                      StrandEntry_Delete( &enumEntry->strand );
1477                      enumEntry = enumEntry->next;
1478 mike     1.1     }
1479 krisbash 1.4     
1480                  // send error back to caller 
1481                  _SendErrorResponse_Opened(interactionParams, enumInteraction, r, FALSE );
1482                  return MI_RESULT_OK;
1483              }
1484 mike     1.1 
1485 krisbash 1.4 #ifndef DISABLE_INDICATION
1486              static MI_Result _HandleSubscribeReq(
1487                  _In_ Disp* self,
1488                  _Inout_ InteractionOpenParams* params )
1489              {
1490                  params->callbackData = self->indmgr;
1491                  IndiMgr_HandleSubscribeReq(params);
1492 mike     1.1     return MI_RESULT_OK;
1493              }
1494 krisbash 1.4 #endif /* ifndef DISABLE_INDICATION */
1495 mike     1.1 
1496              /*
1497              **==============================================================================
1498              **
1499              ** Public definitions
1500              **
1501              **==============================================================================
1502              */
1503              
1504              MI_Result Disp_Init(Disp* self, Selector* selector)
1505              {
1506                  /* Check parameters */
1507                  if (!self)
1508                      return MI_RESULT_INVALID_PARAMETER;
1509              
1510                  memset(self, 0, sizeof(Disp));
1511              
1512              #if 0
1513                  /* Initialize the provider registry */
1514 krisbash 1.4     MI_RETURN_ERR(ProvReg_Init(&self->provreg, OMI_GetPath(ID_REGISTERFILE)));
1515 mike     1.1 #else
1516                  MI_RETURN_ERR(ProvReg_Init2(&self->provreg));
1517              #endif
1518              
1519                  /* Initialize the provider manager */
1520                  MI_RETURN_ERR(AgentMgr_Init(&self->agentmgr, selector));
1521              
1522 krisbash 1.4 #ifndef DISABLE_INDICATION
1523                  /* Initialize indication manager */
1524                  self->indmgr = IndiMgr_NewFromDisp(self);
1525                  if (NULL == self->indmgr)
1526                      MI_RETURN_ERR(MI_RESULT_FAILED);
1527              #endif /* ifndef DISABLE_INDICATION */
1528 mike     1.1 
1529                  return MI_RESULT_OK;
1530              }
1531              
1532              MI_Result Disp_Destroy(Disp* self)
1533              {
1534                  MI_RETURN_ERR(AgentMgr_Destroy(&self->agentmgr));
1535                  ProvReg_Destroy(&self->provreg);
1536              
1537 krisbash 1.4 #ifndef DISABLE_INDICATION
1538                  /* Shutdown indication manager */
1539                  IndiMgr_Shutdown(self->indmgr);
1540              #endif /* ifndef DISABLE_INDICATION */
1541              
1542 mike     1.1     /*ATTN! remove indication contexts! */
1543                  return MI_RESULT_OK;
1544              }
1545              
1546 krisbash 1.4 MI_Result Disp_HandleInteractionRequest(
1547                  _In_ Disp* self,
1548                  _Inout_ InteractionOpenParams* params )
1549 mike     1.1 {
1550 krisbash 1.4     Message* msg = params->msg;
1551                  
1552                  trace_DispHandleInteractionRequest(self, 
1553                      params->interaction, 
1554                      msg,
1555                      msg->tag,
1556                      MessageName(msg->tag),
1557                      msg->operationId);
1558              
1559                  DEBUG_ASSERT( NULL != self );
1560                  DEBUG_ASSERT( NULL != params );
1561                  DEBUG_ASSERT( NULL != params->interaction );
1562                  DEBUG_ASSERT( NULL != params->msg );
1563              
1564 mike     1.1     switch (msg->tag)
1565                  {
1566 krisbash 1.4         case GetInstanceReqTag:
1567 mike     1.1         {
1568 krisbash 1.4             GetInstanceReq* req = (GetInstanceReq*)msg;
1569                          return _HandleGetInstanceReq(self, params, req);
1570 mike     1.1         }
1571              
1572 krisbash 1.4         case GetClassReqTag:
1573 mike     1.1         {
1574 krisbash 1.4             GetClassReq* req = (GetClassReq*)msg;
1575                          return _HandleGetClassReq(self, params, req);
1576 mike     1.1         }
1577              
1578 krisbash 1.4 
1579 mike     1.1         case CreateInstanceReqTag:
1580                      {
1581                          CreateInstanceReq* req = (CreateInstanceReq*)msg;
1582 krisbash 1.4             return _HandleCreateInstanceReq(self, params, req);
1583 mike     1.1         }
1584              
1585                      case ModifyInstanceReqTag:
1586                      {
1587                          ModifyInstanceReq* req = (ModifyInstanceReq*)msg;
1588 krisbash 1.4             return _HandleModifyInstanceReq(self, params, req);
1589 mike     1.1         }
1590              
1591                      case DeleteInstanceReqTag:
1592                      {
1593                          DeleteInstanceReq* req = (DeleteInstanceReq*)msg;
1594 krisbash 1.4             return _HandleDeleteInstanceReq(self, params, req);
1595 mike     1.1         }
1596              
1597                      case InvokeReqTag:
1598                      {
1599                          InvokeReq* req = (InvokeReq*)msg;
1600 krisbash 1.4             return _HandleInvokeReq(self, params, req);
1601                      }
1602              
1603                      case EnumerateInstancesReqTag:
1604                      {
1605                          EnumerateInstancesReq* req = (EnumerateInstancesReq*)msg;
1606                          return _HandleEnumerateInstancesReq(self, params, req);
1607 mike     1.1         }
1608              
1609                      case AssociatorsOfReqTag:
1610                      {
1611 krisbash 1.4             AssociationsOfReq* req = (AssociationsOfReq*)msg;
1612                          return _HandleAssociatorsOfReq(self, params, req);
1613 mike     1.1         }
1614              
1615                      case ReferencesOfReqTag:
1616                      {
1617 krisbash 1.4             AssociationsOfReq* req = (AssociationsOfReq*)msg;
1618                          return _HandleReferencesOfReq(self, params, req);
1619 mike     1.1         }
1620              
1621 krisbash 1.4 #ifndef DISABLE_INDICATION
1622              
1623 mike     1.1         case SubscribeReqTag:
1624                      {
1625 krisbash 1.4             return _HandleSubscribeReq(self, params);
1626 mike     1.1         }
1627              
1628 krisbash 1.4 #endif /* ifndef DISABLE_INDICATION */
1629              
1630 mike     1.1         default:
1631                      {
1632                          /* Unsupported mesage type */
1633 krisbash 1.4             trace_DispUnsupportedMessage( self, 
1634                              params->interaction, 
1635                              msg,
1636                              msg->tag,
1637                              MessageName(msg->tag),
1638                              msg->operationId );
1639                          return MI_RESULT_NOT_SUPPORTED;
1640 mike     1.1         }
1641                  }
1642              }

ViewCVS 0.9.2