1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include "context.h"
|
26 krisbash 1.5 #include "AggregationContext.h"
27 #include "SubscriptionContext.h"
28 #include "LifecycleContext.h"
29 #include "SubMgr.h"
|
30 mike 1.3 #include <wsman/wsbuf.h>
|
31 mike 1.1 #include <wql/wql.h>
|
32 krisbash 1.5 #include <pal/format.h>
33 #include <pal/thread.h>
34 #include <pal/sleep.h>
35 #include "nioproc.h"
36 #include <omi_error/omierror.h>
37
38 STRAND_DEBUGNAME3( Context, TryPostLeft, TryPostLeftNotify, InvokeSubscribe );
|
39 mike 1.1
40 static const MI_Uint32 _MAGIC = 0x35eb3d3b;
41
|
42 krisbash 1.5 static MI_Result MI_CALL _PostError(
43 _In_ MI_Context* self,
44 MI_Uint32 result,
45 _In_z_ const ZChar* type,
46 _In_z_ const ZChar* message);
47
48 void _Context_Destroy(
49 _Inout_ Context* self)
50 {
51 RequestMsg* request = self ? self->request : 0;
52 Message* loadRequest = self ? self->loadRequest : 0;
53
54 trace_ContextDestroy( self, &self->strand, &self->strand.info.interaction );
55
56 DEBUG_ASSERT( self );
57
58 if (self->provider)
59 {
60 Provider_Release(self->provider);
61 }
62
63 krisbash 1.5 memset(self, 0xFF, sizeof(Context));
64
65 /* Context typically allocated from message's batch
66 * so it may be freed right inside 'Release' call
67 */
68 if (request)
69 Message_Release(&request->base);
70
71 if (loadRequest)
72 Message_Release(loadRequest);
73 }
74
75 /*
76 * Post a message to the component to the left
77 */
78 _Use_decl_annotations_
79 void Context_PostMessageLeft(
80 Context* self,
81 Message* msg)
82 {
83 ptrdiff_t tryingToPostLeft;
84 krisbash 1.5 // Uncomment when no longer using Selector
85 //#if !defined(CONFIG_OS_WINDOWS)
86 ThreadID threadId = Thread_ID();
87 Selector* selector = self->provider->lib->provmgr->selector;
88 //#endif
89
90 // It is not clear if a Provider can Post concurrently in different threads (UT does)
91 // so protect against it
92 Lock_Acquire(&self->lock);
93
94 DEBUG_ASSERT( NULL != self->strand.info.interaction.other );
95 DEBUG_ASSERT( NULL == self->msgPostingLeft );
96 DEBUG_ASSERT( 0 == self->tryingToPostLeft );
97
98 // we dont need to add a reference to the message as
99 // we are not going to leave this function on this thread until is sent
100 // (event if it is actually sent in another thread)
101 self->msgPostingLeft = msg;
102
103 // Uncomment when no longer using Selector
104 //#if !defined(CONFIG_OS_WINDOWS)
105 krisbash 1.5 if( Selector_IsSelectorThread( selector, &threadId ) )
106 {
107 Context_PostMessageLeft_IoThread( self );
108 self->postingOnIoThread = MI_TRUE;
109 }
110 //#endif
111 Atomic_Swap(&self->tryingToPostLeft,(ptrdiff_t)(CONTEXT_POSTLEFT_POSTING|CONTEXT_POSTLEFT_SCHEDULED));
112
113 Strand_ScheduleAux( &self->strand, CONTEXT_STRANDAUX_TRYPOSTLEFT );
114
115 while( (tryingToPostLeft = ReadWithFence( &self->tryingToPostLeft )) != 0 )
116 {
117 // Uncomment when no longer using Selector
118 //#if defined(CONFIG_OS_WINDOWS)
119 // CondLock_Wait(
120 // (ptrdiff_t)self, &self->tryingToPostLeft, tryingToPostLeft, CONDLOCK_DEFAULT_SPINCOUNT);
121 //#else
122 if( self->postingOnIoThread )
123 {
124 Selector_Run( selector, TIME_NEVER, MI_TRUE );
125 }
126 krisbash 1.5 else
127 {
128 CondLock_Wait(
129 (ptrdiff_t)self, &self->tryingToPostLeft, tryingToPostLeft, CONDLOCK_DEFAULT_SPINCOUNT);
130 }
131 //#endif
132 }
133
134 // Sent
135 DEBUG_ASSERT( 0 == self->tryingToPostLeft );
136
137 #ifndef DISABLE_INDICATION
138 if (CTX_TYPE_IND_SUBSCRIPTION == self->ctxType ||
139 CTX_TYPE_IND_LIFECYCLE == self->ctxType)
140 {
141 SubscriptionContext* subCtx = (SubscriptionContext*)self;
142 if (ReadWithFence(&subCtx->subscription->finalmsgbit) == 1)
143 {
144 /*
145 * Release the refcount added by SubscrContext_Init
146 */
147 krisbash 1.5 SubMgrSubscription_Release(subCtx->subscription);
148 }
149 }
150 #endif
151
152 Lock_Release(&self->lock);
153 }
154
155 void Context_PostSchema(
156 _In_ Context* self,
157 _In_ Message* msg)
158 {
159 Context_PostMessageLeft(self, msg);
160 }
161
162 _Use_decl_annotations_
163 void Context_Close( Context* self )
164 {
165 // Note that some contexts are used internally (for example to load providers)
166 // and therefore dont have an interaction
167 if( NULL != self->strand.info.interaction.other )
168 krisbash 1.5 {
169 Strand_ScheduleClose(&self->strand);
170 }
171 else
172 {
173 _Context_Destroy(self);
174 }
175 }
176
|
177 mike 1.1 static MI_Result _ProcessResult(
178 MI_Context* self_,
179 MI_Result result,
|
180 krisbash 1.5 const ZChar* errorMessage,
181 const MI_Instance* cimError)
|
182 mike 1.1 {
183 Context* self = (Context*)self_;
184
185 if (!self || self->magic != _MAGIC)
186 return MI_RESULT_INVALID_PARAMETER;
187
|
188 krisbash 1.5 trace_Provider_PostResult(result);
189
190 if (result == MI_RESULT_NOT_SUPPORTED &&
191 self->request && self->request->base.tag == ModifyInstanceReqTag &&
192 self->postedModifyInstance == MI_FALSE &&
193 self->postedModifyGetInstance == MI_TRUE &&
194 self->postedModifyEnumInstance != MI_TRUE)
195 {
196 /* Provider does not support GetInstance so we need to do an Enumerate instead */
197 if (self->provider->classDecl->providerFT->EnumerateInstances)
198 {
199 ModifyInstanceReq* request = (ModifyInstanceReq*)self->request;
200
201 /* convert this into a filtering enum because GetInstance is not implemented. */
202 self->inst = self->keyInstance;
203 self->instanceName = NULL;
204 self->postedModifyEnumInstance = MI_TRUE;
205 self->provider->classDecl->providerFT->EnumerateInstances(self->provider->self, self_, request->nameSpace, self->keyInstance->classDecl->name, NULL, MI_FALSE, NULL);
206 return MI_RESULT_OK;
207 }
208 else
209 krisbash 1.5 {
210 /* We cannot handle the contract, we we need to fail. Fall through to send an error */
211 }
212 }
213 else if (result == MI_RESULT_OK && self->request && self->request->base.tag == ModifyInstanceReqTag && self->postedModifyInstance == MI_FALSE)
214 {
215 ModifyInstanceReq* request = (ModifyInstanceReq*) self->request;
216 /* Need to re-send the request now as a GetInstance so we can get the final result. */
217 if (self->provider->classDecl->providerFT->GetInstance)
218 {
219 self->postedModifyGetInstance = MI_TRUE;
220 self->provider->classDecl->providerFT->GetInstance(self->provider->self, self_, request->nameSpace, self->keyInstance->classDecl->name, self->keyInstance, NULL);
221 return MI_RESULT_OK;
222 }
223 else if (self->provider->classDecl->providerFT->EnumerateInstances)
224 {
225 /* convert this into a filtering enum because GetInstance is not implemented. */
226 self->inst = self->keyInstance;
227 self->instanceName = NULL;
228 self->postedModifyEnumInstance = MI_TRUE;
229 self->postedModifyGetInstance = MI_TRUE; /* For state management need to think we tried a GetInst */
230 krisbash 1.5 self->provider->classDecl->providerFT->EnumerateInstances(self->provider->self, self_, request->nameSpace, self->keyInstance->classDecl->name, NULL, MI_FALSE, NULL);
231 return MI_RESULT_OK;
232 }
233 else
234 {
235 /* Cannot complete the operation because neither Get or Enum is supported. */
236 result = MI_RESULT_NOT_SUPPORTED;
237 }
238 }
|
239 mike 1.1
240 /* If no instances matched during GetInstance over EnumerateInstance */
241 if (self->instanceName && !self->matchedInstanceName)
242 {
243 if (result == MI_RESULT_OK)
244 result = MI_RESULT_NOT_FOUND;
245 }
246
247 if (self->request && !self->cancelled)
248 {
|
249 krisbash 1.5 PostResultMsg* resp = PostResultMsg_New( self->request->base.operationId );
|
250 mike 1.1
251 if (!resp)
252 return MI_RESULT_FAILED;
253
|
254 krisbash 1.5 if (self->request->base.flags & WSMANFlag)
255 {
256 /* Need to clone this in case we need to thread switch. Not the most efficient,
257 * but this is consumed in the error packet creation code and seems to be the
258 * best way to achieve this for now.
259 */
260 resp->cimError = cimError;
261
262 if (cimError)
263 {
264 WSBuf_InstanceToBuf(
265 self->request->userAgent,
266 cimError,
267 NULL, /* filterProperty */
268 NULL, /* filterPropertyData */
269 cimError->classDecl,
270 resp->base.batch,
271 WSMAN_ObjectFlag | WSMAN_IsCimError,
272 &resp->packedInstancePtr,
273 &resp->packedInstanceSize);
274
275 krisbash 1.5 resp->cimErrorClassName = Batch_Tcsdup(resp->base.batch, cimError->classDecl->name);
276 }
277 else
278 {
279 resp->packedInstancePtr = NULL;
280 resp->packedInstanceSize = 0;
281 resp->cimErrorClassName = NULL;
282 }
283
284 /* Need to clone this in case we need to thread switch */
285 if (errorMessage)
286 {
287 resp->errorMessage = Batch_Tcsdup(resp->base.batch, errorMessage);
288 }
289 else
290 {
291 resp->errorMessage = NULL;
292 }
293
294 resp->result = result;
295
296 krisbash 1.5 resp->base.flags |= self->request->base.flags;
297 }
298 else /* Binary protocol */
299 {
300 resp->cimError = cimError;
301 if (cimError)
302 {
303 InstanceToBatch(cimError, NULL, NULL, resp->base.batch, &resp->packedInstancePtr, &resp->packedInstanceSize);
304 /* If the serialization fails we should just send the original error back. Seems bad to overrite it with this error */
305
306 resp->cimErrorClassName = Batch_Tcsdup(resp->base.batch, cimError->classDecl->name);
307 }
308 else
309 {
310 resp->packedInstancePtr = NULL;
311 resp->packedInstanceSize = 0;
312 resp->cimErrorClassName = NULL;
313 }
314 if (errorMessage)
315 {
316 resp->errorMessage = Batch_Tcsdup(resp->base.batch, errorMessage);
317 krisbash 1.5 }
318 else
319 {
320 resp->errorMessage = NULL;
321 }
322 resp->result = result;
323 resp->base.flags |= BinaryProtocolFlag;
324 }
325
326 Context_PostMessageLeft( self, &resp->base);
|
327 mike 1.1 PostResultMsg_Release(resp);
328 }
329
330 if (self->result)
331 *self->result = result;
332
|
333 krisbash 1.5 /* close/destroy context */
334 Context_Close(self);
|
335 mike 1.1
336 return MI_RESULT_OK;
337 }
338
|
339 krisbash 1.5 static MI_Boolean _FilterProperty(const ZChar* name, void *data)
|
340 mike 1.1 {
341 WQL* wql = (WQL*)data;
342
343 if (WQL_ContainsProperty(wql, name))
344 return MI_FALSE;
345 else
346 return MI_TRUE;
347 }
348
|
349 krisbash 1.5 /*
350 * This is an internal helper function that should be called from wrappers
351 * that manage the lifecycle of the instance getting posted.
352 */
353 static MI_Result _PostInstanceToCallback_Common(
354 _In_ Context* self,
355 _In_ const MI_Instance* instance,
356 _In_ PostInstanceMsg* resp)
|
357 mike 1.1 {
|
358 krisbash 1.5 MI_Result r = MI_RESULT_OK;
|
359 mike 1.1
|
360 krisbash 1.5 if (self->request->base.flags & WSMANFlag)
|
361 mike 1.1 {
362 const MI_ClassDecl* castToClassDecl = 0;
363
364 /* Enumerate response with 'base-properties-only' option
365 may require instance conversion */
|
366 krisbash 1.5 if (EnumerateInstancesReqTag == self->request->base.tag)
|
367 mike 1.1 {
368 EnumerateInstancesReq* req = (EnumerateInstancesReq*)self->request;
369
370 if (req->requestClassName)
371 {
372 castToClassDecl = instance->classDecl;
373
374 while (castToClassDecl &&
|
375 krisbash 1.5 Tcscasecmp(req->requestClassName, castToClassDecl->name) != 0)
|
376 mike 1.1 {
377 castToClassDecl = castToClassDecl->superClassDecl;
378 }
379 }
380 }
381
382 {
383 EnumerateInstancesReq* req = NULL;
384
|
385 krisbash 1.5 if (EnumerateInstancesReqTag == self->request->base.tag)
|
386 mike 1.1 req = (EnumerateInstancesReq*)self->request;
387
388 if (req && req->wql)
389 {
|
390 krisbash 1.5 r = WSBuf_InstanceToBuf(
391 self->request->userAgent,
|
392 mike 1.1 instance,
393 _FilterProperty,
394 req->wql,
395 castToClassDecl,
396 resp->base.batch,
|
397 krisbash 1.5 self->request->base.flags,
|
398 mike 1.1 &resp->packedInstancePtr,
399 &resp->packedInstanceSize);
400 }
401 else
402 {
|
403 krisbash 1.5 r = WSBuf_InstanceToBuf(
404 self->request->userAgent,
|
405 mike 1.1 instance,
406 NULL, /* filterProperty */
407 NULL, /* filterPropertyData */
408 castToClassDecl,
409 resp->base.batch,
|
410 krisbash 1.5 self->request->base.flags,
|
411 mike 1.1 &resp->packedInstancePtr,
412 &resp->packedInstanceSize);
413 }
414 }
415
|
416 krisbash 1.5 resp->base.flags |= self->request->base.flags;
|
417 mike 1.1 }
418 else
419 {
420 EnumerateInstancesReq* req = NULL;
421
|
422 krisbash 1.5 if (EnumerateInstancesReqTag == self->request->base.tag)
|
423 mike 1.1 req = (EnumerateInstancesReq*)self->request;
424
425 if (req && req->wql)
426 {
|
427 krisbash 1.5 r = InstanceToBatch(
428 instance,
429 _FilterProperty,
430 req->wql,
431 resp->base.batch,
432 &resp->packedInstancePtr,
433 &resp->packedInstanceSize);
|
434 mike 1.1 }
435 else
436 {
|
437 krisbash 1.5 r = InstanceToBatch(
438 instance,
439 NULL,
440 NULL,
441 resp->base.batch,
442 &resp->packedInstancePtr,
443 &resp->packedInstanceSize);
|
444 mike 1.1 }
445
446 resp->base.flags |= BinaryProtocolFlag;
447 }
448
449
|
450 krisbash 1.5 if (r != MI_RESULT_OK)
451 trace_PackInstanceFailed(r);
452 else
453 Context_PostMessageLeft( self, &resp->base);
454
455 return r;
456 }
457
458 static MI_Result _PostInstanceToCallback(
459 _In_ Context* self,
460 _In_ const MI_Instance* instance)
461 {
462 MI_Result result = MI_RESULT_OK;
463 PostInstanceMsg* resp = PostInstanceMsg_New(self->request->base.operationId);
464
465 if (!resp)
466 return MI_RESULT_FAILED;
467
468 result = _PostInstanceToCallback_Common( self, instance, resp );
|
469 mike 1.1
470 PostInstanceMsg_Release(resp);
471
|
472 krisbash 1.5 return result;
|
473 mike 1.1 }
474
475 /* successfully received instance from 'gi' - call invoke with this instance now */
476 static void _CallInvoke(
477 Context* self,
478 const MI_Instance* instance)
479 {
|
480 krisbash 1.5 Context* ctx = (Context*)Batch_GetClear(self->request->base.batch, sizeof(Context));;
|
481 mike 1.1
|
482 krisbash 1.5 // This is an internal context so it doesn't need an interaction
483 Context_Init(ctx, self->provider, NULL);
|
484 mike 1.1
485 ctx->request = self->request;
486 /* message will be freed in context release*/
|
487 krisbash 1.5 Message_AddRef(&ctx->request->base);
|
488 mike 1.1
489 /* disregard all other messages for this context */
490 self->cancelled = MI_TRUE;
491 /* ATTN! clone instance, since invoke can overlive instance (if it's async)!!! */
|
492 krisbash 1.5 (*self->md->function)(self->prov_self, &ctx->base,
|
493 mike 1.1 __nameSpace, __className, __methodName, instance, self->instParams);
494 }
495
496 static MI_Result MI_CALL _PostResult(
497 MI_Context* self_,
498 MI_Result result)
499 {
|
500 krisbash 1.5 Context* self = (Context*)self_;
|
501 mike 1.1
|
502 krisbash 1.5 /* Suppress MI_RESULT_NOT_SUPPORTED errors for operations which involve
503 * multiple provdiders. For example, suppose the operation is handled by
504 * providers A, B, and C. If providers A and B post MI_RESULT_OK but
505 * provider C posts MI_RESULT_NOT_SUPPORTED, we must translate this error
506 * to a MI_RESULT_OK to prevent the client from receiving it. The client
507 * is only concerned with receiving valid instances, not with whether a
508 * particular provider implements the operation.
509 */
510 if (result == MI_RESULT_NOT_SUPPORTED)
511 {
512 switch (self->request->base.tag)
513 {
514 case AssociatorsOfReqTag:
515 case ReferencesOfReqTag:
516 result = MI_RESULT_OK;
517 break;
518 default:
519 break;
520 }
521 }
|
522 mike 1.1
|
523 krisbash 1.5 if (result == MI_RESULT_OK)
524 return _ProcessResult(self_, result, NULL, NULL);
525 else
526 return _PostError(self_, result, MI_RESULT_TYPE_MI, NULL);
|
527 mike 1.1 }
528
529 static MI_Result MI_CALL _PostInstance(
530 MI_Context* self_,
531 const MI_Instance* instance)
532 {
533 Context* self = (Context*)self_;
534
535 if (!self || self->magic != _MAGIC || !instance)
536 return MI_RESULT_INVALID_PARAMETER;
537
538 if (self->request && !self->cancelled)
539 {
540 if (self->instanceName == NULL)
541 {
|
542 krisbash 1.5 if (!Instance_ValidateNonNullKeys(instance))
543 {
544 /* Fail the Post if it has NULL key properties. It is an
545 * invalid object. */
546 return MI_RESULT_FAILED;
547 }
548
549 if (CTX_TYPE_INVOKE_WITH_INSTANCE == self->ctxType)
|
550 mike 1.1 {
551 _CallInvoke(self, instance);
552 return MI_RESULT_OK;
553 }
|
554 krisbash 1.5 else if (EnumerateInstancesReqTag == self->request->base.tag)
|
555 mike 1.1 {
556 EnumerateInstancesReq* req =
557 (EnumerateInstancesReq*)self->request;
558
559 if (req->wql)
560 {
561 int r;
562
563 r = WQL_Eval(req->wql, WQL_LookupInstanceProperty,
564 (void*)instance);
565
566 if (r == 0)
567 {
568 /* Instance matched the query */
569 return _PostInstanceToCallback(self, instance);
570 }
571 else
572 {
573 /* Mismatch or failure */
574 return MI_RESULT_OK;
575 }
576 mike 1.1 }
577 }
|
578 krisbash 1.5 else if (ModifyInstanceReqTag == self->request->base.tag)
579 {
580 self->postedModifyInstance = MI_TRUE;
581 return _PostInstanceToCallback(self, instance);
582 }
|
583 mike 1.1
584 return _PostInstanceToCallback(self, instance);
585 }
586 else if (Instance_MatchKeys(instance, self->instanceName))
587 {
588 /* Handle GetInstance through EnumerateInstances */
589 if (!self->matchedInstanceName)
590 {
591 self->matchedInstanceName = MI_TRUE;
592 return _PostInstanceToCallback(self, instance);
593 }
594 }
595 }
596
597 return MI_RESULT_OK;
598 }
599
|
600 krisbash 1.5 static Batch* _GetBatch(Context* self)
601 {
602 if (self->provider && self->provider->lib && self->provider->lib->instanceLifetimeContext)
603 {
604 if (self->request)
605 return self->request->base.batch;
606
607 if (self->loadRequest)
608 return self->loadRequest->batch;
609 }
610
611 return NULL;
612 }
613
|
614 mike 1.1 static MI_Result MI_CALL _ConstructInstance(
615 MI_Context* self_,
616 const MI_ClassDecl* classDecl,
617 MI_Instance* instance)
618 {
|
619 krisbash 1.5 Batch *batch = NULL;
|
620 mike 1.1 Context* self = (Context*)self_;
621
622 if (!self || self->magic != _MAGIC || !instance || !classDecl)
623 return MI_RESULT_INVALID_PARAMETER;
624
|
625 krisbash 1.5 batch = _GetBatch(self);
626
627 return Instance_Construct(instance, classDecl, batch);
|
628 mike 1.1 }
629
630 static MI_Result MI_CALL _ConstructParameters(
631 MI_Context* self_,
632 const MI_MethodDecl* methodDecl,
633 MI_Instance* instance)
634 {
|
635 krisbash 1.5 Batch *batch = NULL;
|
636 mike 1.1 Context* self = (Context*)self_;
637
638 if (!self || self->magic != _MAGIC || !instance || !methodDecl)
639 return MI_RESULT_INVALID_PARAMETER;
640
|
641 krisbash 1.5 batch = _GetBatch(self);
642
643 return Parameters_Init(instance, methodDecl, batch);
|
644 mike 1.1 }
645
646 static MI_Result MI_CALL _NewInstance(
647 MI_Context* self_,
648 const MI_ClassDecl* classDecl,
649 MI_Instance** instance)
650 {
|
651 krisbash 1.5 Batch *batch = NULL;
|
652 mike 1.1 Context* self = (Context*)self_;
653
654 if (!self || self->magic != _MAGIC || !classDecl || !instance)
655 return MI_RESULT_INVALID_PARAMETER;
656
|
657 krisbash 1.5 batch = _GetBatch(self);
658
659 return Instance_New(instance, classDecl, batch);
|
660 mike 1.1 }
661
662 static MI_Result MI_CALL _NewDynamicInstance(
663 MI_Context* self_,
|
664 krisbash 1.5 const ZChar* className,
|
665 mike 1.1 MI_Uint32 flags,
666 MI_Instance** instance)
667 {
|
668 krisbash 1.5 Batch *batch = NULL;
|
669 mike 1.1 Context* self = (Context*)self_;
670
671 if (!self || self->magic != _MAGIC || !className || !instance)
672 return MI_RESULT_INVALID_PARAMETER;
673
|
674 krisbash 1.5 batch = _GetBatch(self);
675
|
676 mike 1.1 return Instance_NewDynamic(instance, className, flags,
|
677 krisbash 1.5 batch);
|
678 mike 1.1 }
679
680 static MI_Result MI_CALL _NewParameters(
681 MI_Context* self_,
682 const MI_MethodDecl* methodDecl,
683 MI_Instance** instance)
684 {
|
685 krisbash 1.5 Batch *batch = NULL;
|
686 mike 1.1 Context* self = (Context*)self_;
687
688 if (!self || self->magic != _MAGIC || !methodDecl || !instance)
689 return MI_RESULT_INVALID_PARAMETER;
690
|
691 krisbash 1.5 batch = _GetBatch(self);
692
693 return Parameters_New(instance, methodDecl, batch);
|
694 mike 1.1 }
695
696 static MI_Result MI_CALL _Canceled(
697 const MI_Context* self_,
698 MI_Boolean* flag)
699 {
700 Context* self = (Context*)self_;
701
702 if (!self || self->magic != _MAGIC || !flag)
703 return MI_RESULT_INVALID_PARAMETER;
704
705 *flag = self->cancelled;
706 return MI_RESULT_OK;
707 }
708
|
709 krisbash 1.5 #ifndef DISABLE_INDICATION
710
711 static MI_Result _PostIndicationToCallback(
712 _In_ Context* self,
713 _In_ const MI_Instance* instance,
714 _In_opt_z_ const ZChar* bookmark )
|
715 mike 1.1 {
|
716 krisbash 1.5 MI_Result result = MI_RESULT_OK;
717 PostIndicationMsg* resp = PostIndicationMsg_New(self->request->base.operationId);
718
719 if (!resp)
720 return MI_RESULT_FAILED;
721
722 /* Copy bookmark into the message's Batch to control its lifetime. */
723 if (bookmark)
724 {
725 const ZChar* tmp = Batch_Tcsdup(resp->base.base.batch, bookmark);
726
727 if (!tmp)
728 {
729 PostIndicationMsg_Release(resp);
730 return MI_RESULT_FAILED;
731 }
732
733 resp->bookmark = tmp;
734 }
735
736 result = _PostInstanceToCallback_Common( self, instance, (PostInstanceMsg*)resp );
|
737 mike 1.1
|
738 krisbash 1.5 PostIndicationMsg_Release(resp);
|
739 mike 1.1
|
740 krisbash 1.5 return result;
|
741 mike 1.1 }
742
|
743 krisbash 1.5 /*
744 * PostIndication handler for SubscriptionContext. It evaluates an indication
745 * using a pre-specified indication filter. It is placed here so that
746 * _PostInstanceToCallback remains private to Context.c.
747 */
748 MI_Result _SubscrContext_PostIndication(
749 _In_ SubscriptionContext* context,
750 _In_ const MI_Instance* indication,
751 _In_opt_z_ const ZChar* bookmark,
752 _In_ MI_Boolean subscriptionRefcounted)
753 {
754 MI_Result result = MI_RESULT_OK;
755 SubMgrSubscription* subscription = NULL;
756 MI_Boolean isMatch = MI_FALSE;
757 SubscriptionManager* subMgr;
|
758 mike 1.1
|
759 krisbash 1.5 if (!context || !indication)
760 {
761 trace_PostIndicationWithNullInput();
|
762 mike 1.1 return MI_RESULT_INVALID_PARAMETER;
|
763 krisbash 1.5 }
|
764 mike 1.1
|
765 krisbash 1.5 subMgr = context->baseCtx.provider->subMgr;
766 DEBUG_ASSERT ( subMgr );
767
768 if ( MI_FALSE == SubMgr_CanPostIndication( subMgr ) )
769 return MI_RESULT_NOT_SUPPORTED;
770
771 /* Ref counted, release later */
772 if ( MI_FALSE == subscriptionRefcounted )
773 subscription = SubMgr_GetSubscriptionByContext(subMgr, context);
774 else
775 subscription = context->subscription;
776
777 if ( !subscription )
778 {
779 return MI_RESULT_FAILED;
780 }
781
782 if (SubscriptionState_Unsubscribing == subscription->state ||
783 SubscriptionState_Unsubscribed == subscription->state)
784 {
785 trace_PostIndicationWithUnsubscribedContext();
786 krisbash 1.5 if ( MI_FALSE == subscriptionRefcounted)
787 SubMgrSubscription_Release(subscription);
788 return MI_RESULT_OK;
789 }
790
791 if (!Instance_ValidateNonNullKeys(indication))
792 {
793 /* Fail the Post if it has NULL key properties. It is an
794 * invalid object. */
795 if ( MI_FALSE == subscriptionRefcounted)
796 SubMgrSubscription_Release(subscription);
797 return MI_RESULT_FAILED;
798 }
799
800 result = InstanceFilter_Filter( subscription->filter, indication, &isMatch );
801
802 /* Check the evaluation status. Only forward indications that satisfied
803 * a known filter. */
804 if (MI_RESULT_OK == result && isMatch)
805 {
806 SubMgrSubscription_AcuquirePostLock(subscription);
807 krisbash 1.5 if ( MI_FALSE == SubMgrSubscription_CancelStarted(subscription) )
808 result = _PostIndicationToCallback((Context*)context, indication, bookmark);
809 else
810 result = MI_RESULT_FAILED;
811 SubMgrSubscription_ReleasePostLock(subscription);
812 }
813
814 if ( MI_FALSE == subscriptionRefcounted)
815 SubMgrSubscription_Release(subscription);
816
817 return result;
|
818 mike 1.1 }
819
|
820 krisbash 1.5 MI_Result _SubscrContext_ProcessResult(
821 _In_ Context* context,
822 _In_ MI_Result result,
823 _In_opt_z_ const ZChar* errorMessage,
824 _In_opt_ const MI_Instance* cimError )
|
825 mike 1.1 {
|
826 krisbash 1.5 /* subscription object is guaranteed live here since the provider owning one refcount */
827 /* after this call, the refcount will be released */
828 SubscriptionContext* subCtx = (SubscriptionContext*)context;
829 SubMgrSubscription* subscription = SubscrContext_GetSubscription( subCtx );
830 MI_Result r;
831
832 DEBUG_ASSERT(subscription); /* This identifies any cases that may violate the refcount guarantee */
833
834 SubMgrSubscription_Addref(subscription);
835
836 Provider_RemoveSubscription(context->provider, subscription->subscriptionID);
837
838 #if !defined(_MSC_VER)
839 {
840 ThreadID tempId = Thread_ID();
841 if (Thread_Equal(&tempId, &context->provider->lib->provmgr->ioThreadId))
842 {
843 /* For non-windows platform, there is only one IO thread in current process, */
844 /* which has dead lock issue if have multi-thread (include IO thread) posting messages */
845 /* simultaneously. To resolve the issue, unsubscribe has to be invoked from a separate thread */
846 /* Upon implementing multi-thread IO for OMI server, this workaround should be removed */
847 krisbash 1.5 Schedule_SendFinalResult( subCtx, result );
848 return MI_RESULT_OK;
849 }
850 }
851 #endif
852
853 trace_SubscrContext_ProcessResult(UintThreadID(), subCtx, subscription);
854
855 /* Handle failure responses */
856 if (SubscriptionState_Subscribed == subscription->state ||
857 SubscriptionState_Unsubscribing == subscription->state)
858 {
859 trace_SubscrContext_ProviderPostingFailure(result,
860 ((subscription->state == SubscriptionState_Subscribed) ? PAL_T("subscribed") : PAL_T("unsubscribing")),
861 subscription);
862 }
863 else
864 {
865 trace_SubscrContext_ProcessResult_InvalidState(UintThreadID(), subCtx, subscription, subscription->state);
866 }
867
868 krisbash 1.5 SubMgrSubscription_AcuquirePostLock(subscription);
869 r = SubscrContext_SendFinalResultMsg( subCtx, result, errorMessage, cimError );
870 SubMgrSubscription_ReleasePostLock(subscription);
871
872 SubMgrSubscription_Release(subscription);
873 return r;
874 }
875
876 /*
877 * PostIndication handler for AggregationContext. It forwards an indication
878 * to all known subscriptions for filter evaluation. It is placed here so that
879 * _PostInstanceToCallback remains private to Context.c.
880 */
881 MI_Result _AggrContext_PostIndication(
882 _In_ AggregationContext* context,
883 _In_ const MI_Instance* indication,
884 _In_opt_z_ const ZChar* bookmark )
885 {
886 SubscriptionManager* subMgr = NULL;
887 MI_Boolean atLeastOneDelivered = MI_FALSE;
888 SubMgrSubscriptionPtr* sublist;
889 krisbash 1.5 MI_Result r;
890 size_t count = 0;
891 size_t i;
|
892 mike 1.1
|
893 krisbash 1.5 if (!context || !indication)
894 {
895 trace_PostIndicationWithNullInput();
|
896 mike 1.1 return MI_RESULT_INVALID_PARAMETER;
|
897 krisbash 1.5 }
898
899 subMgr = AggrContext_GetManager( context );
900
901 /* Both of these states result in the same thing: the AggregationContext
902 * must be cleaned up. */
903 if ( (MI_FALSE == SubMgr_IsEnabled ( subMgr )) ||
904 (MI_TRUE == SubMgr_IsSubListEmpty ( subMgr )))
905 {
906 trace_PostIndicationOnDisabledAggContext();
907 return MI_RESULT_FAILED;
908 }
909
910 /* sublist holds one reference count to each subscription */
911 r = SubMgr_GetSubscriptionList(subMgr, &sublist, &count);
912 if ( r != MI_RESULT_OK )
913 return r;
914
915 for ( i = 0; i < count; i++ )
916 {
917 /*
918 krisbash 1.5 * This is a best-effort action
919 * Intermediate failures will be ignored
920 */
921 r = _SubscrContext_PostIndication( sublist[i]->subscribeCtx, indication, bookmark, MI_TRUE );
922 if ( MI_RESULT_OK == r )
923 {
924 atLeastOneDelivered = MI_TRUE;
925 }
926 /* release the one reference count */
927 SubMgrSubscription_Release( sublist[i] );
928 }
|
929 mike 1.1
|
930 krisbash 1.5 return (atLeastOneDelivered ? MI_RESULT_OK : r);
|
931 mike 1.1 }
932
|
933 krisbash 1.5 /*
934 * Handles AggregationContext cleanup during error scenarios derived from
935 * PostResult, PostError, and PostCimError calls on the context.
936 */
937 MI_Result _AggrContext_Terminate(
938 Context* context,
939 MI_Result result,
940 const ZChar* errorMessage,
941 const MI_Instance* cimError )
|
942 mike 1.1 {
|
943 krisbash 1.5 return Provider_TerminateIndication(context->provider, result, errorMessage, cimError);
|
944 mike 1.1 }
945
|
946 krisbash 1.5 /*
947 * Delegates AggregationContext Post calls depending on the state of the
948 * context.
949 */
950 MI_Result _AggrContext_ProcessResult(
951 _In_ Context* context,
952 _In_ MI_Result result,
953 const ZChar* errorMessage,
954 const MI_Instance* cimError )
|
955 mike 1.1 {
|
956 krisbash 1.5 return _AggrContext_Terminate( context, result, errorMessage, cimError );
|
957 mike 1.1 }
958
|
959 krisbash 1.5 static MI_Result _Ind_Common_ProcessResult(
960 _In_ MI_Context* context,
961 _In_ MI_Result result,
962 const ZChar* errorMessage,
963 const MI_Instance* cimError )
964 {
965 Context* self = (Context*)context;
966 MI_Result toReturn = MI_RESULT_OK;
967
968 if (!self || self->magic != _MAGIC)
969 {
970 trace_PostCalledWithInvalidContext();
971 return MI_RESULT_INVALID_PARAMETER;
972 }
973
974 if (!self->cancelled)
975 {
976 /* Engages filter handlers to determine if the indication instance is
977 * appropriate for forwarding to clients. */
978 switch (self->ctxType)
979 {
980 krisbash 1.5 case CTX_TYPE_IND_AGGREGATION:
981 toReturn = _AggrContext_ProcessResult( self, result, errorMessage, cimError );
982 break;
983 case CTX_TYPE_IND_SUBSCRIPTION:
984 case CTX_TYPE_IND_LIFECYCLE: /* Fallthrough expected */
985 toReturn = _SubscrContext_ProcessResult( self, result, errorMessage, cimError );
986 break;
987 default:
988 trace_UnknownIndicationContextType((int)self->ctxType);
989 toReturn = MI_RESULT_NOT_FOUND;
990 break;
991 }
992 }
993 /* else: invalid indication post, so do nothing */
994
995 return toReturn;
996 }
997
998 /* TODO: attach bookmark to PostIndicationMsg */
999 static MI_Result MI_CALL _Ind_PostIndication(
1000 MI_Context* context,
1001 krisbash 1.5 const MI_Instance* indication,
1002 MI_Uint32 subscriptionIDCount,
1003 const ZChar* bookmark)
1004 {
1005 MI_Result result = MI_RESULT_OK;
1006 Context* self = (Context*)context;
1007 MI_UNUSED(subscriptionIDCount);
1008
1009 if (!self || self->magic != _MAGIC || !indication)
1010 {
1011 trace_PostCalledWithInvalidContext();
1012 return MI_RESULT_INVALID_PARAMETER;
1013 }
1014
1015 if (!self->cancelled)
1016 {
1017 /* Engages filter handlers to determine if the indication instance is
1018 * appropriate for forwarding to clients. */
1019 switch (self->ctxType)
1020 {
1021 case CTX_TYPE_IND_AGGREGATION:
1022 krisbash 1.5 result = _AggrContext_PostIndication( (AggregationContext*)self, indication, bookmark );
1023 break;
1024 case CTX_TYPE_IND_SUBSCRIPTION: /* Fallthrough expected */
1025 case CTX_TYPE_IND_LIFECYCLE:
1026 result = _SubscrContext_PostIndication( (SubscriptionContext*)self, indication, bookmark, MI_FALSE );
1027 break;
1028 default:
1029 trace_UnknownIndicationContextType((int)self->ctxType);
1030 result = MI_RESULT_NOT_FOUND;
1031 break;
1032 }
1033 }
1034 /* else: invalid indication post, so do nothing */
1035
1036 return result;
1037 }
1038
1039 /*
1040 *_PostInstance is not supported for indication contexts. Indications
1041 * must be posted using _PostIndication.
1042 */
1043 krisbash 1.5 static MI_Result MI_CALL _Ind_PostInstance(
1044 MI_Context* self_,
1045 const MI_Instance* instance)
1046 {
1047 Context* self = (Context*)self_;
1048
1049 if (!self || self->magic != _MAGIC || !instance)
1050 {
1051 return MI_RESULT_INVALID_PARAMETER;
1052 }
1053 return MI_RESULT_NOT_SUPPORTED;
1054 }
1055
1056 static MI_Result MI_CALL _Ind_PostResult(
1057 MI_Context* self_,
1058 MI_Result result)
1059 {
1060 return _Ind_Common_ProcessResult( self_, result, NULL, NULL );
1061 }
1062
1063 static MI_Result MI_CALL _Ind_PostError(
1064 krisbash 1.5 _In_ MI_Context* self,
1065 MI_Uint32 result,
1066 _In_z_ const ZChar* type,
1067 _In_z_ const ZChar* message)
1068 {
1069 if (NULL == type ||
1070 Tcscmp(type, MI_RESULT_TYPE_MI) != 0)
1071 {
1072 result = MI_RESULT_FAILED;
1073 }
1074 return _Ind_Common_ProcessResult(self, result, message, NULL);
1075 }
1076
1077 static MI_Result MI_CALL _Ind_PostCimError(
1078 _In_ MI_Context* self,
1079 _In_ const MI_Instance *error)
1080 {
1081 MI_Value value;
1082 MI_Type type;
1083 MI_Result result;
1084
1085 krisbash 1.5 result = MI_Instance_GetElement(error, MI_T("CIMStatusCode"), &value, &type, NULL, NULL);
1086 if ((MI_RESULT_OK != result) || (MI_UINT32 != type))
1087 {
1088 return _Ind_Common_ProcessResult(self, MI_RESULT_INVALID_CLASS_HIERARCHY, MI_T("Invalid CIM_Error object posted from provider"), NULL);
1089 }
1090 else
1091 {
1092 MI_Value messageValue;
1093 MI_Type messageType;
1094
1095 result = MI_Instance_GetElement(error, MI_T("Message"), &messageValue, &messageType, NULL, NULL);
1096 if ((MI_RESULT_OK != result) || (MI_STRING != messageType))
1097 {
1098 messageValue.string = NULL;
1099 }
1100 return _Ind_Common_ProcessResult(self, value.uint32, messageValue.string, error);
1101 }
1102 }
1103
1104 #endif /* ifndef DISABLE_INDICATION */
1105
1106 krisbash 1.5 static MI_Result MI_CALL _PostIndication(
1107 MI_Context* context,
1108 const MI_Instance* indication,
1109 MI_Uint32 subscriptionIDCount,
1110 const ZChar* bookmark)
1111 {
1112 MI_UNUSED(context);
1113 MI_UNUSED(indication);
1114 MI_UNUSED(subscriptionIDCount);
1115 MI_UNUSED(bookmark);
1116
1117 return MI_RESULT_NOT_SUPPORTED;
1118 }
1119
1120 static MI_Result MI_CALL _GetLocale(
1121 const MI_Context* context,
1122 MI_LocaleType localeType,
1123 _Pre_writable_size_(MI_MAX_LOCALE_SIZE) ZChar locale[MI_MAX_LOCALE_SIZE])
1124 {
1125 return MI_RESULT_NOT_SUPPORTED;
1126 }
1127 krisbash 1.5
1128 static MI_Result MI_CALL _RegisterCancel(
1129 MI_Context* context,
1130 MI_CancelCallback callback,
1131 void* callbackData)
1132 {
1133 return MI_RESULT_NOT_SUPPORTED;
1134 }
1135
1136 static MI_Result MI_CALL _RequestUnload(
1137 MI_Context* self_)
1138 {
1139 Context* self = (Context*)self_;
1140
1141 if (!self || self->magic != _MAGIC || !self->provider)
1142 return MI_RESULT_INVALID_PARAMETER;
1143
1144 Provider_SetRefuseUnloadFlag(self->provider, MI_FALSE);
1145 return MI_RESULT_OK;
1146 }
1147
1148 krisbash 1.5 static MI_Result MI_CALL _RefuseUnload(
1149 MI_Context* self_)
1150 {
1151 Context* self = (Context*)self_;
1152
1153 if (!self || self->magic != _MAGIC || !self->provider)
1154 return MI_RESULT_INVALID_PARAMETER;
1155
1156 Provider_SetRefuseUnloadFlag(self->provider, MI_TRUE);
1157 return MI_RESULT_OK;
1158 }
1159
1160 static MI_Result MI_CALL _GetLocalSession(
1161 _In_ const MI_Context* self_,
1162 _Out_ MI_Session* session)
|
1163 mike 1.1 {
|
1164 krisbash 1.5 #if defined(DISABLE_LOCALSESSION)
1165 MI_UNREFERENCED_PARAMETER(self_);
1166 MI_UNREFERENCED_PARAMETER(session);
1167
|
1168 mike 1.1 return MI_RESULT_NOT_SUPPORTED;
|
1169 krisbash 1.5 #else
1170 Context* self = (Context*)self_;
1171
1172 if (!self || self->magic != _MAGIC || !self->provider || !self->provider->lib || !self->provider->lib->provmgr)
1173 return MI_RESULT_INVALID_PARAMETER;
1174
1175 return ProvMgr_GetLocalSesson(self->provider->lib->provmgr, session);
1176 #endif /* defined(DISABLE_LOCALSESSION) */
|
1177 mike 1.1 }
1178
|
1179 krisbash 1.5 static MI_Result MI_CALL _SetStringOption(
1180 _In_ MI_Context* context,
1181 _In_z_ const ZChar* name,
1182 _In_z_ const ZChar* value)
|
1183 mike 1.1 {
1184 return MI_RESULT_NOT_SUPPORTED;
|
1185 krisbash 1.5 }
|
1186 mike 1.1
|
1187 krisbash 1.5 static MI_Result MI_CALL _GetCustomOption(
1188 _In_ MI_Context* context_,
1189 _In_z_ const ZChar* name,
|
1190 mike 1.1 _Out_opt_ MI_Type* valueType,
1191 _Out_opt_ MI_Value* value)
1192 {
|
1193 krisbash 1.5 Context* context = (Context*)context_;
1194
1195 /* Check parameters */
1196 if (!context || !context->request)
1197 return MI_RESULT_INVALID_PARAMETER;
1198
1199 /* Return zero if no option object */
1200 if (!context->request->options)
1201 return MI_RESULT_NO_SUCH_PROPERTY;
1202
1203 return __MI_Instance_GetElement(
1204 context->request->options,
1205 name,
1206 value,
1207 valueType,
1208 NULL,
1209 NULL);
|
1210 mike 1.1 }
1211
|
1212 krisbash 1.5 static MI_Result MI_CALL _GetCustomOptionCount(
1213 _In_ MI_Context* context_,
|
1214 mike 1.1 _Out_opt_ MI_Uint32* count)
1215 {
|
1216 krisbash 1.5 Context* context = (Context*)context_;
1217
1218 /* Check parameters */
1219 if (!context || !context->request)
1220 return MI_RESULT_INVALID_PARAMETER;
1221
1222 /* Return zero if no option object */
1223 if (!context->request->options)
1224 {
1225 if (count)
1226 *count = 0;
1227 return MI_RESULT_OK;
1228 }
1229
1230 return __MI_Instance_GetElementCount(context->request->options, count);
|
1231 mike 1.1 }
1232
|
1233 krisbash 1.5 static MI_Result MI_CALL _GetCustomOptionAt(
1234 _In_ MI_Context* context_,
|
1235 mike 1.1 _In_ MI_Uint32 index,
|
1236 krisbash 1.5 _Outptr_opt_result_maybenull_z_ const ZChar** name,
|
1237 mike 1.1 _Out_opt_ MI_Type* valueType,
1238 _Out_opt_ MI_Value* value)
1239 {
|
1240 krisbash 1.5 Context* context = (Context*)context_;
1241
1242 /* Check parameters */
1243 if (!context || !context->request)
1244 return MI_RESULT_INVALID_PARAMETER;
1245
1246 if (!context->request->options)
1247 return MI_RESULT_FAILED;
1248
1249 return __MI_Instance_GetElementAt(
1250 context->request->options,
1251 index,
1252 name,
1253 value,
1254 valueType,
1255 0);
1256 }
1257
1258 static MI_Result MI_CALL _GetStringOption(
1259 _In_ MI_Context* context,
1260 _In_z_ const ZChar* name,
1261 krisbash 1.5 _Outptr_result_z_ const ZChar** valueOut)
1262 {
1263 MI_Type type;
1264 MI_Value value;
1265 MI_Result r;
1266
1267 r = _GetCustomOption(
1268 context,
1269 name,
1270 &type,
1271 &value);
1272
1273 if (r != MI_RESULT_OK)
1274 return r;
1275
1276 if (type != MI_STRING)
1277 return MI_RESULT_NO_SUCH_PROPERTY;
1278
1279 if (valueOut)
1280 *valueOut = value.string;
1281
1282 krisbash 1.5 return MI_RESULT_OK;
1283 }
1284
1285 static MI_Result MI_CALL _GetNumberOption(
1286 _In_ MI_Context* context,
1287 _In_z_ const ZChar *name,
1288 _Out_opt_ MI_Uint32* valueOut)
1289 {
1290 MI_Type type;
1291 MI_Value value;
1292 MI_Result r;
1293
1294 r = _GetCustomOption(
1295 context,
1296 name,
1297 &type,
1298 &value);
1299
1300 if (r != MI_RESULT_OK)
1301 return r;
1302
1303 krisbash 1.5 if (type != MI_UINT32)
1304 return MI_RESULT_NO_SUCH_PROPERTY;
1305
1306 if (valueOut)
1307 *valueOut = value.uint32;
1308
1309 return MI_RESULT_OK;
1310 }
|
1311 mike 1.1
|
1312 krisbash 1.5 static MI_Result MI_CALL _WriteMessage(
|
1313 mike 1.1 _In_ MI_Context* context,
1314 MI_Uint32 channel,
|
1315 krisbash 1.5 _In_z_ const ZChar* message)
|
1316 mike 1.1 {
1317 return MI_RESULT_NOT_SUPPORTED;
1318 }
1319
|
1320 krisbash 1.5 static MI_Result MI_CALL _WriteProgress(
|
1321 mike 1.1 _In_ MI_Context* context,
|
1322 krisbash 1.5 _In_z_ const ZChar* activity,
1323 _In_z_ const ZChar* currentOperation,
1324 _In_z_ const ZChar* statusDescription,
|
1325 mike 1.1 MI_Uint32 percentComplete,
1326 MI_Uint32 secondsRemaining)
1327 {
1328 return MI_RESULT_NOT_SUPPORTED;
1329 }
1330
|
1331 krisbash 1.5 static MI_Result MI_CALL _WriteStreamParameter(
|
1332 mike 1.1 _In_ MI_Context* context,
|
1333 krisbash 1.5 _In_z_ const ZChar* name,
|
1334 mike 1.1 _In_ const MI_Value* value,
1335 _In_ MI_Type type,
1336 _In_ MI_Uint32 flags)
1337 {
1338 return MI_RESULT_NOT_SUPPORTED;
1339 }
1340
|
1341 krisbash 1.5 static MI_Result MI_CALL _WriteCimError(
|
1342 mike 1.1 _In_ MI_Context* context,
1343 _In_ const MI_Instance *error,
1344 _Out_ MI_Boolean *flag)
1345 {
1346 return MI_RESULT_NOT_SUPPORTED;
1347 }
1348
|
1349 krisbash 1.5 static MI_Result MI_CALL _PromptUser(
|
1350 mike 1.1 _In_ MI_Context* context,
|
1351 krisbash 1.5 _In_z_ const ZChar* message,
|
1352 mike 1.1 MI_PromptType promptType,
1353 _Out_ MI_Boolean* result)
1354 {
1355 return MI_RESULT_NOT_SUPPORTED;
1356 }
1357
|
1358 krisbash 1.5 static MI_Result MI_CALL _ShouldProcess(
|
1359 mike 1.1 _In_ MI_Context* context,
|
1360 krisbash 1.5 _In_z_ const ZChar* target,
1361 _In_z_ const ZChar* action,
|
1362 mike 1.1 _Out_ MI_Boolean* result)
1363 {
1364 return MI_RESULT_NOT_SUPPORTED;
1365 }
1366
|
1367 krisbash 1.5 static MI_Result MI_CALL _ShouldContinue(
|
1368 mike 1.1 _In_ MI_Context* context,
|
1369 krisbash 1.5 _In_z_ const ZChar* message,
|
1370 mike 1.1 _Out_ MI_Boolean* result)
1371 {
1372 return MI_RESULT_NOT_SUPPORTED;
1373 }
1374
|
1375 krisbash 1.5 static MI_Result MI_CALL _PostError(
1376 _In_ MI_Context* self,
1377 MI_Uint32 result,
1378 _In_z_ const ZChar* type,
1379 _In_z_ const ZChar* message)
|
1380 mike 1.1 {
|
1381 krisbash 1.5 OMI_Error *omiError = NULL;
1382 MI_Result returnVal;
1383
1384 if (NULL == type)
1385 {
1386 /* Don't know the error type so just use failed */
1387 type = MI_RESULT_TYPE_MI;
1388 result = MI_RESULT_FAILED;
1389 }
1390 returnVal = OMI_ErrorFromErrorCode(NULL, result, type, message, &omiError);
1391 if (returnVal == MI_RESULT_INVALID_PARAMETER)
1392 {
1393 /* invalid error type */
1394 type = MI_RESULT_TYPE_MI;
1395 result = MI_RESULT_FAILED;
1396 }
1397 if (returnVal != MI_RESULT_FAILED)
1398 {
1399 /* We ignore this error as we need to fail the operation */
1400 returnVal = _ProcessResult(self, result, message, (MI_Instance*)omiError);
1401 }
1402 krisbash 1.5 else
1403 {
1404 if (message == NULL)
1405 {
1406 MI_Value messageValue;
1407 MI_Type messageType;
1408
1409 returnVal = MI_Instance_GetElement(&omiError->__instance, MI_T("Message"), &messageValue, &messageType, NULL, NULL);
1410 if ((MI_RESULT_OK == returnVal) && (MI_STRING == messageType))
1411 {
1412 message = messageValue.string;
1413 }
1414 }
1415 returnVal = _ProcessResult(self, result, message, &omiError->__instance);
1416 }
1417
1418 if ( omiError )
1419 MI_Instance_Delete(&omiError->__instance);
1420
1421 return returnVal;
|
1422 mike 1.1 }
1423
|
1424 krisbash 1.5 static MI_Result MI_CALL _PostCimError(
1425 _In_ MI_Context* self,
|
1426 mike 1.1 _In_ const MI_Instance *error)
1427 {
|
1428 krisbash 1.5 MI_Value value;
1429 MI_Type type;
1430 MI_Result result;
1431
1432 result = MI_Instance_GetElement(error, MI_T("CIMStatusCode"), &value, &type, NULL, NULL);
1433 if ((MI_RESULT_OK != result) || (MI_UINT32 != type))
1434 {
1435 return _ProcessResult(self, MI_RESULT_INVALID_CLASS_HIERARCHY, MI_T("Invalid CIM_Error object posted from provider"), NULL);
1436 }
1437 else
1438 {
1439 MI_Value messageValue;
1440 MI_Type messageType;
1441
1442 result = MI_Instance_GetElement(error, MI_T("Message"), &messageValue, &messageType, NULL, NULL);
1443 if ((MI_RESULT_OK != result) || (MI_STRING != messageType))
1444 {
1445 messageValue.string = NULL;
1446 }
1447 return _ProcessResult(self, value.uint32, messageValue.string, error);
1448 }
|
1449 mike 1.1 }
1450
|
1451 krisbash 1.5 static MI_Result MI_CALL _WriteError(
|
1452 mike 1.1 _In_ MI_Context* context,
1453 MI_Uint32 resultCode,
|
1454 krisbash 1.5 _In_z_ const ZChar* resultType,
1455 _In_z_ const ZChar* errorMessage,
|
1456 mike 1.1 _Out_ MI_Boolean *flag)
1457 {
1458 return MI_RESULT_NOT_SUPPORTED;
1459 }
1460
|
1461 krisbash 1.5 static MI_Result _GetLifecycleIndicationContext_NotSupported(
1462 _In_ const MI_Context* context,
1463 _Outptr_ MI_LifecycleIndicationContext** lifecycleContext)
1464 {
1465 MI_UNREFERENCED_PARAMETER(context);
1466 *lifecycleContext = NULL;
1467 return MI_RESULT_NOT_SUPPORTED;
1468 }
1469
1470 /*
1471 * Initializes lifecycle indication handling for a provider and populates the
1472 * lifecycleContext ptr if everything goes well. Returns existing
1473 * LifecycleContext if it has already been initialized.
1474 */
1475 static MI_Result _GetLifecycleIndicationContext(
1476 _In_ const MI_Context* context,
1477 _Outptr_ MI_LifecycleIndicationContext** lifecycleContext)
1478 {
1479 #ifdef DISABLE_INDICATION
1480 return _GetLifecycleIndicationContext_NotSupported(context, lifecycleContext);
1481 #else
1482 krisbash 1.5
1483 Context* internalContext = (Context*)context;
1484 LifecycleContext* lifeCtx = NULL;
1485
1486 /* Check if indication support has been enabled for this _Provider. If
1487 * not, activate it. Previously initialized support means that either
1488 * this provider is an Indication class or that a subscription already
1489 * exists.
1490 */
1491 lifeCtx = internalContext->provider->subMgr->lifecycleCtx;
1492 if (NULL == lifeCtx)
1493 {
1494 lifeCtx = LifeContext_New();
1495 if (NULL == lifeCtx)
1496 {
1497 return MI_RESULT_FAILED;
1498 }
1499 LifeContext_Init( lifeCtx, internalContext->provider );
1500 internalContext->provider->subMgr->lifecycleCtx = lifeCtx;
1501 }
1502
1503 krisbash 1.5 *lifecycleContext = (MI_LifecycleIndicationContext*)lifeCtx;
1504
1505 return MI_RESULT_OK;
1506 #endif
1507 }
1508
1509 MI_ContextFT __mi_contextFT =
|
1510 mike 1.1 {
|
1511 krisbash 1.5 // MI_Context_FT
|
1512 mike 1.1 _PostResult,
1513 _PostInstance,
1514 _PostIndication,
1515 _ConstructInstance,
1516 _ConstructParameters,
1517 _NewInstance,
1518 _NewDynamicInstance,
1519 _NewParameters,
1520 _Canceled,
1521 _GetLocale,
1522 _RegisterCancel,
1523 _RequestUnload,
1524 _RefuseUnload,
1525 _GetLocalSession,
1526 _SetStringOption,
1527 _GetStringOption,
1528 _GetNumberOption,
1529 _GetCustomOption,
1530 _GetCustomOptionCount,
1531 _GetCustomOptionAt,
1532 _WriteMessage,
1533 mike 1.1 _WriteProgress,
1534 _WriteStreamParameter,
1535 _WriteCimError,
1536 _PromptUser,
1537 _ShouldProcess,
1538 _ShouldContinue,
1539 _PostError,
1540 _PostCimError,
1541 _WriteError,
|
1542 krisbash 1.5 _GetLifecycleIndicationContext,
1543 };
1544
1545 #ifndef DISABLE_INDICATION
1546
1547 /*
1548 * Alternate MI_Context function table for handling indication functions.
1549 */
1550 MI_ContextFT __mi_indication_contextFT =
1551 {
1552 _Ind_PostResult,
1553 _Ind_PostInstance,
1554 _Ind_PostIndication,
1555 _ConstructInstance,
1556 _ConstructParameters,
1557 _NewInstance,
1558 _NewDynamicInstance,
1559 _NewParameters,
1560 _Canceled,
1561 _GetLocale,
1562 _RegisterCancel,
1563 krisbash 1.5 _RequestUnload,
1564 _RefuseUnload,
1565 _GetLocalSession,
1566 _SetStringOption,
1567 _GetStringOption,
1568 _GetNumberOption,
1569 _GetCustomOption,
1570 _GetCustomOptionCount,
1571 _GetCustomOptionAt,
1572 _WriteMessage,
1573 _WriteProgress,
1574 _WriteStreamParameter,
1575 _WriteCimError,
1576 _PromptUser,
1577 _ShouldProcess,
1578 _ShouldContinue,
1579 _Ind_PostError,
1580 _Ind_PostCimError,
1581 _WriteError,
1582 _GetLifecycleIndicationContext_NotSupported,
1583 };
1584 krisbash 1.5
1585 /*
1586 * Alternate MI_Context function table for invoking subscribe and unsubscribe
1587 */
1588
1589 static MI_Result _subunsub_ProcessResult(
1590 MI_Context* self_,
1591 MI_Result result,
1592 const ZChar* errorMessage,
1593 const MI_Instance* cimError)
1594 {
1595 Context* self = (Context*)self_;
1596 MI_UNREFERENCED_PARAMETER(errorMessage);
1597 MI_UNREFERENCED_PARAMETER(cimError);
1598 if (!self || self->magic != _MAGIC)
1599 return MI_RESULT_INVALID_PARAMETER;
1600 *self->result = result;
1601 return MI_RESULT_OK;
1602 }
1603
1604 static MI_Result MI_CALL _subunsub_PostResult(
1605 krisbash 1.5 MI_Context* self_,
1606 MI_Result result)
1607 {
1608 return _subunsub_ProcessResult(self_, result, NULL, NULL);
1609 }
1610
1611 static MI_Result MI_CALL _subunsub_PostError(
1612 _In_ MI_Context* self,
1613 MI_Uint32 result,
1614 _In_z_ const ZChar* type,
1615 _In_z_ const ZChar* message)
1616 {
1617 if (NULL == type ||
1618 Tcscmp(type, MI_RESULT_TYPE_MI) != 0)
1619 {
1620 result = MI_RESULT_FAILED;
1621 }
1622 return _subunsub_ProcessResult(self, (MI_Result)result, message, NULL);
1623 }
1624
1625 static MI_Result MI_CALL _subunsub_PostCimError(
1626 krisbash 1.5 _In_ MI_Context* self,
1627 _In_ const MI_Instance *error)
1628 {
1629 return _subunsub_ProcessResult(self, MI_RESULT_FAILED, NULL, error);
1630 }
1631
1632 MI_ContextFT __mi_indication_subunsub_contextFT =
1633 {
1634 _subunsub_PostResult,
1635 _Ind_PostInstance,
1636 _PostIndication,
1637 _ConstructInstance,
1638 _ConstructParameters,
1639 _NewInstance,
1640 _NewDynamicInstance,
1641 _NewParameters,
1642 _Canceled,
1643 _GetLocale,
1644 _RegisterCancel,
1645 _RequestUnload,
1646 _RefuseUnload,
1647 krisbash 1.5 _GetLocalSession,
1648 _SetStringOption,
1649 _GetStringOption,
1650 _GetNumberOption,
1651 _GetCustomOption,
1652 _GetCustomOptionCount,
1653 _GetCustomOptionAt,
1654 _WriteMessage,
1655 _WriteProgress,
1656 _WriteStreamParameter,
1657 _WriteCimError,
1658 _PromptUser,
1659 _ShouldProcess,
1660 _ShouldContinue,
1661 _subunsub_PostError,
1662 _subunsub_PostCimError,
1663 _WriteError,
1664 _GetLifecycleIndicationContext_NotSupported,
|
1665 mike 1.1 };
1666
|
1667 krisbash 1.5 /*
1668 * The Context that uses this table does not get exposed
1669 * to a _Provider, so it is considered "internal."
1670 */
1671 MI_ContextFT __mi_lifecycleIndication_contextFT =
1672 {
1673 _Ind_PostResult,
1674 NULL,
1675 _Ind_PostIndication,
1676 NULL,
1677 NULL,
1678 NULL,
1679 NULL,
1680 NULL,
1681 NULL,
1682 NULL,
1683 NULL,
1684 NULL,
1685 NULL,
1686 NULL,
1687 NULL,
1688 krisbash 1.5 NULL,
1689 NULL,
1690 NULL,
1691 NULL,
1692 NULL,
1693 NULL,
1694 NULL,
1695 NULL,
1696 NULL,
1697 NULL,
1698 NULL,
1699 NULL,
1700 NULL,
1701 NULL,
1702 NULL,
1703 };
1704
1705 #endif /* ifndef DISABLE_INDICATION */
1706
1707 static void _Context_Post( _In_ Strand* self_, _In_ Message* msg)
1708 {
1709 krisbash 1.5 DEBUG_ASSERT( MI_FALSE ); // not used yet (no secondary "semantic" messages)
1710 }
1711
1712 static void _Context_PostControl( _In_ Strand* self, _In_ Message* msg)
1713 {
1714 DEBUG_ASSERT( MI_FALSE ); // not used yet
1715 }
1716
1717 #ifdef _PREFAST_
1718 #pragma prefast (push)
1719 #pragma prefast (disable: 26001) // bogus "we know the interaction points to the middle of the InteractionDispBase struct"
1720 #endif /* _PREFAST_ */
1721
1722 static void _Context_Ack( _In_ Strand* self_)
1723 {
1724 Context* self = FromOffset(Context,strand,self_);
1725 ptrdiff_t tryingToPostLeftValue = ReadWithFence(&self->tryingToPostLeft);
1726
1727 trace_ContextAck(
1728 self_,
1729 self->strand.info.interaction.other,
1730 krisbash 1.5 &self->strand.info.interaction,
1731 self->strand.info.thisClosedOther,
1732 self->strand.info.otherClosedThis,
1733 tryingToPostLeftValue );
1734
1735 // al management done by strand implementation except broadcasting cond var
1736
1737 // wake up Context_PostMessageLeft if appropiate
1738 // (no point on waking up Context_PostMessageLeft if CONTEXT_STRANDAUX_TRYPOSTLEFT is scheduled to run after us)
1739 if( CONTEXT_POSTLEFT_POSTING == Atomic_CompareAndSwap( &self->tryingToPostLeft, (ptrdiff_t)CONTEXT_POSTLEFT_POSTING, (ptrdiff_t)(CONTEXT_POSTLEFT_POSTING|CONTEXT_POSTLEFT_SCHEDULED)) )
1740 {
1741 // Schedule it again
1742 Strand_ScheduleAux( &self->strand, CONTEXT_STRANDAUX_TRYPOSTLEFT );
1743 // again we get a memory barrier on tryingToPostLeft/tryingToPostLeftScheduled after this
1744 }
1745 }
1746
1747 static void _Context_Cancel( _In_ Strand* self )
1748 {
1749 trace_ContextCancel( self );
1750 }
1751 krisbash 1.5
1752 static void _Context_Close( _In_ Strand* self_ )
1753 {
1754 Context* self = FromOffset(Context,strand,self_);
1755 trace_ContextClose(
1756 self_,
1757 self->strand.info.interaction.other,
1758 &self->strand.info.interaction );
1759 }
1760
1761 static void _Context_Finish( _In_ Strand* self_ )
1762 {
1763 Context* self = FromOffset(Context,strand,self_);
1764
1765 trace_ContextFinish( self_ );
1766 _Context_Destroy(self);
1767 }
1768
1769 // CONTEXT_STRANDAUX_TRYPOSTLEFT
1770 static void _Context_Aux_TryPostLeft( _In_ Strand* self_ )
1771 {
1772 krisbash 1.5 Context* self = FromOffset(Context,strand,self_);
1773 ptrdiff_t oldValue;
1774
1775 trace_ContextAuxPostLeft( self_, self->strand.info.thisAckPending );
1776
1777 if( !self->strand.info.thisAckPending )
1778 {
1779 if (!self->strand.info.thisClosedOther) // TODO: Is this correct, or is it indiciative of a different problem?
1780 {
1781 /* Only post the message if this Context has not "closed"
1782 * the connection. Another thread may have done so on the
1783 * context while this thread was waiting. */
1784 Strand_Post( &self->strand, self->msgPostingLeft );
1785 }
1786 self->msgPostingLeft = NULL;
1787 Strand_ScheduleAux(self_, CONTEXT_STRANDAUX_TRYPOSTLEFT_NOTIFY);
1788 }
1789 else
1790 {
1791 oldValue = Atomic_Swap(&self->tryingToPostLeft,(ptrdiff_t)CONTEXT_POSTLEFT_POSTING);
1792 DEBUG_ASSERT( (CONTEXT_POSTLEFT_POSTING|CONTEXT_POSTLEFT_SCHEDULED) == oldValue );
1793 krisbash 1.5 }
1794 }
1795
1796 // CONTEXT_STRANDAUX_TRYPOSTLEFT_NOTIFY
1797 static void _Context_Aux_TryPostLeft_Notify( _In_ Strand* self_ )
1798 {
1799 Context* self = FromOffset(Context,strand,self_);
1800 ptrdiff_t oldValue;
1801
1802 oldValue = Atomic_Swap(&self->tryingToPostLeft,(ptrdiff_t)0);
1803 // wake up _Context_PostMessageLeft
1804
1805 // Uncomment when no longer using Selector
1806 //#if defined(CONFIG_OS_WINDOWS)
1807 // trace_ContextAuxPostLeftNotify( self_ );
1808 // CondLock_Broadcast((ptrdiff_t)self);
1809 //#else
1810 if( self->postingOnIoThread )
1811 {
1812 trace_ContextAuxPostLeftNotify_IoThread( self_ );
1813 self->postingOnIoThread = MI_FALSE;
1814 krisbash 1.5 Selector_StopRunningNoReadsMode( self->provider->lib->provmgr->selector );
1815 }
1816 else
1817 {
1818 trace_ContextAuxPostLeftNotify( self_ );
1819 CondLock_Broadcast((ptrdiff_t)self);
1820 }
1821 //#endif
1822
1823 DEBUG_ASSERT( (CONTEXT_POSTLEFT_POSTING|CONTEXT_POSTLEFT_SCHEDULED) == oldValue );
1824 }
1825
1826
1827 #ifdef _PREFAST_
1828 #pragma prefast (pop)
1829 #endif /* _PREFAST_ */
1830
1831 /*
1832 * This represents a standard Context object. It mediates access to the
1833 * internal strands from providers so that a provider can have only one
1834 * operation outstanding at a time. Provider Posts (Result, Indication,
1835 krisbash 1.5 * Error, CimError, and Instance) are routed through 'TryPostLeft' so that
1836 * they can be handled within a post lock and in the context of a strand
1837 * action. Providers may post from multiple threads to the same Context,
1838 * but only one post will be handled at a time. An ACK releases the
1839 * tryingToPostLeft flag to allow another Post to occur.
1840 *
1841 * Shutdown behavior:
1842 * Cancel and Close do nothing. The strand cannot be finished until it
1843 * schedules a close on itself. This will happen when the Context or
1844 * ProvMgr determine that a connection to a provider should be closed.
1845 * Typically this happens after a provider calls PostResult, PostError,
1846 * or PostCimError.
1847 */
1848 StrandFT _Context_leftInteractionFT =
1849 {
1850 _Context_Post,
1851 _Context_PostControl,
1852 _Context_Ack,
1853 _Context_Cancel,
1854 _Context_Close,
1855 _Context_Finish,
1856 krisbash 1.5 NULL,
1857 _Context_Aux_TryPostLeft,
1858 _Context_Aux_TryPostLeft_Notify,
1859 NULL,
1860 NULL,
1861 NULL
1862 };
1863
1864
1865 #ifndef DISABLE_INDICATION
1866
1867 /*
1868 * IndicationManager cancels the operations upon get cancelled call from protocol or
1869 * received unsubscribe message.
1870 *
1871 * This function works for both Lifecycle and regular subscription contexts
1872 */
1873 static void _SubscribeContext_Cancel(_In_ Strand* self_)
1874 {
1875 SubscriptionContext* self = (SubscriptionContext*)((char*)self_ - offsetof(Context,strand));
1876 trace_SubscribeContext_Cancel(self);
1877 krisbash 1.5
1878 if (NULL == self->subscription ||
1879 SubMgrSubscription_CancelStarted(self->subscription))
1880 {
1881 /* The subscription has already posted a final result, so there is
1882 * nothing to do here. */
1883 return;
1884 }
1885 SubscrContext_Unsubscribe(self);
1886 trace_SubscribeContext_CancelDone(self);
1887 }
1888
1889
1890 // CONTEXT_STRANDAUX_INVOKESUBSCRIBE
1891 static void _Context_Aux_InvokeSubscribe( _In_ Strand* self_ )
1892 {
1893 Context* self = FromOffset(Context,strand,self_);
1894 Message* msg = self->strand.info.stored.msg;
1895
1896 DEBUG_ASSERT( NULL != msg );
1897
1898 krisbash 1.5 self->strand.info.stored.msg = NULL;
1899
1900 Provider_InvokeSubscribe(
1901 self->provider,
1902 (SubscribeReq*)msg,
1903 (SubscriptionContext*)self);
1904
1905 /*
1906 * release the reference count from _SubMgrSubscription_New
1907 */
1908 SubMgrSubscription_Release(((SubscriptionContext*)self)->subscription);
1909
1910 Message_Release( msg );
1911 }
1912
1913 /*
1914 * This represents a SubscriptionContext object. It functions the same way as
1915 * a normal Context (follows the same behavioral pattern), but is designed to
1916 * handle indications. It also includes an AUX subscribe method so that
1917 * subscription requests happen within the protections of a strand invocation.
1918 */
1919 krisbash 1.5 StrandFT _SubscribeContext_leftInteractionFT =
1920 {
1921 _Context_Post,
1922 _Context_PostControl,
1923 _Context_Ack,
1924 _SubscribeContext_Cancel,
1925 _Context_Close,
1926 _Context_Finish,
1927 NULL,
1928 _Context_Aux_TryPostLeft,
1929 _Context_Aux_TryPostLeft_Notify,
1930 _Context_Aux_InvokeSubscribe,
1931 NULL,
1932 NULL
1933 };
1934
1935 #endif /* ifndef DISABLE_INDICATION */
1936
1937 _Use_decl_annotations_
1938 MI_Result _Context_Init(
|
1939 mike 1.1 Context* self,
|
1940 krisbash 1.5 Provider* provider,
1941 InteractionOpenParams* interactionParams,
1942 ContextInitOptions options,
1943 Context_Type ctxType )
|
1944 mike 1.1 {
|
1945 krisbash 1.5 StrandFT *ft = NULL;
1946
1947 if( NULL == self )
1948 return MI_RESULT_FAILED;
1949
|
1950 mike 1.1 memset(self, 0, sizeof(Context));
|
1951 krisbash 1.5
1952 trace_ContextNew( self, interactionParams ? interactionParams->interaction : NULL, &self->strand.info.interaction );
1953
1954 Lock_Init(&self->lock);
1955
1956 self->ctxType = ctxType;
1957
1958 if( NULL != interactionParams && NULL != interactionParams->msg )
1959 {
1960 DEBUG_ASSERT( Message_IsRequest( interactionParams->msg ) );
1961 /* release inside _Context_Destroy */
1962 Message_AddRef( interactionParams->msg );
1963 self->request = (RequestMsg*)interactionParams->msg;
1964 }
1965
1966 #ifndef DISABLE_INDICATION
1967 /*
1968 * Conditionally set function table based on desired context type.
1969 */
1970 if (CTX_TYPE_IND_AGGREGATION == ctxType ||
1971 CTX_TYPE_IND_SUBSCRIPTION == ctxType)
1972 krisbash 1.5 {
1973 self->base.ft = &__mi_indication_contextFT;
1974 ft = &_SubscribeContext_leftInteractionFT;
1975 }
1976 else if (CTX_TYPE_IND_LIFECYCLE == ctxType)
1977 {
1978 self->base.ft = &__mi_lifecycleIndication_contextFT;
1979 ft = &_SubscribeContext_leftInteractionFT;
1980 }
1981 else if (CTX_TYPE_IND_SUB_UNSUB == ctxType)
1982 {
1983 DEBUG_ASSERT( provider == NULL );
1984 DEBUG_ASSERT( interactionParams == NULL );
1985 DEBUG_ASSERT( ContextInit_NoInteraction == options );
1986 self->base.ft = &__mi_indication_subunsub_contextFT;
1987 }
1988 else
1989 #endif /* ifndef DISABLE_INDICATION */
1990 {
1991 self->base.ft = &__mi_contextFT;
1992 ft = &_Context_leftInteractionFT;
1993 krisbash 1.5 }
1994
|
1995 mike 1.1 self->magic = _MAGIC;
1996 self->provider = provider;
|
1997 krisbash 1.5
1998 if( ContextInit_DelayOpen == options )
1999 {
2000 DEBUG_ASSERT( NULL != interactionParams );
2001 Strand_Init( STRAND_DEBUG( Context ) &self->strand, ft, STRAND_FLAG_ENTERSTRAND|STRAND_FLAG_DELAYACCEPTOPEN, interactionParams );
2002 }
2003 else if ( ContextInit_NoInteraction != options )
2004 {
2005 Strand_Init( STRAND_DEBUG( Context ) &self->strand, ft, STRAND_FLAG_ENTERSTRAND, interactionParams );
2006 if( NULL != interactionParams )
2007 {
2008 DEBUG_ASSERT( NULL != interactionParams->msg );
2009 Strand_Ack( &self->strand );
2010 }
2011 if( ContextInit_DontLeaveStrand != options )
2012 {
2013 Strand_Leave( &self->strand );
2014 }
2015 }
2016
|
2017 mike 1.1 Provider_Addref(self->provider);
|
2018 krisbash 1.5
2019 return MI_RESULT_OK;
|
2020 mike 1.1 }
2021
|
2022 krisbash 1.5 void Context_CompleteOpen(
2023 _In_ Context* self,
2024 _In_ InteractionOpenParams* params,
2025 MI_Result result)
|
2026 mike 1.1 {
|
2027 krisbash 1.5 DEBUG_ASSERT( NULL != params->msg );
|
2028 mike 1.1
|
2029 krisbash 1.5 if( MI_RESULT_OK == result )
2030 {
2031 Strand_AcceptOpen( &self->strand, params );
2032 Strand_Ack( &self->strand );
2033 Strand_Leave( &self->strand );
2034 }
2035 else
2036 {
2037 // Just destroy the context
2038 _Context_Destroy(self);
2039 Strand_FailOpenWithResult(params, result, PostResultMsg_NewAndSerialize);
2040 }
2041 }
|
2042 mike 1.1
|
2043 krisbash 1.5 //
2044 // Initialize subscribe/unsubscribe context
2045 //
2046 MI_Result Subunsub_Context_Init(
2047 _Out_ Context* self,
2048 _In_ MI_Result* result,
2049 _In_ RequestMsg* msg)
2050 {
2051 MI_Result r;
2052 DEBUG_ASSERT( msg && result );
2053 r = _Context_Init(self, NULL, NULL, ContextInit_NoInteraction, CTX_TYPE_IND_SUB_UNSUB);
2054 if ( r == MI_RESULT_OK )
2055 {
2056 Message_AddRef( &msg->base );
2057 self->request = msg;
2058 self->result = result;
2059 }
2060 return r;
|
2061 mike 1.1 }
|