1 krisbash 1.1 /*============================================================================
2 * Copyright (C) Microsoft Corporation, All rights reserved.
3 *============================================================================
4 */
5 #include <MI.h>
6 #include "InteractionProtocolHandler.h"
7 #include "Options.h"
8 #include <pal/atomic.h>
9 #include <pal/thread.h>
10 #include <pal/format.h>
11 #include <pal/strings.h>
12 #include <pal/lock.h>
13 #include <pal/sleep.h>
14 #include <base/Strand.h>
15 #include <base/messages.h>
16 #include <base/packing.h>
17 #include <base/paths.h>
18 #include <base/result.h>
19 #include <base/log.h>
20 #include <protocol/protocol.h>
21 #include <stdlib.h>
22 krisbash 1.1
23 //#define LOGD(a) {Tprintf a;Tprintf(MI_T("\n"));}
24 //#define LOGD(...)
25
26 extern const MI_ApplicationFT g_interactionProtocolHandler_ApplicationFT;
27 extern const MI_SessionFT g_interactionProtocolHandler_SessionFT;
28 extern const MI_OperationFT g_interactionProtocolHandler_OperationFT;
29 extern const MI_SessionFT g_interactionProtocolHandler_SessionFT_Dummy;
30
31 typedef struct _ApplicationThread
32 {
33 struct _ApplicationThread *next;
34 Thread thread;
35 } ApplicationThread;
36
37 typedef struct _InteractionProtocolHandler_Application
38 {
39 MI_Char *applicationID;
40 MI_Application myMiApplication;
41 ptrdiff_t threadCount;
42 Lock listOfThreadsLock;
43 krisbash 1.1 ApplicationThread *listOfThreads;
44 Thread safeShutdownThread;
45 } InteractionProtocolHandler_Application;
46
47 typedef void * SessionCloseCompletionContext;
48 typedef void (MI_CALL * SessionCloseCompletionCallback)(_In_opt_ SessionCloseCompletionContext);
49
50 typedef struct _SessionCloseCompletion
51 {
52 // count indicating who many protocool run thread are running
53 // so who ever finish last session close or the last protocol run thread
54 // will take care of releasing this completion and calling the callback (if necessary)
55 volatile ptrdiff_t count;
56 SessionCloseCompletionCallback completionCallback;
57 SessionCloseCompletionContext completionContext;
58 } SessionCloseCompletion;
59
60 typedef struct _InteractionProtocolHandler_Session
61 {
62 InteractionProtocolHandler_Application * parentApplication;
63 MI_DestinationOptions destinationOptions;
64 krisbash 1.1 MI_Session myMiSession;
65 // released by either session close or the protocol run thread, whoever finishes last
66 SessionCloseCompletion * sessionCloseCompletion;
67 } InteractionProtocolHandler_Session;
68
69 typedef enum _InteractionProtocolHandler_Operation_CurrentState
70 {
71 InteractionProtocolHandler_Operation_CurrentState_NotConnected = 0,
72 InteractionProtocolHandler_Operation_CurrentState_WaitingForConnect,
73 InteractionProtocolHandler_Operation_CurrentState_WaitingForClientResultAck,
74 InteractionProtocolHandler_Operation_CurrentState_WaitingForResult,
75 InteractionProtocolHandler_Operation_CurrentState_ConnectionFailed,
76 InteractionProtocolHandler_Operation_CurrentState_Disconnected,
77 InteractionProtocolHandler_Operation_CurrentState_Closed
78
79 } InteractionProtocolHandler_Operation_CurrentState;
80
81 typedef enum _InteractionProtocolHandler_Operation_OperationType
82 {
83 InteractionProtocolHandler_Operation_OperationType_Instance,
84 InteractionProtocolHandler_Operation_OperationType_Indication,
85 krisbash 1.1 InteractionProtocolHandler_Operation_OperationType_Class
86 } InteractionProtocolHandler_Operation_OperationType;
87
88
89 typedef struct _InteractionProtocolHandler_Operation
90 {
91 InteractionProtocolHandler_Session *parentSession;
92 MI_Operation myMiOperation;
93 MI_OperationCallbacks asyncOperationCallbacks;
94 Strand strand; /* To manage interaction with ProtocolSocket */
95 RequestMsg* req; /* Base pointer of full operation request message */
96 ProtocolSocketAndBase* protocol;
97 ApplicationThread *protocolRunThread;
98 volatile ptrdiff_t currentState; /* InteractionProtocolHandler_Operation_CurrentState */
99 MI_Boolean deliveredFinalResult;
100 InteractionProtocolHandler_Operation_OperationType operationType;
101 Message* cachedResultRequest;
102 MI_Boolean callingFinalResult;
103 Message* currentObjectMessage;
104 Message* currentResultMessage;
105 MI_Class currentClassResult;
106 krisbash 1.1
107 } InteractionProtocolHandler_Operation;
108
109 STRAND_DEBUGNAME(ProtocolHandler);
110
111 MI_Result InteractionProtocolHandler_Application_IncrementThreadCount(
112 _In_ InteractionProtocolHandler_Application *application);
113 MI_Result InteractionProtocolHandler_Application_DecrementThreadCount(
114 _In_ InteractionProtocolHandler_Application *application);
115 MI_Result InteractionProtocolHandler_Application_SafeCloseThread(
116 _In_ InteractionProtocolHandler_Application *application,
117 _In_ ApplicationThread *operationThread);
118
119
120 MI_Result MI_CALL InteractionProtocolHandler_Session_New(
121 _In_ MI_Application *miApplication,
122 _In_opt_z_ const MI_Char *protocol,
123 _In_opt_z_ const MI_Char *destination,
124 _In_opt_ MI_DestinationOptions *options,
125 _In_opt_ MI_SessionCallbacks *callbacks,
126 _Outptr_opt_result_maybenull_ MI_Instance **extendedError,
127 krisbash 1.1 _Out_ MI_Session *session);
128
129 MI_Result MI_CALL InteractionProtocolHandler_Client_Ack_PostToInteraction(_In_ MI_Operation *_operation)
130 {
131 InteractionProtocolHandler_Operation* operation = (InteractionProtocolHandler_Operation *)_operation->reserved2;
132
133 trace_InteractionProtocolHandler_Client_Ack_Post(operation);
134
135 /* Clean up all the result data for this iteration of results */
136 if (operation->currentObjectMessage)
137 {
138 Message_Release(operation->currentObjectMessage);
139 operation->currentObjectMessage = NULL;
140 }
141 if (operation->currentResultMessage)
142 {
143 Message_Release(operation->currentResultMessage);
144 operation->currentResultMessage = NULL;
145 }
146 if (operation->currentClassResult.ft)
147 {
148 krisbash 1.1 MI_Class_Delete(&operation->currentClassResult);
149 memset(&operation->currentClassResult, 0, sizeof(operation->currentClassResult));
150 }
151
152 Strand_ScheduleAck(&operation->strand);
153
154 return MI_RESULT_OK;
155 }
156 MI_Result MI_CALL InteractionProtocolHandler_Client_Ack_NoPostToInteraction(_In_ MI_Operation *_operation)
157 {
158 InteractionProtocolHandler_Operation* operation = (InteractionProtocolHandler_Operation *)_operation->reserved2;
159
160 /* Processing an ack that requires no ack to the interaction interface */
161 trace_InteractionProtocolHandler_Client_Ack_NoPost(operation);
162 return MI_RESULT_OK;
163 }
164
165 static MI_Uint64 _NextOperationId()
166 {
167 static ptrdiff_t _operationId = 10000;
168 return (MI_Uint64) Atomic_Inc(&_operationId);
169 krisbash 1.1 }
170
171 static char* _StringToStr(const MI_Char* str)
172 {
173 MI_Uint32 n = Tcslen(str);
174 MI_Uint32 i;
175 char* r = PAL_Malloc(sizeof(char)* (n + 1));
176
177 if (!r)
178 return NULL;
179
180 for (i = 0; i < n; i++)
181 {
182 r[i] = (char)str[i];
183 }
184
185 r[n] = '\0';
186
187 return r;
188 }
189
190 krisbash 1.1
191 /* ===================================================================================
192 * ===================================================================================
193 * ===================================================================================
194 * ===================================================================================
195 * ===================================================================================
196 * ===================================================================================
197 */
198
199 static void InteractionProtocolHandler_Operation_Strand_Post( _In_ Strand* self_, _In_ Message* msg)
200 {
201 InteractionProtocolHandler_Operation *operation = FromOffset(InteractionProtocolHandler_Operation, strand, self_);
202 trace_InteractionProtocolHandler_Operation_StrandPost(
203 operation,
204 msg,
205 msg->tag,
206 MessageName(msg->tag),
207 msg->operationId );
208
209 switch(msg->tag)
210 {
211 krisbash 1.1 case PostInstanceMsgTag:
212 {
213 MI_Boolean needToAck = MI_FALSE;
214
215 //If we have a previous item we need to send it
216 if (operation->cachedResultRequest)
217 {
218 PostInstanceMsg* rsp = (PostInstanceMsg*)operation->cachedResultRequest;
219
220 operation->currentObjectMessage = operation->cachedResultRequest; /* Needs releasing in Ack */
221 operation->cachedResultRequest = NULL;
222
223 #ifdef _PREFAST_
224 #pragma prefast(push)
225 #pragma prefast(disable:26001)
226 #endif
227
228 operation->asyncOperationCallbacks.instanceResult(&operation->myMiOperation, operation->asyncOperationCallbacks.callbackContext, rsp->instance, MI_TRUE, MI_RESULT_OK, NULL, NULL, InteractionProtocolHandler_Client_Ack_PostToInteraction);
229
230 #ifdef _PREFAST_
231 #pragma prefast(pop)
232 krisbash 1.1 #endif
233 }
234 else
235 needToAck = MI_TRUE;
236
237 {
238 PostInstanceMsg* rsp = (PostInstanceMsg*)msg;
239 if (rsp->instance)
240 {
241 /* if we have an instance we need to cache it */
242 Message_AddRef(msg);
243 operation->cachedResultRequest = msg; /* This will be used next time around or when we deliver final result */
244 }
245 }
246
247 if (needToAck)
248 {
249 Strand_ScheduleAck(&operation->strand);
250 return;
251 }
252
253 krisbash 1.1 break;
254 }
255 case PostIndicationMsgTag:
256 {
257 PostIndicationMsg* indication = (PostIndicationMsg*)msg;
258 trace_InteractionProtocolHandler_Operation_Strand_Post(
259 operation,
260 indication->base.instance);
261 Message_AddRef(msg);
262 operation->currentObjectMessage = msg; /* Needs releasing in Ack */
263 operation->asyncOperationCallbacks.indicationResult(&operation->myMiOperation, operation->asyncOperationCallbacks.callbackContext, indication->base.instance, indication->bookmark, indication->machineID, MI_TRUE, MI_RESULT_OK, NULL, NULL, InteractionProtocolHandler_Client_Ack_PostToInteraction);
264
265 break;
266 }
267 case PostResultMsgTag:
268 {
269 PostResultMsg* resp = (PostResultMsg*)msg;
270
271 trace_MIResult( Result_ToString(resp->result) );
272
273 operation->callingFinalResult = 1;
274 krisbash 1.1
275 Message_AddRef(msg);
276 operation->currentResultMessage = msg; /* Released in Ack() */
277
278 if (operation->req->base.tag == SubscribeReqTag)
279 {
280 PostInstanceMsg* previousResp = (PostInstanceMsg*)operation->cachedResultRequest;
281 MI_Instance *previousInstance = NULL;
282
283 if (previousResp)
284 previousInstance = previousResp->instance;
285
286 /* Need to get bookmark from message that doesn't yet exist */
287 operation->asyncOperationCallbacks.indicationResult(&operation->myMiOperation, operation->asyncOperationCallbacks.callbackContext, previousInstance, NULL, NULL, MI_FALSE, resp->result, resp->errorMessage, resp->cimError, InteractionProtocolHandler_Client_Ack_PostToInteraction);
288 operation->deliveredFinalResult = MI_TRUE;
289 }
290 else if (operation->req->base.tag == GetClassReqTag)
291 {
292 PostSchemaMsg* previousResp = (PostSchemaMsg*)operation->cachedResultRequest;
293 MI_Class *classItem = NULL;
294
295 krisbash 1.1 if (previousResp)
296 {
297 MI_Instance_GetClassExt(previousResp->schemaInstance, &operation->currentClassResult);/* Needs deleting in Ack() */
298 classItem = &operation->currentClassResult;
299 }
300
301 operation->currentObjectMessage = operation->cachedResultRequest; /* Needs releasing in Ack() */
302
303 operation->asyncOperationCallbacks.classResult(&operation->myMiOperation, operation->asyncOperationCallbacks.callbackContext, classItem, MI_FALSE, resp->result, resp->errorMessage, resp->cimError, InteractionProtocolHandler_Client_Ack_PostToInteraction);
304 }
305 else
306 {
307 PostInstanceMsg* previousResp = (PostInstanceMsg*)operation->cachedResultRequest;
308 MI_Instance *previousInstance = NULL;
309
310 if (previousResp)
311 previousInstance = previousResp->instance;
312
313 operation->currentObjectMessage = operation->cachedResultRequest; /* Needs releasing in Ack() */
314
315 operation->asyncOperationCallbacks.instanceResult(&operation->myMiOperation, operation->asyncOperationCallbacks.callbackContext, previousInstance, MI_FALSE, resp->result, resp->errorMessage, resp->cimError, InteractionProtocolHandler_Client_Ack_PostToInteraction);
316 krisbash 1.1 }
317
318
319 break;
320 }
321 case NoOpRspTag:
322 {
323 //NoOpRsp* resp = (NoOpRsp*)msg;
324 /* If we have an existing result then we need to send that along with the result.
325 * Note that the Strand_Ack will be done in the Ack we get back from the client.
326 */
327 trace_InteractionProtocolHandler_NoopRspTag();
328 operation->callingFinalResult = 1;
329 operation->asyncOperationCallbacks.instanceResult(&operation->myMiOperation, operation->asyncOperationCallbacks.callbackContext, NULL, MI_FALSE, MI_RESULT_OK, NULL, NULL, InteractionProtocolHandler_Client_Ack_PostToInteraction);
330 operation->deliveredFinalResult = MI_TRUE;
331 break;
332 }
333 case PostSchemaMsgTag:
334 {
335 MI_Boolean needToAck = MI_FALSE;
336
337 krisbash 1.1 //If we have a previous item we need to send it
338 if (operation->cachedResultRequest)
339 {
340 PostSchemaMsg* rsp = (PostSchemaMsg*)operation->cachedResultRequest;
341
342 operation->currentObjectMessage = operation->cachedResultRequest; /* Needs releasing in Ack */
343 operation->cachedResultRequest = NULL;
344
345 MI_Instance_GetClassExt(rsp->schemaInstance, &operation->currentClassResult);/* Needs deleting in Ack() */
346
347 #ifdef _PREFAST_
348 #pragma prefast(push)
349 #pragma prefast(disable:26001)
350 #endif
351 operation->asyncOperationCallbacks.classResult(&operation->myMiOperation, operation->asyncOperationCallbacks.callbackContext, &operation->currentClassResult, MI_TRUE, MI_RESULT_OK, NULL, NULL, InteractionProtocolHandler_Client_Ack_PostToInteraction);
352
353 #ifdef _PREFAST_
354 #pragma prefast(pop)
355 #endif
356 }
357 else
358 krisbash 1.1 needToAck = MI_TRUE;
359
360 {
361 PostSchemaMsg* rsp = (PostSchemaMsg*)msg;
362 if (rsp->schemaInstance)
363 {
364 /* if we have an instance we need to cache it */
365 Message_AddRef(msg);
366 operation->cachedResultRequest = msg; /* This will be used next time around or when we deliver final result */
367 }
368 }
369
370 if (needToAck)
371 {
372 Strand_ScheduleAck(&operation->strand);
373 return;
374 }
375
376 break;
377 }
378 case BinProtocolNotificationTag:
379 krisbash 1.1 {
380 /* Don't support these responses yet so just Ack them */
381 Strand_Ack(self_);
382 return;
383 }
384 case SubscribeResTag:
385 {
386 /* Subscribe succeeded */
387 Strand_Ack(self_);
388 return;
389 }
390 case GetInstanceReqTag:
391 case EnumerateInstancesReqTag:
392 case NoOpReqTag:
393 case InvokeReqTag:
394 case AssociatorsOfReqTag:
395 case ReferencesOfReqTag:
396 case SubscribeReqTag:
397 case DeleteInstanceReqTag:
398 case CreateInstanceReqTag:
399 case ModifyInstanceReqTag:
400 krisbash 1.1 case GetClassReqTag:
401 case UnsubscribeReqTag:
402 default:
403 {
404 /* We should not get any of these messages as they are the requests. We should only get the responses. Ack anyway for now. */
405 DEBUG_ASSERT( MI_FALSE );
406 Strand_Ack(self_);
407 return;
408 }
409 }
410
411 }
412
413 #ifdef _PREFAST_
414 #pragma prefast (push)
415 #pragma prefast (disable: 26001) // bogus "we know the strand points to the middle of the InteractionProtocolHandler_Operation struct" and Linux sal parser doesnt recognize something like _Readable_elements_(_Inexpressible_(InteractionProtocolHandler_Operation))
416 #endif /* _PREFAST_ */
417
418 static void InteractionProtocolHandler_Operation_Strand_PostControl( _In_ Strand* self_, _In_ Message* msg)
419 {
420 InteractionProtocolHandler_Operation *operation = FromOffset(InteractionProtocolHandler_Operation, strand, self_);
421 krisbash 1.1 ProtocolEventConnect* eventMsg = (ProtocolEventConnect*)msg;
422
423 trace_InteractionProtocolHandler_Operation_Strand_PostControl( operation );
424 DEBUG_ASSERT( ProtocolEventConnectTag == msg->tag );
425
426 if( eventMsg->success )
427 {
428 trace_InteractionProtocolHandler_Session_ProtocolConnecting();
429
430 /* Posting the operation message so set the state to waiting for a result message */
431 operation->currentState = InteractionProtocolHandler_Operation_CurrentState_WaitingForResult;
432 Strand_Post(&operation->strand, &operation->req->base);
433 }
434 else
435 {
436 trace_InteractionProtocolHandler_Session_ConnectFailed();
437
438 }
439 }
440
441 static void InteractionProtocolHandler_Operation_Strand_Ack( _In_ Strand* self_ )
442 krisbash 1.1 {
443 InteractionProtocolHandler_Operation *operation = FromOffset(InteractionProtocolHandler_Operation, strand, self_);
444 trace_InteractionProtocolHandler_Operation_Strand_Ack(operation);
445 // We are not streaming any results, so no need to manage flow control on Ack
446 }
447
448 static void InteractionProtocolHandler_Operation_Strand_Cancel( _In_ Strand* self_ )
449 {
450 InteractionProtocolHandler_Operation *operation = FromOffset(InteractionProtocolHandler_Operation, strand, self_);
451 trace_InteractionProtocolHandler_Operation_Strand_Cancel(operation);
452 // DEBUG_ASSERT( MI_FALSE ); // not used in this direction
453 }
454
455 static void _Operation_SendFinalResult_Internal(InteractionProtocolHandler_Operation *operation)
456 {
457 operation->currentState = InteractionProtocolHandler_Operation_CurrentState_NotConnected;
458 operation->callingFinalResult = MI_TRUE;
459 if (operation->operationType == InteractionProtocolHandler_Operation_OperationType_Class)
460 {
461 operation->asyncOperationCallbacks.classResult(&operation->myMiOperation, operation->asyncOperationCallbacks.callbackContext, NULL, MI_FALSE, MI_RESULT_FAILED, NULL, NULL, InteractionProtocolHandler_Client_Ack_NoPostToInteraction);
462 }
463 krisbash 1.1 else if (operation->operationType == InteractionProtocolHandler_Operation_OperationType_Indication)
464 {
465 operation->asyncOperationCallbacks.indicationResult(&operation->myMiOperation, operation->asyncOperationCallbacks.callbackContext, NULL, NULL, NULL, MI_FALSE, MI_RESULT_FAILED, NULL, NULL, InteractionProtocolHandler_Client_Ack_NoPostToInteraction);
466 }
467 else
468 {
469 operation->asyncOperationCallbacks.instanceResult(&operation->myMiOperation, operation->asyncOperationCallbacks.callbackContext, NULL, MI_FALSE, MI_RESULT_FAILED, NULL, NULL, InteractionProtocolHandler_Client_Ack_NoPostToInteraction);
470 }
471 operation->deliveredFinalResult = MI_TRUE;
472 }
473
474 static void InteractionProtocolHandler_Operation_Strand_Close( _In_ Strand* self_ )
475 {
476 InteractionProtocolHandler_Operation *operation = FromOffset(InteractionProtocolHandler_Operation, strand, self_);
477
478 trace_InteractionProtocolHandler_Operation_Strand_Close(operation);
479
480 if (!operation->callingFinalResult)
481 {
482 _Operation_SendFinalResult_Internal(operation);
483 }
484 krisbash 1.1 }
485
486 static void InteractionProtocolHandler_Operation_Strand_Finish( _In_ Strand* self_ )
487 {
488 InteractionProtocolHandler_Operation *operation = FromOffset(InteractionProtocolHandler_Operation, strand, self_);
489 // MI_Uint32 returnCode;
490
491 trace_InteractionProtocolHandler_Operation_Strand_Finish(operation);
492
493 //TODO: At some point we need to make sure the thread is shutdown properly without causing deadlocks
494 // Thread_Join(&operation->protocolRunThread, &returnCode);
495
496 Message_Release(&operation->req->base);
497 PAL_Free(operation);
498 }
499
500 #ifdef _PREFAST_
501 #pragma prefast (pop)
502 #endif /* _PREFAST_ */
503
504 /*
505 krisbash 1.1 Object that implements the MI Protocol Handler as an Interaction Interface
506 over the binary protocol.
507
508 Behavior:
509 - Post implementes different behaviour depending on the type of message
510 being posted
511 * For PostInstanceMsg stores the instance in a cache var, and if there is
512 previous cached instance not yet delivered will deliver that one first
513 (waiting if necessary).
514 * For PostIndicationMsg always delivers it to the client asynchronously.
515 * For PostResultMsg it will delivered it thru the proper callback and
516 set callingFinalResult to 1 to indicate final result already sent.
517 Also note that NoOpRsp is another case of inal result.
518 * PostSchemaMsg is treated the same as PostInstanceMsg with the same
519 cached var mechanism.
520 * SubscribeRes is just acked immediately as nothing is needed there
521 * All other message types are not expected
522 just passed the operation to tries to ClientRep::MessageCallback
523 if that fails it sends the Ack immediately
524 - Ack does nothing as there are no secondary messages to be sent to the
525 protocol
526 krisbash 1.1 - Post control notified when the connect has succeeded (or failed). If succeeded
527 the request corresponding to the operartion is send there.
528 - Cancel does nothing at this point.
529 - Close sends the final result if not being sent already
530 (as indicated by callingFinalResult set on Post)
531 if not it triggers a timeout that will close it
532 - Shutdown:
533 The InteractionProtocolHandler objects are shutdown/deleted thru the normal
534 Strand logic (once the interaction is closed both ways).
535 */
536 StrandFT InteractionProtocolHandler_Operation_Strand_FT =
537 {
538 InteractionProtocolHandler_Operation_Strand_Post,
539 InteractionProtocolHandler_Operation_Strand_PostControl,
540 InteractionProtocolHandler_Operation_Strand_Ack,
541 InteractionProtocolHandler_Operation_Strand_Cancel,
542 InteractionProtocolHandler_Operation_Strand_Close,
543 InteractionProtocolHandler_Operation_Strand_Finish,
544 NULL,
545 NULL,
546 NULL,
547 krisbash 1.1 NULL
548 };
549
550
551 /* ===================================================================================
552 * ===================================================================================
553 * ===================================================================================
554 * ===================================================================================
555 * ===================================================================================
556 * ===================================================================================
557 */
558
559 MI_Result MI_CALL InteractionProtocolHandler_Operation_Close(
560 _Inout_ MI_Operation *_operation)
561 {
562 InteractionProtocolHandler_Operation* operation = (InteractionProtocolHandler_Operation *)_operation->reserved2;
563 trace_InteractionProtocolHandler_Operation_Close(operation);
564
565 Strand_ScheduleClose(&operation->strand);
566
567 return MI_RESULT_OK;
568 krisbash 1.1 }
569
570 MI_Result MI_CALL InteractionProtocolHandler_Operation_Cancel(
571 _Inout_ MI_Operation *_operation,
572 MI_CancellationReason reason)
573 {
574 InteractionProtocolHandler_Operation* operation = (InteractionProtocolHandler_Operation *)_operation->reserved2;
575
576 if (!operation->callingFinalResult)
577 {
578 /*
579 * Send unsubscribe if and only if not received FinalResult;
580 * Cancellation is not implemented yet in protocol layer
581 * For subscribe operation, sending UnsubscribeReq to server,
582 * which will cleanup the subscribe operation;
583 * TODO Upon end to end cancellation implemented, following 'if'
584 * clause should be removed;
585 */
586 if (operation->req->base.tag == SubscribeReqTag)
587 {
588 UnsubscribeReq *req = UnsubscribeReq_New(operation->req->base.operationId, BinaryProtocolFlag);
589 krisbash 1.1 if (req)
590 {
591 trace_InteractionProtocolHandler_Operation_Cancel_PostUnsubscribeReq(operation);
592 Strand_SchedulePost(&operation->strand, &req->base.base);
593 }
594 else
595 {
596 trace_InteractionProtocolHandler_Operation_Cancel_OutOfMemory(operation);
597 }
598 }
599
600 trace_InteractionProtocolHandler_Operation_Cancel(operation);
601 Strand_ScheduleCancel(&operation->strand);
602 }
603 else
604 {
605 trace_InteractionProtocolHandler_Operation_CancelAfterFinal(operation);
606 }
607 return MI_RESULT_OK;
608 }
609
610 krisbash 1.1 MI_Result MI_CALL InteractionProtocolHandler_Operation_GetSession(
611 _In_ MI_Operation *_operation,
612 _Out_ MI_Session *session)
613 {
614 InteractionProtocolHandler_Operation *operation;
615 if (_operation)
616 {
617 operation = (InteractionProtocolHandler_Operation *)_operation->reserved2;
618 if (operation->parentSession)
619 {
620 memcpy(session, &operation->parentSession->myMiSession, sizeof(*session));
621 return MI_RESULT_OK;
622 }
623 else
624 return MI_RESULT_INVALID_PARAMETER;
625 }
626 else
627 return MI_RESULT_INVALID_PARAMETER;
628 }
629
630 const MI_OperationFT g_interactionProtocolHandler_OperationFT =
631 krisbash 1.1 {
632 InteractionProtocolHandler_Operation_Close,
633 InteractionProtocolHandler_Operation_Cancel,
634 InteractionProtocolHandler_Operation_GetSession,
635 NULL, /* GetInstance, only async supported in protocol handlers */
636 NULL, /* GetIndication, only async supported in protocol handlers */
637 NULL /* GetClass, only async supported in protocol handlers */
638 };
639
640 MI_Result MI_CALL InteractionProtocolHandler_Operation_Close_Error(
641 _Inout_ MI_Operation *operation)
642 {
643 return MI_RESULT_OK;
644 }
645
646 MI_Result MI_CALL InteractionProtocolHandler_Operation_Cancel_Error(
647 _Inout_ MI_Operation *operation,
648 MI_CancellationReason reason)
649 {
650 return MI_RESULT_OK;
651 }
652 krisbash 1.1
653 MI_Result MI_CALL InteractionProtocolHandler_Operation_GetSession_Error(
654 _In_ MI_Operation *operation,
655 _Out_ MI_Session *session)
656 {
657 if (session)
658 memset(session, 0, sizeof(*session));
659 return MI_RESULT_FAILED;
660 }
661
662
663 MI_Result MI_CALL InteractionProtocolHandler_Operation_GetInstance_Error(
664 _In_ MI_Operation *operation,
665 _Outptr_result_maybenull_ const MI_Instance **instance,
666 _Out_opt_ MI_Boolean *moreResults,
667 _Out_opt_ MI_Result *result,
668 _Outptr_opt_result_maybenull_z_ const MI_Char **errorMessage,
669 _Outptr_opt_result_maybenull_ const MI_Instance **completionDetails)
670 {
671 if (instance)
672 *instance = NULL;
673 krisbash 1.1 if (moreResults)
674 *moreResults = MI_FALSE;
675 if (result)
676 *result = MI_RESULT_FAILED;
677 if (errorMessage)
678 *errorMessage = NULL;
679 if (completionDetails)
680 *completionDetails = NULL;
681 return MI_RESULT_FAILED;
682 }
683 MI_Result MI_CALL InteractionProtocolHandler_Operation_GetIndication_Error(
684 _In_ MI_Operation *operation,
685 _Outptr_result_maybenull_ const MI_Instance **instance,
686 _Outptr_opt_result_maybenull_z_ const MI_Char **bookmark,
687 _Outptr_opt_result_maybenull_z_ const MI_Char **machineID,
688 _Out_opt_ MI_Boolean *moreResults,
689 _Out_opt_ MI_Result *result,
690 _Outptr_opt_result_maybenull_z_ const MI_Char **errorMessage,
691 _Outptr_opt_result_maybenull_ const MI_Instance **completionDetails)
692 {
693 if (instance)
694 krisbash 1.1 *instance = NULL;
695 if (bookmark)
696 *bookmark = NULL;
697 if (machineID)
698 *machineID = NULL;
699 if (moreResults)
700 *moreResults = MI_FALSE;
701 if (result)
702 *result = MI_RESULT_FAILED;
703 if (errorMessage)
704 *errorMessage = NULL;
705 if (completionDetails)
706 *completionDetails = NULL;
707 return MI_RESULT_FAILED;
708 }
709
710 MI_Result MI_CALL InteractionProtocolHandler_Operation_GetClass_Error(
711 _In_ MI_Operation *operation,
712 _Outptr_result_maybenull_ const MI_Class **classResult,
713 _Out_opt_ MI_Boolean *moreResults,
714 _Out_opt_ MI_Result *result,
715 krisbash 1.1 _Outptr_opt_result_maybenull_z_ const MI_Char **errorMessage,
716 _Outptr_opt_result_maybenull_ const MI_Instance **completionDetails)
717 {
718 if (classResult)
719 *classResult = NULL;
720 if (moreResults)
721 *moreResults = MI_FALSE;
722 if (result)
723 *result = MI_RESULT_FAILED;
724 if (errorMessage)
725 *errorMessage = NULL;
726 if (completionDetails)
727 *completionDetails = NULL;
728 return MI_RESULT_FAILED;
729 }
730
731
732 const MI_OperationFT g_interactionProtocolHandler_OperationFT_Dummy =
733 {
734 InteractionProtocolHandler_Operation_Close_Error,
735 InteractionProtocolHandler_Operation_Cancel_Error,
736 krisbash 1.1 InteractionProtocolHandler_Operation_GetSession_Error,
737 InteractionProtocolHandler_Operation_GetInstance_Error,
738 InteractionProtocolHandler_Operation_GetIndication_Error,
739 InteractionProtocolHandler_Operation_GetClass_Error
740 };
741
742
743
744 /* ===================================================================================
745 * ===================================================================================
746 * ===================================================================================
747 * ===================================================================================
748 * ===================================================================================
749 * ===================================================================================
750 */
751
752 void SessionCloseCompletion_Release( _In_ SessionCloseCompletion* sessionCloseCompletion )
753 {
754 ptrdiff_t count = Atomic_Dec( &sessionCloseCompletion->count );
755 if( 0 == count )
756 {
757 krisbash 1.1 SessionCloseCompletionCallback completionCallback;
758 SessionCloseCompletionContext completionContext;
759
760 // That means that this is the final release
761 // so we call the completion callback (if necessary)
762 // and delete the sessionCloseCompletion
763 completionCallback = sessionCloseCompletion->completionCallback;
764 completionContext = sessionCloseCompletion->completionContext;
765 trace_SessionCloseCompletion_Release_CompletionCallback(sessionCloseCompletion, (void *)completionCallback);
766 PAL_Free(sessionCloseCompletion);
767 if( completionCallback )
768 {
769 completionCallback(completionContext);
770 }
771 }
772 else
773 {
774 trace_SessionCloseCompletion_Release_Count(sessionCloseCompletion, (int)count );
775 }
776 }
777
778 krisbash 1.1 MI_Result MI_CALL InteractionProtocolHandler_Session_New(
779 _In_ MI_Application *miApplication,
780 _In_opt_z_ const MI_Char *protocol,
781 _In_opt_z_ const MI_Char *destination,
782 _In_opt_ MI_DestinationOptions *options,
783 _In_opt_ MI_SessionCallbacks *callbacks,
784 _Outptr_opt_result_maybenull_ MI_Instance **extendedError,
785 _Out_ MI_Session *_session)
786 {
787 InteractionProtocolHandler_Session *session = NULL;
788 MI_Result result = MI_RESULT_OK;
789
790 if (extendedError)
791 *extendedError = NULL;
792
793 memset(_session, 0, sizeof(*_session));
794
795 session = PAL_Calloc(1, sizeof(InteractionProtocolHandler_Session));
796 if (session == NULL)
797 {
798 result = MI_RESULT_SERVER_LIMITS_EXCEEDED;
799 krisbash 1.1 goto done;
800 }
801 session->sessionCloseCompletion = (SessionCloseCompletion*)PAL_Calloc(1, sizeof(SessionCloseCompletion));
802 if (session->sessionCloseCompletion == NULL)
803 {
804 result = MI_RESULT_SERVER_LIMITS_EXCEEDED;
805 goto done;
806 }
807 memset( session->sessionCloseCompletion, 0, sizeof(SessionCloseCompletion) );
808 session->sessionCloseCompletion->count = 1; // The session itself, released on session close
809
810 if (options)
811 {
812 result = MI_DestinationOptions_Clone(options, &session->destinationOptions);
813 if (result != MI_RESULT_OK)
814 goto done;
815 }
816
817 done:
818 if (result == MI_RESULT_OK)
819 {
820 krisbash 1.1 session->parentApplication = (InteractionProtocolHandler_Application*) miApplication->reserved2;
821 _session->ft = &g_interactionProtocolHandler_SessionFT;
822 _session->reserved1 = 0;
823 _session->reserved2 = (ptrdiff_t) session;
824 memcpy(&session->myMiSession, _session, sizeof(session->myMiSession));
825 }
826 else
827 {
828 _session->ft = &g_interactionProtocolHandler_SessionFT_Dummy;
829 _session->reserved1 = 0;
830 _session->reserved2 = 0;
831 if (session)
832 PAL_Free(session);
833
834 }
835
836 return result;
837 }
838
839 MI_Result MI_CALL InteractionProtocolHandler_Session_Close(
840 _Inout_ MI_Session *_session,
841 krisbash 1.1 _In_opt_ void *completionContext,
842 _In_opt_ void (MI_CALL *completionCallback)(_In_opt_ void *completionContext))
843 {
844 InteractionProtocolHandler_Session *session = (InteractionProtocolHandler_Session *)_session->reserved2;
845 if (session)
846 {
847 SessionCloseCompletion* sessionCloseCompletion = session->sessionCloseCompletion;
848 trace_InteractionProtocolHandler_Session_Close(session, (void *)completionCallback);
849
850 if (session->destinationOptions.ft)
851 {
852 MI_DestinationOptions_Delete(&session->destinationOptions);
853 }
854
855 DEBUG_ASSERT( NULL != sessionCloseCompletion );
856
857 sessionCloseCompletion->completionContext = completionContext;
858 sessionCloseCompletion->completionCallback = completionCallback;
859
860 PAL_Free(session);
861 SessionCloseCompletion_Release( sessionCloseCompletion );
862 krisbash 1.1 }
863 else if (completionCallback)
864 {
865 completionCallback(completionContext);
866 }
867
868 return MI_RESULT_OK;
869 }
870
871 MI_Result MI_CALL InteractionProtocolHandler_Session_GetApplication(
872 _In_ MI_Session *_session,
873 _Out_ MI_Application *application)
874 {
875 InteractionProtocolHandler_Session *session;
876 if (_session)
877 {
878 session = (InteractionProtocolHandler_Session*)_session->reserved2;
879 if (session)
880 {
881 memcpy(application, &session->parentApplication->myMiApplication, sizeof(*application));
882 return MI_RESULT_OK;
883 krisbash 1.1 }
884 else
885 return MI_RESULT_INVALID_PARAMETER;
886 }
887 else
888 {
889 return MI_RESULT_INVALID_PARAMETER;
890 }
891 }
892
893 static void* MI_CALL InteractionProtocolHandler_Protocol_RunThread(void* _operation)
894 {
895 InteractionProtocolHandler_Operation *operation = (InteractionProtocolHandler_Operation*) _operation;
896 MI_Result miResult;
897 ProtocolSocketAndBase* protocol = operation->protocol;
898 SessionCloseCompletion* sessionCloseCompletion = NULL;
899 ApplicationThread *operationThread = NULL;
900 InteractionProtocolHandler_Application *application = NULL;
901
902 trace_InteractionProtocolHandler_Protocol_RunThread();
903
904 krisbash 1.1 // Since for now we create this thread for each operation (instead of per each session)
905 // we need to release the refcount when finishing
906 sessionCloseCompletion = operation->parentSession->sessionCloseCompletion;
907
908 operationThread = operation->protocolRunThread;
909
910 application = operation->parentSession->parentApplication;
911
912 //printf("InteractionProtocolHandler_Protocol_RunThread starting - application=%p, thread=%p\n", application, operationThread);
913
914 miResult = Protocol_Run( &protocol->internalProtocolBase, TIME_NEVER);
915
916 trace_InteractionProtocolHandler_Protocol_RunThread_WithResult(miResult);
917 ProtocolSocketAndBase_ReadyToFinish( protocol );
918
919 if( sessionCloseCompletion )
920 {
921 SessionCloseCompletion_Release( sessionCloseCompletion );
922 }
923
924 InteractionProtocolHandler_Application_SafeCloseThread(application, operationThread);
925 krisbash 1.1 //printf("InteractionProtocolHandler_Protocol_RunThread - exiting, application=%p, thread=%p\n", application, operationThread);
926
927 return 0;
928 }
929
930 MI_Result InteractionProtocolHandler_Session_Connect(
931 InteractionProtocolHandler_Operation *operation,
932 const MI_Char *locatorIn,
933 const MI_Char * user,
934 const MI_Char * password)
935 {
936 MI_Result r = MI_RESULT_SERVER_LIMITS_EXCEEDED;
937 int res;
938 const char* locator_ = NULL;
939 char* user_ = NULL;
940 char* password_ = NULL;
941 SessionCloseCompletion* sessionCloseCompletion = NULL;
942
943 // Fail if already connected:
944 if (operation->protocol)
945 {
946 krisbash 1.1 trace_MI_SessionAlreadyConnected(operation);
947 r = MI_RESULT_FAILED;
948 goto done;
949 }
950
951 // Locator defaults to SOCKETFILE:
952 if (locatorIn == 0)
953 {
954 #ifdef CONFIG_POSIX
955 locator_ = OMI_GetPath(ID_SOCKETFILE);
956 #else
957 locator_ = "localhost:7777";
958 #endif
959 }
960 else
961 {
962 locator_ = _StringToStr(locatorIn);
963 if (!locator_)
964 {
965 trace_MI_OutOfMemoryInOperation(operation);
966 goto done;
967 krisbash 1.1 }
968 }
969
970 // Convert host to 'char' type:
971 if (user)
972 {
973 user_ = _StringToStr(user);
974 if (!user_)
975 {
976 trace_MI_OutOfMemoryInOperation(operation);
977 goto done;
978 }
979 }
980 if (password)
981 {
982 password_ = _StringToStr(password);
983 if (!password_)
984 {
985 trace_MI_OutOfMemoryInOperation(operation);
986 goto done;
987 }
988 krisbash 1.1 }
989
990 // Set connection state to pending.
991 operation->currentState = InteractionProtocolHandler_Operation_CurrentState_WaitingForConnect;
992
993 // this is the one that Opens the interaction (not the one that receives the open)
994 Strand_Init( STRAND_DEBUG(ProtocolHandler) &operation->strand, &InteractionProtocolHandler_Operation_Strand_FT, STRAND_FLAG_ENTERSTRAND, NULL );
995
996 // Establish connection with server:
997 {
998 InteractionOpenParams interactionParams;
999 ProtocolSocketAndBase* protocol = NULL;
1000
1001 Strand_OpenPrepare( &operation->strand, &interactionParams, NULL, NULL, MI_TRUE );
1002
1003 r = ProtocolSocketAndBase_New_Connector(
1004 &protocol,
1005 NULL,
1006 locator_,
1007 &interactionParams,
1008 user_,
1009 krisbash 1.1 password_);
1010
1011 if (r != MI_RESULT_OK)
1012 {
1013 trace_MI_SocketConnectorFailed(operation, r);
1014 goto done;
1015 }
1016
1017 operation->protocol = protocol;
1018
1019 if (operation->parentSession)
1020 {
1021 ptrdiff_t count;
1022
1023 sessionCloseCompletion = operation->parentSession->sessionCloseCompletion;
1024 // we just assign a non-zero value to flag indicating if we got here first
1025 count = Atomic_Inc( &sessionCloseCompletion->count );
1026 DEBUG_ASSERT( count > 0 );
1027 }
1028
1029 operation->protocolRunThread = PAL_Calloc(1, sizeof(ApplicationThread));
1030 krisbash 1.1 if (operation->protocolRunThread == NULL)
1031 {
1032 if (NULL != sessionCloseCompletion)
1033 {
1034 SessionCloseCompletion_Release(sessionCloseCompletion);
1035 }
1036 trace_MI_OutOfMemoryInOperation(operation);
1037 goto done;
1038 }
1039
1040 InteractionProtocolHandler_Application_IncrementThreadCount(operation->parentSession->parentApplication);
1041 //printf("InteractionProtocolHandler_Session_Connect - creating protocol thread, application=%p, thread=%p\n", operation->parentSession->parentApplication, operation->protocolRunThread);
1042 res = Thread_CreateJoinable(
1043 &operation->protocolRunThread->thread,
1044 (ThreadProc)InteractionProtocolHandler_Protocol_RunThread,
1045 NULL,
1046 operation);
1047
1048 if (res != 0)
1049 {
1050 trace_MI_FailedToStartRunThread(operation);
1051 krisbash 1.1
1052 InteractionProtocolHandler_Application_DecrementThreadCount(operation->parentSession->parentApplication);
1053 if( NULL != sessionCloseCompletion )
1054 {
1055 SessionCloseCompletion_Release( sessionCloseCompletion );
1056 }
1057 r = MI_RESULT_FAILED;
1058 goto done1;
1059 }
1060 }
1061
1062 done1:
1063 if (r)
1064 {
1065 PAL_Free(operation->protocolRunThread);
1066 operation->protocolRunThread = NULL;
1067 }
1068
1069 done:
1070 if (locatorIn && locator_)
1071 PAL_Free((void*)locator_);
1072 krisbash 1.1 if (user_)
1073 PAL_Free(user_);
1074 if (password_)
1075 PAL_Free(password_);
1076
1077 return r;
1078 }
1079
1080 MI_Result InteractionProtocolHandler_Session_CommonInstanceCode(
1081 _In_ MI_Session *_session,
1082 MI_Uint32 flags,
1083 _In_opt_ MI_OperationOptions *options,
1084 _In_opt_ MI_OperationCallbacks *callbacks,
1085 _In_opt_ RequestMsg *req,
1086 _Out_ MI_Operation *_operation)
1087 {
1088 MI_Result miResult = MI_RESULT_OK;
1089 InteractionProtocolHandler_Operation *operation = NULL;
1090 const MI_Char *user = NULL;
1091 MI_Char *password = NULL;
1092 MI_Uint32 passwordLength = 0;
1093 krisbash 1.1 InteractionProtocolHandler_Session *session = (InteractionProtocolHandler_Session *)_session->reserved2;
1094
1095 if (req == NULL)
1096 {
1097 /* Means caller failed to allocate this */
1098 miResult = MI_RESULT_SERVER_LIMITS_EXCEEDED;
1099 trace_MI_SessionFailed(session, miResult);
1100 goto done;
1101 }
1102
1103 DEBUG_ASSERT( Message_IsRequest( &req->base ) );
1104
1105 if (callbacks == NULL)
1106 {
1107 miResult = MI_RESULT_INVALID_PARAMETER;
1108 trace_MI_SessionFailed(session, miResult);
1109 goto done;
1110 }
1111
1112 memset(_operation, 0, sizeof(*_operation));
1113
1114 krisbash 1.1 //Create actual operation object that holds all the state of the operation
1115 {
1116 operation = PAL_Calloc(1, sizeof(InteractionProtocolHandler_Operation));
1117 if (operation == NULL)
1118 {
1119 trace_MI_OutOfMemoryInSession(session);
1120 miResult = MI_RESULT_SERVER_LIMITS_EXCEEDED;
1121 goto done;
1122 }
1123 }
1124
1125 {
1126 operation->parentSession = session;
1127
1128 if (session->destinationOptions.ft)
1129 {
1130 MI_UserCredentials credentials;
1131 const MI_Char *optionName;
1132 miResult = MI_DestinationOptions_GetCredentialsAt(&session->destinationOptions, 0, &optionName, &credentials, &flags);
1133 if ((miResult == MI_RESULT_NOT_FOUND) || (miResult == MI_RESULT_INVALID_PARAMETER))
1134 miResult = MI_RESULT_OK;
1135 krisbash 1.1 else if (miResult != MI_RESULT_OK)
1136 goto done;
1137 else
1138 {
1139 if ((Tcscmp(credentials.authenticationType, MI_AUTH_TYPE_CLIENT_CERTS) != 0) && (Tcscmp(credentials.authenticationType, MI_AUTH_TYPE_ISSUER_CERT) != 0))
1140 {
1141 user = credentials.credentials.usernamePassword.username;
1142 miResult = MI_DestinationOptions_GetCredentialsPasswordAt(&session->destinationOptions, 0, &optionName, NULL, 0, &passwordLength, &flags);
1143 if ((miResult != MI_RESULT_NOT_FOUND) && (miResult != MI_RESULT_SERVER_LIMITS_EXCEEDED))
1144 {
1145 password = PAL_Malloc(passwordLength * sizeof(MI_Char));
1146 if (password == NULL)
1147 {
1148 miResult = MI_RESULT_SERVER_LIMITS_EXCEEDED;
1149 trace_MI_SessionFailed(session, miResult);
1150 goto done;
1151 }
1152 miResult = MI_DestinationOptions_GetCredentialsPasswordAt(&session->destinationOptions, 0, &optionName, password, passwordLength, &passwordLength, &flags);
1153 if (miResult != MI_RESULT_OK)
1154 goto done;
1155 }
1156 krisbash 1.1 else if (miResult != MI_RESULT_OK)
1157 goto done;
1158 }
1159 }
1160 }
1161 }
1162
1163 if (options)
1164 {
1165 struct _GenericOptions_Handle *genericOptions = (struct _GenericOptions_Handle*) options;
1166
1167 if (genericOptions->genericOptions && genericOptions->genericOptions->optionsInstance)
1168 {
1169 miResult = InstanceToBatch(
1170 genericOptions->genericOptions->optionsInstance,
1171 NULL,
1172 NULL,
1173 req->base.batch,
1174 &req->packedOptionsPtr,
1175 &req->packedOptionsSize);
1176
1177 krisbash 1.1 if (miResult != MI_RESULT_OK)
1178 {
1179 trace_MI_InstanceToBatch_Failed(session, miResult);
1180 goto done;
1181 }
1182 req->options = genericOptions->genericOptions->optionsInstance;
1183 }
1184 }
1185 operation->asyncOperationCallbacks = *callbacks;
1186 _operation->ft = &g_interactionProtocolHandler_OperationFT;
1187 _operation->reserved2 = (ptrdiff_t) operation;
1188 operation->myMiOperation = *_operation;
1189 if (req->base.tag == SubscribeReqTag)
1190 {
1191 operation->operationType = InteractionProtocolHandler_Operation_OperationType_Indication;
1192 }
1193 else if (req->base.tag == GetClassReqTag)
1194 {
1195 operation->operationType = InteractionProtocolHandler_Operation_OperationType_Class;
1196 }
1197 else
1198 krisbash 1.1 {
1199 operation->operationType = InteractionProtocolHandler_Operation_OperationType_Instance;
1200 }
1201 operation->req = req;
1202
1203 /* Kick off protocol initialization */
1204 miResult = InteractionProtocolHandler_Session_Connect(operation, NULL, user, password);
1205 if (miResult != MI_RESULT_OK)
1206 {
1207 trace_MI_SessionConnectFailed(session, miResult);
1208 goto done;
1209 }
1210
1211 trace_InteractionProtocolHandler_SessionConnect_Passed();
1212
1213 /* Everything is asynchronous from this point onwards if we were successful */
1214
1215 done:
1216 if (password)
1217 {
1218 #if defined(_MSC_VER)
1219 krisbash 1.1 SecureZeroMemory(password, passwordLength * sizeof(MI_Char));
1220 #else
1221 memset(password, 0, passwordLength * sizeof(MI_Char));
1222 #endif
1223 PAL_Free(password);
1224 }
1225
1226 if (miResult != MI_RESULT_OK)
1227 {
1228 trace_MI_SessionFailed(session, miResult);
1229
1230 if (operation)
1231 {
1232 _Operation_SendFinalResult_Internal(operation);
1233 PAL_Free(operation);
1234 }
1235
1236 memset(_operation, 0, sizeof(_operation));
1237 _operation->ft = &g_interactionProtocolHandler_OperationFT_Dummy;
1238 }
1239
1240 krisbash 1.1 return miResult;
1241 }
1242
1243
1244 void MI_CALL InteractionProtocolHandler_Session_GetInstance(
1245 _In_ MI_Session *_session,
1246 MI_Uint32 flags,
1247 _In_opt_ MI_OperationOptions *options,
1248 _In_opt_z_ const MI_Char *namespaceName,
1249 _In_ const MI_Instance *inboundInstance,
1250 _In_opt_ MI_OperationCallbacks *callbacks,
1251 _Out_ MI_Operation *_operation)
1252 {
1253 MI_Result miResult = MI_RESULT_OK;
1254 GetInstanceReq *req = NULL;
1255
1256 memset(_operation, 0, sizeof(*_operation));
1257
1258
1259 // Create the request message:
1260 {
1261 krisbash 1.1 req = GetInstanceReq_New(_NextOperationId(), BinaryProtocolFlag);
1262 }
1263 // Set nameSpace:
1264 if (req && namespaceName)
1265 {
1266 req->nameSpace = Batch_Tcsdup(req->base.base.batch, namespaceName);
1267 if (!req->nameSpace)
1268 {
1269 GetInstanceReq_Release(req);
1270 req = NULL;
1271 }
1272 }
1273 // Pack the instance name into the message's batch.
1274 if (req)
1275 {
1276 miResult = InstanceToBatch(
1277 inboundInstance,
1278 NULL,
1279 NULL,
1280 req->base.base.batch,
1281 &req->packedInstanceNamePtr,
1282 krisbash 1.1 &req->packedInstanceNameSize);
1283
1284 if (miResult != MI_RESULT_OK)
1285 {
1286 GetInstanceReq_Release(req);
1287 req = NULL;
1288 }
1289 }
1290
1291 miResult = InteractionProtocolHandler_Session_CommonInstanceCode(_session, flags, options, callbacks, (RequestMsg*)req, _operation);
1292
1293 if ((miResult != MI_RESULT_OK) && req)
1294 {
1295 GetInstanceReq_Release(req);
1296 }
1297 }
1298
1299 void MI_CALL InteractionProtocolHandler_Session_ModifyInstance(
1300 _In_ MI_Session *_session,
1301 MI_Uint32 flags,
1302 _In_opt_ MI_OperationOptions *options,
1303 krisbash 1.1 _In_opt_z_ const MI_Char *namespaceName,
1304 _In_ const MI_Instance *inboundInstance,
1305 _In_opt_ MI_OperationCallbacks *callbacks,
1306 _Out_ MI_Operation *_operation)
1307 {
1308 MI_Result miResult = MI_RESULT_OK;
1309 ModifyInstanceReq *req = NULL;
1310
1311 memset(_operation, 0, sizeof(*_operation));
1312
1313
1314 // Create the request message:
1315 {
1316 req = ModifyInstanceReq_New(_NextOperationId(), BinaryProtocolFlag);
1317 }
1318 // Set nameSpace:
1319 if (req && namespaceName)
1320 {
1321 req->nameSpace = Batch_Tcsdup(req->base.base.batch, namespaceName);
1322 if (!req->nameSpace)
1323 {
1324 krisbash 1.1 ModifyInstanceReq_Release(req);
1325 req = NULL;
1326 }
1327 }
1328 // Pack the instance name into the message's batch.
1329 if (req)
1330 {
1331 miResult = InstanceToBatch(
1332 inboundInstance,
1333 NULL,
1334 NULL,
1335 req->base.base.batch,
1336 &req->packedInstancePtr,
1337 &req->packedInstanceSize);
1338
1339 if (miResult != MI_RESULT_OK)
1340 {
1341 ModifyInstanceReq_Release(req);
1342 req = NULL;
1343 }
1344 }
1345 krisbash 1.1
1346 miResult = InteractionProtocolHandler_Session_CommonInstanceCode(_session, flags, options, callbacks, (RequestMsg*)req, _operation);
1347
1348 if ((miResult != MI_RESULT_OK) && req)
1349 {
1350 ModifyInstanceReq_Release(req);
1351 }
1352 }
1353
1354 void MI_CALL InteractionProtocolHandler_Session_CreateInstance(
1355 _In_ MI_Session *_session,
1356 MI_Uint32 flags,
1357 _In_opt_ MI_OperationOptions *options,
1358 _In_opt_z_ const MI_Char *namespaceName,
1359 _In_ const MI_Instance *inboundInstance,
1360 _In_opt_ MI_OperationCallbacks *callbacks,
1361 _Out_ MI_Operation *_operation)
1362 {
1363 MI_Result miResult = MI_RESULT_OK;
1364 CreateInstanceReq *req = NULL;
1365
1366 krisbash 1.1 memset(_operation, 0, sizeof(*_operation));
1367
1368
1369 // Create the request message:
1370 {
1371 req = CreateInstanceReq_New(_NextOperationId(), BinaryProtocolFlag);
1372 }
1373 // Set nameSpace:
1374 if (req && namespaceName)
1375 {
1376 req->nameSpace = Batch_Tcsdup(req->base.base.batch, namespaceName);
1377 if (!req->nameSpace)
1378 {
1379 CreateInstanceReq_Release(req);
1380 req = NULL;
1381 }
1382 }
1383 // Pack the instance name into the message's batch.
1384 if (req)
1385 {
1386 miResult = InstanceToBatch(
1387 krisbash 1.1 inboundInstance,
1388 NULL,
1389 NULL,
1390 req->base.base.batch,
1391 &req->packedInstancePtr,
1392 &req->packedInstanceSize);
1393
1394 if (miResult != MI_RESULT_OK)
1395 {
1396 CreateInstanceReq_Release(req);
1397 req = NULL;
1398 }
1399 }
1400
1401 miResult = InteractionProtocolHandler_Session_CommonInstanceCode(_session, flags, options, callbacks, (RequestMsg*)req, _operation);
1402
1403 if ((miResult != MI_RESULT_OK) && req)
1404 {
1405 CreateInstanceReq_Release(req);
1406 }
1407 }
1408 krisbash 1.1
1409 void MI_CALL InteractionProtocolHandler_Session_DeleteInstance(
1410 _In_ MI_Session *_session,
1411 MI_Uint32 flags,
1412 _In_opt_ MI_OperationOptions *options,
1413 _In_opt_z_ const MI_Char *namespaceName,
1414 _In_ const MI_Instance *inboundInstance,
1415 _In_opt_ MI_OperationCallbacks *callbacks,
1416 _Out_ MI_Operation *_operation)
1417 {
1418 MI_Result miResult = MI_RESULT_OK;
1419 DeleteInstanceReq *req = NULL;
1420
1421 memset(_operation, 0, sizeof(*_operation));
1422
1423
1424 // Create the request message:
1425 {
1426 req = DeleteInstanceReq_New(_NextOperationId(), BinaryProtocolFlag);
1427 }
1428 // Set nameSpace:
1429 krisbash 1.1 if (req && namespaceName)
1430 {
1431 req->nameSpace = Batch_Tcsdup(req->base.base.batch, namespaceName);
1432 if (!req->nameSpace)
1433 {
1434 DeleteInstanceReq_Release(req);
1435 req = NULL;
1436 }
1437 }
1438 // Pack the instance name into the message's batch.
1439 if (req)
1440 {
1441 miResult = InstanceToBatch(
1442 inboundInstance,
1443 NULL,
1444 NULL,
1445 req->base.base.batch,
1446 &req->packedInstanceNamePtr,
1447 &req->packedInstanceNameSize);
1448
1449 if (miResult != MI_RESULT_OK)
1450 krisbash 1.1 {
1451 DeleteInstanceReq_Release(req);
1452 req = NULL;
1453 }
1454 }
1455
1456 miResult = InteractionProtocolHandler_Session_CommonInstanceCode(_session, flags, options, callbacks, (RequestMsg*)req, _operation);
1457
1458 if ((miResult != MI_RESULT_OK) && req)
1459 {
1460 DeleteInstanceReq_Release(req);
1461 }
1462 }
1463
1464 void MI_CALL InteractionProtocolHandler_Session_Invoke(
1465 _In_ MI_Session *_session,
1466 MI_Uint32 flags,
1467 _In_opt_ MI_OperationOptions *options,
1468 _In_opt_z_ const MI_Char *namespaceName,
1469 _In_opt_z_ const MI_Char *className,
1470 _In_z_ const MI_Char *methodName,
1471 krisbash 1.1 _In_opt_ const MI_Instance *inboundInstance,
1472 _In_opt_ const MI_Instance *inboundProperties,
1473 _In_opt_ MI_OperationCallbacks *callbacks,
1474 _Out_ MI_Operation *_operation)
1475 {
1476 MI_Result miResult = MI_RESULT_OK;
1477 InvokeReq *req = NULL;
1478
1479 memset(_operation, 0, sizeof(*_operation));
1480
1481
1482 // Create the request message:
1483 {
1484 req = InvokeReq_New(_NextOperationId(), BinaryProtocolFlag);
1485 }
1486 // Set nameSpace:
1487 if (req && namespaceName)
1488 {
1489 req->nameSpace = Batch_Tcsdup(req->base.base.batch, namespaceName);
1490 if (!req->nameSpace)
1491 {
1492 krisbash 1.1 InvokeReq_Release(req);
1493 req = NULL;
1494 }
1495 }
1496 // Set method name:
1497 if (req && methodName)
1498 {
1499 req->function = Batch_Tcsdup(req->base.base.batch, methodName);
1500 if (!req->function)
1501 {
1502 InvokeReq_Release(req);
1503 req = NULL;
1504 }
1505 }
1506 // Pack the instance into the message's batch.
1507 if (req && inboundInstance)
1508 {
1509 miResult = InstanceToBatch(
1510 inboundInstance,
1511 NULL,
1512 NULL,
1513 krisbash 1.1 req->base.base.batch,
1514 &req->packedInstancePtr,
1515 &req->packedInstanceSize);
1516
1517 if (miResult != MI_RESULT_OK)
1518 {
1519 InvokeReq_Release(req);
1520 req = NULL;
1521 }
1522 }
1523 else if (req && className)
1524 {
1525 req->className = Batch_Tcsdup(req->base.base.batch, className);
1526 if (!req->className)
1527 {
1528 InvokeReq_Release(req);
1529 req = NULL;
1530 }
1531 }
1532 if (req && inboundProperties)
1533 {
1534 krisbash 1.1 miResult = InstanceToBatch(
1535 inboundProperties,
1536 NULL,
1537 NULL,
1538 req->base.base.batch,
1539 &req->packedInstanceParamsPtr,
1540 &req->packedInstanceParamsSize);
1541
1542 if (miResult != MI_RESULT_OK)
1543 {
1544 InvokeReq_Release(req);
1545 req = NULL;
1546 }
1547 }
1548
1549 miResult = InteractionProtocolHandler_Session_CommonInstanceCode(_session, flags, options, callbacks, (RequestMsg*)req, _operation);
1550
1551 if ((miResult != MI_RESULT_OK) && req)
1552 {
1553 InvokeReq_Release(req);
1554 }
1555 krisbash 1.1 }
1556
1557 void MI_CALL InteractionProtocolHandler_Session_EnumerateInstances(
1558 _In_ MI_Session *_session,
1559 MI_Uint32 flags,
1560 _In_opt_ MI_OperationOptions *options,
1561 _In_opt_z_ const MI_Char *namespaceName,
1562 _In_opt_z_ const MI_Char *className,
1563 MI_Boolean keysOnly,
1564 _In_opt_ MI_OperationCallbacks *callbacks,
1565 _Out_ MI_Operation *_operation)
1566 {
1567 MI_Result miResult = MI_RESULT_OK;
1568 EnumerateInstancesReq *req = NULL;
1569
1570 memset(_operation, 0, sizeof(*_operation));
1571
1572
1573 // Create the request message:
1574 {
1575 req = EnumerateInstancesReq_New(_NextOperationId(), BinaryProtocolFlag);
1576 krisbash 1.1 }
1577
1578 // If no shallow flag, use deep inheritance.
1579 if (req && !(flags & MI_OPERATIONFLAGS_POLYMORPHISM_SHALLOW))
1580 {
1581 req->deepInheritance = MI_TRUE;
1582 }
1583
1584 // Set nameSpace:
1585 if (req && namespaceName)
1586 {
1587 req->nameSpace = Batch_Tcsdup(req->base.base.batch, namespaceName);
1588 if (!req->nameSpace)
1589 {
1590 EnumerateInstancesReq_Release(req);
1591 req = NULL;
1592 }
1593 }
1594 if (req && className)
1595 {
1596 req->className = Batch_Tcsdup(req->base.base.batch, className);
1597 krisbash 1.1 if (!req->className)
1598 {
1599 EnumerateInstancesReq_Release(req);
1600 req = NULL;
1601 }
1602 }
1603
1604 miResult = InteractionProtocolHandler_Session_CommonInstanceCode(_session, flags, options, callbacks, (RequestMsg*)req, _operation);
1605
1606 if ((miResult != MI_RESULT_OK) && req)
1607 {
1608 EnumerateInstancesReq_Release(req);
1609 }
1610 }
1611
1612 void MI_CALL InteractionProtocolHandler_Session_QueryInstances(
1613 _In_ MI_Session *_session,
1614 MI_Uint32 flags,
1615 _In_opt_ MI_OperationOptions *options,
1616 _In_opt_z_ const MI_Char *namespaceName,
1617 _In_opt_z_ const MI_Char *queryDialect,
1618 krisbash 1.1 _In_opt_z_ const MI_Char *queryExpression,
1619 _In_opt_ MI_OperationCallbacks *callbacks,
1620 _Out_ MI_Operation *_operation)
1621 {
1622 {
1623 MI_Result miResult = MI_RESULT_OK;
1624 EnumerateInstancesReq *req = NULL;
1625
1626 memset(_operation, 0, sizeof(*_operation));
1627
1628
1629 // Create the request message:
1630 {
1631 req = EnumerateInstancesReq_New(_NextOperationId(), BinaryProtocolFlag);
1632 }
1633 // Set nameSpace:
1634 if (req && namespaceName)
1635 {
1636 req->nameSpace = Batch_Tcsdup(req->base.base.batch, namespaceName);
1637 if (!req->nameSpace)
1638 {
1639 krisbash 1.1 EnumerateInstancesReq_Release(req);
1640 req = NULL;
1641 }
1642 }
1643 if (req && queryDialect)
1644 {
1645 req->queryLanguage = Batch_Tcsdup(req->base.base.batch, queryDialect);
1646 if (!req->queryLanguage)
1647 {
1648 EnumerateInstancesReq_Release(req);
1649 req = NULL;
1650 }
1651 }
1652 if (req && queryExpression)
1653 {
1654 req->queryExpression = Batch_Tcsdup(req->base.base.batch, queryExpression);
1655 if (!req->queryExpression)
1656 {
1657 EnumerateInstancesReq_Release(req);
1658 req = NULL;
1659 }
1660 krisbash 1.1 }
1661 // If no shallow flag, use deep inheritance.
1662 if (req && !(flags & MI_OPERATIONFLAGS_POLYMORPHISM_SHALLOW))
1663 {
1664 req->deepInheritance = MI_TRUE;
1665 }
1666
1667 miResult = InteractionProtocolHandler_Session_CommonInstanceCode(_session, flags, options, callbacks, (RequestMsg*)req, _operation);
1668
1669 if ((miResult != MI_RESULT_OK) && req)
1670 {
1671 EnumerateInstancesReq_Release(req);
1672 }
1673 }}
1674
1675 void MI_CALL InteractionProtocolHandler_Session_AssociatorInstances(
1676 _In_ MI_Session *_session,
1677 MI_Uint32 flags,
1678 _In_opt_ MI_OperationOptions *options,
1679 _In_opt_z_ const MI_Char *namespaceName,
1680 _In_ const MI_Instance *instanceKeys,
1681 krisbash 1.1 _In_opt_z_ const MI_Char *assocClass,
1682 _In_opt_z_ const MI_Char *resultClass,
1683 _In_opt_z_ const MI_Char *role,
1684 _In_opt_z_ const MI_Char *resultRole,
1685 MI_Boolean keysOnly,
1686 _In_opt_ MI_OperationCallbacks *callbacks,
1687 _Out_ MI_Operation *_operation)
1688 {
1689 MI_Result miResult = MI_RESULT_OK;
1690 AssociationsOfReq *req = NULL;
1691
1692 memset(_operation, 0, sizeof(*_operation));
1693
1694
1695 // Create the request message:
1696 {
1697 req = AssociationsOfReq_New(_NextOperationId(), BinaryProtocolFlag, AssociatorsOfReqTag);
1698 }
1699 // Set nameSpace:
1700 if (req && namespaceName)
1701 {
1702 krisbash 1.1 req->nameSpace = Batch_Tcsdup(req->base.base.batch, namespaceName);
1703 if (!req->nameSpace)
1704 {
1705 AssociationsOfReq_Release(req);
1706 req = NULL;
1707 }
1708 }
1709 if (req && assocClass)
1710 {
1711 req->assocClass = Batch_Tcsdup(req->base.base.batch, assocClass);
1712 if (!req->assocClass)
1713 {
1714 AssociationsOfReq_Release(req);
1715 req = NULL;
1716 }
1717 }
1718 if (req && resultClass)
1719 {
1720 req->resultClass = Batch_Tcsdup(req->base.base.batch, resultClass);
1721 if (!req->resultClass)
1722 {
1723 krisbash 1.1 AssociationsOfReq_Release(req);
1724 req = NULL;
1725 }
1726 }
1727 if (req && role)
1728 {
1729 req->role = Batch_Tcsdup(req->base.base.batch, role);
1730 if (!req->role)
1731 {
1732 AssociationsOfReq_Release(req);
1733 req = NULL;
1734 }
1735 }
1736 if (req && resultRole)
1737 {
1738 req->resultRole = Batch_Tcsdup(req->base.base.batch, resultRole);
1739 if (!req->resultRole)
1740 {
1741 AssociationsOfReq_Release(req);
1742 req = NULL;
1743 }
1744 krisbash 1.1 }
1745 // Pack the instance into the message's batch.
1746 if (req && instanceKeys)
1747 {
1748 miResult = InstanceToBatch(
1749 instanceKeys,
1750 NULL,
1751 NULL,
1752 req->base.base.batch,
1753 &req->packedInstancePtr,
1754 &req->packedInstanceSize);
1755
1756 if (miResult != MI_RESULT_OK)
1757 {
1758 AssociationsOfReq_Release(req);
1759 req = NULL;
1760 }
1761 }
1762
1763 miResult = InteractionProtocolHandler_Session_CommonInstanceCode(_session, flags, options, callbacks, (RequestMsg*)req, _operation);
1764
1765 krisbash 1.1 if ((miResult != MI_RESULT_OK) && req)
1766 {
1767 AssociationsOfReq_Release(req);
1768 }
1769 }
1770
1771 void MI_CALL InteractionProtocolHandler_Session_ReferenceInstances(
1772 _In_ MI_Session *_session,
1773 MI_Uint32 flags,
1774 _In_opt_ MI_OperationOptions *options,
1775 _In_opt_z_ const MI_Char *namespaceName,
1776 _In_ const MI_Instance *instanceKeys,
1777 _In_opt_z_ const MI_Char *resultClass,
1778 _In_opt_z_ const MI_Char *role,
1779 MI_Boolean keysOnly,
1780 _In_opt_ MI_OperationCallbacks *callbacks,
1781 _Out_ MI_Operation *_operation)
1782 {
1783 MI_Result miResult = MI_RESULT_OK;
1784 AssociationsOfReq *req = NULL;
1785
1786 krisbash 1.1 memset(_operation, 0, sizeof(*_operation));
1787
1788
1789 // Create the request message:
1790 {
1791 req = AssociationsOfReq_New(_NextOperationId(), BinaryProtocolFlag, ReferencesOfReqTag);
1792 }
1793 // Set nameSpace:
1794 if (req && namespaceName)
1795 {
1796 req->nameSpace = Batch_Tcsdup(req->base.base.batch, namespaceName);
1797 if (!req->nameSpace)
1798 {
1799 AssociationsOfReq_Release(req);
1800 req = NULL;
1801 }
1802 }
1803 if (req && resultClass)
1804 {
1805 req->resultClass = Batch_Tcsdup(req->base.base.batch, resultClass);
1806 if (!req->resultClass)
1807 krisbash 1.1 {
1808 AssociationsOfReq_Release(req);
1809 req = NULL;
1810 }
1811 }
1812 if (req && role)
1813 {
1814 req->role = Batch_Tcsdup(req->base.base.batch, role);
1815 if (!req->role)
1816 {
1817 AssociationsOfReq_Release(req);
1818 req = NULL;
1819 }
1820 }
1821 // Pack the instance into the message's batch.
1822 if (req && instanceKeys)
1823 {
1824 miResult = InstanceToBatch(
1825 instanceKeys,
1826 NULL,
1827 NULL,
1828 krisbash 1.1 req->base.base.batch,
1829 &req->packedInstancePtr,
1830 &req->packedInstanceSize);
1831
1832 if (miResult != MI_RESULT_OK)
1833 {
1834 AssociationsOfReq_Release(req);
1835 req = NULL;
1836 }
1837 }
1838
1839 miResult = InteractionProtocolHandler_Session_CommonInstanceCode(_session, flags, options, callbacks, (RequestMsg*)req, _operation);
1840
1841 if ((miResult != MI_RESULT_OK) && req)
1842 {
1843 AssociationsOfReq_Release(req);
1844 }
1845 }
1846
1847 void MI_CALL InteractionProtocolHandler_Session_Subscribe(
1848 _In_ MI_Session *_session,
1849 krisbash 1.1 MI_Uint32 flags,
1850 _In_opt_ MI_OperationOptions *options,
1851 _In_opt_z_ const MI_Char *namespaceName,
1852 _In_opt_z_ const MI_Char *queryDialect,
1853 _In_opt_z_ const MI_Char *queryExpression,
1854 _In_opt_ const MI_SubscriptionDeliveryOptions *deliverOptions,
1855 _In_opt_ MI_OperationCallbacks *callbacks,
1856 _Out_ MI_Operation *_operation)
1857 {
1858 MI_Result miResult = MI_RESULT_OK;
1859 SubscribeReq *req = NULL;
1860
1861 memset(_operation, 0, sizeof(*_operation));
1862
1863
1864 // Create the request message:
1865 {
1866 req = SubscribeReq_New(_NextOperationId(), BinaryProtocolFlag);
1867 }
1868 // Set nameSpace:
1869 if (req && namespaceName)
1870 krisbash 1.1 {
1871 req->nameSpace = Batch_Tcsdup(req->base.base.batch, namespaceName);
1872 if (!req->nameSpace)
1873 {
1874 SubscribeReq_Release(req);
1875 req = NULL;
1876 }
1877 }
1878 if (req && queryDialect)
1879 {
1880 req->language = Batch_Tcsdup(req->base.base.batch, queryDialect);
1881 if (!req->language)
1882 {
1883 SubscribeReq_Release(req);
1884 req = NULL;
1885 }
1886 }
1887 if (req && queryExpression)
1888 {
1889 req->filter = Batch_Tcsdup(req->base.base.batch, queryExpression);
1890 if (!req->filter)
1891 krisbash 1.1 {
1892 SubscribeReq_Release(req);
1893 req = NULL;
1894 }
1895 }
1896
1897 /* TODO: Attach options */
1898
1899 miResult = InteractionProtocolHandler_Session_CommonInstanceCode(_session, flags, options, callbacks, (RequestMsg*)req, _operation);
1900
1901 if ((miResult != MI_RESULT_OK) && req)
1902 {
1903 SubscribeReq_Release(req);
1904 }
1905 }
1906
1907 void MI_CALL InteractionProtocolHandler_Session_GetClass(
1908 _In_ MI_Session *_session,
1909 MI_Uint32 flags,
1910 _In_opt_ MI_OperationOptions *options,
1911 _In_opt_z_ const MI_Char *namespaceName,
1912 krisbash 1.1 _In_opt_z_ const MI_Char *className,
1913 _In_opt_ MI_OperationCallbacks *callbacks,
1914 _Out_ MI_Operation *_operation)
1915 {
1916 MI_Result miResult = MI_RESULT_OK;
1917 GetClassReq *req = NULL;
1918
1919 memset(_operation, 0, sizeof(*_operation));
1920
1921
1922 // Create the request message:
1923 {
1924 req = GetClassReq_New(_NextOperationId(), BinaryProtocolFlag);
1925 }
1926 // Set nameSpace:
1927 if (req && namespaceName)
1928 {
1929 req->nameSpace = Batch_Tcsdup(req->base.base.batch, namespaceName);
1930 if (!req->nameSpace)
1931 {
1932 GetClassReq_Release(req);
1933 krisbash 1.1 req = NULL;
1934 }
1935 }
1936 if (req && className)
1937 {
1938 req->className = Batch_Tcsdup(req->base.base.batch, className);
1939 if (!req->className)
1940 {
1941 GetClassReq_Release(req);
1942 req = NULL;
1943 }
1944 }
1945
1946 miResult = InteractionProtocolHandler_Session_CommonInstanceCode(_session, flags, options, callbacks, (RequestMsg*)req, _operation);
1947
1948 if ((miResult != MI_RESULT_OK) && req)
1949 {
1950 GetClassReq_Release(req);
1951 }
1952 }
1953
1954 krisbash 1.1 void MI_CALL InteractionProtocolHandler_Session_EnumerateClasses(
1955 _In_ MI_Session *session,
1956 MI_Uint32 flags,
1957 _In_opt_ MI_OperationOptions *options,
1958 _In_opt_z_ const MI_Char *namespaceName,
1959 _In_opt_z_ const MI_Char *className,
1960 MI_Boolean classNamesOnly,
1961 _In_opt_ MI_OperationCallbacks *callbacks,
1962 _Out_ MI_Operation *operation)
1963 {
1964 memset(operation, 0, sizeof(*operation));
1965 operation->ft = &g_interactionProtocolHandler_OperationFT;
1966 if (callbacks && callbacks->classResult)
1967 callbacks->classResult(operation, callbacks->callbackContext, NULL, MI_FALSE, MI_RESULT_NOT_SUPPORTED, NULL, NULL, InteractionProtocolHandler_Client_Ack_PostToInteraction);
1968 }
1969
1970 void MI_CALL InteractionProtocolHandler_Session_TestConnection(
1971 _In_ MI_Session *_session,
1972 MI_Uint32 flags,
1973 _In_opt_ MI_OperationCallbacks *callbacks,
1974 _Out_ MI_Operation *_operation
1975 krisbash 1.1 )
1976 {
1977
1978 MI_Result miResult = MI_RESULT_OK;
1979 NoOpReq *req = NULL;
1980
1981 memset(_operation, 0, sizeof(*_operation));
1982
1983
1984 // Create the request message:
1985 {
1986 req = NoOpReq_New(_NextOperationId());
1987 }
1988
1989 miResult = InteractionProtocolHandler_Session_CommonInstanceCode(_session, flags, NULL, callbacks, (RequestMsg*)req, _operation);
1990
1991 if ((miResult != MI_RESULT_OK) && req)
1992 {
1993 NoOpReq_Release(req);
1994 }
1995 }
1996 krisbash 1.1
1997
1998 const MI_SessionFT g_interactionProtocolHandler_SessionFT =
1999 {
2000 InteractionProtocolHandler_Session_Close,
2001 InteractionProtocolHandler_Session_GetApplication,
2002 InteractionProtocolHandler_Session_GetInstance,
2003 InteractionProtocolHandler_Session_ModifyInstance,
2004 InteractionProtocolHandler_Session_CreateInstance,
2005 InteractionProtocolHandler_Session_DeleteInstance,
2006 InteractionProtocolHandler_Session_Invoke,
2007 InteractionProtocolHandler_Session_EnumerateInstances,
2008 InteractionProtocolHandler_Session_QueryInstances,
2009 InteractionProtocolHandler_Session_AssociatorInstances,
2010 InteractionProtocolHandler_Session_ReferenceInstances,
2011 InteractionProtocolHandler_Session_Subscribe,
2012 InteractionProtocolHandler_Session_GetClass,
2013 InteractionProtocolHandler_Session_EnumerateClasses,
2014 InteractionProtocolHandler_Session_TestConnection
2015 };
2016
2017 krisbash 1.1 MI_Result MI_CALL InteractionProtocolHandler_Session_Close_Dummy(
2018 _Inout_ MI_Session *session,
2019 _In_opt_ void *completionContext,
2020 _In_opt_ void (MI_CALL *completionCallback)(_In_opt_ void *completionContext))
2021 {
2022 if (completionCallback)
2023 completionCallback(completionContext);
2024
2025 return MI_RESULT_OK;
2026 }
2027 const MI_SessionFT g_interactionProtocolHandler_SessionFT_Dummy =
2028 {
2029 InteractionProtocolHandler_Session_Close_Dummy
2030 };
2031
2032
2033 /* ===================================================================================
2034 * ===================================================================================
2035 * ===================================================================================
2036 * ===================================================================================
2037 * ===================================================================================
2038 krisbash 1.1 * ===================================================================================
2039 */
2040
2041 PAL_Uint32 THREAD_API InteractionProtocolHandler_ThreadShutdown(void *_application)
2042 {
2043 InteractionProtocolHandler_Application *application = (InteractionProtocolHandler_Application*) _application;
2044 ApplicationThread *nextThread;
2045 PAL_Uint32 returnValue;
2046 //printf("InteractionProtocolHandler_ThreadShutdown start - application = %p\n", application);
2047 do
2048 {
2049 ptrdiff_t notification = (ptrdiff_t) Atomic_Read((ptrdiff_t*) &application->listOfThreads);
2050 while (notification == 0)
2051 {
2052 CondLock_Wait((ptrdiff_t)application, (ptrdiff_t*) &application->listOfThreads, notification, CONDLOCK_DEFAULT_SPINCOUNT);
2053
2054 notification = (ptrdiff_t) application->listOfThreads;
2055 }
2056 //printf("InteractionProtocolHandler_ThreadShutdown Got something to do - application = %p\n", application);
2057
2058 do
2059 krisbash 1.1 {
2060 Lock_Acquire(&application->listOfThreadsLock);
2061
2062 nextThread = application->listOfThreads;
2063 if ((application->listOfThreads != NULL) && (application->listOfThreads != (ApplicationThread*)-1))
2064 {
2065 application->listOfThreads = nextThread->next;
2066 }
2067
2068 Lock_Release(&application->listOfThreadsLock);
2069
2070 if ((nextThread == NULL) || (nextThread == (ApplicationThread*)-1))
2071 {
2072 //printf("InteractionProtocolHandler_ThreadShutdown - Finished iteration, application=%p, nextThread=%p\n", application, nextThread);
2073 break;
2074 }
2075
2076 //printf("InteractionProtocolHandler_ThreadShutdown - shutting down thread, application=%p, thread=%p\n", application, nextThread);
2077 Thread_Join(&nextThread->thread, &returnValue);
2078 Thread_Destroy(&nextThread->thread);
2079 PAL_Free(nextThread);
2080 krisbash 1.1 InteractionProtocolHandler_Application_DecrementThreadCount(application);
2081 }
2082 while (1);
2083 }
2084 while (application->listOfThreads != (ApplicationThread*) -1);
2085
2086 //printf("InteractionProtocolHandler_ThreadShutdown shutdown - application = %p\n", application);
2087
2088 return 0;
2089 }
2090
2091 MI_Result MI_MAIN_CALL InteractionProtocolHandler_Application_Initialize(MI_Uint32 flags,
2092 _In_opt_z_ const MI_Char * applicationID,
2093 _Outptr_opt_result_maybenull_ MI_Instance **extendedError,
2094 _Out_ MI_Application *miApplication)
2095 {
2096 InteractionProtocolHandler_Application *application;
2097
2098 memset(miApplication, 0, sizeof(*miApplication));
2099
2100 application = PAL_Calloc(1, sizeof(InteractionProtocolHandler_Application));
2101 krisbash 1.1 if (application == 0)
2102 {
2103 return MI_RESULT_SERVER_LIMITS_EXCEEDED;
2104 }
2105
2106 if (applicationID)
2107 {
2108 application->applicationID = PAL_Tcsdup(applicationID);
2109 if (application->applicationID == NULL)
2110 {
2111 PAL_Free(application);
2112 return MI_RESULT_SERVER_LIMITS_EXCEEDED;
2113 }
2114 }
2115
2116 if (Thread_CreateJoinable(&application->safeShutdownThread, InteractionProtocolHandler_ThreadShutdown, NULL, application) != 0)
2117 {
2118 if (application->applicationID)
2119 PAL_Free(application->applicationID);
2120 PAL_Free(application);
2121 return MI_RESULT_SERVER_LIMITS_EXCEEDED;
2122 krisbash 1.1 }
2123
2124 miApplication->reserved2 = (ptrdiff_t) application;
2125 miApplication->ft = &g_interactionProtocolHandler_ApplicationFT;
2126 memcpy(&application->myMiApplication, miApplication, sizeof(application->myMiApplication));
2127 if (extendedError)
2128 *extendedError = NULL;
2129 return MI_RESULT_OK;
2130 }
2131
2132 MI_Result MI_CALL InteractionProtocolHandler_Application_Close(
2133 _Inout_ MI_Application *miApplication)
2134 {
2135 InteractionProtocolHandler_Application *application = (InteractionProtocolHandler_Application *)miApplication->reserved2;
2136 if (application)
2137 {
2138 PAL_Uint32 threadValue;
2139 ApplicationThread **lastThreadPtr = &application->listOfThreads;
2140 int didBroadcast = 0;
2141
2142 /* Wait for all other threads to shutdown. Possible some notification got missed */
2143 krisbash 1.1 while (Atomic_Read(&application->threadCount))
2144 {
2145 //printf("InteractionProtocolHandler_Application_Close - thread count is not zero - application = %p, threadcount=%p, first thread left=%p\n", application, (void*)Atomic_Read(&application->threadCount), (void*)application->listOfThreads);
2146 Sleep_Milliseconds(100);
2147 if (didBroadcast == 0)
2148 {
2149 /* Only broadcast the first time */
2150 CondLock_Broadcast((ptrdiff_t) application);
2151 didBroadcast = 1;
2152 }
2153 }
2154
2155 //printf("InteractionProtocolHandler_Application_Close - Notifying ThreadShutdown to finish - application = %p\n", application);
2156 Lock_Acquire(&application->listOfThreadsLock);
2157 while (*lastThreadPtr != 0)
2158 {
2159 lastThreadPtr = &(*lastThreadPtr)->next;
2160 }
2161 *lastThreadPtr = (ApplicationThread*) -1;
2162 Lock_Release(&application->listOfThreadsLock);
2163
2164 krisbash 1.1 CondLock_Broadcast((ptrdiff_t) application);
2165
2166 //printf("InteractionProtocolHandler_Application_Close - Closing down main shutdown thread - application = %p, threadcount=%p\n", application, (void*)Atomic_Read(&application->threadCount));
2167 Thread_Join(&application->safeShutdownThread, &threadValue);
2168 Thread_Destroy(&application->safeShutdownThread);
2169
2170 //printf("InteractionProtocolHandler_Application_Close - shutdown thread gone - application = %p, threadcount=%p\n", application, (void*)Atomic_Read(&application->threadCount));
2171
2172 if (application->applicationID)
2173 PAL_Free(application->applicationID);
2174 PAL_Free(application);
2175 }
2176 memset(miApplication, 0, sizeof(miApplication));
2177 return MI_RESULT_OK;
2178 }
2179
2180 MI_Result InteractionProtocolHandler_Application_IncrementThreadCount(
2181 _In_ InteractionProtocolHandler_Application *application)
2182 {
2183 //ptrdiff_t a =
2184 Atomic_Inc(&application->threadCount);
2185 krisbash 1.1 //printf("InteractionProtocolHandler_Application_IncrementThreadCount - application = %p, new count=%p\n", application, (void*)a);
2186 return MI_RESULT_OK;
2187 }
2188 MI_Result InteractionProtocolHandler_Application_DecrementThreadCount(
2189 _In_ InteractionProtocolHandler_Application *application)
2190 {
2191 //ptrdiff_t a =
2192 Atomic_Dec(&application->threadCount);
2193 //printf("InteractionProtocolHandler_Application_DecrementThreadCount - application = %p, new count=%p\n", application, (void*)a);
2194 return MI_RESULT_OK;
2195 }
2196 MI_Result InteractionProtocolHandler_Application_SafeCloseThread(
2197 _In_ InteractionProtocolHandler_Application *application,
2198 _In_ ApplicationThread *operationThread)
2199 {
2200 //printf("InteractionProtocolHandler_Application_SafeCloseThread - queueing up handle to close - application = %p, thread=%p\n", application, operationThread);
2201 Lock_Acquire(&application->listOfThreadsLock);
2202 operationThread->next = application->listOfThreads;
2203 application->listOfThreads = operationThread;
2204 Lock_Release(&application->listOfThreadsLock);
2205
2206 krisbash 1.1 CondLock_Broadcast((ptrdiff_t) application);
2207 return MI_RESULT_OK;
2208 }
2209
2210 MI_Result MI_CALL InteractionProtocolHandler_Application_NewDestinationOptions(
2211 _In_ MI_Application *miApplication,
2212 _Out_ MI_DestinationOptions *options)
2213 {
2214 return DestinationOptions_Create(miApplication, options);
2215 }
2216
2217 MI_Result MI_CALL InteractionProtocolHandler_Application_NewOperationOptions(
2218 _In_ MI_Application *miApplication,
2219 _In_ MI_Boolean customOptionsMustUnderstand,
2220 _Out_ MI_OperationOptions *options)
2221 {
2222 return OperationOptions_Create(miApplication, customOptionsMustUnderstand, options);
2223 }
2224
2225 MI_Result MI_CALL InteractionProtocolHandler_Application_NewSubscriptionDeliveryOptions(
2226 _In_ MI_Application *miApplication,
2227 krisbash 1.1 _In_ MI_SubscriptionDeliveryType deliveryType,
2228 _Out_ MI_SubscriptionDeliveryOptions *deliveryOptions)
2229 {
2230 return SubscriptionDeliveryOptions_Create(miApplication, deliveryType, deliveryOptions);
2231 }
2232
2233 _Success_(return == MI_RESULT_OK)
2234 MI_Result MI_CALL InteractionProtocolHandler_Application_NewHostedProvider(
2235 _In_ MI_Application *application,
2236 _In_z_ const MI_Char * namespaceName,
2237 _In_z_ const MI_Char * providerName,
2238 _In_ MI_MainFunction mi_Main,
2239 _Outptr_opt_result_maybenull_ MI_Instance **extendedError,
2240 _Out_ MI_HostedProvider *hostedProvider)
2241 {
2242 if ((application == NULL) || (application->ft == NULL) ||
2243 (application->reserved2 == 0) || (application->reserved1 != 1))
2244 {
2245 /* Probably already deleted or failed to initialize */
2246 return MI_RESULT_INVALID_PARAMETER;
2247 }
2248 krisbash 1.1
2249 return MI_RESULT_NOT_SUPPORTED;
2250 }
2251
2252
2253
2254 const MI_ApplicationFT g_interactionProtocolHandler_ApplicationFT =
2255 {
2256 InteractionProtocolHandler_Application_Close,
2257 InteractionProtocolHandler_Session_New,
2258 InteractionProtocolHandler_Application_NewHostedProvider,
2259 NULL, /* NewInstance, not needed in protocol handler */
2260 InteractionProtocolHandler_Application_NewDestinationOptions,
2261 InteractionProtocolHandler_Application_NewOperationOptions,
2262 InteractionProtocolHandler_Application_NewSubscriptionDeliveryOptions,
2263 NULL, /* NewSerializer, not needed in protocol handler */
2264 NULL, /* NewDeserializer, not needed in protocol handler */
2265 NULL /* NewInstanceFromClass, not needed in protocol handler */
2266 };
|