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

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

ViewCVS 0.9.2