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

Diff for /omi/disp/disp.c between version 1.3 and 1.4

version 1.3, 2015/04/20 18:10:11 version 1.4, 2015/04/20 18:19:51
Line 22 
Line 22 
 **============================================================================== **==============================================================================
 */ */
  
 #include <base/strings.h>  #include <pal/strings.h>
   #include <pal/format.h>
 #include <base/messages.h> #include <base/messages.h>
   #include <base/Strand.h>
 #include <base/log.h> #include <base/log.h>
 #include <base/strings.h>  
 #include <base/paths.h> #include <base/paths.h>
 #include <base/io.h>  #include <pal/hashmap.h>
 #include <base/hashtable.h>  #include <base/naming.h>
 #include <wql/wql.h> #include <wql/wql.h>
 #include "disp.h" #include "disp.h"
   #include <omi_error/errorutil.h>
  
 #define T MI_T  /*
   **==============================================================================
   */
   
   #define DISPENUMPARENT_STRANDAUX_ENUMDONE      0
   
   STRAND_DEBUGNAME1( DispEnumParent, EnumDone );
   STRAND_DEBUGNAME( DispEnumEntry );
  
 /* /*
 **============================================================================== **==============================================================================
Line 45 
Line 54 
 typedef struct _ClassNameBucket /* derives from HashBucket */ typedef struct _ClassNameBucket /* derives from HashBucket */
 { {
     struct _ClassNameBucket* next;     struct _ClassNameBucket* next;
     char* key;      ZChar* key;
 } }
 ClassNameBucket; ClassNameBucket;
  
Line 55 
Line 64 
     /* Note: this algorithm has a poor distribution */     /* Note: this algorithm has a poor distribution */
     ClassNameBucket* bucket = (ClassNameBucket*)bucket_;     ClassNameBucket* bucket = (ClassNameBucket*)bucket_;
     size_t h = 0;     size_t h = 0;
     char* key = bucket->key;      ZChar* key = bucket->key;
  
     while (*key)     while (*key)
     {     {
Line 71 
Line 80 
 { {
     ClassNameBucket* bucket1 = (ClassNameBucket*)bucket1_;     ClassNameBucket* bucket1 = (ClassNameBucket*)bucket1_;
     ClassNameBucket* bucket2 = (ClassNameBucket*)bucket2_;     ClassNameBucket* bucket2 = (ClassNameBucket*)bucket2_;
     return Strcasecmp(bucket1->key, bucket2->key) == 0;      return Tcscasecmp(bucket1->key, bucket2->key) == 0;
 } }
  
 static void ClassNameRelease( static void ClassNameRelease(
Line 79 
Line 88 
 { {
     ClassNameBucket* bucket = (ClassNameBucket*)bucket_;     ClassNameBucket* bucket = (ClassNameBucket*)bucket_;
  
     free(bucket->key);      PAL_Free(bucket->key);
     free(bucket);      PAL_Free(bucket);
 } }
  
 /* /*
 **============================================================================== **==============================================================================
 ** **
 ** Data structures  ** Local definitions
 ** **
 **============================================================================== **==============================================================================
 */ */
  
 /*  typedef struct _DispEnumParent
     subscription item - represents single subscription;  
 */  
 typedef struct _DispSubscriptionItem  
 { {
     struct _DispSubscriptionItem* next;      StrandMany              strand;
     struct _DispSubscriptionItem* prev;      Disp*                   disp;
       RequestMsg*             baseRequest;
     /* The batch this context was allocated from */      MI_Result               result;
     Batch batch;      MI_Boolean              done;
   
     /* filter */  
     MI_ConstString  filter;  
     MI_ConstString  language;  
   
     /* unique id of the sub */  
     MI_Uint64       subscriptionID;  
   
     /* Client identifier if supported */  
     MI_Uint64 clientID;  
   
 } }
 DispSubscriptionItem;  DispEnumParent;
  
   typedef struct _EnumEntry EnumEntry;
  
 /* subscriptions context -  struct _EnumEntry
     used to track indicaiton providers  
     and store indications for 'pull' operation  
     one context per ns/cn pair  
 */  
 typedef struct _DispIndicationContext  
 { {
     struct _DispIndicationContext* next;      StrandEntry             strand;
     struct _DispIndicationContext* prev;      const ZChar*            className;
       EnumEntry*              next;       // Links the entries that are about to be dispatched
     /* The batch this context was allocated from */                                          // We cannot use list on StrandMany as that one can get modify in the meantime
     Batch batch;                                          // as the interactions are being dinamically closed themselves
                                           // (that is why that list requires to be in the strand to use it)
     /* namespace/cn */  };
     MI_ConstString  nameSpace;  
     MI_ConstString  className;  MI_INLINE void _DispEnumParent_Delete(
       _In_ DispEnumParent* self)
     /* unique id of the context (used by ProvMgr) */  {
     MI_Uint64       ctxID;      trace_DispDeleteInteraction(self);
       Message_Release( &self->baseRequest->base );
     /* provider info */      StrandMany_Delete(&self->strand);
     const ProvRegEntry* provEntry;  }
   
     /* exisitng subscriptions */  // interaction is already opened, we can have left the Strand or not indicated by leftStrand
     DispSubscriptionItem* headSubscriptions;  static void _SendErrorResponse_Opened(
     DispSubscriptionItem* tailSubscriptions;      _Inout_ InteractionOpenParams* interactionParams,
 }      _In_ DispEnumParent* self,
 DispIndicationContext;      _In_ MI_Result r,
       MI_Boolean leftStrand
       )
 /*  
 **==============================================================================  
 **  
 ** Local definitions  
 **  
 **==============================================================================  
 */  
 static MI_Result _SendErrorResponse(  
     Message* req,  
     MI_Result r);  
   
 static DispIndicationContext* _FindIndCtxByNScn(  
     Disp* self,  
     MI_ConstString  nameSpace,  
     MI_ConstString  className)  
 { {
     DispIndicationContext* current = (DispIndicationContext*)self->headIndCtx;      PostResultMsg* openResp = PostResultMsg_NewAndSerialize( &self->baseRequest->base, NULL, NULL, MI_RESULT_TYPE_MI, r);
  
     while (current)      if( openResp )
     {     {
         if (0 == Zcasecmp(nameSpace, current->nameSpace) &&          if( leftStrand )
             0 == Zcasecmp(className, current->className))          {
             break;              StrandMany_SchedulePost( &self->strand, &openResp->base );
               StrandMany_ScheduleClose( &self->strand );
         current = current->next;  
     }  
     return current;  
 } }
           else
 static DispIndicationContext* _FindIndCtxByID(  
     Disp* self,  
     MI_Uint64 id)  
 { {
     DispIndicationContext* current = (DispIndicationContext*)self->headIndCtx;              Strand_Post( &self->strand.strand, &openResp->base );
               Strand_Close( &self->strand.strand );
     while (current)              Strand_Leave( &self->strand.strand );
           }
           PostResultMsg_Release(openResp);
       }
       else
     {     {
         if (id == current->ctxID)          // delete the object directly
             break;          _DispEnumParent_Delete( self );
  
         current = current->next;          interactionParams->msg = NULL;  // Null this out since we have already sent an Ack
           interactionParams->origin= NULL;  // Null this out since we have already left origin strand
           Strand_FailOpenWithResult(interactionParams, r, PostResultMsg_NewAndSerialize);
     }     }
     return current;  
 } }
  
 static DispSubscriptionItem* _FindSubscriptionItem(  static void _DispEnumParent__SendLastResponse(
     DispIndicationContext* ctx,      _In_ DispEnumParent* interaction
     MI_Uint64 subscriptionID)      )
 { {
     DispSubscriptionItem* item = ctx->headSubscriptions;      PostResultMsg* resp;
  
     while (item)      resp = PostResultMsg_NewAndSerialize(&interaction->baseRequest->base, NULL, NULL, MI_RESULT_TYPE_MI, interaction->result);
       if( resp )
     {     {
         if (item->subscriptionID == subscriptionID)          Strand_Post( &interaction->strand.strand, &resp->base );
             break;          Message_Release(&resp->base);
   
         item = item->next;  
     }  
     return item;  
 } }
  
       Strand_Close( &interaction->strand.strand );
   }
  
 static void _DestroySubscriptionItem(  static void _DispEnumParent_Transport_Post( _In_ Strand* self_, _In_ Message* msg)
     DispSubscriptionItem* item)  
 { {
     Batch_Destroy(&item->batch);      DEBUG_ASSERT( MI_FALSE );  // we dont expect any additional messages at this point
 } }
 static void _DestroyIndCtx(  
     DispIndicationContext* ctx)  
 {  
     DispSubscriptionItem* item = ctx->headSubscriptions;  
  
     while (item)  static void _DispEnumParent_Transport_PostControl( _In_ Strand* self, _In_ Message* msg)
     {     {
         DispSubscriptionItem* next = item->next;      DEBUG_ASSERT( MI_FALSE );  // not used yet
   
         _DestroySubscriptionItem(item);  
         item = next;  
     }     }
     Batch_Destroy(&ctx->batch);  
 }  
   
  
 static MI_Result _FindCreateIndCtx(  static void _DispEnumParent_Transport_Cancel( _In_ Strand* self)
     Disp* self,  
     SubscribeReq* req,  
     ProvRegEntry const** reg)  
 { {
     /* look for exisiting first */      // not used yet
     DispIndicationContext* ctx = _FindIndCtxByNScn( self, req->nameSpace, req->className );  }
  
     if (!ctx)  static void _DispEnumParent_Finished( _In_ Strand* self_)
     {     {
         Batch batch = BATCH_INITIALIZER;      DispEnumParent* self = (DispEnumParent*)StrandMany_FromStrand(self_);
       _DispEnumParent_Delete( self );
         /* Allocate heap space for message */  }
         ctx = (DispIndicationContext*) Batch_GetClear(&batch, sizeof(DispIndicationContext) );  
  
         if (!ctx)  //DISPENUMPARENT_STRANDAUX_ENUMDONE
             return MI_RESULT_FAILED;  static void _DispEnumParent_EnumDone( _In_ Strand* self_)
   {
       DispEnumParent* self = (DispEnumParent*)StrandMany_FromStrand(self_);
  
         /* Copy batch into context (released by _Destroy method) */      trace_DispEnumDone(self, self->strand.numEntries, self->result );
         memcpy(&ctx->batch, &batch, sizeof(batch));  
  
         ctx->className = Batch_Zdup(&batch, req->className);      self->done = MI_TRUE;
         ctx->nameSpace = Batch_Zdup(&batch, req->nameSpace);  
  
         if (!ctx->className || !ctx->nameSpace)      if( 0 == self->strand.numEntries )
         {         {
             _DestroyIndCtx(ctx);          _DispEnumParent__SendLastResponse( self );
             return MI_RESULT_FAILED;      }
         }         }
         ctx->ctxID = ++self->nextID;  
  
         /* Look for provider info */  /*
         ctx->provEntry = ProvReg_FindProviderForClass(&self->provreg,      This object manages a a "Parent" enumeration on the dispatcher level.
             req->nameSpace, req->className);      Enumerations in this context include also Associations and References.
       The dispatcher converts that parent enumertion coming from the client
       into several actual child enumerations that can go to the same or different providers
       for each of those child enumerations a "EnumEntry" object (see more info below) will be
       created and attached to this Parent enumeration using the one-to-many
       strand interface (StrandMany).
   
       Behavior:
       - Post and PostControl are not used yet as no secondary messages after
          initial request are issued currently
       - Cancel is also not implememented as Cancelation e2e is not implemented
       - Shutdown:
          once all the child enumerations have been issued DISPENUMPARENT_STRANDAUX_ENUMDONE
          is scheduled on the parent, what in turn set the done flag to true and sends the last response
          (final result) to the transport. That would happen if all the enumerations ran in the same thread
          as by that point all of them would have completed. However if one or more enumerations
          are run in the own thread (by the provider or out-of-proc) then may not be completed
          at that point and then the sending of last response and shutdown will occur once
          the last enumeration is closed and deleted and the parent is notified on
          _DispEnumParent_Entry_Deleted (implemented below on the internal FT)
   
       Internal interface and unique features:
       - When a message is sent internally (from EnumEntry) it is just sent pass
          thru to the transport EXCEPT if it is a PostResultMsg as in that case the result
          is just stored internally (if it is not success) as we are only returning one single
          result to the parent interaction (managed on _DispEnumParent_Entry_Post below)
   */
   static StrandFT _DispEnumParent_TransportFT = {
       _DispEnumParent_Transport_Post,
       _DispEnumParent_Transport_PostControl,
       NULL,
       _DispEnumParent_Transport_Cancel,
       NULL,
       _DispEnumParent_Finished,
       NULL,
       _DispEnumParent_EnumDone,
       NULL,
       NULL,
       NULL,
       NULL };
   
   static void _DispEnumEntry_Provider_PostControl( _In_ Strand* self, _In_ Message* msg)
   {
       DEBUG_ASSERT( MI_FALSE );  // not used yet
   }
  
         if (!ctx->provEntry)  static void _DispEnumEntry_Provider_Close( _In_ Strand* self )
   {
       if(!self->info.thisClosedOther)
         {         {
             _DestroyIndCtx(ctx);          // Just close back
             return MI_RESULT_INVALID_NAMESPACE;          Strand_Close( self );
         }         }
   
         /* add context to the list */  
         List_Append(&self->headIndCtx, &self->tailIndCtx, (ListElem*)ctx);  
     }     }
  
     /* Update request with correct IDs */  /*
     req->ctxID = ctx->ctxID;      This object manages the interaction wich each particular provider enumeration
     req->subscriptionID = ++self->nextID;      that a parent provider is divided into (see more info above on _DispEnumParent_TransportFT)
   
     /* Set out parameter */  
     *reg = ctx->provEntry;  
  
     return MI_RESULT_OK;      Behavior:
 }      - PostControl is not used yet
       - Posts are just passed pass thru (and acks are managed by StrandMany)
       - Shutdown: once the provider side closes the interaction this object closes the
          interaction back what will trigger automatically deletion of the object
   */
   static StrandFT _DispEnumEntry_ProviderFT = {
       NULL,
       _DispEnumEntry_Provider_PostControl,
       NULL,
       NULL,
       _DispEnumEntry_Provider_Close,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL };
  
 static MI_Result _UpdateIndicationCtxWithSub(  static void _DispEnumParent_Entry_Deleted( _In_ StrandMany* self_ )
     Disp* self,  
     SubscribeReq* dispReq)  
 { {
     DispIndicationContext* ctx;      DispEnumParent* self = (DispEnumParent*)self_;
     DispSubscriptionItem* subItem;  
   
     ctx = _FindIndCtxByID( self, dispReq->ctxID );  
  
     /* unlikely, but it can be removed by other operation */      DEBUG_ASSERT( NULL != self );
     if (!ctx)  
         return MI_RESULT_FAILED;  
   
     /* */  
     subItem = _FindSubscriptionItem(ctx, dispReq->subscriptionID);  
  
     if (subItem)      trace_DispEntryDeleted(self, self->strand.numEntries, self->done );
         return MI_RESULT_ALREADY_EXISTS;  
  
       if( self->done && 0 == self->strand.numEntries )
     {     {
         Batch batch = BATCH_INITIALIZER;          _DispEnumParent__SendLastResponse( self );
       }
   }
  
         /* Allocate heap space for message */  static void _DispEnumParent_Entry_Post( _In_ StrandMany* self_, _In_ Message* msg)
         subItem = (DispSubscriptionItem*) Batch_GetClear(&batch, sizeof(DispSubscriptionItem) );  {
       DispEnumParent* self = (DispEnumParent*)self_;
  
         if (!subItem)      DEBUG_ASSERT( NULL != self );
             return MI_RESULT_FAILED;  
  
         /* Copy batch into context (released by _Destroy method) */      trace_DispPostingMessage( self->strand.strand.info.interaction.other, self_);
         memcpy(&subItem->batch, &batch, sizeof(batch));  
  
         subItem->filter = Batch_Zdup(&batch, dispReq->filter);      if( PostResultMsgTag == msg->tag )
         subItem->language = Batch_Zdup(&batch, dispReq->language);      {
           PostResultMsg* rsp = (PostResultMsg*)msg;
  
         if (!subItem->filter || !subItem->language)          if( MI_RESULT_OK != rsp->result && MI_RESULT_OK == self->result )
         {         {
             _DestroySubscriptionItem(subItem);              self->result = rsp->result;
             return MI_RESULT_FAILED;  
         }         }
         subItem->subscriptionID = dispReq->subscriptionID;  
         subItem->clientID = dispReq->base.request->clientID;  
  
         /* add item to the context */          // This is not posted here
         List_Append(      }
             (ListElem**)&ctx->headSubscriptions,      else
             (ListElem**)&ctx->tailSubscriptions,      {
             (ListElem*)subItem);          Strand_Post( &self->strand.strand, msg );
     }     }
   
     return MI_RESULT_OK;  
 } }
  
 static void _ProcessSubscribeResponse(  // used for enums, associators, references and subcriptions
     Disp* self,  static StrandManyInternalFT _DispEnumParent_InternalFT = {
     PostResultMsg* rsp)      NULL,
       _DispEnumParent_Entry_Deleted,
       _DispEnumParent_Entry_Post,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL };
   
   static MI_Result _DispatchEnumerateInstancesReq(
       _In_ Disp* disp,
       _In_ EnumerateInstancesReq* request,
       _In_ const ZChar* className,
       _In_opt_ EnumEntry* enumEntry,
       _In_opt_ InteractionOpenParams* interactionParams )
 { {
     MI_Result r;      const ProvRegEntry* provEntry;
     SubscribeReq* dispReq = (SubscribeReq*)rsp->base.request;      MI_Result result;
       EnumerateInstancesReq* msg;
       AgentMgr_OpenCallbackData openCallbackData;
     /* Find context, create subscription struct */  
     Mutex_Lock(&self->mt);  
  
     r = _UpdateIndicationCtxWithSub( self, dispReq );      DEBUG_ASSERT( NULL != className );
  
     Mutex_Unlock(&self->mt);      /* Attempt to find a provider for this class */
       provEntry = ProvReg_FindProviderForClass(&disp->provreg,
           request->nameSpace, className, &result );
  
     /* check if error was detected */      if (!provEntry)
     if (MI_RESULT_OK != r)  
     {     {
         _SendErrorResponse(rsp->base.request->request, r);          return MI_RESULT_NOT_SUPPORTED;
     }     }
  
     /* send subscription response */      /* Create new request to send to provider */
       msg = EnumerateInstancesReq_New(request->base.base.operationId, request->base.base.flags);
       if( NULL == msg )
     {     {
         SubscribeRes* resp;          trace_DispatchEnumerateInstancesReq_OutOfMemory();
         char s[50];          return MI_RESULT_SERVER_LIMITS_EXCEEDED;
   
         resp = SubscribeRes_New( rsp->base.request->request->msgID );  
   
         if (!resp)  
             return ;  
   
         Snprintf(s, MI_COUNT(s), UINT64_FMT "," UINT64_FMT,  
             dispReq->ctxID,  
             dispReq->subscriptionID);  
   
         resp->subscriptionID = Batch_Strdup2(resp->base.batch, s);  
   
         Message_SetRequest(&resp->base,rsp->base.request->request);  
         (*rsp->base.request->request->callback)(&resp->base, rsp->base.request->request->callbackData);  
   
         SubscribeRes_Release(resp);  
     }     }
  
 }      msg->base.options = request->base.options;
       AuthInfo_Copy( &msg->base.authInfo, &request->base.authInfo );
       msg->nameSpace = Batch_Tcsdup(msg->base.base.batch, request->nameSpace);
       msg->className = Batch_Tcsdup(msg->base.base.batch, className);
       msg->base.userAgent = request->base.userAgent;
  
 static void _ProviderToDispatcherCallback(      if (!msg->nameSpace || !msg->className)
     Message* msg,  
     void* callbackData)  
 {  
     switch ( msg->tag )  
     {     {
         case PostResultMsgTag:          goto OutOfMemory;
         {      }
             PostResultMsg* rsp = (PostResultMsg*)msg;  
  
             if (msg->request && msg->request->request &&  msg->request->request->tag == DispResultMsgTag)      /* Clone the query fields (if any) */
       if (request->queryLanguage)
             {             {
                 DispResultMsg* dispStateMsg = (DispResultMsg*)msg->request->request;          msg->queryLanguage = Batch_Tcsdup(msg->base.base.batch, request->queryLanguage);
           if (!msg->queryLanguage)
                 if (rsp->result != MI_RESULT_OK && dispStateMsg->result == MI_RESULT_OK)  
                 {                 {
                     dispStateMsg->result = rsp->result;              goto OutOfMemory;
                 }                 }
   
                 if ( AtomicDec(&dispStateMsg->requestCounter) )  
                 {   /* last result - forward it to the net stack */  
                     rsp->result = dispStateMsg->result;  
                 }                 }
                 else    /* not the last result - skip it */  
                     return;  
  
             }      if( request->queryExpression )
             else if (msg->request && msg->request->tag == SubscribeReqTag)  
             {             {
                 /* process subscription response */          msg->queryExpression = Batch_Tcsdup(msg->base.base.batch,request->queryExpression);
                 if (MI_RESULT_OK != rsp->result )          if (!msg->queryExpression)
                     break;  
   
                 /*  
                     validate parameter msg->request->request is a parameter received from network transport;  
                     msg->request is a message created by disp for provmgr  
                 */  
                 if (msg->request->request)  
                 {                 {
                     _ProcessSubscribeResponse((Disp*)callbackData, rsp);              goto OutOfMemory;
                     return;  
                 }  
             }  
         }         }
         break;  
   
         default:  
             break;  
     }     }
  
     /* forward message to the other side */      /* Save request's class name to allow provmgr pack back only base properties */
     if (msg->request && msg->request->request)      if( request->basePropertiesOnly )
     {     {
         /* delegate message to protocol stack */          msg->requestClassName = Batch_Tcsdup(msg->base.base.batch, request->className);
         msg->clientID = msg->request->request->clientID;          if (!msg->requestClassName)
         (*msg->request->request->callback)(msg, msg->request->request->callbackData);  
     }  
     else if (msg->request)  
     {  
         /* delegate message to protocol stack */  
         msg->clientID = msg->request->clientID;  
         (*msg->request->callback)(msg, msg->request->callbackData);  
     }  
     else  
     {     {
         (*msg->callback)(msg, msg->callbackData);              goto OutOfMemory;
     }     }
 } }
  
 static MI_Boolean _DispatchEnumerateInstancesReq(      openCallbackData.self = &disp->agentmgr;
     Disp* self,      openCallbackData.proventry = provEntry;
     const MI_Char* className,  
     const EnumerateInstancesReq* req,  
     DispResultMsg* dispStateMsg)  
 {  
     const ProvRegEntry* entry;  
     EnumerateInstancesReq* msg;  
     MI_Result r;  
  
     /* Attempt to find a provider for this class */      if( NULL != enumEntry )
     {     {
         entry = ProvReg_FindProviderForClass(&self->provreg,          trace_DispatchEnumDispInteraction(tcs(className));
             req->nameSpace, className);  
  
         if (!entry)          /* Send the request to provider manager */
             return MI_FALSE;          Strand_Open( &enumEntry->strand.strand, AgentMgr_OpenCallback, &openCallbackData, &msg->base.base, MI_TRUE );
     }     }
       else
       {
           DEBUG_ASSERT( NULL != interactionParams );
  
     /* Create new request to send to provider */          // send it directly to AgentMgr
     msg = EnumerateInstancesReq_New(req->base.msgID, req->base.flags);          interactionParams->callbackData = &openCallbackData;
     msg->base.clientID = req->base.clientID;          interactionParams->msg = &request->base.base;
     msg->base.uid = req->base.uid;  
     msg->base.gid = req->base.gid;  
     msg->nameSpace = Batch_Zdup(msg->base.batch, req->nameSpace);  
     msg->className = Batch_Zdup(msg->base.batch, className);  
   
     /* Clone the query fields (if any) */  
     if (req->queryLanguage)  
         msg->queryLanguage = Batch_Zdup(msg->base.batch, req->queryLanguage);  
   
     if (req->queryExpression)  
         msg->queryExpression = Batch_Zdup(msg->base.batch,req->queryExpression);  
   
     if (req->wql)  
         msg->wql = WQL_Clone(req->wql, msg->base.batch);  
   
     /* Save request's class name to allow porvmgr pack back only base properties */  
     if (req->basePropertiesOnly)  
         msg->requestClassName = Batch_Zdup(msg->base.batch, req->className);  
   
     AtomicInc(&dispStateMsg->requestCounter);  
     Message_SetRequest(&msg->base, &dispStateMsg->base);  
  
     /* Setup callback */          trace_DispatchEnumDirectly(tcs(className));
     msg->base.callback = _ProviderToDispatcherCallback;  
     msg->base.callbackData = self;  
  
     /* Send the request to provider manager */          AgentMgr_OpenCallback( interactionParams );
     r = AgentMgr_HandleRequest(&self->agentmgr, &msg->base, entry);      }
  
     /* Release the original message */     /* Release the original message */
     EnumerateInstancesReq_Release(msg);     EnumerateInstancesReq_Release(msg);
  
     /* Log failure */      return MI_RESULT_OK;
     if (r != MI_RESULT_OK)  
     {  
         LOGW((T("AgentMgr_HandleRequest() failed: %u: %s"), r,  
             Result_ToString(r)));  
   
         AtomicDec(&dispStateMsg->requestCounter);  
         return MI_FALSE;  
     }  
  
   OutOfMemory:
       trace_DispatchEnumerateInstancesReq_OutOfMemory();
       EnumerateInstancesReq_Release(msg);
  
     return MI_TRUE;      return MI_RESULT_SERVER_LIMITS_EXCEEDED;
 } }
  
   // Also used for References
 static MI_Boolean _DispatchAssocReq( static MI_Boolean _DispatchAssocReq(
     Disp* self,      _In_ Disp* disp,
     const MI_Char* className,      _In_ AssociationsOfReq* req,
     const AssociatorsOfReq* req,      _In_ EnumEntry* enumEntry,
     DispResultMsg* dispStateMsg)      MessageTag tag )
 { {
     const ProvRegEntry* entry;     const ProvRegEntry* entry;
     AssociatorsOfReq* msg;      AssociationsOfReq* msg;
     MI_Result r;      const ZChar* className = enumEntry->className;
       MI_Result result;
       AgentMgr_OpenCallbackData openCallbackData;
  
     /* Attempt to find a provider for this class */     /* Attempt to find a provider for this class */
     {      entry = ProvReg_FindProviderForClass(&disp->provreg,
         entry = ProvReg_FindProviderForClass(&self->provreg,          req->nameSpace, className, &result );
             req->nameSpace, className);  
  
         if (!entry)         if (!entry)
       {
           trace__DispatchAssocReq_OutOfMemory();
             return MI_FALSE;             return MI_FALSE;
     }     }
  
     /* Create new request to send to provider */     /* Create new request to send to provider */
     msg = AssociatorsOfReq_New(req->base.msgID, req->base.flags);      msg = AssociationsOfReq_New(req->base.base.operationId, req->base.base.flags, tag);
     msg->base.clientID = req->base.clientID;      msg->base.options = req->base.options;
     msg->base.uid = req->base.uid;      AuthInfo_Copy( &msg->base.authInfo, &req->base.authInfo );
     msg->base.gid = req->base.gid;  
     /* original request will be kept for the request duration, so perform shallow copy only */     /* original request will be kept for the request duration, so perform shallow copy only */
     /*ATTN! perform full copy*/  
     msg->nameSpace = req->nameSpace;     msg->nameSpace = req->nameSpace;
     msg->assocClass = req->assocClass;     msg->assocClass = req->assocClass;
     msg->resultClass = req->resultClass;     msg->resultClass = req->resultClass;
Line 552 
Line 493 
     msg->instance = req->instance;     msg->instance = req->instance;
     msg->packedInstancePtr = req->packedInstancePtr;     msg->packedInstancePtr = req->packedInstancePtr;
     msg->packedInstanceSize = req->packedInstanceSize;     msg->packedInstanceSize = req->packedInstanceSize;
       msg->base.userAgent = req->base.userAgent;
  
     msg->className = className;      msg->className = Batch_Tcsdup(msg->base.base.batch, className);
  
     AtomicInc(&dispStateMsg->requestCounter);      trace_DispatchAssoc(tcs(className));
     Message_SetRequest(&msg->base, &dispStateMsg->base);  
   
     /* Setup callback */  
     msg->base.callback = _ProviderToDispatcherCallback;  
     msg->base.callbackData = self;  
  
     /* Send the request to provider manager */     /* Send the request to provider manager */
     r = AgentMgr_HandleRequest(&self->agentmgr, &msg->base, entry);      openCallbackData.self = &disp->agentmgr;
       openCallbackData.proventry = entry;
       Strand_Open( &enumEntry->strand.strand, AgentMgr_OpenCallback, &openCallbackData, &msg->base.base, MI_TRUE );
  
     /* Release the original message */     /* Release the original message */
     AssociatorsOfReq_Release(msg);      AssociationsOfReq_Release(msg);
   
     /* Log failure */  
     if (r != MI_RESULT_OK)  
     {  
         LOGW((T("AgentMgr_HandleRequest() failed: %u: %s"), r,  
             Result_ToString(r)));  
   
         AtomicDec(&dispStateMsg->requestCounter);  
         return MI_FALSE;  
     }  
  
     return MI_TRUE;     return MI_TRUE;
 } }
  
 static MI_Boolean _DispatchRefReq(  DispEnumParent* _DispEnumParent_New(
     Disp* self,      _In_ Disp*                  disp,
     const MI_Char* className,      _In_ InteractionOpenParams* interactionParams )
     const ReferencesOfReq* req,  
     DispResultMsg* dispStateMsg)  
 { {
     const ProvRegEntry* entry;      DispEnumParent* self;
     ReferencesOfReq* msg;  
     MI_Result r;  
  
     /* Attempt to find a provider for this class */      self = (DispEnumParent*)StrandMany_New(
                   STRAND_DEBUG( DispEnumParent )
                   &_DispEnumParent_TransportFT,
                   &_DispEnumParent_InternalFT,
                   sizeof( DispEnumParent ),
                   STRAND_FLAG_ENTERSTRAND,
                   interactionParams,
                   1,
                   NULL,
                   NULL,
                   NULL);
   
       if(self)
     {     {
         entry = ProvReg_FindProviderForClass(&self->provreg,          RequestMsg* req = (RequestMsg*)interactionParams->msg;
             req->nameSpace, className);          DEBUG_ASSERT( NULL != req );
  
         if (!entry)          Message_AddRef( &req->base );
             return MI_FALSE;          self->baseRequest = req;
     }  
  
     /* Create new request to send to provider */          self->disp = disp;
     msg = ReferencesOfReq_New(req->base.msgID, req->base.flags);          self->result = MI_RESULT_OK;
     msg->base.clientID = req->base.clientID;  
     msg->base.uid = req->base.uid;  
     msg->base.gid = req->base.gid;  
     /* original request will be kept for the request duration, so perform shallow copy only */  
     /*ATTN! perform full copy*/  
     msg->nameSpace = req->nameSpace;  
     msg->assocClass = req->assocClass;  
     msg->role = req->role;  
     msg->instance = req->instance;  
     msg->packedInstancePtr = req->packedInstancePtr;  
     msg->packedInstanceSize = req->packedInstanceSize;  
  
     msg->className = className;          // As soon as we accept the open we can send the open msg ack
           Strand_Ack( &self->strand.strand );
       }
  
     AtomicInc(&dispStateMsg->requestCounter);      return self;
     Message_SetRequest(&msg->base, &dispStateMsg->base);  }
  
     /* Setup callback */  static MI_Result _HandleGetInstanceReq(
     msg->base.callback = _ProviderToDispatcherCallback;      _In_ Disp* self,
     msg->base.callbackData = self;      _Inout_ InteractionOpenParams* interactionParams,
       _In_ GetInstanceReq* req)
   {
       MI_Result r;
       const ProvRegEntry* reg;
  
     /* Send the request to provider manager */      /* Validate input parameters */
     r = AgentMgr_HandleRequest(&self->agentmgr, &msg->base, entry);      if (!req->instanceName || !req->nameSpace)
           return MI_RESULT_INVALID_PARAMETER;
  
     /* Release the original message */      // Find a provider for this class.
     ReferencesOfReq_Release(msg);      reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,
           req->instanceName->classDecl->name, &r );
  
     /* Log failure */      if (!reg)
     if (r != MI_RESULT_OK)  
     {     {
         LOGW((T("AgentMgr_HandleRequest() failed: %u: %s"), r,          trace_NoProviderForClass(
             Result_ToString(r)));              req->nameSpace,
               req->instanceName->classDecl->name);
         AtomicDec(&dispStateMsg->requestCounter);          goto sendErrorBack;
         return MI_FALSE;  
     }     }
  
     return MI_TRUE;      // Send the request to provider manager.
 }      r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, reg);
  
 static MI_Result _SendErrorResponse(      if (r != MI_RESULT_OK)
     Message* req,  
     MI_Result r  
     )  
 { {
     PostResultMsg* resp;          trace_AgentMgrHandleRequestForNS(
               req->nameSpace);
     resp = PostResultMsg_New( req->msgID );          goto sendErrorBack;
       }
     if (!resp)  
         return MI_RESULT_FAILED;  
   
     resp->result = r;  
     Message_SetRequest(&resp->base,req);  
     (*req->callback)(&resp->base, req->callbackData);  
   
     PostResultMsg_Release(resp);  
  
     return MI_RESULT_OK;     return MI_RESULT_OK;
   
   sendErrorBack:
       // Just abort creating any interaction at all
       return r;
 } }
  
 static MI_Result _HandleEnumerateInstancesReq(  static MI_Result _HandleGetClassReq(
     Disp* self,      _In_ Disp* self,
     EnumerateInstancesReq* req)      _Inout_ InteractionOpenParams* interactionParams,
       _In_ GetClassReq* req)
 { {
     ProvRegPosition pos;  
     MI_Result r;     MI_Result r;
     MI_Boolean sentOk = MI_FALSE;      const ProvRegEntry* reg;
     DispResultMsg* dispStateMsg;      ProvRegEntry freg;
       ProvRegPosition pos;
  
     /* Validate input parameters */     /* Validate input parameters */
     if (!req->className || !req->nameSpace)     if (!req->className || !req->nameSpace)
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
  
     /* create a state message that will keep track of results from providers */      // client must specify classname for GetClass request
     dispStateMsg = DispResultMsg_New(req->base.msgID);      if(Tcscmp(req->className, PAL_T("*")) == 0)
     if (!dispStateMsg)          return MI_RESULT_INVALID_CLASS;
         return MI_RESULT_FAILED;  
  
     /* add one for sending thread so first 'fast' provider will not send its response all the way */      memset( &freg, 0, sizeof(freg) );
     AtomicInc(&dispStateMsg->requestCounter);  
  
     dispStateMsg->base.clientID = req->base.clientID;      // Find a provider for this class.
     /* Setup callback */      reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,
     dispStateMsg->base.callback = req->base.callback;          req->className, &r );
     dispStateMsg->base.callbackData = req->base.callbackData;  
  
     /* Precompile the query */      if (!reg)
     if (req->queryLanguage || req->queryExpression)  
     {     {
         /* Fail if either query language or expression is missing */          if(MI_RESULT_INVALID_CLASS == r)
         if (!req->queryLanguage || !req->queryExpression)  
         {         {
             LOGW((T("queryLanguage or queryExpression is missing")));              /* Checking if the requested class is a base class of an implemented class */
             r = MI_RESULT_INVALID_QUERY;              r = ProvReg_BeginClasses(&self->provreg, req->nameSpace,
             goto sendErrorBack;                      req->className, MI_TRUE, &pos, MI_FALSE);
         }  
  
         /* Reject non-WQL queries */              if(MI_RESULT_INVALID_CLASS == r)
         if (Zcmp(req->queryLanguage, T("WQL")) != 0)  
         {         {
             LOGW((T("unknown query language: %s"), req->queryLanguage));                  /* Checking if the requested class is an extraclass (Class without key property or Class with key property but not part of any
             r = MI_RESULT_QUERY_LANGUAGE_NOT_SUPPORTED;                      class heirarchy of an implemented class.)
             goto sendErrorBack;                      Class with valid providerFT is called as an implemented class */
         }  
  
         /* Compile the query */                  /* In extra classes inheritance tree a namespace node is created only if there is at least one extra class in the namespace.
         {                      So namespace node need not exist in extra classes inheritance tree even for valid namespace */
             req->wql = WQL_Parse(req->queryExpression, req->base.batch);                  r = ProvReg_BeginClasses(&self->provreg, req->nameSpace,
                           req->className, MI_TRUE, &pos, MI_TRUE);
  
             if (!req->wql)                  if(MI_RESULT_INVALID_NAMESPACE == r)
             {                      r = MI_RESULT_INVALID_CLASS;
                 LOGW((T("invalid query expression: %s"), req->queryExpression));  
                 r = MI_RESULT_INVALID_QUERY;  
                 goto sendErrorBack;  
             }  
         }         }
               if (MI_RESULT_OK == r)
         /* Verify that the query classname matches the enumeration classname */  
         if (Zcmp(req->wql->className, req->className) != 0)  
         {         {
             LOGW((T("query/enumeration class name mismatch: %s/%s"),                  DEBUG_ASSERT(pos.start != NULL);
                 req->className, req->className));                  MapRegPositionValuesToRegEntry(&freg, &pos);
             r = MI_RESULT_INVALID_QUERY;                  freg.nameSpace = req->nameSpace;
             goto sendErrorBack;                  freg.nameSpaceHash = Hash(req->nameSpace);
         }         }
     }     }
  
     /* Send to direct name */  
     if (_DispatchEnumerateInstancesReq(self, req->className, req, dispStateMsg))  
         sentOk = MI_TRUE;  
   
     if (req->deepInheritance)  
     {  
         /* Begin enumeration of classes for this request */  
         {  
             r = ProvReg_BeginClasses(&self->provreg, req->nameSpace,  
                 req->className, MI_TRUE, &pos);  
   
             if (MI_RESULT_OK != r)             if (MI_RESULT_OK != r)
             {             {
                 LOGD((T("ProvReg_BeginClasses() failed: %u: %s"),              trace_NoProviderForClass(
                     r, Result_ToString(r)));                  req->nameSpace,
                   req->className);
                 LOGI((T("unknown class in enumerate request: %s:%s"),  
                     req->nameSpace, req->className));  
   
                 /* send error back to caller */  
                 goto sendErrorBack;                 goto sendErrorBack;
             }             }
         }         }
       else
         /* While more classes */  
         for (;;)  
         {         {
             const MI_Char* derived = NULL;          freg = *reg;
             MI_Boolean done;      }
   
             r = ProvReg_NextClass(&pos, &derived, &done);  
  
             if (done)      // Send the request to provider manager.
                 break;      r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, &freg);
  
             if (MI_RESULT_OK != r)      if (r != MI_RESULT_OK)
             {             {
                 LOGD((T("ProvReg_NextClass() failed: %u: %s"),          trace_AgentMgrHandleRequestForNS(
                     r, Result_ToString(r)));              req->nameSpace);
   
                 LOGI((T("unknown class in enumerate request: %s:%s"),  
                     req->nameSpace, req->className));  
   
                 /* send error back to caller */  
                 goto sendErrorBack;                 goto sendErrorBack;
             }             }
  
             if (_DispatchEnumerateInstancesReq(self, derived, req, dispStateMsg))      return MI_RESULT_OK;
                 sentOk = MI_TRUE;  
   sendErrorBack:
       // Just abort creating any interaction at all
       return r;
         }         }
  
         /* Finalize enumeration */  static MI_Result _HandleCreateInstanceReq(
       _In_ Disp* self,
       _Inout_ InteractionOpenParams* interactionParams,
       _In_ CreateInstanceReq* req)
         {         {
             r = ProvReg_EndClasses(&pos);      MI_Result r;
       const ProvRegEntry* reg;
  
             if (MI_RESULT_OK != r)      /* Validate input parameters */
             {      if (!req->instance || !req->nameSpace)
                 LOGD((T("ProvReg_EndClasses() failed: %u: %s"),          return MI_RESULT_INVALID_PARAMETER;
                     r, Result_ToString(r)));  
                 /* send error back to caller */  
                 goto sendErrorBack;  
             }  
         }  
     } /* if deep*/  
  
     /* Fail if no provider was found for request */      // Find a provider for this class.
     if (!sentOk)      reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,
           req->instance->classDecl->name, &r );
   
       if (!reg)
     {     {
         LOGD((T("found no providers for class: %s"), MI_GET_SAFE_PRINTF_STRING(req->className)));          trace_NoProviderForClass(
         r = MI_RESULT_NOT_FOUND;              req->nameSpace,
               req->instance->classDecl->name);
         goto sendErrorBack;         goto sendErrorBack;
     }     }
  
     if ( AtomicDec(&dispStateMsg->requestCounter) )      // Send the request to provider manager.
     {   /* last result - forward it to the net stack */      r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, reg);
         r = dispStateMsg->result;  
       if (r != MI_RESULT_OK)
       {
           trace_AgentMgrHandleRequestForNS(
               req->nameSpace);
         goto sendErrorBack;         goto sendErrorBack;
     }     }
  
     DispResultMsg_Release(dispStateMsg);  
     return MI_RESULT_OK;     return MI_RESULT_OK;
  
 sendErrorBack: sendErrorBack:
     DispResultMsg_Release(dispStateMsg);      // Just abort creating any interaction at all
     return _SendErrorResponse(&req->base,r);      return r;
 } }
  
   static MI_Result _HandleModifyInstanceReq(
 static MI_Result _HandleGetInstanceReq(      _In_ Disp* self,
     Disp* self,      _Inout_ InteractionOpenParams* interactionParams,
     GetInstanceReq* req)      _In_ ModifyInstanceReq* req)
 { {
     MI_Result r;     MI_Result r;
     const ProvRegEntry* reg;     const ProvRegEntry* reg;
  
     /* Validate input parameters */     /* Validate input parameters */
     if (!req->instanceName || !req->nameSpace)      if (!req->instance || !req->nameSpace)
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
  
     // Find a provider for this class.     // Find a provider for this class.
     reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,     reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,
         req->instanceName->classDecl->name );          req->instance->classDecl->name, &r );
  
     if (!reg)     if (!reg)
     {     {
         r = MI_RESULT_INVALID_NAMESPACE; /*ATTN! or class?*/          trace_NoProviderForClass(
         LOGD((T("cannot find provider for class: %s/%s"),              req->nameSpace,
             MI_GET_SAFE_PRINTF_STRING(req->nameSpace),              req->instance->classDecl->name);
             MI_GET_SAFE_PRINTF_STRING(req->instanceName->classDecl->name)));  
         goto sendErrorBack;         goto sendErrorBack;
     }     }
  
     // Send the request to provider manager.     // Send the request to provider manager.
     r = AgentMgr_HandleRequest(&self->agentmgr, &req->base, reg);      r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, reg);
  
     if (r != MI_RESULT_OK)     if (r != MI_RESULT_OK)
     {     {
         LOGD((T("AgentMgr_HandleRequest for namespace: %s"),          trace_AgentMgrHandleRequestForNS(
             MI_GET_SAFE_PRINTF_STRING(req->nameSpace)));              req->nameSpace);
         goto sendErrorBack;         goto sendErrorBack;
     }     }
  
     return MI_RESULT_OK;     return MI_RESULT_OK;
  
 sendErrorBack: sendErrorBack:
     return _SendErrorResponse(&req->base,r);      // Just abort creating any interaction at all
       return r;
 } }
  
 static MI_Result _HandleCreateInstanceReq(  static MI_Result _HandleDeleteInstanceReq(
     Disp* self,      _In_ Disp* self,
     CreateInstanceReq* req)      _Inout_ InteractionOpenParams* interactionParams,
       _In_ DeleteInstanceReq* req)
 { {
     MI_Result r;     MI_Result r;
     const ProvRegEntry* reg;     const ProvRegEntry* reg;
  
     /* Validate input parameters */     /* Validate input parameters */
     if (!req->instance || !req->nameSpace)      if (!req->instanceName || !req->nameSpace)
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
  
     // Find a provider for this class.     // Find a provider for this class.
     reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,     reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,
         req->instance->classDecl->name );          req->instanceName->classDecl->name, &r);
  
     if (!reg)     if (!reg)
     {     {
         r = MI_RESULT_INVALID_NAMESPACE; /*ATTN! or class?*/          trace_NoProviderForClass(
         LOGD((T("cannot find provider for class: %s/%s"),              req->nameSpace,
             MI_GET_SAFE_PRINTF_STRING(req->nameSpace),              req->instanceName->classDecl->name);
             MI_GET_SAFE_PRINTF_STRING(req->instance->classDecl->name)));  
         goto sendErrorBack;         goto sendErrorBack;
     }     }
  
     // Send the request to provider manager.     // Send the request to provider manager.
     r = AgentMgr_HandleRequest(&self->agentmgr, &req->base, reg);      r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, reg);
  
     if (r != MI_RESULT_OK)     if (r != MI_RESULT_OK)
     {     {
         LOGD((T("AgentMgr_HandleRequest for namespace: %s"),          trace_AgentMgrHandleRequestForNS(
             MI_GET_SAFE_PRINTF_STRING(req->nameSpace)));              req->nameSpace);
         goto sendErrorBack;         goto sendErrorBack;
     }     }
  
     return MI_RESULT_OK;     return MI_RESULT_OK;
  
 sendErrorBack: sendErrorBack:
     return _SendErrorResponse(&req->base,r);      // Just abort creating any interaction at all
       return r;
 } }
  
 static MI_Result _HandleModifyInstanceReq(  static MI_Result _HandleInvokeReq(
     Disp* self,      _In_ Disp* self,
     ModifyInstanceReq* req)      _Inout_ InteractionOpenParams* interactionParams,
       _In_ InvokeReq* req)
 { {
     MI_Result r;     MI_Result r;
     const ProvRegEntry* reg;     const ProvRegEntry* reg;
       MI_ConstString cn = 0;
   
       /* Validate input parameters */
       if (!req->nameSpace)
           return MI_RESULT_INVALID_PARAMETER;
   
       if (req->className)
           cn = req->className;
       else if (req->instance)
           cn = req->instance->classDecl->name;
   
       if (!cn)
       {
           r = MI_RESULT_INVALID_CLASS;
           trace_ClassNameIsExpectedForInvoke();
           goto sendErrorBack;
       }
  
     /* Validate input parameters */  
     if (!req->instance || !req->nameSpace)  
         return MI_RESULT_INVALID_PARAMETER;  
  
     // Find a provider for this class.     // Find a provider for this class.
     reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,      reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace, cn, &r);
         req->instance->classDecl->name );  
  
     if (!reg)     if (!reg)
     {     {
         r = MI_RESULT_INVALID_NAMESPACE; /*ATTN! or class?*/          trace_FoundNoProvider(
         LOGD((T("cannot find provider for class: %s/%s"),              cn);
             MI_GET_SAFE_PRINTF_STRING(req->nameSpace),  
             MI_GET_SAFE_PRINTF_STRING(req->instance->classDecl->name)));  
         goto sendErrorBack;         goto sendErrorBack;
     }     }
  
     // Send the request to provider manager.     // Send the request to provider manager.
     r = AgentMgr_HandleRequest(&self->agentmgr, &req->base, reg);      r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, reg);
  
     if (r != MI_RESULT_OK)     if (r != MI_RESULT_OK)
     {     {
         LOGD((T("AgentMgr_HandleRequest for namespace: %s"),          trace_AgentMgrHandleRequestForNS(
             MI_GET_SAFE_PRINTF_STRING(req->nameSpace)));              req->nameSpace);
         goto sendErrorBack;         goto sendErrorBack;
     }     }
  
     return MI_RESULT_OK;     return MI_RESULT_OK;
  
 sendErrorBack: sendErrorBack:
     return _SendErrorResponse(&req->base,r);      // Just abort creating any interaction at all
       return r;
 } }
  
 static MI_Result _HandleDeleteInstanceReq(  static MI_Result _HandleEnumerateInstancesReq(
     Disp* self,      _In_ Disp* self,
     DeleteInstanceReq* req)      _Inout_ InteractionOpenParams* interactionParams,
       _In_ EnumerateInstancesReq* req)
 { {
     MI_Result r;      MI_Result r = MI_RESULT_FAILED;
     const ProvRegEntry* reg;      MI_Boolean sentOk = MI_FALSE;
       WQL_Dialect dialect;
       DispEnumParent* enumInteraction;
       EnumEntry* enumEntry;
       EnumEntry* enumEntryHead = NULL;
  
     /* Validate input parameters */     /* Validate input parameters */
     if (!req->instanceName || !req->nameSpace)      if (!req->nameSpace)
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
  
     // Find a provider for this class.      /* Precompile the query */
     reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,      if (req->queryLanguage || req->queryExpression)
         req->instanceName->classDecl->name);      {
           /* Fail if either query language or expression is missing */
           if (!req->queryLanguage || !req->queryExpression)
           {
               trace_QueryLanguageOrExpressionMissing();
               return MI_RESULT_INVALID_QUERY;
           }
  
     if (!reg)          /* Reject non-WQL queries */
           if (Tcscasecmp(req->queryLanguage, MI_QUERY_DIALECT_WQL) == 0)
     {     {
         r = MI_RESULT_INVALID_NAMESPACE; /*ATTN! or class?*/              dialect = WQL_DIALECT_WQL;
         LOGD((T("cannot find provider for class: %s/%s"),          }
             MI_GET_SAFE_PRINTF_STRING(req->nameSpace),          else if (Tcscasecmp(req->queryLanguage, MI_QUERY_DIALECT_CQL) == 0)
             MI_GET_SAFE_PRINTF_STRING(req->instanceName->classDecl->name)));          {
         goto sendErrorBack;              dialect = WQL_DIALECT_CQL;
           }
           else
           {
               trace_UnsupportedQueryLanguage(tcs(req->queryLanguage));
               return MI_RESULT_QUERY_LANGUAGE_NOT_SUPPORTED;
     }     }
  
     // Send the request to provider manager.          /* Compile the query */
     r = AgentMgr_HandleRequest(&self->agentmgr, &req->base, reg);          {
               req->wql = WQL_Parse(req->queryExpression, req->base.base.batch,
                   dialect);
  
     if (r != MI_RESULT_OK)              if (!req->wql)
     {     {
         LOGD((T("AgentMgr_HandleRequest for namespace: %s"),                  trace_InvalidQueryExpression(tcs(req->queryExpression));
             MI_GET_SAFE_PRINTF_STRING(req->nameSpace)));                  return MI_RESULT_INVALID_QUERY;
         goto sendErrorBack;              }
     }     }
  
     return MI_RESULT_OK;          /* WQL queries from WinRM pass '*' as the class name */
  
 sendErrorBack:          if (!req->className || (Tcscmp(req->className, PAL_T("*")) == 0))
     return _SendErrorResponse(&req->base,r);          {
               req->className = req->wql->className;
 } }
  
 static MI_Result _HandleSubscribeReq(          /* Verify that the query classname matches the enumeration classname */
     Disp* self,          if (Tcscmp(req->wql->className, req->className) != 0)
     SubscribeReq* req)  
 { {
     MI_Result r;              trace_QueryEnumClassnameMismatch(
     const ProvRegEntry* reg = 0;                  tcs(req->wql->className), tcs(req->className));
     SubscribeReq* msg = 0;              return MI_RESULT_INVALID_QUERY;
           }
     /* Validate input parameters */      }
     if (!req->className || !req->nameSpace || !req->language || !req->filter)      else if (!req->className)
       {
           trace_EnumHasNoClassname();
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
       }
  
     // Duplicate incoming request to substitute callback pointer      if (req->deepInheritance)
     msg = SubscribeReq_New(req->base.msgID, req->base.flags);      {
           ProvRegPosition pos;
     msg->base.uid = req->base.uid;          EnumEntry* enumEntryPrev;
     msg->base.gid = req->base.gid;  
     msg->nameSpace = Batch_Zdup(msg->base.batch, req->nameSpace);  
     msg->className = Batch_Zdup(msg->base.batch, req->className);  
     msg->filter = Batch_Zdup(msg->base.batch, req->filter);  
     msg->language = Batch_Zdup(msg->base.batch, req->language);  
  
     msg->base.clientID = req->base.clientID;          /* create the interaction that will keep track of results from providers */
           enumInteraction = _DispEnumParent_New(
                               self,
                               interactionParams);
           if (!enumInteraction)
           {
               trace_Disp_ErrorInteractionAlloc();
               return MI_RESULT_FAILED;
           }
  
     Message_SetRequest(&msg->base, &req->base);          /* Send to direct name */
           /* Start by sending to direct name */
           enumEntry = (EnumEntry*)StrandEntry_New( STRAND_DEBUG( DispEnumEntry )
                                                       &enumInteraction->strand,
                                                       &_DispEnumEntry_ProviderFT,
                                                       sizeof(EnumEntry),
                                                       STRAND_FLAG_ENTERSTRAND,
                                                       NULL);
           if( NULL == enumEntry )
           {
               trace_Disp_ErrorEnumEntryAlloc();
               goto sendErrorBack_Opened;
           }
           r = StrandMany_AddEntry( &enumEntry->strand );
           if( MI_RESULT_OK != r )
           {
               StrandEntry_DeleteNoAdded( &enumEntry->strand );
               goto sendErrorBack_Opened;
           }
           enumEntry->className = req->className;
           enumEntryHead = enumEntry;
           enumEntryPrev = enumEntry;
  
     /* Setup callback */          /* Begin enumeration of classes for this request */
     msg->base.callback = _ProviderToDispatcherCallback;          {
     msg->base.callbackData = self;              r = ProvReg_BeginClasses(&self->provreg, req->nameSpace,
                   req->className, MI_TRUE, &pos, MI_FALSE);
  
     // Find a indication context by ns/cn              if (MI_RESULT_OK != r)
     Mutex_Lock(&self->mt);              {
                   {
                       /* Checking if the class is in extra classes to return appropriate error */
                       MI_Result result;
                       result = ProvReg_BeginClasses(&self->provreg, req->nameSpace,
                                       req->className, MI_TRUE, &pos, MI_TRUE);
                       if(MI_RESULT_OK == result)
                       {
                           ProvReg_EndClasses(&pos);
                           r = MI_RESULT_NOT_SUPPORTED;
                           goto sendErrorBack_Opened;
                       }
                   }
                   trace_ProvReg_BeginClasses_Failed(
                       r, tcs(Result_ToString(r)));
  
     r = _FindCreateIndCtx( self, msg, &reg );                  trace_DispEnum_UnknownClass(
                       tcs(req->nameSpace), tcs(req->className));
  
     Mutex_Unlock(&self->mt);                  /* send error back to caller */
                   goto sendErrorBack_Opened;
               }
           }
  
     /* check if error was detected */          /* While more classes */
     if (MI_RESULT_OK != r)          for (;;)
         goto sendErrorBack;          {
               const ZChar* derived = NULL;
               MI_Boolean done;
  
     /* empty reg with OK means context is being initialized;              r = ProvReg_NextClass(&pos, &derived, &done);
         sub command will be processed later, once EnableIndicaitons is processed */  
     if (!reg)  
         return MI_RESULT_OK;  
  
     // Send the request to provider manager.              if (done)
     r = AgentMgr_HandleRequest(&self->agentmgr, &msg->base, reg);                  break;
  
     if (r != MI_RESULT_OK)              if (MI_RESULT_OK != r)
     {     {
         LOGD((T("AgentMgr_HandleRequest for namespace: %s"), MI_GET_SAFE_PRINTF_STRING(req->nameSpace)));                  trace_ProvReg_NextClass_Failed(
         goto sendErrorBack;                      r, tcs(Result_ToString(r)));
     }  
   
     if (msg)  
         SubscribeReq_Release(msg);  
  
     return MI_RESULT_OK;                  trace_DispEnum_UnknownClass(
                       tcs(req->nameSpace), tcs(req->className));
  
 sendErrorBack:                  /* send error back to caller */
     if (msg)                  goto sendErrorBack_Opened;
         SubscribeReq_Release(msg);              }
  
     return _SendErrorResponse(&req->base,r);              enumEntry = (EnumEntry*)StrandEntry_New( STRAND_DEBUG( DispEnumEntry )
                                                           &enumInteraction->strand,
                                                           &_DispEnumEntry_ProviderFT,
                                                           sizeof(EnumEntry),
                                                           STRAND_FLAG_ENTERSTRAND,
                                                           NULL);
               if( NULL == enumEntry )
               {
                   trace_Disp_ErrorEnumEntryAlloc();
                   goto sendErrorBack_Opened;
 } }
  
 static MI_Result _HandleInvokeReq(              r = StrandMany_AddEntry( &enumEntry->strand );
     Disp* self,              if( MI_RESULT_OK != r )
     InvokeReq* req)  
 { {
     MI_Result r;                  trace_Disp_ErrorAddEntry();
     const ProvRegEntry* reg;                  StrandEntry_DeleteNoAdded( &enumEntry->strand );
     MI_ConstString cn = 0;                  goto sendErrorBack_Opened;
               }
  
     /* Validate input parameters */              // Use the original message batch, it will not be deleted until enumInteraction (who holds a ref to the message) is deleted
     if (!req->nameSpace)              enumEntry->className = Batch_Tcsdup(req->base.base.batch, derived);
         return MI_RESULT_INVALID_PARAMETER;              enumEntry->next = NULL;
               enumEntryPrev->next = enumEntry;
               enumEntryPrev = enumEntry;
           }
  
     if (req->className)          /* Finalize enumeration */
         cn = req->className;          {
     else if (req->instance)              r = ProvReg_EndClasses(&pos);
         cn = req->instance->classDecl->name;  
  
     if (!cn)              if (MI_RESULT_OK != r)
     {     {
         r = MI_RESULT_INVALID_CLASS;                  trace_ProvReg_EndClasses_Failed(
         LOGD((T("class name is expected for invoke\n")));                      r, tcs(Result_ToString(r)));
         goto sendErrorBack;                  /* send error back to caller */
                   goto sendErrorBack_Opened;
               }
     }     }
  
           Strand_Leave( &enumInteraction->strand.strand );
  
     // Find a provider for this class.          // Now go thru the added entries and dispatch the interactions
     reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace, cn);          enumEntry = enumEntryHead;
           while( NULL != enumEntry )
           {
               // Move to the next one before the object can be deleted by itself or by delete below
               enumEntryPrev = enumEntry;
               enumEntry = enumEntry->next;
               if( _DispatchEnumerateInstancesReq(self, req, enumEntryPrev->className, enumEntryPrev, NULL) == MI_RESULT_OK)
               {
                   sentOk = MI_TRUE;
               }
               else
               {
                   StrandEntry_Delete( &enumEntryPrev->strand );
               }
           }
           enumEntryHead = NULL;
  
     if (!reg)          /* Fail if no provider was found for request */
           if (!sentOk)
     {     {
         r = MI_RESULT_INVALID_NAMESPACE; /*ATTN! or class?*/              trace_FoundNoProvider(
         LOGD((T("cannot find provider for class: %s"), MI_GET_SAFE_PRINTF_STRING(cn)));                  req->className);
         goto sendErrorBack;              r = MI_RESULT_NOT_SUPPORTED;
               goto sendErrorBack_Opened;
     }     }
  
     // Send the request to provider manager.          StrandMany_ScheduleAux(&enumInteraction->strand,DISPENUMPARENT_STRANDAUX_ENUMDONE);
     r = AgentMgr_HandleRequest(&self->agentmgr, &req->base, reg);      } /* if deep*/
       else
       {
           /* Checking to see if the requested className is valid */
           ProvRegPosition pos;
           r = ProvReg_BeginClasses(&self->provreg, req->nameSpace,
               req->className, MI_TRUE, &pos, MI_FALSE);
  
     if (r != MI_RESULT_OK)          if (MI_RESULT_OK != r)
     {     {
         LOGD((T("AgentMgr_HandleRequest for namespace: %s"), MI_GET_SAFE_PRINTF_STRING(req->nameSpace)));              /* Checking if the class is in extra classes to return appropriate error */
         goto sendErrorBack;              MI_Result result;
               result = ProvReg_BeginClasses(&self->provreg, req->nameSpace,
                               req->className, MI_TRUE, &pos, MI_TRUE);
               if(MI_RESULT_OK == result)
               {
                   r = MI_RESULT_NOT_SUPPORTED;
                   ProvReg_EndClasses(&pos);
               }
               return r;
           }
           else
           {
               ProvReg_EndClasses(&pos);
           }
   
           // no need to create new interaction
           return _DispatchEnumerateInstancesReq(self, req, req->className, NULL, interactionParams);
     }     }
  
     return MI_RESULT_OK;     return MI_RESULT_OK;
  
 sendErrorBack:  sendErrorBack_Opened:
     return _SendErrorResponse(&req->base,r);      // Delete not dispatched entries
       enumEntry = enumEntryHead;
       while( NULL != enumEntry )
       {
           StrandEntry_Delete( &enumEntry->strand );
           enumEntry = enumEntry->next;
 } }
  
       // send error back to caller
       _SendErrorResponse_Opened(interactionParams, enumInteraction, r, MI_FALSE );
       return MI_RESULT_OK;
   }
  
 static MI_Result _HandleAssociatorsOfReq( static MI_Result _HandleAssociatorsOfReq(
     Disp* self,      _In_ Disp* self,
     AssociatorsOfReq* req)      _Inout_ InteractionOpenParams* interactionParams,
       _In_ AssociationsOfReq* req)
 { {
     MI_Result r;      int res;
       MI_Result r = MI_RESULT_FAILED;
     MI_ConstString cn = 0;     MI_ConstString cn = 0;
     DispResultMsg* dispStateMsg;  
     ProvRegAssocPosition pos;     ProvRegAssocPosition pos;
     MI_Boolean sentOk = MI_FALSE;     MI_Boolean sentOk = MI_FALSE;
     HashTable classNames;      HashMap classNames;
       DispEnumParent* enumInteraction;
       EnumEntry* enumEntry;
       EnumEntry* enumEntryHead = NULL;
       EnumEntry* enumEntryPrev = NULL;
  
     /* Create a hash table of class names */     /* Create a hash table of class names */
  
     r = HashTable_Init(      res = HashMap_Init(
         &classNames,         &classNames,
         64,         64,
         ClassNameHash,         ClassNameHash,
         ClassNameEqual,         ClassNameEqual,
         ClassNameRelease);         ClassNameRelease);
  
     if (r != 0)      if (res != 0)
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
  
     /* Validate input parameters */     /* Validate input parameters */
     if (!req->instance || !req->nameSpace)     if (!req->instance || !req->nameSpace)
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
  
     /* create a state message that will keep track of results from providers */      /* create the interaction that will keep track of results from providers */
     dispStateMsg = DispResultMsg_New(req->base.msgID);      enumInteraction = _DispEnumParent_New(
     if (!dispStateMsg)                          self,
                           interactionParams);
       if (!enumInteraction)
       {
           trace_Disp_ErrorInteractionAlloc();
           HashMap_Destroy(&classNames);
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
       }
     /* add one for sending thread so first 'fast' provider will not send its response all the way */  
     AtomicInc(&dispStateMsg->requestCounter);  
   
     dispStateMsg->base.clientID = req->base.clientID;  
     /* Setup callback */  
     dispStateMsg->base.callback = req->base.callback;  
     dispStateMsg->base.callbackData = req->base.callbackData;  
     Message_SetRequest(&dispStateMsg->base, &req->base);  
  
     r = ProvReg_BeginAssocClasses(&self->provreg, req->nameSpace,     r = ProvReg_BeginAssocClasses(&self->provreg, req->nameSpace,
         req->instance->classDecl->name,         req->instance->classDecl->name,
Line 1143 
Line 1178 
  
     if (MI_RESULT_OK != r)     if (MI_RESULT_OK != r)
     {     {
         LOGD((T("ProvReg_BeginAssocClasses() failed: %u: %s"),          trace_ProvReg_BeginAssocClasses_Failed(r, tcs(Result_ToString(r)));
             r, Result_ToString(r)));  
  
         /* send error back to caller */         /* send error back to caller */
         goto sendErrorBack;          goto sendErrorBack_Opened;
     }     }
  
     /* ATTN: there is a bug in the provider registration tree causing     /* ATTN: there is a bug in the provider registration tree causing
Line 1166 
Line 1200 
  
         if (MI_RESULT_OK != r)         if (MI_RESULT_OK != r)
         {         {
             LOGD((T("ProvReg_NextAssocClass() failed: %u: %s"),              trace_ProvReg_NextAssocClass_Failed(r, tcs(Result_ToString(r)));
                 r, Result_ToString(r)));  
             /* send error back to caller */             /* send error back to caller */
             goto sendErrorBack;              goto sendErrorBack_Opened;
         }         }
  
         /* Check whether this class has been dispatched */         /* Check whether this class has been dispatched */
         {         {
             ClassNameBucket bucket;             ClassNameBucket bucket;
             bucket.key = (char*)cn;              bucket.key = (ZChar*)cn;
  
             if (!HashTable_Find(&classNames, (const HashBucket*)&bucket))              if (!HashMap_Find(&classNames, (const HashBucket*)&bucket))
             {             {
                 if (_DispatchAssocReq(self, cn, req, dispStateMsg))                  enumEntry = (EnumEntry*)StrandEntry_New( STRAND_DEBUG( DispEnumEntry )
                     sentOk = MI_TRUE;                                                              &enumInteraction->strand,
                                                               &_DispEnumEntry_ProviderFT,
                                                               sizeof(EnumEntry),
                                                               STRAND_FLAG_ENTERSTRAND,
                                                               NULL);
                   if( NULL == enumEntry )
                   {
                       trace_Disp_ErrorEnumEntryAlloc();
                       goto sendErrorBack_Opened;
                   }
   
                   r = StrandMany_AddEntry( &enumEntry->strand );
                   if( MI_RESULT_OK != r )
                   {
                       trace_Disp_ErrorAddEntry();
                       StrandEntry_DeleteNoAdded( &enumEntry->strand );
                       goto sendErrorBack_Opened;
                   }
   
                   // Use the original message batch, it will not be deleted until enumInteraction (who holds a ref to the message) is deleted
                   enumEntry->className = Batch_Tcsdup(req->base.base.batch, cn);
                   enumEntry->next = NULL;
                   if( NULL == enumEntryHead )
                   {
                       enumEntryHead = enumEntry;
                   }
                   else
                   {
                       enumEntryPrev->next = enumEntry;
                   }
                   enumEntryPrev = enumEntry;
  
                 {                 {
                     ClassNameBucket* bucket = (ClassNameBucket*)calloc(                      ClassNameBucket* bucket = (ClassNameBucket*)PAL_Calloc(
                         1, sizeof(ClassNameBucket));                         1, sizeof(ClassNameBucket));
  
                     if (!bucket)                     if (!bucket)
                     {                     {
                         r = MI_RESULT_FAILED;                         r = MI_RESULT_FAILED;
                         goto sendErrorBack;                          goto sendErrorBack_Opened;
                     }                     }
  
                     bucket->key = strdup(cn);                      bucket->key = PAL_Tcsdup(cn);
  
                     if (HashTable_Insert(&classNames, (HashBucket*)bucket) != 0)                      if (HashMap_Insert(&classNames, (HashBucket*)bucket) != 0)
                     {                     {
                         r = MI_RESULT_FAILED;                         r = MI_RESULT_FAILED;
                         goto sendErrorBack;                          goto sendErrorBack_Opened;
                     }                     }
                 }                 }
             }             }
Line 1210 
Line 1274 
  
         if (MI_RESULT_OK != r)         if (MI_RESULT_OK != r)
         {         {
             LOGD((T("ProvReg_EndAssocClasses() failed: %u: %s"),              trace_ProvReg_EndAssocClasses_Failed(r, tcs(Result_ToString(r)));
                 r, Result_ToString(r)));  
             /* send error back to caller */             /* send error back to caller */
             goto sendErrorBack;              goto sendErrorBack_Opened;
         }         }
     }     }
  
       Strand_Leave( &enumInteraction->strand.strand );
   
       // Now go thru the added entries and dispatch the interactions
       enumEntry = enumEntryHead;
       while( NULL != enumEntry )
       {
           // Move to the next one before the object can be deleted by itself or by delete below
           enumEntryPrev = enumEntry;
           enumEntry = enumEntry->next;
           if (_DispatchAssocReq(self, req, enumEntryPrev, AssociatorsOfReqTag))
           {
               sentOk = MI_TRUE;
           }
           else
           {
               StrandEntry_Delete( &enumEntryPrev->strand );
           }
       }
       enumEntryHead = NULL;
   
       HashMap_Destroy(&classNames);
   
     /* Fail if no provider was found for request */     /* Fail if no provider was found for request */
     if (!sentOk)     if (!sentOk)
     {     {
         LOGD((T("found no providers for class: %s"), req->instance->classDecl->name));          trace_FoundNoProvider(
         r = MI_RESULT_NOT_FOUND;              tcs(req->instance->classDecl->name));
         goto sendErrorBack;          _SendErrorResponse_Opened(interactionParams, enumInteraction, MI_RESULT_NOT_SUPPORTED, MI_TRUE );
           return MI_RESULT_OK;
     }     }
  
     if ( AtomicDec(&dispStateMsg->requestCounter) )      StrandMany_ScheduleAux(&enumInteraction->strand,DISPENUMPARENT_STRANDAUX_ENUMDONE);
     {   /* last result - forward it to the net stack */      return MI_RESULT_OK;
         r = dispStateMsg->result;  
         goto sendErrorBack;  sendErrorBack_Opened:
       HashMap_Destroy(&classNames);
       // Delete not dispatched entries
       enumEntry = enumEntryHead;
       while( NULL != enumEntry )
       {
           StrandEntry_Delete( &enumEntry->strand );
           enumEntry = enumEntry->next;
     }     }
  
     HashTable_Destroy(&classNames);      // send error back to caller
     DispResultMsg_Release(dispStateMsg);      _SendErrorResponse_Opened(interactionParams, enumInteraction, r, MI_FALSE );
     return MI_RESULT_OK;     return MI_RESULT_OK;
   
 sendErrorBack:  
     DispResultMsg_Release(dispStateMsg);  
     HashTable_Destroy(&classNames);  
     return _SendErrorResponse(&req->base,r);  
 } }
  
 static MI_Result _HandleReferencesOfReq( static MI_Result _HandleReferencesOfReq(
     Disp* self,      _In_ Disp* self,
     ReferencesOfReq* req)      _Inout_ InteractionOpenParams* interactionParams,
       _In_ AssociationsOfReq* req)
 { {
     MI_Result r;      MI_Result r = MI_RESULT_FAILED;
     MI_ConstString cn = 0;     MI_ConstString cn = 0;
     DispResultMsg* dispStateMsg;  
     ProvRegAssocPosition pos;     ProvRegAssocPosition pos;
     MI_Boolean sentOk = MI_FALSE;     MI_Boolean sentOk = MI_FALSE;
       DispEnumParent* enumInteraction;
       EnumEntry* enumEntry;
       EnumEntry* enumEntryHead = NULL;
       EnumEntry* enumEntryPrev = NULL;
  
     /* Validate input parameters */     /* Validate input parameters */
     if (!req->instance || !req->nameSpace)     if (!req->instance || !req->nameSpace)
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
  
     /* create a state message that will keep track of results from providers */      /* create the interaction that will keep track of results from providers */
     dispStateMsg = DispResultMsg_New(req->base.msgID);      enumInteraction = _DispEnumParent_New(
     if (!dispStateMsg)                              self,
                               interactionParams);
       if (!enumInteraction)
       {
           trace_Disp_ErrorInteractionAlloc();
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
       }
  
     /* add one for sending thread so first 'fast' provider will not send its response all the way */      /* resultClass parameter of ReferencesOf operation contains association class name.
     AtomicInc(&dispStateMsg->requestCounter);        Here using req->resultClass for passing assocClassName to ProvReg_BeginAssocClasses function */
   
     dispStateMsg->base.clientID = req->base.clientID;  
     /* Setup callback */  
     dispStateMsg->base.callback = req->base.callback;  
     dispStateMsg->base.callbackData = req->base.callbackData;  
     Message_SetRequest(&dispStateMsg->base, &req->base);  
   
     r = ProvReg_BeginAssocClasses(&self->provreg, req->nameSpace,     r = ProvReg_BeginAssocClasses(&self->provreg, req->nameSpace,
         req->instance->classDecl->name,         req->instance->classDecl->name,
         req->assocClass, 0, &pos);          req->resultClass, 0, &pos);
  
     if (MI_RESULT_OK != r)     if (MI_RESULT_OK != r)
     {     {
         LOGD((T("ProvReg_BeginAssocClasses() failed: %u: %s"),          trace_ProvReg_BeginAssocClasses_Failed(r, tcs(Result_ToString(r)));
             r, Result_ToString(r)));  
  
         /* send error back to caller */         /* send error back to caller */
         goto sendErrorBack;          goto sendErrorBack_Opened;
     }     }
  
     /* While more classes */     /* While more classes */
Line 1293 
Line 1383 
  
         if (MI_RESULT_OK != r)         if (MI_RESULT_OK != r)
         {         {
             LOGD((T("ProvReg_NextAssocClass() failed: %u: %s"),              trace_ProvReg_NextAssocClass_Failed(r, tcs(Result_ToString(r)));
                 r, Result_ToString(r)));  
             /* send error back to caller */             /* send error back to caller */
             goto sendErrorBack;              goto sendErrorBack_Opened;
         }         }
  
         if (_DispatchRefReq(self, cn, req, dispStateMsg))          enumEntry = (EnumEntry*)StrandEntry_New( STRAND_DEBUG( DispEnumEntry )
             sentOk = MI_TRUE;                                                      &enumInteraction->strand,
                                                       &_DispEnumEntry_ProviderFT,
                                                       sizeof(EnumEntry),
                                                       STRAND_FLAG_ENTERSTRAND,
                                                       NULL);
           if( NULL == enumEntry )
           {
               trace_Disp_ErrorEnumEntryAlloc();
               goto sendErrorBack_Opened;
           }
   
           r = StrandMany_AddEntry( &enumEntry->strand );
           if( MI_RESULT_OK != r )
           {
               trace_Disp_ErrorAddEntry();
               StrandEntry_DeleteNoAdded( &enumEntry->strand );
               goto sendErrorBack_Opened;
           }
   
           // Use the original message batch, it will not be deleted until enumInteraction (who holds a ref to the message) is deleted
           enumEntry->className = Batch_Tcsdup(req->base.base.batch, cn);
           enumEntry->next = NULL;
           if( NULL == enumEntryHead )
           {
               enumEntryHead = enumEntry;
           }
           else
           {
               enumEntryPrev->next = enumEntry;
           }
           enumEntryPrev = enumEntry;
     }     }
  
     /* Finalize enumeration */     /* Finalize enumeration */
Line 1309 
Line 1429 
  
         if (MI_RESULT_OK != r)         if (MI_RESULT_OK != r)
         {         {
             LOGD((T("ProvReg_EndAssocClasses() failed: %u: %s"),              trace_ProvReg_EndAssocClasses_Failed(r, tcs(Result_ToString(r)));
                 r, Result_ToString(r)));  
             /* send error back to caller */             /* send error back to caller */
             goto sendErrorBack;              goto sendErrorBack_Opened;
           }
       }
   
       Strand_Leave( &enumInteraction->strand.strand );
   
       // Now go thru the added entries and dispatch the interactions
       enumEntry = enumEntryHead;
       while( NULL != enumEntry )
       {
           // Move to the next one before the object can be deleted by itself or by delete below
           enumEntryPrev = enumEntry;
           enumEntry = enumEntry->next;
           if (_DispatchAssocReq(self, req, enumEntryPrev, ReferencesOfReqTag))
           {
               sentOk = MI_TRUE;
           }
           else
           {
               StrandEntry_Delete( &enumEntryPrev->strand );
         }         }
     }     }
       enumEntryHead = NULL;
  
     /* Fail if no provider was found for request */     /* Fail if no provider was found for request */
     if (!sentOk)     if (!sentOk)
     {     {
         LOGD((T("found no providers for class: %s"), req->instance->classDecl->name));          trace_FoundNoProvider(
         r = MI_RESULT_NOT_FOUND;              tcs(req->instance->classDecl->name));
         goto sendErrorBack;          _SendErrorResponse_Opened(interactionParams, enumInteraction, MI_RESULT_NOT_SUPPORTED, MI_TRUE );
           return MI_RESULT_OK;
     }     }
  
     if ( AtomicDec(&dispStateMsg->requestCounter) )      StrandMany_ScheduleAux(&enumInteraction->strand,DISPENUMPARENT_STRANDAUX_ENUMDONE);
     {   /* last result - forward it to the net stack */      return MI_RESULT_OK;
         r = dispStateMsg->result;  
         goto sendErrorBack;  sendErrorBack_Opened:
       // Delete not dispatched entries
       enumEntry = enumEntryHead;
       while( NULL != enumEntry )
       {
           StrandEntry_Delete( &enumEntry->strand );
           enumEntry = enumEntry->next;
     }     }
  
     DispResultMsg_Release(dispStateMsg);      // send error back to caller
       _SendErrorResponse_Opened(interactionParams, enumInteraction, r, FALSE );
     return MI_RESULT_OK;     return MI_RESULT_OK;
   }
  
 sendErrorBack:  #ifndef DISABLE_INDICATION
     DispResultMsg_Release(dispStateMsg);  static MI_Result _HandleSubscribeReq(
     return _SendErrorResponse(&req->base,r);      _In_ Disp* self,
       _Inout_ InteractionOpenParams* params )
   {
       params->callbackData = self->indmgr;
       IndiMgr_HandleSubscribeReq(params);
       return MI_RESULT_OK;
 } }
   #endif /* ifndef DISABLE_INDICATION */
  
 /* /*
 **============================================================================== **==============================================================================
Line 1356 
Line 1511 
  
 #if 0 #if 0
     /* Initialize the provider registry */     /* Initialize the provider registry */
     MI_RETURN_ERR(ProvReg_Init(&self->provreg, GetPath(ID_REGISTERFILE)));      MI_RETURN_ERR(ProvReg_Init(&self->provreg, OMI_GetPath(ID_REGISTERFILE)));
 #else #else
     MI_RETURN_ERR(ProvReg_Init2(&self->provreg));     MI_RETURN_ERR(ProvReg_Init2(&self->provreg));
 #endif #endif
Line 1364 
Line 1519 
     /* Initialize the provider manager */     /* Initialize the provider manager */
     MI_RETURN_ERR(AgentMgr_Init(&self->agentmgr, selector));     MI_RETURN_ERR(AgentMgr_Init(&self->agentmgr, selector));
  
     /* Initialize indications part */  #ifndef DISABLE_INDICATION
     MI_RETURN_ERR(Mutex_Init(&self->mt));      /* Initialize indication manager */
       self->indmgr = IndiMgr_NewFromDisp(self);
       if (NULL == self->indmgr)
           MI_RETURN_ERR(MI_RESULT_FAILED);
   #endif /* ifndef DISABLE_INDICATION */
  
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
Line 1375 
Line 1534 
     MI_RETURN_ERR(AgentMgr_Destroy(&self->agentmgr));     MI_RETURN_ERR(AgentMgr_Destroy(&self->agentmgr));
     ProvReg_Destroy(&self->provreg);     ProvReg_Destroy(&self->provreg);
  
   #ifndef DISABLE_INDICATION
       /* Shutdown indication manager */
       IndiMgr_Shutdown(self->indmgr);
   #endif /* ifndef DISABLE_INDICATION */
   
     /*ATTN! remove indication contexts! */     /*ATTN! remove indication contexts! */
     Mutex_Destroy(&self->mt);  
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
  
 MI_Result Disp_HandleRequest(  MI_Result Disp_HandleInteractionRequest(
     Disp* self,      _In_ Disp* self,
     Message* msg)      _Inout_ InteractionOpenParams* params )
 {  {
       Message* msg = params->msg;
   
       trace_DispHandleInteractionRequest(self,
           params->interaction,
           msg,
           msg->tag,
           MessageName(msg->tag),
           msg->operationId);
   
       DEBUG_ASSERT( NULL != self );
       DEBUG_ASSERT( NULL != params );
       DEBUG_ASSERT( NULL != params->interaction );
       DEBUG_ASSERT( NULL != params->msg );
   
     switch (msg->tag)     switch (msg->tag)
     {     {
         case EnumerateInstancesReqTag:          case GetInstanceReqTag:
         {         {
             EnumerateInstancesReq* req = (EnumerateInstancesReq*)msg;              GetInstanceReq* req = (GetInstanceReq*)msg;
             return _HandleEnumerateInstancesReq(self, req);              return _HandleGetInstanceReq(self, params, req);
         }         }
  
         case GetInstanceReqTag:          case GetClassReqTag:
         {         {
             GetInstanceReq* req = (GetInstanceReq*)msg;              GetClassReq* req = (GetClassReq*)msg;
             return _HandleGetInstanceReq(self, req);              return _HandleGetClassReq(self, params, req);
         }         }
  
   
         case CreateInstanceReqTag:         case CreateInstanceReqTag:
         {         {
             CreateInstanceReq* req = (CreateInstanceReq*)msg;             CreateInstanceReq* req = (CreateInstanceReq*)msg;
             return _HandleCreateInstanceReq(self, req);              return _HandleCreateInstanceReq(self, params, req);
         }         }
  
         case ModifyInstanceReqTag:         case ModifyInstanceReqTag:
         {         {
             ModifyInstanceReq* req = (ModifyInstanceReq*)msg;             ModifyInstanceReq* req = (ModifyInstanceReq*)msg;
             return _HandleModifyInstanceReq(self, req);              return _HandleModifyInstanceReq(self, params, req);
         }         }
  
         case DeleteInstanceReqTag:         case DeleteInstanceReqTag:
         {         {
             DeleteInstanceReq* req = (DeleteInstanceReq*)msg;             DeleteInstanceReq* req = (DeleteInstanceReq*)msg;
             return _HandleDeleteInstanceReq(self, req);              return _HandleDeleteInstanceReq(self, params, req);
         }         }
  
         case InvokeReqTag:         case InvokeReqTag:
         {         {
             InvokeReq* req = (InvokeReq*)msg;             InvokeReq* req = (InvokeReq*)msg;
             return _HandleInvokeReq(self, req);              return _HandleInvokeReq(self, params, req);
           }
   
           case EnumerateInstancesReqTag:
           {
               EnumerateInstancesReq* req = (EnumerateInstancesReq*)msg;
               return _HandleEnumerateInstancesReq(self, params, req);
         }         }
  
         case AssociatorsOfReqTag:         case AssociatorsOfReqTag:
         {         {
             AssociatorsOfReq* req = (AssociatorsOfReq*)msg;              AssociationsOfReq* req = (AssociationsOfReq*)msg;
             return _HandleAssociatorsOfReq(self, req);              return _HandleAssociatorsOfReq(self, params, req);
         }         }
  
         case ReferencesOfReqTag:         case ReferencesOfReqTag:
         {         {
             ReferencesOfReq* req = (ReferencesOfReq*)msg;              AssociationsOfReq* req = (AssociationsOfReq*)msg;
             return _HandleReferencesOfReq(self, req);              return _HandleReferencesOfReq(self, params, req);
         }         }
  
   #ifndef DISABLE_INDICATION
   
         case SubscribeReqTag:         case SubscribeReqTag:
         {         {
             SubscribeReq* req = (SubscribeReq*)msg;              return _HandleSubscribeReq(self, params);
             return _HandleSubscribeReq(self, req);  
         }         }
  
   #endif /* ifndef DISABLE_INDICATION */
   
         default:         default:
         {         {
             /* Unsupported mesage type */             /* Unsupported mesage type */
             return _SendErrorResponse(msg,MI_RESULT_NOT_SUPPORTED);              trace_DispUnsupportedMessage( self,
                   params->interaction,
                   msg,
                   msg->tag,
                   MessageName(msg->tag),
                   msg->operationId );
               return MI_RESULT_NOT_SUPPORTED;
         }         }
     }     }
 } }


Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4

ViewCVS 0.9.2