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

   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              };

ViewCVS 0.9.2