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

Diff for /omi/provmgr/context.c between version 1.4 and 1.5

version 1.4, 2015/04/20 18:10:13 version 1.5, 2015/04/20 18:19:56
Line 23 
Line 23 
 */ */
  
 #include "context.h" #include "context.h"
   #include "AggregationContext.h"
   #include "SubscriptionContext.h"
   #include "LifecycleContext.h"
   #include "SubMgr.h"
 #include <wsman/wsbuf.h> #include <wsman/wsbuf.h>
 #include <wql/wql.h> #include <wql/wql.h>
   #include <pal/format.h>
   #include <pal/thread.h>
   #include <pal/sleep.h>
   #include "nioproc.h"
   #include <omi_error/omierror.h>
   
   STRAND_DEBUGNAME3( Context, TryPostLeft, TryPostLeftNotify, InvokeSubscribe );
  
 static const MI_Uint32 _MAGIC = 0x35eb3d3b; static const MI_Uint32 _MAGIC = 0x35eb3d3b;
  
   static MI_Result MI_CALL _PostError(
       _In_ MI_Context* self,
       MI_Uint32 result,
       _In_z_ const ZChar* type,
       _In_z_ const ZChar* message);
   
   void _Context_Destroy(
       _Inout_ Context* self)
   {
       RequestMsg* request = self ? self->request : 0;
       Message* loadRequest = self ? self->loadRequest : 0;
   
       trace_ContextDestroy( self, &self->strand, &self->strand.info.interaction );
   
       DEBUG_ASSERT( self );
   
       if (self->provider)
       {
           Provider_Release(self->provider);
       }
   
       memset(self, 0xFF, sizeof(Context));
   
       /* Context typically allocated from message's batch
        * so it may be freed right inside 'Release' call
        */
       if (request)
           Message_Release(&request->base);
   
       if (loadRequest)
           Message_Release(loadRequest);
   }
   
   /*
    * Post a message to the component to the left
    */
   _Use_decl_annotations_
   void Context_PostMessageLeft(
       Context* self,
       Message* msg)
   {
       ptrdiff_t tryingToPostLeft;
   // Uncomment when no longer using Selector
   //#if !defined(CONFIG_OS_WINDOWS)
       ThreadID threadId = Thread_ID();
       Selector* selector = self->provider->lib->provmgr->selector;
   //#endif
   
       // It is not clear if a Provider can Post concurrently in different threads (UT does)
       // so protect against it
       Lock_Acquire(&self->lock);
   
       DEBUG_ASSERT( NULL != self->strand.info.interaction.other );
       DEBUG_ASSERT( NULL == self->msgPostingLeft );
       DEBUG_ASSERT( 0 == self->tryingToPostLeft );
   
       // we dont need to add a reference to the message as
       // we are not going to leave this function on this thread until is sent
       // (event if it is actually sent in another thread)
       self->msgPostingLeft = msg;
   
   // Uncomment when no longer using Selector
   //#if !defined(CONFIG_OS_WINDOWS)
       if( Selector_IsSelectorThread( selector, &threadId ) )
       {
           Context_PostMessageLeft_IoThread( self );
           self->postingOnIoThread = MI_TRUE;
       }
   //#endif
       Atomic_Swap(&self->tryingToPostLeft,(ptrdiff_t)(CONTEXT_POSTLEFT_POSTING|CONTEXT_POSTLEFT_SCHEDULED));
   
       Strand_ScheduleAux( &self->strand, CONTEXT_STRANDAUX_TRYPOSTLEFT );
   
       while( (tryingToPostLeft = ReadWithFence( &self->tryingToPostLeft )) != 0 )
       {
   // Uncomment when no longer using Selector
   //#if defined(CONFIG_OS_WINDOWS)
   //        CondLock_Wait(
   //            (ptrdiff_t)self, &self->tryingToPostLeft, tryingToPostLeft, CONDLOCK_DEFAULT_SPINCOUNT);
   //#else
           if( self->postingOnIoThread )
           {
               Selector_Run( selector, TIME_NEVER, MI_TRUE );
           }
           else
           {
               CondLock_Wait(
                   (ptrdiff_t)self, &self->tryingToPostLeft, tryingToPostLeft, CONDLOCK_DEFAULT_SPINCOUNT);
           }
   //#endif
       }
   
       // Sent
       DEBUG_ASSERT( 0 == self->tryingToPostLeft );
   
   #ifndef DISABLE_INDICATION
       if (CTX_TYPE_IND_SUBSCRIPTION == self->ctxType ||
           CTX_TYPE_IND_LIFECYCLE == self->ctxType)
       {
           SubscriptionContext* subCtx = (SubscriptionContext*)self;
           if (ReadWithFence(&subCtx->subscription->finalmsgbit) == 1)
           {
               /*
                * Release the refcount added by SubscrContext_Init
                */
               SubMgrSubscription_Release(subCtx->subscription);
           }
       }
   #endif
   
       Lock_Release(&self->lock);
   }
   
   void Context_PostSchema(
       _In_ Context* self,
       _In_ Message* msg)
   {
       Context_PostMessageLeft(self, msg);
   }
   
   _Use_decl_annotations_
   void Context_Close( Context* self )
   {
       // Note that some contexts are used internally (for example to load providers)
       // and therefore dont have an interaction
       if( NULL != self->strand.info.interaction.other )
       {
           Strand_ScheduleClose(&self->strand);
       }
       else
       {
           _Context_Destroy(self);
       }
   }
   
 static MI_Result _ProcessResult( static MI_Result _ProcessResult(
     MI_Context* self_,     MI_Context* self_,
     MI_Result result,     MI_Result result,
     const MI_Char* message,      const ZChar* errorMessage,
     const MI_Instance* error)      const MI_Instance* cimError)
 { {
     Context* self = (Context*)self_;     Context* self = (Context*)self_;
  
     if (!self || self->magic != _MAGIC)     if (!self || self->magic != _MAGIC)
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
  
     LOGD_CHAR(("post result from provider, %d", (int)result));      trace_Provider_PostResult(result);
   
       if (result == MI_RESULT_NOT_SUPPORTED &&
           self->request && self->request->base.tag == ModifyInstanceReqTag &&
           self->postedModifyInstance == MI_FALSE &&
           self->postedModifyGetInstance == MI_TRUE &&
           self->postedModifyEnumInstance != MI_TRUE)
       {
           /* Provider does not support GetInstance so we need to do an Enumerate instead */
           if (self->provider->classDecl->providerFT->EnumerateInstances)
           {
               ModifyInstanceReq* request = (ModifyInstanceReq*)self->request;
   
               /* convert this into a filtering enum because GetInstance is not implemented. */
               self->inst = self->keyInstance;
               self->instanceName = NULL;
               self->postedModifyEnumInstance = MI_TRUE;
               self->provider->classDecl->providerFT->EnumerateInstances(self->provider->self, self_, request->nameSpace, self->keyInstance->classDecl->name, NULL, MI_FALSE, NULL);
               return MI_RESULT_OK;
           }
           else
           {
               /* We cannot handle the contract, we we need to fail. Fall through to send an error */
           }
       }
       else if (result == MI_RESULT_OK && self->request && self->request->base.tag == ModifyInstanceReqTag && self->postedModifyInstance == MI_FALSE)
       {
           ModifyInstanceReq* request = (ModifyInstanceReq*) self->request;
           /* Need to re-send the request now as a GetInstance so we can get the final result. */
           if (self->provider->classDecl->providerFT->GetInstance)
           {
               self->postedModifyGetInstance = MI_TRUE;
               self->provider->classDecl->providerFT->GetInstance(self->provider->self, self_, request->nameSpace, self->keyInstance->classDecl->name, self->keyInstance, NULL);
               return MI_RESULT_OK;
           }
           else if (self->provider->classDecl->providerFT->EnumerateInstances)
           {
               /* convert this into a filtering enum because GetInstance is not implemented. */
               self->inst = self->keyInstance;
               self->instanceName = NULL;
               self->postedModifyEnumInstance = MI_TRUE;
               self->postedModifyGetInstance = MI_TRUE; /* For state management need to think we tried a GetInst */
               self->provider->classDecl->providerFT->EnumerateInstances(self->provider->self, self_, request->nameSpace, self->keyInstance->classDecl->name, NULL, MI_FALSE, NULL);
               return MI_RESULT_OK;
           }
           else
           {
               /* Cannot complete the operation because neither Get or Enum is supported. */
               result = MI_RESULT_NOT_SUPPORTED;
           }
       }
  
     /* If no instances matched during GetInstance over EnumerateInstance */     /* If no instances matched during GetInstance over EnumerateInstance */
     if (self->instanceName && !self->matchedInstanceName)     if (self->instanceName && !self->matchedInstanceName)
Line 48 
Line 244 
             result = MI_RESULT_NOT_FOUND;             result = MI_RESULT_NOT_FOUND;
     }     }
  
     message = message;  
     error = error;  
   
     if (self->request && !self->cancelled)     if (self->request && !self->cancelled)
     {     {
         PostResultMsg* resp = PostResultMsg_New( self->request ? self->request->msgID : 0 );          PostResultMsg* resp = PostResultMsg_New( self->request->base.operationId );
  
         if (!resp)         if (!resp)
             return MI_RESULT_FAILED;             return MI_RESULT_FAILED;
  
           if (self->request->base.flags & WSMANFlag)
           {
               /* Need to clone this in case we need to thread switch. Not the most efficient,
                * but this is consumed in the error packet creation code and seems to be the
                * best way to achieve this for now.
                */
               resp->cimError = cimError;
   
               if (cimError)
               {
                   WSBuf_InstanceToBuf(
                       self->request->userAgent,
                       cimError,
                       NULL, /* filterProperty */
                       NULL, /* filterPropertyData */
                       cimError->classDecl,
                       resp->base.batch,
                       WSMAN_ObjectFlag | WSMAN_IsCimError,
                       &resp->packedInstancePtr,
                       &resp->packedInstanceSize);
   
                   resp->cimErrorClassName = Batch_Tcsdup(resp->base.batch, cimError->classDecl->name);
               }
               else
               {
                   resp->packedInstancePtr = NULL;
                   resp->packedInstanceSize = 0;
                   resp->cimErrorClassName = NULL;
               }
   
               /* Need to clone this in case we need to thread switch */
               if (errorMessage)
               {
                   resp->errorMessage = Batch_Tcsdup(resp->base.batch, errorMessage);
               }
               else
               {
                   resp->errorMessage = NULL;
               }
   
               resp->result = result;
   
               resp->base.flags |= self->request->base.flags;
           }
           else /* Binary protocol */
           {
               resp->cimError = cimError;
               if (cimError)
               {
                   InstanceToBatch(cimError, NULL, NULL, resp->base.batch, &resp->packedInstancePtr, &resp->packedInstanceSize);
                   /* If the serialization fails we should just send the original error back. Seems bad to overrite it with this error */
   
                   resp->cimErrorClassName = Batch_Tcsdup(resp->base.batch, cimError->classDecl->name);
               }
               else
               {
                   resp->packedInstancePtr = NULL;
                   resp->packedInstanceSize = 0;
                   resp->cimErrorClassName = NULL;
               }
               if (errorMessage)
               {
                   resp->errorMessage = Batch_Tcsdup(resp->base.batch, errorMessage);
               }
               else
               {
                   resp->errorMessage = NULL;
               }
         resp->result = result;         resp->result = result;
         Message_SetRequest(&resp->base,self->request);              resp->base.flags |= BinaryProtocolFlag;
         (*self->request->callback)(&resp->base, self->request->callbackData);          }
   
           Context_PostMessageLeft( self, &resp->base);
         PostResultMsg_Release(resp);         PostResultMsg_Release(resp);
     }     }
  
     if (self->result)     if (self->result)
         *self->result = result;         *self->result = result;
  
     /* destory context */      /* close/destroy context */
     Context_Destroy(self);      Context_Close(self);
  
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
  
 static MI_Boolean _FilterProperty(const MI_Char* name, void *data)  static MI_Boolean _FilterProperty(const ZChar* name, void *data)
 { {
     WQL* wql = (WQL*)data;     WQL* wql = (WQL*)data;
  
Line 83 
Line 346 
         return MI_TRUE;         return MI_TRUE;
 } }
  
 static MI_Result _PostInstanceToCallback(  /*
     Context* self,   * This is an internal helper function that should be called from wrappers
     const MI_Instance* instance)   * that manage the lifecycle of the instance getting posted.
    */
   static MI_Result _PostInstanceToCallback_Common(
       _In_ Context* self,
       _In_ const MI_Instance* instance,
       _In_ PostInstanceMsg* resp)
 { {
     PostInstanceMsg* resp = PostInstanceMsg_New(self->request->msgID);      MI_Result r = MI_RESULT_OK;
   
     if (!resp)  
         return MI_RESULT_FAILED;  
  
     if (self->request->flags & WSMANFlag)      if (self->request->base.flags & WSMANFlag)
     {     {
         const MI_ClassDecl* castToClassDecl = 0;         const MI_ClassDecl* castToClassDecl = 0;
  
         /* Enumerate response with 'base-properties-only' option         /* Enumerate response with 'base-properties-only' option
             may require instance conversion */             may require instance conversion */
         if (EnumerateInstancesReqTag == self->request->tag)          if (EnumerateInstancesReqTag == self->request->base.tag)
         {         {
             EnumerateInstancesReq* req = (EnumerateInstancesReq*)self->request;             EnumerateInstancesReq* req = (EnumerateInstancesReq*)self->request;
  
Line 107 
Line 372 
                 castToClassDecl = instance->classDecl;                 castToClassDecl = instance->classDecl;
  
                 while (castToClassDecl &&                 while (castToClassDecl &&
                     Zcasecmp(req->requestClassName, castToClassDecl->name) != 0)                      Tcscasecmp(req->requestClassName, castToClassDecl->name) != 0)
                 {                 {
                     castToClassDecl = castToClassDecl->superClassDecl;                     castToClassDecl = castToClassDecl->superClassDecl;
                 }                 }
Line 117 
Line 382 
         {         {
             EnumerateInstancesReq* req = NULL;             EnumerateInstancesReq* req = NULL;
  
             if (EnumerateInstancesReqTag == self->request->tag)              if (EnumerateInstancesReqTag == self->request->base.tag)
                 req = (EnumerateInstancesReq*)self->request;                 req = (EnumerateInstancesReq*)self->request;
  
             if (req && req->wql)             if (req && req->wql)
             {             {
                 WSBuf_InstanceToBuf(                  r = WSBuf_InstanceToBuf(
                       self->request->userAgent,
                     instance,                     instance,
                     _FilterProperty,                     _FilterProperty,
                     req->wql,                     req->wql,
                     castToClassDecl,                     castToClassDecl,
                     resp->base.batch,                     resp->base.batch,
                     self->request->flags,                      self->request->base.flags,
                     &resp->packedInstancePtr,                     &resp->packedInstancePtr,
                     &resp->packedInstanceSize);                     &resp->packedInstanceSize);
             }             }
             else             else
             {             {
                 WSBuf_InstanceToBuf(                  r = WSBuf_InstanceToBuf(
                       self->request->userAgent,
                     instance,                     instance,
                     NULL, /* filterProperty */                     NULL, /* filterProperty */
                     NULL, /* filterPropertyData */                     NULL, /* filterPropertyData */
                     castToClassDecl,                     castToClassDecl,
                     resp->base.batch,                     resp->base.batch,
                     self->request->flags,                      self->request->base.flags,
                     &resp->packedInstancePtr,                     &resp->packedInstancePtr,
                     &resp->packedInstanceSize);                     &resp->packedInstanceSize);
             }             }
         }         }
  
         resp->base.flags |= self->request->flags;          resp->base.flags |= self->request->base.flags;
     }     }
     else     else
     {     {
         EnumerateInstancesReq* req = NULL;         EnumerateInstancesReq* req = NULL;
  
         if (EnumerateInstancesReqTag == self->request->tag)          if (EnumerateInstancesReqTag == self->request->base.tag)
             req = (EnumerateInstancesReq*)self->request;             req = (EnumerateInstancesReq*)self->request;
  
         if (req && req->wql)         if (req && req->wql)
         {         {
             InstanceToBatch(instance, _FilterProperty, req->wql,              r = InstanceToBatch(
                 resp->base.batch, &resp->packedInstancePtr,                  instance,
                   _FilterProperty,
                   req->wql,
                   resp->base.batch,
                   &resp->packedInstancePtr,
                 &resp->packedInstanceSize);                 &resp->packedInstanceSize);
         }         }
         else         else
         {         {
             InstanceToBatch(instance, NULL, NULL, resp->base.batch,              r = InstanceToBatch(
                 &resp->packedInstancePtr, &resp->packedInstanceSize);                  instance,
                   NULL,
                   NULL,
                   resp->base.batch,
                   &resp->packedInstancePtr,
                   &resp->packedInstanceSize);
         }         }
  
         resp->base.flags |= BinaryProtocolFlag;         resp->base.flags |= BinaryProtocolFlag;
     }     }
  
     /* count message in for back-pressure feature (only Instances) */  
     if (self->provider)  
         Provider_NewInstanceCreated(self->provider, &resp->base);  
  
       if (r != MI_RESULT_OK)
           trace_PackInstanceFailed(r);
       else
           Context_PostMessageLeft( self, &resp->base);
   
       return r;
   }
   
   static MI_Result _PostInstanceToCallback(
       _In_ Context* self,
       _In_ const MI_Instance* instance)
   {
       MI_Result result = MI_RESULT_OK;
       PostInstanceMsg* resp = PostInstanceMsg_New(self->request->base.operationId);
   
       if (!resp)
           return MI_RESULT_FAILED;
   
       result = _PostInstanceToCallback_Common( self, instance, resp );
  
     Message_SetRequest(&resp->base,self->request);  
     (*self->request->callback)(&resp->base, self->request->callbackData);  
     PostInstanceMsg_Release(resp);     PostInstanceMsg_Release(resp);
  
     return MI_RESULT_OK;      return result;
 } }
  
 /* successfully received instance from 'gi' - call invoke with this instance now */ /* successfully received instance from 'gi' - call invoke with this instance now */
Line 187 
Line 477 
     Context* self,     Context* self,
     const MI_Instance* instance)     const MI_Instance* instance)
 { {
     Context* ctx = (Context*)Batch_GetClear(self->request->batch, sizeof(Context));;      Context* ctx = (Context*)Batch_GetClear(self->request->base.batch, sizeof(Context));;
  
     Context_Init(ctx, self->provider);      // This is an internal context so it doesn't need an interaction
       Context_Init(ctx, self->provider, NULL);
  
     ctx->request = self->request;     ctx->request = self->request;
     /* message will be freed in context release*/     /* message will be freed in context release*/
     Message_AddRef(ctx->request);      Message_AddRef(&ctx->request->base);
  
     /* disregard all other messages for this context */     /* disregard all other messages for this context */
     self->cancelled = MI_TRUE;     self->cancelled = MI_TRUE;
Line 202 
Line 493 
         __nameSpace, __className, __methodName, instance, self->instParams);         __nameSpace, __className, __methodName, instance, self->instParams);
 } }
  
   
 static MI_Result MI_CALL _PostResult( static MI_Result MI_CALL _PostResult(
     MI_Context* self_,     MI_Context* self_,
     MI_Result result)     MI_Result result)
 { {
     return _ProcessResult(self_, result, 0, 0);      Context* self = (Context*)self_;
 }  
  
 static MI_Result MI_CALL _PostResultWithMessage(      /* Suppress MI_RESULT_NOT_SUPPORTED errors for operations which involve
     MI_Context* self_,       * multiple provdiders. For example, suppose the operation is handled by
     MI_Result result,       * providers A, B, and C. If providers A and B post MI_RESULT_OK but
     const MI_Char* message)       * provider C posts MI_RESULT_NOT_SUPPORTED, we must translate this error
        * to a MI_RESULT_OK to prevent the client from receiving it. The client
        * is only concerned with receiving valid instances, not with whether a
        * particular provider implements the operation.
        */
       if (result == MI_RESULT_NOT_SUPPORTED)
       {
           switch (self->request->base.tag)
 { {
     return _ProcessResult(self_, result, message, 0);              case AssociatorsOfReqTag:
               case ReferencesOfReqTag:
                   result = MI_RESULT_OK;
                   break;
               default:
                   break;
           }
 } }
  
       if (result == MI_RESULT_OK)
 static MI_Result MI_CALL _PostResultWithError(          return _ProcessResult(self_, result, NULL, NULL);
     _In_ MI_Context* self_,      else
     MI_Result result,          return _PostError(self_, result, MI_RESULT_TYPE_MI, NULL);
     _In_ const MI_Instance* error)  
 {  
     return _ProcessResult(self_, result, 0, error);  
 } }
  
 static MI_Result MI_CALL _PostInstance( static MI_Result MI_CALL _PostInstance(
Line 240 
Line 539 
     {     {
         if (self->instanceName == NULL)         if (self->instanceName == NULL)
         {         {
             if (CTX_TYPE_INVOKE_WITH_INSTANCE == self->chainType)              if (!Instance_ValidateNonNullKeys(instance))
               {
                   /* Fail the Post if it has NULL key properties.  It is an
                    * invalid object. */
                   return MI_RESULT_FAILED;
               }
   
               if (CTX_TYPE_INVOKE_WITH_INSTANCE == self->ctxType)
             {             {
                 _CallInvoke(self, instance);                 _CallInvoke(self, instance);
                 return MI_RESULT_OK;                 return MI_RESULT_OK;
             }             }
             else if (EnumerateInstancesReqTag == self->request->tag)              else if (EnumerateInstancesReqTag == self->request->base.tag)
             {             {
                 EnumerateInstancesReq* req =                 EnumerateInstancesReq* req =
                     (EnumerateInstancesReq*)self->request;                     (EnumerateInstancesReq*)self->request;
Line 269 
Line 575 
                     }                     }
                 }                 }
             }             }
               else if (ModifyInstanceReqTag == self->request->base.tag)
               {
                   self->postedModifyInstance = MI_TRUE;
                   return _PostInstanceToCallback(self, instance);
               }
  
             return _PostInstanceToCallback(self, instance);             return _PostInstanceToCallback(self, instance);
         }         }
Line 286 
Line 597 
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
  
   static Batch* _GetBatch(Context* self)
   {
       if (self->provider && self->provider->lib && self->provider->lib->instanceLifetimeContext)
       {
           if (self->request)
               return self->request->base.batch;
   
           if (self->loadRequest)
               return self->loadRequest->batch;
       }
   
       return NULL;
   }
   
 static MI_Result MI_CALL _ConstructInstance( static MI_Result MI_CALL _ConstructInstance(
     MI_Context* self_,     MI_Context* self_,
     const MI_ClassDecl* classDecl,     const MI_ClassDecl* classDecl,
     MI_Instance* instance)     MI_Instance* instance)
 { {
       Batch *batch = NULL;
     Context* self = (Context*)self_;     Context* self = (Context*)self_;
  
     if (!self || self->magic != _MAGIC || !instance || !classDecl)     if (!self || self->magic != _MAGIC || !instance || !classDecl)
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
  
     return Instance_Construct(instance, classDecl, self->request->batch);      batch = _GetBatch(self);
   
       return Instance_Construct(instance, classDecl, batch);
 } }
  
 static MI_Result MI_CALL _ConstructParameters( static MI_Result MI_CALL _ConstructParameters(
Line 304 
Line 632 
     const MI_MethodDecl* methodDecl,     const MI_MethodDecl* methodDecl,
     MI_Instance* instance)     MI_Instance* instance)
 { {
       Batch *batch = NULL;
     Context* self = (Context*)self_;     Context* self = (Context*)self_;
  
     if (!self || self->magic != _MAGIC || !instance || !methodDecl)     if (!self || self->magic != _MAGIC || !instance || !methodDecl)
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
  
     return Parameters_Init(instance, methodDecl, self->request->batch);      batch = _GetBatch(self);
   
       return Parameters_Init(instance, methodDecl, batch);
 } }
  
 static MI_Result MI_CALL _NewInstance( static MI_Result MI_CALL _NewInstance(
Line 317 
Line 648 
     const MI_ClassDecl* classDecl,     const MI_ClassDecl* classDecl,
     MI_Instance** instance)     MI_Instance** instance)
 { {
       Batch *batch = NULL;
     Context* self = (Context*)self_;     Context* self = (Context*)self_;
  
     if (!self || self->magic != _MAGIC || !classDecl || !instance)     if (!self || self->magic != _MAGIC || !classDecl || !instance)
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
  
     return Instance_New(instance, classDecl, self->request->batch);      batch = _GetBatch(self);
   
       return Instance_New(instance, classDecl, batch);
 } }
  
 static MI_Result MI_CALL _NewDynamicInstance( static MI_Result MI_CALL _NewDynamicInstance(
     MI_Context* self_,     MI_Context* self_,
     const MI_Char* className,      const ZChar* className,
     MI_Uint32 flags,     MI_Uint32 flags,
     MI_Instance** instance)     MI_Instance** instance)
 { {
       Batch *batch = NULL;
     Context* self = (Context*)self_;     Context* self = (Context*)self_;
  
     if (!self || self->magic != _MAGIC || !className || !instance)     if (!self || self->magic != _MAGIC || !className || !instance)
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
  
       batch = _GetBatch(self);
   
     return Instance_NewDynamic(instance, className, flags,     return Instance_NewDynamic(instance, className, flags,
         self->request->batch);          batch);
 } }
  
 static MI_Result MI_CALL _NewParameters( static MI_Result MI_CALL _NewParameters(
Line 345 
Line 682 
     const MI_MethodDecl* methodDecl,     const MI_MethodDecl* methodDecl,
     MI_Instance** instance)     MI_Instance** instance)
 { {
       Batch *batch = NULL;
     Context* self = (Context*)self_;     Context* self = (Context*)self_;
  
     if (!self || self->magic != _MAGIC || !methodDecl || !instance)     if (!self || self->magic != _MAGIC || !methodDecl || !instance)
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
  
     return Parameters_New(instance, methodDecl, self->request->batch);      batch = _GetBatch(self);
   
       return Parameters_New(instance, methodDecl, batch);
 } }
  
 static MI_Result MI_CALL _Canceled( static MI_Result MI_CALL _Canceled(
Line 366 
Line 706 
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
  
 static MI_Result MI_CALL _PostIndication(  #ifndef DISABLE_INDICATION
     MI_Context* context,  
     const MI_Instance* indication,  static MI_Result _PostIndicationToCallback(
     MI_Uint32 subscriptionIDCount,      _In_ Context* self,
     const MI_Char* bookmark)      _In_ const MI_Instance* instance,
       _In_opt_z_ const ZChar* bookmark )
 { {
     /* ATTN: just use _PostInstance() for now */      MI_Result result = MI_RESULT_OK;
     MI_UNUSED(subscriptionIDCount);      PostIndicationMsg* resp = PostIndicationMsg_New(self->request->base.operationId);
     MI_UNUSED(bookmark);  
     return _PostInstance(context, indication);  
 }  
  
 static MI_Result MI_CALL _GetLocale(      if (!resp)
     const MI_Context* context,          return MI_RESULT_FAILED;
     MI_LocaleType localeType,  
     MI_Char locale[MI_MAX_LOCALE_SIZE])      /* Copy bookmark into the message's Batch to control its lifetime. */
       if (bookmark)
 { {
     return MI_RESULT_NOT_SUPPORTED;          const ZChar* tmp = Batch_Tcsdup(resp->base.base.batch, bookmark);
 }  
  
 static MI_Result MI_CALL _RegisterCancel(          if (!tmp)
     MI_Context* context,  
     MI_CancelCallback callback,  
     void* callbackData)  
 { {
     return MI_RESULT_NOT_SUPPORTED;              PostIndicationMsg_Release(resp);
               return MI_RESULT_FAILED;
 } }
  
 static MI_Result MI_CALL _RequestUnload(          resp->bookmark = tmp;
     MI_Context* self_)      }
 {  
     Context* self = (Context*)self_;  
  
     if (!self || self->magic != _MAGIC || !self->provider)      result = _PostInstanceToCallback_Common( self, instance, (PostInstanceMsg*)resp );
         return MI_RESULT_INVALID_PARAMETER;  
  
     Provider_SetRefuseUnloadFlag(self->provider, MI_FALSE);      PostIndicationMsg_Release(resp);
     return MI_RESULT_OK;  
       return result;
 } }
  
 static MI_Result MI_CALL _RefuseUnload(  /*
     MI_Context* self_)   * PostIndication handler for SubscriptionContext.  It evaluates an indication
 {   * using a pre-specified indication filter.  It is placed here so that
     Context* self = (Context*)self_;   * _PostInstanceToCallback remains private to Context.c.
    */
   MI_Result _SubscrContext_PostIndication(
       _In_ SubscriptionContext* context,
       _In_ const MI_Instance* indication,
       _In_opt_z_ const ZChar* bookmark,
       _In_ MI_Boolean subscriptionRefcounted)
   {
       MI_Result result = MI_RESULT_OK;
       SubMgrSubscription* subscription = NULL;
       MI_Boolean isMatch = MI_FALSE;
       SubscriptionManager* subMgr;
  
     if (!self || self->magic != _MAGIC || !self->provider)      if (!context || !indication)
       {
           trace_PostIndicationWithNullInput();
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
   
     Provider_SetRefuseUnloadFlag(self->provider, MI_TRUE);  
     return MI_RESULT_OK;  
 } }
  
 static MI_Result _GetLocalSession(      subMgr = context->baseCtx.provider->subMgr;
     _In_ const MI_Context* context,      DEBUG_ASSERT ( subMgr );
     _Out_ MI_Session* session)  
 {      if ( MI_FALSE == SubMgr_CanPostIndication( subMgr ) )
     return MI_RESULT_NOT_SUPPORTED;     return MI_RESULT_NOT_SUPPORTED;
 }  
  
 static MI_Result _SetStringOption(      /* Ref counted, release later */
     _In_ MI_Context* context,      if ( MI_FALSE == subscriptionRefcounted )
     _In_z_ const MI_Char* name,          subscription = SubMgr_GetSubscriptionByContext(subMgr, context);
     _In_z_ const MI_Char* value)      else
           subscription = context->subscription;
   
       if ( !subscription )
 { {
     return MI_RESULT_NOT_SUPPORTED;          return MI_RESULT_FAILED;
 } }
  
 static MI_Result _GetStringOption(      if (SubscriptionState_Unsubscribing == subscription->state ||
     _In_  MI_Context* context,          SubscriptionState_Unsubscribed == subscription->state)
     _In_z_ const MI_Char* name,  
     _Outptr_result_z_  const MI_Char** value)  
 { {
     return MI_RESULT_NOT_SUPPORTED;          trace_PostIndicationWithUnsubscribedContext();
           if ( MI_FALSE == subscriptionRefcounted)
               SubMgrSubscription_Release(subscription);
           return MI_RESULT_OK;
 } }
  
 static MI_Result _GetNumberOption(      if (!Instance_ValidateNonNullKeys(indication))
     _In_  MI_Context* context,  
     _In_z_ const MI_Char *name,  
     _Out_opt_  MI_Uint32* value)  
 { {
     return MI_RESULT_NOT_SUPPORTED;          /* Fail the Post if it has NULL key properties.  It is an
            * invalid object. */
           if ( MI_FALSE == subscriptionRefcounted)
               SubMgrSubscription_Release(subscription);
           return MI_RESULT_FAILED;
 } }
  
 static MI_Result _GetCustomOption(      result = InstanceFilter_Filter( subscription->filter, indication, &isMatch );
     _In_  MI_Context* context,  
     _In_z_ const MI_Char* name,      /* Check the evaluation status.  Only forward indications that satisfied
     _Out_opt_  MI_Type* valueType,       * a known filter. */
     _Out_opt_  MI_Value* value)      if (MI_RESULT_OK == result && isMatch)
 {      {
     return MI_RESULT_NOT_SUPPORTED;          SubMgrSubscription_AcuquirePostLock(subscription);
           if ( MI_FALSE == SubMgrSubscription_CancelStarted(subscription) )
               result = _PostIndicationToCallback((Context*)context, indication, bookmark);
           else
               result = MI_RESULT_FAILED;
           SubMgrSubscription_ReleasePostLock(subscription);
 } }
  
 static MI_Result _GetCustomOptionCount(      if ( MI_FALSE == subscriptionRefcounted)
     _In_  MI_Context* context,          SubMgrSubscription_Release(subscription);
     _Out_opt_ MI_Uint32* count)  
 {      return result;
     return MI_RESULT_NOT_SUPPORTED;  
 } }
  
 static MI_Result _GetCustomOptionAt(  MI_Result _SubscrContext_ProcessResult(
     _In_  MI_Context* context,      _In_ Context* context,
     _In_ MI_Uint32 index,      _In_ MI_Result result,
     _Outptr_opt_result_maybenull_z_  const MI_Char** name,      _In_opt_z_ const ZChar* errorMessage,
     _Out_opt_  MI_Type* valueType,      _In_opt_ const MI_Instance* cimError )
     _Out_opt_  MI_Value* value)  
 { {
     return MI_RESULT_NOT_SUPPORTED;      /* subscription object is guaranteed live here since the provider owning one refcount */
 }      /* after this call, the refcount will be released */
       SubscriptionContext* subCtx = (SubscriptionContext*)context;
       SubMgrSubscription* subscription = SubscrContext_GetSubscription( subCtx );
       MI_Result r;
  
 static MI_Result _WriteMessage(      DEBUG_ASSERT(subscription); /* This identifies any cases that may violate the refcount guarantee */
     _In_ MI_Context* context,  
     MI_Uint32 channel,      SubMgrSubscription_Addref(subscription);
     _In_z_ const MI_Char* message)  
       Provider_RemoveSubscription(context->provider, subscription->subscriptionID);
   
   #if !defined(_MSC_VER)
 { {
     return MI_RESULT_NOT_SUPPORTED;          ThreadID tempId = Thread_ID();
           if (Thread_Equal(&tempId, &context->provider->lib->provmgr->ioThreadId))
           {
               /* For non-windows platform, there is only one IO thread in current process, */
               /* which has dead lock issue if have multi-thread (include IO thread) posting messages */
               /* simultaneously. To resolve the issue, unsubscribe has to be invoked from a separate thread */
               /* Upon implementing multi-thread IO for OMI server, this workaround should be removed */
               Schedule_SendFinalResult( subCtx, result );
               return MI_RESULT_OK;
 } }
       }
   #endif
  
 static MI_Result _WriteProgress(      trace_SubscrContext_ProcessResult(UintThreadID(), subCtx, subscription);
     _In_ MI_Context* context,  
     _In_z_ const MI_Char* activity,      /* Handle failure responses */
     _In_z_ const MI_Char* currentOperation,      if (SubscriptionState_Subscribed == subscription->state ||
     _In_z_ const MI_Char* statusDescription,          SubscriptionState_Unsubscribing == subscription->state)
     MI_Uint32 percentComplete,      {
     MI_Uint32 secondsRemaining)          trace_SubscrContext_ProviderPostingFailure(result,
               ((subscription->state == SubscriptionState_Subscribed) ? PAL_T("subscribed") : PAL_T("unsubscribing")),
               subscription);
       }
       else
       {
           trace_SubscrContext_ProcessResult_InvalidState(UintThreadID(), subCtx, subscription, subscription->state);
       }
   
       SubMgrSubscription_AcuquirePostLock(subscription);
       r = SubscrContext_SendFinalResultMsg( subCtx, result, errorMessage, cimError );
       SubMgrSubscription_ReleasePostLock(subscription);
   
       SubMgrSubscription_Release(subscription);
       return r;
   }
   
   /*
    * PostIndication handler for AggregationContext.  It forwards an indication
    * to all known subscriptions for filter evaluation.  It is placed here so that
    * _PostInstanceToCallback remains private to Context.c.
    */
   MI_Result _AggrContext_PostIndication(
       _In_ AggregationContext* context,
       _In_ const MI_Instance* indication,
       _In_opt_z_ const ZChar* bookmark )
   {
       SubscriptionManager* subMgr = NULL;
       MI_Boolean atLeastOneDelivered = MI_FALSE;
       SubMgrSubscriptionPtr* sublist;
       MI_Result r;
       size_t count = 0;
       size_t i;
   
       if (!context || !indication)
       {
           trace_PostIndicationWithNullInput();
           return MI_RESULT_INVALID_PARAMETER;
       }
   
       subMgr = AggrContext_GetManager( context );
   
       /* Both of these states result in the same thing: the AggregationContext
        * must be cleaned up. */
       if ( (MI_FALSE == SubMgr_IsEnabled ( subMgr )) ||
            (MI_TRUE == SubMgr_IsSubListEmpty ( subMgr )))
       {
           trace_PostIndicationOnDisabledAggContext();
           return MI_RESULT_FAILED;
       }
   
       /* sublist holds one reference count to each subscription */
       r = SubMgr_GetSubscriptionList(subMgr, &sublist, &count);
       if ( r != MI_RESULT_OK )
           return r;
   
       for ( i = 0; i < count; i++ )
       {
           /*
            * This is a best-effort action
            * Intermediate failures will be ignored
            */
           r = _SubscrContext_PostIndication( sublist[i]->subscribeCtx, indication, bookmark, MI_TRUE );
           if ( MI_RESULT_OK == r )
           {
               atLeastOneDelivered = MI_TRUE;
           }
           /* release the one reference count */
           SubMgrSubscription_Release( sublist[i] );
       }
   
       return (atLeastOneDelivered ? MI_RESULT_OK : r);
   }
   
   /*
    * Handles AggregationContext cleanup during error scenarios derived from
    * PostResult, PostError, and PostCimError calls on the context.
    */
   MI_Result _AggrContext_Terminate(
       Context* context,
       MI_Result result,
       const ZChar* errorMessage,
       const MI_Instance* cimError )
   {
       return Provider_TerminateIndication(context->provider, result, errorMessage, cimError);
   }
   
   /*
    * Delegates AggregationContext Post calls depending on the state of the
    * context.
    */
   MI_Result _AggrContext_ProcessResult(
       _In_ Context* context,
       _In_ MI_Result result,
       const ZChar* errorMessage,
       const MI_Instance* cimError )
   {
       return _AggrContext_Terminate( context, result, errorMessage, cimError );
   }
   
   static MI_Result _Ind_Common_ProcessResult(
       _In_ MI_Context* context,
       _In_ MI_Result result,
       const ZChar* errorMessage,
       const MI_Instance* cimError )
   {
       Context* self = (Context*)context;
       MI_Result toReturn = MI_RESULT_OK;
   
       if (!self || self->magic != _MAGIC)
       {
           trace_PostCalledWithInvalidContext();
           return MI_RESULT_INVALID_PARAMETER;
       }
   
       if (!self->cancelled)
       {
           /* Engages filter handlers to determine if the indication instance is
            * appropriate for forwarding to clients. */
           switch (self->ctxType)
           {
               case CTX_TYPE_IND_AGGREGATION:
                   toReturn = _AggrContext_ProcessResult( self, result, errorMessage, cimError );
                   break;
               case CTX_TYPE_IND_SUBSCRIPTION:
               case CTX_TYPE_IND_LIFECYCLE:    /* Fallthrough expected */
                   toReturn = _SubscrContext_ProcessResult( self, result, errorMessage, cimError );
                   break;
               default:
                   trace_UnknownIndicationContextType((int)self->ctxType);
                   toReturn = MI_RESULT_NOT_FOUND;
                   break;
           }
       }
       /* else: invalid indication post, so do nothing */
   
       return toReturn;
   }
   
   /* TODO: attach bookmark to PostIndicationMsg */
   static MI_Result MI_CALL _Ind_PostIndication(
       MI_Context* context,
       const MI_Instance* indication,
       MI_Uint32 subscriptionIDCount,
       const ZChar* bookmark)
   {
       MI_Result result = MI_RESULT_OK;
       Context* self = (Context*)context;
       MI_UNUSED(subscriptionIDCount);
   
       if (!self || self->magic != _MAGIC || !indication)
       {
           trace_PostCalledWithInvalidContext();
           return MI_RESULT_INVALID_PARAMETER;
       }
   
       if (!self->cancelled)
       {
           /* Engages filter handlers to determine if the indication instance is
            * appropriate for forwarding to clients. */
           switch (self->ctxType)
           {
               case CTX_TYPE_IND_AGGREGATION:
                   result = _AggrContext_PostIndication( (AggregationContext*)self, indication, bookmark );
                   break;
               case CTX_TYPE_IND_SUBSCRIPTION: /* Fallthrough expected */
               case CTX_TYPE_IND_LIFECYCLE:
                   result = _SubscrContext_PostIndication( (SubscriptionContext*)self, indication, bookmark, MI_FALSE );
                   break;
               default:
                   trace_UnknownIndicationContextType((int)self->ctxType);
                   result = MI_RESULT_NOT_FOUND;
                   break;
           }
       }
       /* else: invalid indication post, so do nothing */
   
       return result;
   }
   
   /*
    *_PostInstance is not supported for indication contexts.  Indications
    * must be posted using _PostIndication.
    */
   static MI_Result MI_CALL _Ind_PostInstance(
       MI_Context* self_,
       const MI_Instance* instance)
   {
       Context* self = (Context*)self_;
   
       if (!self || self->magic != _MAGIC || !instance)
       {
           return MI_RESULT_INVALID_PARAMETER;
       }
       return MI_RESULT_NOT_SUPPORTED;
    }
   
   static MI_Result MI_CALL _Ind_PostResult(
       MI_Context* self_,
       MI_Result result)
   {
       return _Ind_Common_ProcessResult( self_, result, NULL, NULL );
   }
   
   static MI_Result MI_CALL _Ind_PostError(
       _In_ MI_Context* self,
       MI_Uint32 result,
       _In_z_ const ZChar* type,
       _In_z_ const ZChar* message)
   {
       if (NULL == type ||
           Tcscmp(type, MI_RESULT_TYPE_MI) != 0)
       {
           result = MI_RESULT_FAILED;
       }
       return _Ind_Common_ProcessResult(self, result, message, NULL);
   }
   
   static MI_Result MI_CALL _Ind_PostCimError(
       _In_ MI_Context* self,
       _In_ const MI_Instance *error)
   {
       MI_Value value;
       MI_Type type;
       MI_Result result;
   
       result = MI_Instance_GetElement(error, MI_T("CIMStatusCode"), &value, &type, NULL, NULL);
       if ((MI_RESULT_OK != result) || (MI_UINT32 != type))
       {
           return _Ind_Common_ProcessResult(self, MI_RESULT_INVALID_CLASS_HIERARCHY, MI_T("Invalid CIM_Error object posted from provider"), NULL);
       }
       else
       {
           MI_Value messageValue;
           MI_Type messageType;
   
           result = MI_Instance_GetElement(error, MI_T("Message"), &messageValue, &messageType, NULL, NULL);
           if ((MI_RESULT_OK != result) || (MI_STRING != messageType))
           {
               messageValue.string = NULL;
           }
           return _Ind_Common_ProcessResult(self, value.uint32, messageValue.string, error);
       }
   }
   
   #endif /* ifndef DISABLE_INDICATION */
   
   static MI_Result MI_CALL _PostIndication(
       MI_Context* context,
       const MI_Instance* indication,
       MI_Uint32 subscriptionIDCount,
       const ZChar* bookmark)
   {
       MI_UNUSED(context);
       MI_UNUSED(indication);
       MI_UNUSED(subscriptionIDCount);
       MI_UNUSED(bookmark);
   
       return MI_RESULT_NOT_SUPPORTED;
   }
   
   static MI_Result MI_CALL _GetLocale(
       const MI_Context* context,
       MI_LocaleType localeType,
       _Pre_writable_size_(MI_MAX_LOCALE_SIZE) ZChar locale[MI_MAX_LOCALE_SIZE])
   {
       return MI_RESULT_NOT_SUPPORTED;
   }
   
   static MI_Result MI_CALL _RegisterCancel(
       MI_Context* context,
       MI_CancelCallback callback,
       void* callbackData)
   {
       return MI_RESULT_NOT_SUPPORTED;
   }
   
   static MI_Result MI_CALL _RequestUnload(
       MI_Context* self_)
   {
       Context* self = (Context*)self_;
   
       if (!self || self->magic != _MAGIC || !self->provider)
           return MI_RESULT_INVALID_PARAMETER;
   
       Provider_SetRefuseUnloadFlag(self->provider, MI_FALSE);
       return MI_RESULT_OK;
   }
   
   static MI_Result MI_CALL _RefuseUnload(
       MI_Context* self_)
   {
       Context* self = (Context*)self_;
   
       if (!self || self->magic != _MAGIC || !self->provider)
           return MI_RESULT_INVALID_PARAMETER;
   
       Provider_SetRefuseUnloadFlag(self->provider, MI_TRUE);
       return MI_RESULT_OK;
   }
   
   static MI_Result MI_CALL _GetLocalSession(
       _In_ const MI_Context* self_,
       _Out_ MI_Session* session)
   {
   #if defined(DISABLE_LOCALSESSION)
       MI_UNREFERENCED_PARAMETER(self_);
       MI_UNREFERENCED_PARAMETER(session);
   
       return MI_RESULT_NOT_SUPPORTED;
   #else
       Context* self = (Context*)self_;
   
       if (!self || self->magic != _MAGIC || !self->provider || !self->provider->lib || !self->provider->lib->provmgr)
           return MI_RESULT_INVALID_PARAMETER;
   
       return ProvMgr_GetLocalSesson(self->provider->lib->provmgr, session);
   #endif /* defined(DISABLE_LOCALSESSION) */
   }
   
   static MI_Result MI_CALL _SetStringOption(
       _In_ MI_Context* context,
       _In_z_ const ZChar* name,
       _In_z_ const ZChar* value)
   {
       return MI_RESULT_NOT_SUPPORTED;
   }
   
   static MI_Result MI_CALL _GetCustomOption(
       _In_  MI_Context* context_,
       _In_z_ const ZChar* name,
       _Out_opt_  MI_Type* valueType,
       _Out_opt_  MI_Value* value)
   {
       Context* context = (Context*)context_;
   
       /* Check parameters */
       if (!context || !context->request)
           return MI_RESULT_INVALID_PARAMETER;
   
       /* Return zero if no option object */
       if (!context->request->options)
           return MI_RESULT_NO_SUCH_PROPERTY;
   
       return __MI_Instance_GetElement(
           context->request->options,
           name,
           value,
           valueType,
           NULL,
           NULL);
   }
   
   static MI_Result MI_CALL _GetCustomOptionCount(
       _In_  MI_Context* context_,
       _Out_opt_ MI_Uint32* count)
   {
       Context* context = (Context*)context_;
   
       /* Check parameters */
       if (!context || !context->request)
           return MI_RESULT_INVALID_PARAMETER;
   
       /* Return zero if no option object */
       if (!context->request->options)
       {
           if (count)
               *count = 0;
           return MI_RESULT_OK;
       }
   
       return __MI_Instance_GetElementCount(context->request->options, count);
   }
   
   static MI_Result MI_CALL _GetCustomOptionAt(
       _In_  MI_Context* context_,
       _In_ MI_Uint32 index,
       _Outptr_opt_result_maybenull_z_  const ZChar** name,
       _Out_opt_  MI_Type* valueType,
       _Out_opt_  MI_Value* value)
   {
       Context* context = (Context*)context_;
   
       /* Check parameters */
       if (!context || !context->request)
           return MI_RESULT_INVALID_PARAMETER;
   
       if (!context->request->options)
           return MI_RESULT_FAILED;
   
       return __MI_Instance_GetElementAt(
           context->request->options,
           index,
           name,
           value,
           valueType,
           0);
   }
   
   static MI_Result MI_CALL _GetStringOption(
       _In_  MI_Context* context,
       _In_z_ const ZChar* name,
       _Outptr_result_z_  const ZChar** valueOut)
   {
       MI_Type type;
       MI_Value value;
       MI_Result r;
   
       r = _GetCustomOption(
           context,
           name,
           &type,
           &value);
   
       if (r != MI_RESULT_OK)
           return r;
   
       if (type != MI_STRING)
           return MI_RESULT_NO_SUCH_PROPERTY;
   
       if (valueOut)
           *valueOut = value.string;
   
       return MI_RESULT_OK;
   }
   
   static MI_Result MI_CALL _GetNumberOption(
       _In_  MI_Context* context,
       _In_z_ const ZChar *name,
       _Out_opt_  MI_Uint32* valueOut)
   {
       MI_Type type;
       MI_Value value;
       MI_Result r;
   
       r = _GetCustomOption(
           context,
           name,
           &type,
           &value);
   
       if (r != MI_RESULT_OK)
           return r;
   
       if (type != MI_UINT32)
           return MI_RESULT_NO_SUCH_PROPERTY;
   
       if (valueOut)
           *valueOut = value.uint32;
   
       return MI_RESULT_OK;
   }
   
   static MI_Result MI_CALL _WriteMessage(
       _In_ MI_Context* context,
       MI_Uint32 channel,
       _In_z_ const ZChar* message)
 { {
     return MI_RESULT_NOT_SUPPORTED;     return MI_RESULT_NOT_SUPPORTED;
 } }
  
 static MI_Result _WriteStreamParameter(  static MI_Result MI_CALL _WriteProgress(
     _In_ MI_Context* context,     _In_ MI_Context* context,
     _In_z_ const MI_Char* name,      _In_z_ const ZChar* activity,
       _In_z_ const ZChar* currentOperation,
       _In_z_ const ZChar* statusDescription,
       MI_Uint32 percentComplete,
       MI_Uint32 secondsRemaining)
   {
       return MI_RESULT_NOT_SUPPORTED;
   }
   
   static MI_Result MI_CALL _WriteStreamParameter(
       _In_ MI_Context* context,
       _In_z_ const ZChar* name,
     _In_ const MI_Value* value,     _In_ const MI_Value* value,
     _In_ MI_Type type,     _In_ MI_Type type,
     _In_ MI_Uint32 flags)     _In_ MI_Uint32 flags)
Line 504 
Line 1338 
     return MI_RESULT_NOT_SUPPORTED;     return MI_RESULT_NOT_SUPPORTED;
 } }
  
 static MI_Result _WriteCimError(  static MI_Result MI_CALL _WriteCimError(
     _In_ MI_Context* context,     _In_ MI_Context* context,
     _In_ const MI_Instance *error,     _In_ const MI_Instance *error,
     _Out_ MI_Boolean *flag)     _Out_ MI_Boolean *flag)
Line 512 
Line 1346 
     return MI_RESULT_NOT_SUPPORTED;     return MI_RESULT_NOT_SUPPORTED;
 } }
  
 static MI_Result _PromptUser(  static MI_Result MI_CALL _PromptUser(
     _In_ MI_Context* context,     _In_ MI_Context* context,
     _In_z_ const MI_Char* message,      _In_z_ const ZChar* message,
     MI_PromptType promptType,     MI_PromptType promptType,
     _Out_ MI_Boolean* result)     _Out_ MI_Boolean* result)
 { {
     return MI_RESULT_NOT_SUPPORTED;     return MI_RESULT_NOT_SUPPORTED;
 } }
  
 static MI_Result _ShouldProcess(  static MI_Result MI_CALL _ShouldProcess(
     _In_ MI_Context* context,     _In_ MI_Context* context,
     _In_z_ const MI_Char* target,      _In_z_ const ZChar* target,
     _In_z_ const MI_Char* action,      _In_z_ const ZChar* action,
     _Out_ MI_Boolean* result)     _Out_ MI_Boolean* result)
 { {
     return MI_RESULT_NOT_SUPPORTED;     return MI_RESULT_NOT_SUPPORTED;
 } }
  
 static MI_Result _ShouldContinue(  static MI_Result MI_CALL _ShouldContinue(
     _In_ MI_Context* context,     _In_ MI_Context* context,
     _In_z_ const MI_Char* message,      _In_z_ const ZChar* message,
     _Out_ MI_Boolean* result)     _Out_ MI_Boolean* result)
 { {
     return MI_RESULT_NOT_SUPPORTED;     return MI_RESULT_NOT_SUPPORTED;
 } }
  
 static MI_Result _PostError(  static MI_Result MI_CALL _PostError(
     _In_ MI_Context* context,      _In_ MI_Context* self,
     MI_Uint32 resultCode,      MI_Uint32 result,
     _In_z_ const MI_Char* resultType,      _In_z_ const ZChar* type,
     _In_z_ const MI_Char* errorMessage)      _In_z_ const ZChar* message)
 { {
     return MI_RESULT_NOT_SUPPORTED;      OMI_Error *omiError = NULL;
       MI_Result returnVal;
   
       if (NULL == type)
       {
           /* Don't know the error type so just use failed */
           type = MI_RESULT_TYPE_MI;
           result = MI_RESULT_FAILED;
       }
       returnVal = OMI_ErrorFromErrorCode(NULL, result, type, message, &omiError);
       if (returnVal == MI_RESULT_INVALID_PARAMETER)
       {
           /* invalid error type */
           type = MI_RESULT_TYPE_MI;
           result = MI_RESULT_FAILED;
       }
       if (returnVal != MI_RESULT_FAILED)
       {
           /* We ignore this error as we need to fail the operation */
           returnVal = _ProcessResult(self, result, message, (MI_Instance*)omiError);
 } }
       else
       {
           if (message == NULL)
           {
               MI_Value messageValue;
               MI_Type messageType;
  
 static MI_Result _PostCimError(              returnVal = MI_Instance_GetElement(&omiError->__instance, MI_T("Message"), &messageValue, &messageType, NULL, NULL);
     _In_ MI_Context* context,              if ((MI_RESULT_OK == returnVal) && (MI_STRING == messageType))
               {
                   message = messageValue.string;
               }
           }
           returnVal = _ProcessResult(self, result, message, &omiError->__instance);
       }
   
       if ( omiError )
           MI_Instance_Delete(&omiError->__instance);
   
       return returnVal;
   }
   
   static MI_Result MI_CALL _PostCimError(
       _In_ MI_Context* self,
     _In_ const MI_Instance *error)     _In_ const MI_Instance *error)
 { {
     return MI_RESULT_NOT_SUPPORTED;      MI_Value value;
       MI_Type type;
       MI_Result result;
   
       result = MI_Instance_GetElement(error, MI_T("CIMStatusCode"), &value, &type, NULL, NULL);
       if ((MI_RESULT_OK != result) || (MI_UINT32 != type))
       {
           return _ProcessResult(self, MI_RESULT_INVALID_CLASS_HIERARCHY, MI_T("Invalid CIM_Error object posted from provider"), NULL);
       }
       else
       {
           MI_Value messageValue;
           MI_Type messageType;
   
           result = MI_Instance_GetElement(error, MI_T("Message"), &messageValue, &messageType, NULL, NULL);
           if ((MI_RESULT_OK != result) || (MI_STRING != messageType))
           {
               messageValue.string = NULL;
           }
           return _ProcessResult(self, value.uint32, messageValue.string, error);
       }
 } }
  
 static MI_Result _WriteError(  static MI_Result MI_CALL _WriteError(
     _In_ MI_Context* context,     _In_ MI_Context* context,
     MI_Uint32 resultCode,     MI_Uint32 resultCode,
     _In_z_ const MI_Char* resultType,      _In_z_ const ZChar* resultType,
     _In_z_ const MI_Char* errorMessage,      _In_z_ const ZChar* errorMessage,
     _Out_ MI_Boolean *flag)     _Out_ MI_Boolean *flag)
 { {
     return MI_RESULT_NOT_SUPPORTED;     return MI_RESULT_NOT_SUPPORTED;
 } }
  
   static MI_Result _GetLifecycleIndicationContext_NotSupported(
       _In_ const MI_Context* context,
       _Outptr_ MI_LifecycleIndicationContext** lifecycleContext)
   {
       MI_UNREFERENCED_PARAMETER(context);
       *lifecycleContext = NULL;
       return MI_RESULT_NOT_SUPPORTED;
   }
   
   /*
    * Initializes lifecycle indication handling for a provider and populates the
    * lifecycleContext ptr if everything goes well.  Returns existing
    * LifecycleContext if it has already been initialized.
    */
   static MI_Result _GetLifecycleIndicationContext(
       _In_ const MI_Context* context,
       _Outptr_ MI_LifecycleIndicationContext** lifecycleContext)
   {
   #ifdef DISABLE_INDICATION
       return _GetLifecycleIndicationContext_NotSupported(context, lifecycleContext);
   #else
   
       Context* internalContext = (Context*)context;
       LifecycleContext* lifeCtx = NULL;
   
       /* Check if indication support has been enabled for this _Provider.  If
        * not, activate it.  Previously initialized support means that either
        * this provider is an Indication class or that a subscription already
        * exists.
        */
       lifeCtx = internalContext->provider->subMgr->lifecycleCtx;
       if (NULL == lifeCtx)
       {
           lifeCtx = LifeContext_New();
           if (NULL == lifeCtx)
           {
               return MI_RESULT_FAILED;
           }
           LifeContext_Init( lifeCtx, internalContext->provider );
           internalContext->provider->subMgr->lifecycleCtx = lifeCtx;
       }
   
       *lifecycleContext = (MI_LifecycleIndicationContext*)lifeCtx;
   
       return MI_RESULT_OK;
   #endif
   }
   
 MI_ContextFT __mi_contextFT = MI_ContextFT __mi_contextFT =
 { {
       // MI_Context_FT
     _PostResult,     _PostResult,
     _PostResultWithMessage,  
     _PostResultWithError,  
     _PostInstance,     _PostInstance,
     _PostIndication,     _PostIndication,
     _ConstructInstance,     _ConstructInstance,
Line 598 
Line 1539 
     _PostError,     _PostError,
     _PostCimError,     _PostCimError,
     _WriteError,     _WriteError,
       _GetLifecycleIndicationContext,
   };
   
   #ifndef DISABLE_INDICATION
   
   /*
    * Alternate MI_Context function table for handling indication functions.
    */
   MI_ContextFT __mi_indication_contextFT =
   {
       _Ind_PostResult,
       _Ind_PostInstance,
       _Ind_PostIndication,
       _ConstructInstance,
       _ConstructParameters,
       _NewInstance,
       _NewDynamicInstance,
       _NewParameters,
       _Canceled,
       _GetLocale,
       _RegisterCancel,
       _RequestUnload,
       _RefuseUnload,
       _GetLocalSession,
       _SetStringOption,
       _GetStringOption,
       _GetNumberOption,
       _GetCustomOption,
       _GetCustomOptionCount,
       _GetCustomOptionAt,
       _WriteMessage,
       _WriteProgress,
       _WriteStreamParameter,
       _WriteCimError,
       _PromptUser,
       _ShouldProcess,
       _ShouldContinue,
       _Ind_PostError,
       _Ind_PostCimError,
       _WriteError,
       _GetLifecycleIndicationContext_NotSupported,
   };
   
   /*
    * Alternate MI_Context function table for invoking subscribe and unsubscribe
    */
   
   static MI_Result _subunsub_ProcessResult(
       MI_Context* self_,
       MI_Result result,
       const ZChar* errorMessage,
       const MI_Instance* cimError)
   {
       Context* self = (Context*)self_;
       MI_UNREFERENCED_PARAMETER(errorMessage);
       MI_UNREFERENCED_PARAMETER(cimError);
       if (!self || self->magic != _MAGIC)
           return MI_RESULT_INVALID_PARAMETER;
       *self->result = result;
       return MI_RESULT_OK;
   }
   
   static MI_Result MI_CALL _subunsub_PostResult(
       MI_Context* self_,
       MI_Result result)
   {
       return _subunsub_ProcessResult(self_, result, NULL, NULL);
   }
   
   static MI_Result MI_CALL _subunsub_PostError(
       _In_ MI_Context* self,
       MI_Uint32 result,
       _In_z_ const ZChar* type,
       _In_z_ const ZChar* message)
   {
       if (NULL == type ||
           Tcscmp(type, MI_RESULT_TYPE_MI) != 0)
       {
           result = MI_RESULT_FAILED;
       }
       return _subunsub_ProcessResult(self, (MI_Result)result, message, NULL);
   }
   
   static MI_Result MI_CALL _subunsub_PostCimError(
       _In_ MI_Context* self,
       _In_ const MI_Instance *error)
   {
       return _subunsub_ProcessResult(self, MI_RESULT_FAILED, NULL, error);
   }
   
   MI_ContextFT __mi_indication_subunsub_contextFT =
   {
       _subunsub_PostResult,
       _Ind_PostInstance,
       _PostIndication,
       _ConstructInstance,
       _ConstructParameters,
       _NewInstance,
       _NewDynamicInstance,
       _NewParameters,
       _Canceled,
       _GetLocale,
       _RegisterCancel,
       _RequestUnload,
       _RefuseUnload,
       _GetLocalSession,
       _SetStringOption,
       _GetStringOption,
       _GetNumberOption,
       _GetCustomOption,
       _GetCustomOptionCount,
       _GetCustomOptionAt,
       _WriteMessage,
       _WriteProgress,
       _WriteStreamParameter,
       _WriteCimError,
       _PromptUser,
       _ShouldProcess,
       _ShouldContinue,
       _subunsub_PostError,
       _subunsub_PostCimError,
       _WriteError,
       _GetLifecycleIndicationContext_NotSupported,
   };
   
   /*
    * The Context that uses this table does not get exposed
    * to a _Provider, so it is considered "internal."
    */
   MI_ContextFT __mi_lifecycleIndication_contextFT =
   {
       _Ind_PostResult,
       NULL,
       _Ind_PostIndication,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
   };
   
   #endif /* ifndef DISABLE_INDICATION */
   
   static void _Context_Post( _In_ Strand* self_, _In_ Message* msg)
   {
       DEBUG_ASSERT( MI_FALSE );  // not used yet (no secondary "semantic" messages)
   }
   
   static void _Context_PostControl( _In_ Strand* self, _In_ Message* msg)
   {
       DEBUG_ASSERT( MI_FALSE );  // not used yet
   }
   
   #ifdef _PREFAST_
   #pragma prefast (push)
   #pragma prefast (disable: 26001) // bogus "we know the interaction points to the middle of the InteractionDispBase struct"
   #endif /* _PREFAST_ */
   
   static void _Context_Ack( _In_ Strand* self_)
   {
       Context* self = FromOffset(Context,strand,self_);
       ptrdiff_t tryingToPostLeftValue = ReadWithFence(&self->tryingToPostLeft);
   
       trace_ContextAck(
           self_,
           self->strand.info.interaction.other,
           &self->strand.info.interaction,
           self->strand.info.thisClosedOther,
           self->strand.info.otherClosedThis,
           tryingToPostLeftValue );
   
       // al management done by strand implementation except broadcasting cond var
   
       // wake up Context_PostMessageLeft if appropiate
       // (no point on waking up Context_PostMessageLeft if CONTEXT_STRANDAUX_TRYPOSTLEFT is scheduled to run after us)
       if( CONTEXT_POSTLEFT_POSTING == Atomic_CompareAndSwap( &self->tryingToPostLeft, (ptrdiff_t)CONTEXT_POSTLEFT_POSTING, (ptrdiff_t)(CONTEXT_POSTLEFT_POSTING|CONTEXT_POSTLEFT_SCHEDULED)) )
       {
           // Schedule it again
           Strand_ScheduleAux( &self->strand, CONTEXT_STRANDAUX_TRYPOSTLEFT );
           // again we get a memory barrier on tryingToPostLeft/tryingToPostLeftScheduled after this
       }
   }
   
   static void _Context_Cancel( _In_ Strand* self )
   {
       trace_ContextCancel( self );
   }
   
   static void _Context_Close( _In_ Strand* self_ )
   {
       Context* self = FromOffset(Context,strand,self_);
       trace_ContextClose(
           self_,
           self->strand.info.interaction.other,
           &self->strand.info.interaction );
   }
   
   static void _Context_Finish( _In_ Strand* self_ )
   {
       Context* self = FromOffset(Context,strand,self_);
   
       trace_ContextFinish( self_ );
       _Context_Destroy(self);
   }
   
   // CONTEXT_STRANDAUX_TRYPOSTLEFT
   static void _Context_Aux_TryPostLeft( _In_ Strand* self_ )
   {
       Context* self = FromOffset(Context,strand,self_);
       ptrdiff_t oldValue;
   
       trace_ContextAuxPostLeft( self_, self->strand.info.thisAckPending );
   
       if( !self->strand.info.thisAckPending )
       {
           if (!self->strand.info.thisClosedOther)  // TODO: Is this correct, or is it indiciative of a different problem?
           {
               /* Only post the message if this Context has not "closed"
                * the connection.  Another thread may have done so on the
                * context while this thread was waiting. */
               Strand_Post( &self->strand, self->msgPostingLeft );
           }
           self->msgPostingLeft = NULL;
           Strand_ScheduleAux(self_, CONTEXT_STRANDAUX_TRYPOSTLEFT_NOTIFY);
       }
       else
       {
           oldValue = Atomic_Swap(&self->tryingToPostLeft,(ptrdiff_t)CONTEXT_POSTLEFT_POSTING);
           DEBUG_ASSERT( (CONTEXT_POSTLEFT_POSTING|CONTEXT_POSTLEFT_SCHEDULED) == oldValue );
       }
   }
   
   // CONTEXT_STRANDAUX_TRYPOSTLEFT_NOTIFY
   static void _Context_Aux_TryPostLeft_Notify( _In_ Strand* self_ )
   {
       Context* self = FromOffset(Context,strand,self_);
       ptrdiff_t oldValue;
   
       oldValue = Atomic_Swap(&self->tryingToPostLeft,(ptrdiff_t)0);
       // wake up _Context_PostMessageLeft
   
   // Uncomment when no longer using Selector
   //#if defined(CONFIG_OS_WINDOWS)
   //    trace_ContextAuxPostLeftNotify( self_ );
   //    CondLock_Broadcast((ptrdiff_t)self);
   //#else
       if( self->postingOnIoThread )
       {
           trace_ContextAuxPostLeftNotify_IoThread( self_ );
           self->postingOnIoThread = MI_FALSE;
           Selector_StopRunningNoReadsMode( self->provider->lib->provmgr->selector );
       }
       else
       {
           trace_ContextAuxPostLeftNotify( self_ );
           CondLock_Broadcast((ptrdiff_t)self);
       }
   //#endif
   
       DEBUG_ASSERT( (CONTEXT_POSTLEFT_POSTING|CONTEXT_POSTLEFT_SCHEDULED) == oldValue );
   }
   
   
   #ifdef _PREFAST_
   #pragma prefast (pop)
   #endif /* _PREFAST_ */
   
   /*
    * This represents a standard Context object.  It mediates access to the
    * internal strands from providers so that a provider can have only one
    * operation outstanding at a time.  Provider Posts (Result, Indication,
    * Error, CimError, and Instance) are routed through 'TryPostLeft' so that
    * they can be handled within a post lock and in the context of a strand
    * action.  Providers may post from multiple threads to the same Context,
    * but only one post will be handled at a time.  An ACK releases the
    * tryingToPostLeft flag to allow another Post to occur.
    *
    * Shutdown behavior:
    *     Cancel and Close do nothing.  The strand cannot be finished until it
    *     schedules a close on itself.  This will happen when the Context or
    *     ProvMgr determine that a connection to a provider should be closed.
    *     Typically this happens after a provider calls PostResult, PostError,
    *     or PostCimError.
    */
   StrandFT _Context_leftInteractionFT =
   {
       _Context_Post,
       _Context_PostControl,
       _Context_Ack,
       _Context_Cancel,
       _Context_Close,
       _Context_Finish,
       NULL,
       _Context_Aux_TryPostLeft,
       _Context_Aux_TryPostLeft_Notify,
       NULL,
       NULL,
       NULL
   };
   
   
   #ifndef DISABLE_INDICATION
   
   /*
    * IndicationManager cancels the operations upon get cancelled call from protocol or
    * received unsubscribe message.
    *
    * This function works for both Lifecycle and regular subscription contexts
    */
   static void _SubscribeContext_Cancel(_In_ Strand* self_)
   {
       SubscriptionContext* self = (SubscriptionContext*)((char*)self_ - offsetof(Context,strand));
       trace_SubscribeContext_Cancel(self);
   
       if (NULL == self->subscription ||
           SubMgrSubscription_CancelStarted(self->subscription))
       {
           /* The subscription has already posted a final result, so there is
            * nothing to do here. */
           return;
       }
       SubscrContext_Unsubscribe(self);
       trace_SubscribeContext_CancelDone(self);
   }
   
   
   // CONTEXT_STRANDAUX_INVOKESUBSCRIBE
   static void _Context_Aux_InvokeSubscribe( _In_ Strand* self_ )
   {
       Context* self = FromOffset(Context,strand,self_);
       Message* msg = self->strand.info.stored.msg;
   
       DEBUG_ASSERT( NULL != msg );
   
       self->strand.info.stored.msg = NULL;
   
       Provider_InvokeSubscribe(
           self->provider,
           (SubscribeReq*)msg,
           (SubscriptionContext*)self);
   
       /*
        * release the reference count from _SubMgrSubscription_New
        */
       SubMgrSubscription_Release(((SubscriptionContext*)self)->subscription);
   
       Message_Release( msg );
   }
   
   /*
    * This represents a SubscriptionContext object.  It functions the same way as
    * a normal Context (follows the same behavioral pattern), but is designed to
    * handle indications.  It also includes an AUX subscribe method so that
    * subscription requests happen within the protections of a strand invocation.
    */
   StrandFT _SubscribeContext_leftInteractionFT =
   {
       _Context_Post,
       _Context_PostControl,
       _Context_Ack,
       _SubscribeContext_Cancel,
       _Context_Close,
       _Context_Finish,
       NULL,
       _Context_Aux_TryPostLeft,
       _Context_Aux_TryPostLeft_Notify,
       _Context_Aux_InvokeSubscribe,
       NULL,
       NULL
 }; };
  
 void Context_Init(  #endif /* ifndef DISABLE_INDICATION */
   
   _Use_decl_annotations_
   MI_Result _Context_Init(
     Context* self,     Context* self,
     Provider*   provider)      Provider* provider,
       InteractionOpenParams* interactionParams,
       ContextInitOptions options,
       Context_Type ctxType )
 { {
       StrandFT *ft = NULL;
   
       if( NULL == self )
           return MI_RESULT_FAILED;
   
     memset(self, 0, sizeof(Context));     memset(self, 0, sizeof(Context));
   
       trace_ContextNew( self, interactionParams ? interactionParams->interaction : NULL, &self->strand.info.interaction );
   
       Lock_Init(&self->lock);
   
       self->ctxType = ctxType;
   
       if( NULL != interactionParams && NULL != interactionParams->msg )
       {
           DEBUG_ASSERT( Message_IsRequest( interactionParams->msg ) );
           /* release inside _Context_Destroy */
           Message_AddRef( interactionParams->msg );
           self->request = (RequestMsg*)interactionParams->msg;
       }
   
   #ifndef DISABLE_INDICATION
       /*
        * Conditionally set function table based on desired context type.
        */
       if (CTX_TYPE_IND_AGGREGATION == ctxType ||
           CTX_TYPE_IND_SUBSCRIPTION == ctxType)
       {
           self->base.ft = &__mi_indication_contextFT;
           ft = &_SubscribeContext_leftInteractionFT;
       }
       else if (CTX_TYPE_IND_LIFECYCLE == ctxType)
       {
           self->base.ft = &__mi_lifecycleIndication_contextFT;
           ft = &_SubscribeContext_leftInteractionFT;
       }
       else if (CTX_TYPE_IND_SUB_UNSUB == ctxType)
       {
           DEBUG_ASSERT( provider == NULL );
           DEBUG_ASSERT( interactionParams == NULL );
           DEBUG_ASSERT( ContextInit_NoInteraction == options );
           self->base.ft = &__mi_indication_subunsub_contextFT;
       }
       else
   #endif /* ifndef DISABLE_INDICATION */
       {
     self->base.ft = &__mi_contextFT;     self->base.ft = &__mi_contextFT;
           ft = &_Context_leftInteractionFT;
       }
   
     self->magic = _MAGIC;     self->magic = _MAGIC;
     self->provider = provider;     self->provider = provider;
   
       if( ContextInit_DelayOpen == options )
       {
           DEBUG_ASSERT( NULL != interactionParams );
           Strand_Init( STRAND_DEBUG( Context ) &self->strand, ft, STRAND_FLAG_ENTERSTRAND|STRAND_FLAG_DELAYACCEPTOPEN, interactionParams );
       }
       else if ( ContextInit_NoInteraction != options )
       {
           Strand_Init( STRAND_DEBUG( Context ) &self->strand, ft, STRAND_FLAG_ENTERSTRAND, interactionParams );
           if( NULL != interactionParams )
           {
               DEBUG_ASSERT( NULL != interactionParams->msg );
               Strand_Ack( &self->strand );
           }
           if( ContextInit_DontLeaveStrand  != options  )
           {
               Strand_Leave( &self->strand );
           }
       }
   
     Provider_Addref(self->provider);     Provider_Addref(self->provider);
   
       return MI_RESULT_OK;
 } }
  
 void Context_Destroy(  void Context_CompleteOpen(
     Context* self)      _In_ Context* self,
       _In_ InteractionOpenParams* params,
            MI_Result result)
 { {
     Message* req = self ? self->request : 0;      DEBUG_ASSERT( NULL != params->msg );
   
     if (self)  
         Provider_Release(self->provider);  
  
     memset(self, -1, sizeof(Context));      if( MI_RESULT_OK == result )
       {
           Strand_AcceptOpen( &self->strand, params );
           Strand_Ack( &self->strand );
           Strand_Leave( &self->strand );
       }
       else
       {
           // Just destroy the context
           _Context_Destroy(self);
           Strand_FailOpenWithResult(params, result, PostResultMsg_NewAndSerialize);
       }
   }
  
     /* Context typ[ically allocated from message's batch  //
         so it may be freed right inside 'Release' call */  // Initialize subscribe/unsubscribe context
     if (req)  //
         Message_Release(req);  MI_Result Subunsub_Context_Init(
       _Out_ Context* self,
       _In_ MI_Result* result,
       _In_ RequestMsg* msg)
   {
       MI_Result r;
       DEBUG_ASSERT( msg && result );
       r = _Context_Init(self, NULL, NULL, ContextInit_NoInteraction, CTX_TYPE_IND_SUB_UNSUB);
       if ( r == MI_RESULT_OK )
       {
           Message_AddRef( &msg->base );
           self->request = msg;
           self->result = result;
       }
       return r;
 } }


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

ViewCVS 0.9.2