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

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

version 1.1, 2012/05/30 22:47:39 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/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 );
  
 /* /*
 **============================================================================== **==============================================================================
 ** **
 ** Data structures  ** ClassName hash implementation
 ** **
 **============================================================================== **==============================================================================
 */ */
  
 /*  typedef struct _ClassNameBucket /* derives from HashBucket */
     subscription item - represents single subscription;  
 */  
 typedef struct _DispSubscriptionItem  
 { {
     struct _DispSubscriptionItem* next;      struct _ClassNameBucket* next;
     struct _DispSubscriptionItem* prev;      ZChar* key;
   
     /* The batch this context was allocated from */  
     Batch batch;  
   
     /* filter */  
     MI_ConstString  filter;  
     MI_ConstString  language;  
   
     /* unique id of the sub */  
     MI_Uint64       subscriptionID;  
   
     /* Client identifier if supported */  
     MI_Uint64 clientID;  
   
 } }
 DispSubscriptionItem;  ClassNameBucket;
  
   static size_t ClassNameHash(
 /* subscriptions context -      const HashBucket* bucket_)
     used to track indicaiton providers  
     and store indications for 'pull' operation  
     one context per ns/cn pair  
 */  
 typedef struct _DispIndicationContext  
 { {
     struct _DispIndicationContext* next;      /* Note: this algorithm has a poor distribution */
     struct _DispIndicationContext* prev;      ClassNameBucket* bucket = (ClassNameBucket*)bucket_;
       size_t h = 0;
       ZChar* key = bucket->key;
  
     /* The batch this context was allocated from */      while (*key)
     Batch batch;      {
           h += 5 * *key++;
       }
  
     /* namespace/cn */      return h;
     MI_ConstString  nameSpace;  }
     MI_ConstString  className;  
  
     /* unique id of the context (used by ProvMgr) */  static int ClassNameEqual(
     MI_Uint64       ctxID;      const HashBucket* bucket1_,
       const HashBucket* bucket2_)
   {
       ClassNameBucket* bucket1 = (ClassNameBucket*)bucket1_;
       ClassNameBucket* bucket2 = (ClassNameBucket*)bucket2_;
       return Tcscasecmp(bucket1->key, bucket2->key) == 0;
   }
  
     /* provider info */  static void ClassNameRelease(
     const ProvRegEntry* provEntry;      HashBucket* bucket_)
   {
       ClassNameBucket* bucket = (ClassNameBucket*)bucket_;
  
     /* exisitng subscriptions */      PAL_Free(bucket->key);
     DispSubscriptionItem* headSubscriptions;      PAL_Free(bucket);
     DispSubscriptionItem* tailSubscriptions;  
 } }
 DispIndicationContext;  
   
  
 /* /*
 **============================================================================== **==============================================================================
Line 103 
Line 99 
 ** **
 **============================================================================== **==============================================================================
 */ */
 static MI_Result _SendErrorResponse(  
     Message* req,  
     MI_Result r);  
  
 static DispIndicationContext* _FindIndCtxByNScn(  typedef struct _DispEnumParent
     Disp* self,  
     MI_ConstString  nameSpace,  
     MI_ConstString  className)  
 { {
     DispIndicationContext* current = (DispIndicationContext*)self->headIndCtx;      StrandMany              strand;
       Disp*                   disp;
       RequestMsg*             baseRequest;
       MI_Result               result;
       MI_Boolean              done;
   }
   DispEnumParent;
   
   typedef struct _EnumEntry EnumEntry;
  
     while (current)  struct _EnumEntry
     {     {
         if (0 == Zcasecmp(nameSpace, current->nameSpace) &&      StrandEntry             strand;
             0 == Zcasecmp(className, current->className))      const ZChar*            className;
             break;      EnumEntry*              next;       // Links the entries that are about to be dispatched
                                           // We cannot use list on StrandMany as that one can get modify in the meantime
                                           // as the interactions are being dinamically closed themselves
                                           // (that is why that list requires to be in the strand to use it)
   };
   
   MI_INLINE void _DispEnumParent_Delete(
       _In_ DispEnumParent* self)
   {
       trace_DispDeleteInteraction(self);
       Message_Release( &self->baseRequest->base );
       StrandMany_Delete(&self->strand);
   }
   
   // interaction is already opened, we can have left the Strand or not indicated by leftStrand
   static void _SendErrorResponse_Opened(
       _Inout_ InteractionOpenParams* interactionParams,
       _In_ DispEnumParent* self,
       _In_ MI_Result r,
       MI_Boolean leftStrand
       )
   {
       PostResultMsg* openResp = PostResultMsg_NewAndSerialize( &self->baseRequest->base, NULL, NULL, MI_RESULT_TYPE_MI, r);
  
         current = current->next;      if( openResp )
     }      {
     return current;          if( leftStrand )
           {
               StrandMany_SchedulePost( &self->strand, &openResp->base );
               StrandMany_ScheduleClose( &self->strand );
 } }
           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 void _DispEnumParent_Transport_Cancel( _In_ Strand* self)
 static MI_Result _FindCreateIndCtx(  
     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 */  
     if (!ctx)  
         return MI_RESULT_FAILED;  
  
     /* */      DEBUG_ASSERT( NULL != self );
     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:  
         {         {
             PostResultMsg* rsp = (PostResultMsg*)msg;          goto OutOfMemory;
       }
  
             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:      /* Save request's class name to allow provmgr pack back only base properties */
             break;      if( request->basePropertiesOnly )
     }  
   
     /* forward message to the other side */  
     if (msg->request && msg->request->request)  
     {     {
         /* 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 502 
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;
               }
               if (MI_RESULT_OK == r)
             {             {
                 LOGW((T("invalid query expression: %s"), req->queryExpression));                  DEBUG_ASSERT(pos.start != NULL);
                 r = MI_RESULT_INVALID_QUERY;                  MapRegPositionValuesToRegEntry(&freg, &pos);
                 goto sendErrorBack;                  freg.nameSpace = req->nameSpace;
                   freg.nameSpaceHash = Hash(req->nameSpace);
             }             }
         }         }
  
         /* Verify that the query classname matches the enumeration classname */          if (MI_RESULT_OK != r)
         if (Zcmp(req->wql->className, req->className) != 0)  
         {         {
             LOGW((T("query/enumeration class name mismatch: %s/%s"),              trace_NoProviderForClass(
                 req->className, req->className));                  req->nameSpace,
             r = MI_RESULT_INVALID_QUERY;                  req->className);
             goto sendErrorBack;             goto sendErrorBack;
         }         }
     }     }
       else
     /* 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)  
             {             {
                 LOGD((T("ProvReg_BeginClasses() failed: %u: %s"),          freg = *reg;
                     r, Result_ToString(r)));      }
  
                 LOGI((T("unknown class in enumerate request: %s:%s"),      // Send the request to provider manager.
                     req->nameSpace, req->className));      r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, &freg);
  
                 /* send error back to caller */      if (r != MI_RESULT_OK)
       {
           trace_AgentMgrHandleRequestForNS(
               req->nameSpace);
                 goto sendErrorBack;                 goto sendErrorBack;
             }             }
   
       return MI_RESULT_OK;
   
   sendErrorBack:
       // Just abort creating any interaction at all
       return r;
         }         }
  
         /* While more classes */  static MI_Result _HandleCreateInstanceReq(
         for (;;)      _In_ Disp* self,
       _Inout_ InteractionOpenParams* interactionParams,
       _In_ CreateInstanceReq* req)
         {         {
             const MI_Char* derived = NULL;      MI_Result r;
             MI_Boolean done;      const ProvRegEntry* reg;
  
             r = ProvReg_NextClass(&pos, &derived, &done);      /* Validate input parameters */
       if (!req->instance || !req->nameSpace)
           return MI_RESULT_INVALID_PARAMETER;
  
             if (done)      // Find a provider for this class.
                 break;      reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,
           req->instance->classDecl->name, &r );
  
             if (MI_RESULT_OK != r)      if (!reg)
             {             {
                 LOGD((T("ProvReg_NextClass() failed: %u: %s"),          trace_NoProviderForClass(
                     r, Result_ToString(r)));              req->nameSpace,
               req->instance->classDecl->name);
           goto sendErrorBack;
       }
  
                 LOGI((T("unknown class in enumerate request: %s:%s"),      // Send the request to provider manager.
                     req->nameSpace, req->className));      r = AgentMgr_HandleRequest(&self->agentmgr, interactionParams, reg);
  
                 /* send error back to caller */      if (r != MI_RESULT_OK)
       {
           trace_AgentMgrHandleRequestForNS(
               req->nameSpace);
                 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 _HandleModifyInstanceReq(
       _In_ Disp* self,
       _Inout_ InteractionOpenParams* interactionParams,
       _In_ ModifyInstanceReq* 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 _HandleDeleteInstanceReq(
 static MI_Result _HandleGetInstanceReq(      _In_ Disp* self,
     Disp* self,      _Inout_ InteractionOpenParams* interactionParams,
     GetInstanceReq* req)      _In_ DeleteInstanceReq* req)
 { {
     MI_Result r;     MI_Result r;
     const ProvRegEntry* reg;     const ProvRegEntry* reg;
Line 781 
Line 768 
  
     // 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->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->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 _HandleInvokeReq(
     Disp* self,      _In_ Disp* self,
     CreateInstanceReq* 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 */     /* Validate input parameters */
     if (!req->instance || !req->nameSpace)      if (!req->nameSpace)
         return MI_RESULT_INVALID_PARAMETER;         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;
       }
   
   
     // 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 _HandleModifyInstanceReq(  static MI_Result _HandleEnumerateInstancesReq(
     Disp* self,      _In_ Disp* self,
     ModifyInstanceReq* 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->instance || !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->instance->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)
           {
               dialect = WQL_DIALECT_WQL;
           }
           else if (Tcscasecmp(req->queryLanguage, MI_QUERY_DIALECT_CQL) == 0)
           {
               dialect = WQL_DIALECT_CQL;
           }
           else
           {
               trace_UnsupportedQueryLanguage(tcs(req->queryLanguage));
               return MI_RESULT_QUERY_LANGUAGE_NOT_SUPPORTED;
           }
   
           /* Compile the query */
           {
               req->wql = WQL_Parse(req->queryExpression, req->base.base.batch,
                   dialect);
   
               if (!req->wql)
     {     {
         r = MI_RESULT_INVALID_NAMESPACE; /*ATTN! or class?*/                  trace_InvalidQueryExpression(tcs(req->queryExpression));
         LOGD((T("cannot find provider for class: %s/%s"),                  return MI_RESULT_INVALID_QUERY;
             MI_GET_SAFE_PRINTF_STRING(req->nameSpace),              }
             MI_GET_SAFE_PRINTF_STRING(req->instance->classDecl->name)));  
         goto sendErrorBack;  
     }     }
  
     // Send the request to provider manager.          /* WQL queries from WinRM pass '*' as the class name */
     r = AgentMgr_HandleRequest(&self->agentmgr, &req->base, reg);  
  
     if (r != MI_RESULT_OK)          if (!req->className || (Tcscmp(req->className, PAL_T("*")) == 0))
     {     {
         LOGD((T("AgentMgr_HandleRequest for namespace: %s"),              req->className = req->wql->className;
             MI_GET_SAFE_PRINTF_STRING(req->nameSpace)));  
         goto sendErrorBack;  
     }     }
  
     return MI_RESULT_OK;          /* Verify that the query classname matches the enumeration classname */
           if (Tcscmp(req->wql->className, req->className) != 0)
 sendErrorBack:          {
     return _SendErrorResponse(&req->base,r);              trace_QueryEnumClassnameMismatch(
                   tcs(req->wql->className), tcs(req->className));
               return MI_RESULT_INVALID_QUERY;
 } }
       }
 static MI_Result _HandleDeleteInstanceReq(      else if (!req->className)
     Disp* self,  
     DeleteInstanceReq* req)  
 { {
     MI_Result r;          trace_EnumHasNoClassname();
     const ProvRegEntry* reg;  
   
     /* Validate input parameters */  
     if (!req->instanceName || !req->nameSpace)  
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
       }
  
     // Find a provider for this class.      if (req->deepInheritance)
     reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,      {
         req->instanceName->classDecl->name);          ProvRegPosition pos;
           EnumEntry* enumEntryPrev;
  
     if (!reg)          /* create the interaction that will keep track of results from providers */
           enumInteraction = _DispEnumParent_New(
                               self,
                               interactionParams);
           if (!enumInteraction)
     {     {
         r = MI_RESULT_INVALID_NAMESPACE; /*ATTN! or class?*/              trace_Disp_ErrorInteractionAlloc();
         LOGD((T("cannot find provider for class: %s/%s"),              return MI_RESULT_FAILED;
             MI_GET_SAFE_PRINTF_STRING(req->nameSpace),  
             MI_GET_SAFE_PRINTF_STRING(req->instanceName->classDecl->name)));  
         goto sendErrorBack;  
     }     }
  
     // Send the request to provider manager.          /* Send to direct name */
     r = AgentMgr_HandleRequest(&self->agentmgr, &req->base, reg);          /* Start by sending to direct name */
           enumEntry = (EnumEntry*)StrandEntry_New( STRAND_DEBUG( DispEnumEntry )
     if (r != MI_RESULT_OK)                                                      &enumInteraction->strand,
                                                       &_DispEnumEntry_ProviderFT,
                                                       sizeof(EnumEntry),
                                                       STRAND_FLAG_ENTERSTRAND,
                                                       NULL);
           if( NULL == enumEntry )
     {     {
         LOGD((T("AgentMgr_HandleRequest for namespace: %s"),              trace_Disp_ErrorEnumEntryAlloc();
             MI_GET_SAFE_PRINTF_STRING(req->nameSpace)));              goto sendErrorBack_Opened;
         goto sendErrorBack;  
     }     }
           r = StrandMany_AddEntry( &enumEntry->strand );
     return MI_RESULT_OK;          if( MI_RESULT_OK != r )
           {
 sendErrorBack:              StrandEntry_DeleteNoAdded( &enumEntry->strand );
     return _SendErrorResponse(&req->base,r);              goto sendErrorBack_Opened;
 } }
           enumEntry->className = req->className;
           enumEntryHead = enumEntry;
           enumEntryPrev = enumEntry;
  
 static MI_Result _HandleSubscribeReq(          /* Begin enumeration of classes for this request */
     Disp* self,  
     SubscribeReq* req)  
 { {
     MI_Result r;              r = ProvReg_BeginClasses(&self->provreg, req->nameSpace,
     const ProvRegEntry* reg = 0;                  req->className, MI_TRUE, &pos, MI_FALSE);
     SubscribeReq* msg = 0;  
   
     /* Validate input parameters */  
     if (!req->className || !req->nameSpace || !req->language || !req->filter)  
         return MI_RESULT_INVALID_PARAMETER;  
   
     // Duplicate incoming request to substitute callback pointer  
     msg = SubscribeReq_New(req->base.msgID, req->base.flags);  
   
     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, 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;              if (MI_RESULT_OK != r)
               {
                   {
                       /* 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)));
  
     Message_SetRequest(&msg->base, &req->base);                  trace_DispEnum_UnknownClass(
                       tcs(req->nameSpace), tcs(req->className));
  
     /* Setup callback */                  /* send error back to caller */
     msg->base.callback = _ProviderToDispatcherCallback;                  goto sendErrorBack_Opened;
     msg->base.callbackData = self;              }
           }
  
     // Find a indication context by ns/cn          /* While more classes */
     Mutex_Lock(&self->mt);          for (;;)
           {
               const ZChar* derived = NULL;
               MI_Boolean done;
  
     r = _FindCreateIndCtx( self, msg, &reg );              r = ProvReg_NextClass(&pos, &derived, &done);
  
     Mutex_Unlock(&self->mt);              if (done)
                   break;
  
     /* check if error was detected */  
     if (MI_RESULT_OK != r)     if (MI_RESULT_OK != r)
         goto sendErrorBack;              {
                   trace_ProvReg_NextClass_Failed(
                       r, tcs(Result_ToString(r)));
  
     /* empty reg with OK means context is being initialized;                  trace_DispEnum_UnknownClass(
         sub command will be processed later, once EnableIndicaitons is processed */                      tcs(req->nameSpace), tcs(req->className));
     if (!reg)  
         return MI_RESULT_OK;  
  
     // Send the request to provider manager.                  /* send error back to caller */
     r = AgentMgr_HandleRequest(&self->agentmgr, &msg->base, reg);                  goto sendErrorBack_Opened;
               }
  
     if (r != MI_RESULT_OK)              enumEntry = (EnumEntry*)StrandEntry_New( STRAND_DEBUG( DispEnumEntry )
                                                           &enumInteraction->strand,
                                                           &_DispEnumEntry_ProviderFT,
                                                           sizeof(EnumEntry),
                                                           STRAND_FLAG_ENTERSTRAND,
                                                           NULL);
               if( NULL == enumEntry )
     {     {
         LOGD((T("AgentMgr_HandleRequest for namespace: %s"), MI_GET_SAFE_PRINTF_STRING(req->nameSpace)));                  trace_Disp_ErrorEnumEntryAlloc();
         goto sendErrorBack;                  goto sendErrorBack_Opened;
     }     }
  
     if (msg)              r = StrandMany_AddEntry( &enumEntry->strand );
         SubscribeReq_Release(msg);              if( MI_RESULT_OK != r )
               {
     return MI_RESULT_OK;                  trace_Disp_ErrorAddEntry();
                   StrandEntry_DeleteNoAdded( &enumEntry->strand );
 sendErrorBack:                  goto sendErrorBack_Opened;
     if (msg)              }
         SubscribeReq_Release(msg);  
  
     return _SendErrorResponse(&req->base,r);              // 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, derived);
               enumEntry->next = NULL;
               enumEntryPrev->next = enumEntry;
               enumEntryPrev = enumEntry;
 } }
  
 static MI_Result _HandleInvokeReq(          /* Finalize enumeration */
     Disp* self,  
     InvokeReq* req)  
 { {
     MI_Result r;              r = ProvReg_EndClasses(&pos);
     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)              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;
       HashMap classNames;
       DispEnumParent* enumInteraction;
       EnumEntry* enumEntry;
       EnumEntry* enumEntryHead = NULL;
       EnumEntry* enumEntryPrev = NULL;
   
       /* Create a hash table of class names */
   
       res = HashMap_Init(
           &classNames,
           64,
           ClassNameHash,
           ClassNameEqual,
           ClassNameRelease);
   
       if (res != 0)
           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 1080 
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
        * the association provider to be called twice. To avoid this for now,
        * we maintain a hash table of already dispatched classes.
        */
   
     /* While more classes */     /* While more classes */
     for (;;)     for (;;)
     {     {
Line 1098 
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;
         }         }
  
         if (_DispatchAssocReq(self, cn, req, dispStateMsg))          /* Check whether this class has been dispatched */
             sentOk = MI_TRUE;          {
               ClassNameBucket bucket;
               bucket.key = (ZChar*)cn;
   
               if (!HashMap_Find(&classNames, (const HashBucket*)&bucket))
               {
                   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 )
                   {
                       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*)PAL_Calloc(
                           1, sizeof(ClassNameBucket));
   
                       if (!bucket)
                       {
                           r = MI_RESULT_FAILED;
                           goto sendErrorBack_Opened;
                       }
   
                       bucket->key = PAL_Tcsdup(cn);
   
                       if (HashMap_Insert(&classNames, (HashBucket*)bucket) != 0)
                       {
                           r = MI_RESULT_FAILED;
                           goto sendErrorBack_Opened;
                       }
                   }
               }
           }
     }     }
  
     /* Finalize enumeration */     /* Finalize enumeration */
Line 1114 
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;
     }     }
  
     DispResultMsg_Release(dispStateMsg);      // send error back to caller
       _SendErrorResponse_Opened(interactionParams, enumInteraction, r, MI_FALSE );
     return MI_RESULT_OK;     return MI_RESULT_OK;
   
 sendErrorBack:  
     DispResultMsg_Release(dispStateMsg);  
     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 1195 
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 1211 
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 1258 
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 1266 
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 1277 
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.1  
changed lines
  Added in v.1.4

ViewCVS 0.9.2