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

   1 krisbash 1.1 /*============================================================================
   2               * Copyright (C) Microsoft Corporation, All rights reserved. 
   3               *============================================================================
   4               */
   5              
   6              #if defined (_MSC_VER)
   7              #include <nt.h>
   8              #include <ntrtl.h>
   9              #include <windef.h>
  10              #include <ntstatus.h>
  11              #include <winerror.h>
  12              #include <nturtl.h>
  13              #include <sddl.h>
  14              #include <windows.h>
  15              #else
  16              #include <base/user.h>
  17              #endif
  18              
  19              #include "miapi_common.h"
  20              #include "Application.h"
  21              #include "Session.h"
  22 krisbash 1.1 #include "Operation.h"
  23              #include "SafeHandle.h"
  24              #include "ChildList.h"
  25              #include "Options.h"
  26              #include <MI.h>
  27              #include <pal/lock.h>
  28              #include <pal/format.h>
  29              #include <base/log.h>
  30              
  31              #if defined(_MSC_VER)
  32              MI_Result WindowsError_To_MI_Result(DWORD winError) 
  33              { 
  34                  switch(winError)
  35                  {
  36                      case NO_ERROR:
  37                          return MI_RESULT_OK;
  38                      case ERROR_ACCESS_DENIED:
  39                          return MI_RESULT_ACCESS_DENIED;
  40                      case ERROR_OUTOFMEMORY:
  41                          return MI_RESULT_SERVER_LIMITS_EXCEEDED;
  42                      default:
  43 krisbash 1.1             return MI_RESULT_FAILED;
  44                  }
  45              }
  46              #define MAX_TOKEN_USER_SIZE sizeof(TOKEN_USER)+sizeof(SID)+(SID_MAX_SUB_AUTHORITIES*sizeof(DWORD))
  47              #endif
  48              
  49              /* Defined for real at bottom of file */
  50              extern const MI_SessionFT g_sessionFT; /* Main function table for session */
  51              extern const MI_SessionFT g_sessionFT_OOM; /* Special out of memory version */
  52              
  53              /* Real back-end MI_Session structure */
  54              typedef struct _SessionObject SessionObject;
  55              
  56              struct _SessionObject
  57              {
  58                  /* Linked list for child application sessions.  Includes clients session handle */
  59                  ChildListNode sessionNode;
  60              
  61                  MI_Application clientApplication;
  62                  ProtocolHandlerCacheItem *protocolHandlerItem;
  63                  MI_Session protocolHandlerSession;
  64 krisbash 1.1     MI_Session *clientSessionPtr;  /*Pointer for client session for logging purposes only */
  65                  MI_SessionCallbacks callbacks;
  66                  ChildList operationList;    /* List of child operations */
  67                  MI_DestinationOptions clientDestinationOptions;
  68              
  69              #if defined(_MSC_VER)
  70                  HANDLE clientSessionCreationToken; //duplicate of clients token.  All operations need to use the same token
  71                  BYTE _SIDArray[MAX_TOKEN_USER_SIZE];
  72                  TOKEN_USER *clientSessionCreationTokenSID;
  73              #else
  74                  uid_t uid;
  75                  gid_t gid; 
  76              
  77              #endif
  78              
  79                  /* MI_Session_Close data */
  80                  void *sessionCloseCallbackContext;
  81                  void (MI_CALL *sessionCloseCallback)(_In_opt_ void *completionContext) ;
  82                  volatile ptrdiff_t sessionCloseCallbackCalled;
  83              };
  84              
  85 krisbash 1.1 MI_Result Session_ImpersonateClientInternal(_In_ SessionObject *sessionObject, _Out_ MI_CLIENT_IMPERSONATION_TOKEN *originalImpersonation);
  86              
  87              /* CIM Extension callback pass-through for WriteMessage */
  88              void MI_CALL Session_WriteMessage_Callback(
  89                  _In_     MI_Application *application,
  90                  _In_opt_ void *callbackContext, 
  91                              MI_Uint32 channel,
  92                  _In_z_   const MI_Char *  message)
  93              {
  94                  SessionObject *sessionObject = (SessionObject*) callbackContext;
  95                  if (sessionObject->callbacks.writeMessage)
  96                  {
  97                      sessionObject->callbacks.writeMessage(&sessionObject->clientApplication, sessionObject->callbacks.callbackContext, channel, message);
  98                  }
  99              }
 100              
 101              /* CIM Extensions callback pass-through for WriteError */
 102              void MI_CALL Session_WriteError_Callback(
 103                  _In_     MI_Application *application,
 104                  _In_opt_ void *callbackContext, 
 105                  _In_ MI_Instance *instance)
 106 krisbash 1.1 {
 107                  SessionObject *sessionObject = (SessionObject*) callbackContext;
 108                  if (sessionObject->callbacks.writeError)
 109                  {
 110                      sessionObject->callbacks.writeError(&sessionObject->clientApplication, sessionObject->callbacks.callbackContext, instance);
 111                  }
 112              }
 113              
 114              /* When thunk handle ref count gets to zero means no one is referencing this object any more
 115               * so we can now delete the SessionObject
 116               */
 117              void Session_Destructor(
 118                  _In_ ThunkHandle *thunkHandle)
 119              {
 120                  SessionObject *sessionObject = (SessionObject *) thunkHandle->u.object;
 121                  thunkHandle->u.object = NULL;
 122                  //NitsAssert(sessionObject->operationList.childCount == 0, L"child operation count should be zero");
 123              
 124                  ChildList_DeInitialize(&sessionObject->operationList);
 125              
 126                  /* Unregister self from application */
 127 krisbash 1.1     Application_UnregisterSession(&sessionObject->clientApplication, &sessionObject->sessionNode);
 128              
 129                  /* Free our copy of the client-side destination options */
 130                  MI_DestinationOptions_Delete(&sessionObject->clientDestinationOptions);
 131              
 132              #if defined(_MSC_VER)
 133                  if (sessionObject->clientSessionCreationToken != INVALID_HANDLE_VALUE)
 134                  {
 135                      CloseHandle(sessionObject->clientSessionCreationToken);
 136                  }
 137              #endif
 138              
 139                  PAL_Free(sessionObject);
 140              
 141              }
 142              void Session_Destructor_NoAppUnRegister(
 143                  _In_ ThunkHandle *thunkHandle)
 144              {
 145                  SessionObject *sessionObject = (SessionObject *) thunkHandle->u.object;
 146                  //NitsAssert(sessionObject->operationList.childCount == 0, L"child operation count should be zero");
 147              
 148 krisbash 1.1     ChildList_DeInitialize(&sessionObject->operationList);
 149              
 150                  /* Note: No need to Unregister self from application as we didn't successfully register */
 151              
 152              
 153                  PAL_Free(sessionObject);
 154              
 155              }
 156              
 157              /* PUBLIC: Application calls this
 158               * This function needs to find the transport handler and load if not already loaded.
 159               * Then calls into the transport handler to itself to create their session.
 160               */
 161              _Success_(return == MI_RESULT_OK)
 162              MI_Result MI_CALL Session_Create(
 163                  _In_     MI_Application *application, 
 164                  _In_opt_z_ const MI_Char *protocol,
 165                  _In_opt_z_ const MI_Char *destination,
 166                  _In_opt_ MI_DestinationOptions *options,
 167                  _In_opt_ MI_SessionCallbacks *callbacks,
 168                  _Outptr_opt_result_maybenull_ MI_Instance **extendedError,
 169 krisbash 1.1     _Out_    MI_Session *session)
 170              {
 171                  SessionObject *sessionObject = NULL;
 172                  MI_DestinationOptions protocolHandlerDestinationOptions = MI_DESTINATIONOPTIONS_NULL;
 173                  MI_DestinationOptions tempDestinationOptions = MI_DESTINATIONOPTIONS_NULL;
 174                  GenericHandle *genericHandle = (GenericHandle *)session;
 175                  MI_SessionCallbacks myCallbacks;
 176                  MI_Result returnCode = MI_RESULT_OK;
 177                  MI_CLIENT_IMPERSONATION_TOKEN originalImpersonation = INVALID_HANDLE_VALUE;
 178              
 179                  trace_MISessionEnter(__FUNCTION__, application, protocol, destination, session);
 180              
 181                  /* initialize the client session in case we fail to fill it in */
 182                  if (session)
 183                  {
 184                      memset(session, 0, sizeof(MI_Session));
 185                  }
 186                  if (extendedError)
 187                  {
 188                      *extendedError = NULL;
 189                  }
 190 krisbash 1.1 
 191                  if ((application == NULL) || (session == NULL))
 192                  {
 193                      return MI_RESULT_INVALID_PARAMETER;
 194                  }
 195              
 196                  /* Allocate our real back-end session */
 197                  sessionObject = (SessionObject *) PAL_Malloc(sizeof(SessionObject));
 198                  if (sessionObject == NULL)
 199                  {
 200                      session->ft = &g_sessionFT_OOM;
 201                      return MI_RESULT_FAILED;
 202                  }
 203                  memset(sessionObject, 0, sizeof(SessionObject));
 204              #if defined(_MSC_VER)
 205                  sessionObject->clientSessionCreationToken = INVALID_HANDLE_VALUE;
 206                  sessionObject->clientSessionCreationTokenSID = (TOKEN_USER*) sessionObject->_SIDArray;
 207              #endif
 208              
 209                  returnCode = ChildList_Initialize(&sessionObject->operationList);
 210                  if (returnCode != MI_RESULT_OK)
 211 krisbash 1.1     {
 212                      PAL_Free(sessionObject);
 213                      return returnCode;
 214                  }
 215              
 216                  /* Get a safe-handle */
 217                  if (Application_NewGenericHandle(application, genericHandle) != MI_RESULT_OK)
 218                  {
 219                      ChildList_DeInitialize(&sessionObject->operationList);
 220                      PAL_Free(sessionObject);
 221                      session->ft = &g_sessionFT_OOM;
 222                      return MI_RESULT_FAILED;
 223                  }
 224              
 225                  /* Set up links within thunk handle */
 226                  sessionObject->clientApplication = *application;
 227                  genericHandle->thunkHandle->u.object = sessionObject;
 228              
 229              
 230                  /* Copy callbacks */
 231                  if (callbacks)
 232 krisbash 1.1     {
 233                      sessionObject->callbacks = *callbacks;
 234                  }
 235              
 236                  /* Set up protocol handlers callbacks to call back into us */
 237                  memset(&myCallbacks, 0, sizeof(myCallbacks));
 238                  myCallbacks.callbackContext = sessionObject;
 239                  myCallbacks.writeMessage = Session_WriteMessage_Callback;
 240                  myCallbacks.writeError = Session_WriteError_Callback;
 241              
 242                  /* copy the clients token.  This is the token that all operations validate against */
 243              #if defined(_MSC_VER)
 244                  {
 245                      DWORD windowsError = ERROR_SUCCESS;
 246                      MI_CLIENT_IMPERSONATION_TOKEN currentToken = INVALID_HANDLE_VALUE;
 247                      BOOL bRet = OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE|TOKEN_READ|TOKEN_DUPLICATE, TRUE, &currentToken) ;
 248                      if (bRet == FALSE)
 249                      {
 250                          /*Not impersonating or out of memory*/
 251                          windowsError = GetLastError();
 252                          if (windowsError == ERROR_NO_TOKEN)
 253 krisbash 1.1             {
 254                              /*OK, so no token on thread so try process token instead*/
 255                              bRet = ImpersonateSelf(SecurityImpersonation);
 256                              if (bRet == FALSE)
 257                              {
 258                                  /* failed */
 259                                  windowsError = GetLastError();
 260                              }
 261                              else
 262                              {
 263                                  bRet = OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE|TOKEN_READ|TOKEN_DUPLICATE, TRUE, &currentToken) ;
 264                                  if (bRet == FALSE)
 265                                  {
 266                                      /* failed */
 267                                      windowsError = GetLastError();
 268                                  }
 269                                  else
 270                                  {
 271                                      //Now got the impersonated process token
 272                                  }
 273                                  RevertToSelf();
 274 krisbash 1.1                 }
 275                          }
 276                          else
 277                          {
 278                              /*Failed, either out of memory or anonymous token*/
 279                          }
 280                      }
 281                      else
 282                      {
 283                          /*Using impersonation token*/
 284                      }
 285              
 286                      if (bRet == TRUE)
 287                      {
 288                          //Copy off the token for later validation and impersonation use
 289                          sessionObject->clientSessionCreationToken = currentToken;
 290                      }
 291                      else
 292                      {
 293                          ThunkHandle_Shutdown(genericHandle->thunkHandle, NULL);
 294                          ChildList_DeInitialize(&sessionObject->operationList);
 295 krisbash 1.1             PAL_Free(sessionObject);
 296                          session->reserved2 = 0;
 297                          session->ft = &g_sessionFT_OOM;
 298                          return WindowsError_To_MI_Result(windowsError);
 299                      }
 300                  }
 301              
 302                  {
 303                      DWORD windowsError;
 304                      DWORD tokenUserSizeUsed;
 305                      if (!GetTokenInformation(sessionObject->clientSessionCreationToken,TokenUser,sessionObject->clientSessionCreationTokenSID, MAX_TOKEN_USER_SIZE, &tokenUserSizeUsed))
 306                      {
 307                          ThunkHandle_Shutdown(genericHandle->thunkHandle, NULL);
 308                          ChildList_DeInitialize(&sessionObject->operationList);
 309                          CloseHandle(sessionObject->clientSessionCreationToken);
 310                          PAL_Free(sessionObject);
 311                          session->reserved2 = 0;
 312                          session->ft = &g_sessionFT_OOM;
 313                          return MI_RESULT_FAILED;
 314                      }
 315                  }
 316 krisbash 1.1 #else
 317                  sessionObject->uid = getuid();
 318                  sessionObject->gid = getgid();
 319              #endif
 320              
 321                  /* Register session with application */
 322                  returnCode = Application_RegisterSession(application, &sessionObject->sessionNode);
 323                  if (returnCode != MI_RESULT_OK)
 324                  {
 325                      ThunkHandle_Shutdown(genericHandle->thunkHandle, NULL);
 326                      ChildList_DeInitialize(&sessionObject->operationList);
 327              #if defined(_MSC_VER)
 328                      CloseHandle(sessionObject->clientSessionCreationToken);
 329              #endif
 330                      PAL_Free(sessionObject);
 331                      session->reserved2 = 0;
 332                      session->ft = &g_sessionFT_OOM;
 333                      return returnCode;
 334                  }
 335              
 336                  returnCode = Session_ImpersonateClientInternal(sessionObject, &originalImpersonation);
 337 krisbash 1.1     if (returnCode != MI_RESULT_OK)
 338                  {
 339                      Application_UnregisterSession(application, &sessionObject->sessionNode);
 340                      ThunkHandle_Shutdown(genericHandle->thunkHandle, NULL);
 341                      ChildList_DeInitialize(&sessionObject->operationList);
 342              #if defined(_MSC_VER)
 343                      CloseHandle(sessionObject->clientSessionCreationToken);
 344              #endif
 345                      PAL_Free(sessionObject);
 346                      session->reserved2 = 0;
 347                      session->ft = &g_sessionFT_OOM;
 348                      return returnCode;
 349                  }
 350              
 351                  /* select transport & load it */
 352                  returnCode = Application_GetProtocolHandler(application, destination, protocol, &sessionObject->protocolHandlerItem);
 353                  if (returnCode != MI_RESULT_OK)
 354                  {
 355                      if (Session_RevertImpersonation(originalImpersonation) != MI_RESULT_OK)
 356                      {
 357                          TerminateProcess(GetCurrentProcess(), -1);
 358 krisbash 1.1         }
 359                      Application_UnregisterSession(application, &sessionObject->sessionNode);
 360                      ThunkHandle_Shutdown(genericHandle->thunkHandle, NULL);
 361                      ChildList_DeInitialize(&sessionObject->operationList);
 362              #if defined(_MSC_VER)
 363                      CloseHandle(sessionObject->clientSessionCreationToken);
 364              #endif
 365                      PAL_Free(sessionObject);
 366                      session->reserved2 = 0;
 367                      session->ft = &g_sessionFT_OOM;
 368                      return returnCode;
 369                  }
 370              
 371                  /* create a DestinationOptions if not given */
 372                  if (!options)
 373                  {
 374                      returnCode = MI_Application_NewDestinationOptions(application, &tempDestinationOptions);
 375                      if (returnCode == MI_RESULT_OK)
 376                      {
 377                          options = &tempDestinationOptions;
 378                      }
 379 krisbash 1.1     }
 380              
 381                  if (returnCode == MI_RESULT_OK)
 382                  {
 383                      /* duplicate the client options so we can use them to merge with operation options */
 384                      DestinationOptions_Duplicate(options, &sessionObject->clientDestinationOptions);
 385              
 386                      /* Create a protocol handler version to use now */
 387                      returnCode = MI_Application_NewDestinationOptions(&sessionObject->protocolHandlerItem->application, &protocolHandlerDestinationOptions);
 388                      if (returnCode == MI_RESULT_OK)
 389                      {
 390                          returnCode = DestinationOptions_MigrateOptions(options, &protocolHandlerDestinationOptions, sessionObject->protocolHandlerItem->name != NULL? sessionObject->protocolHandlerItem->name : MI_T(""), extendedError);
 391                          if (returnCode != MI_RESULT_OK)
 392                          {
 393                              MI_DestinationOptions_Delete(&protocolHandlerDestinationOptions);
 394                          }
 395                      }
 396                  }
 397              
 398                  if (returnCode != MI_RESULT_OK)
 399                  {
 400 krisbash 1.1         if (tempDestinationOptions.ft != NULL)
 401                      {
 402                          MI_DestinationOptions_Delete(&tempDestinationOptions);
 403                      }
 404                      if (Session_RevertImpersonation(originalImpersonation) != MI_RESULT_OK)
 405                      {
 406                          TerminateProcess(GetCurrentProcess(), -1);
 407                      }
 408                      Application_UnregisterSession(application, &sessionObject->sessionNode);
 409                      ThunkHandle_Shutdown(genericHandle->thunkHandle, NULL);
 410                      ChildList_DeInitialize(&sessionObject->operationList);
 411                      MI_DestinationOptions_Delete(&sessionObject->clientDestinationOptions);
 412              #if defined(_MSC_VER)
 413                      CloseHandle(sessionObject->clientSessionCreationToken);
 414              #endif
 415                      PAL_Free(sessionObject);
 416                      session->reserved2 = 0;
 417                      session->ft = &g_sessionFT_OOM;
 418                      return returnCode;
 419                  }
 420              
 421 krisbash 1.1     /* Copy client application handle */
 422                  sessionObject->clientApplication = *application;
 423              
 424                  returnCode = sessionObject->protocolHandlerItem->application.ft->NewSession(&sessionObject->protocolHandlerItem->application, protocol, destination, &protocolHandlerDestinationOptions, &myCallbacks, extendedError, &sessionObject->protocolHandlerSession);
 425                  if (returnCode != MI_RESULT_OK)
 426                  {
 427                      if (tempDestinationOptions.ft != NULL)
 428                      {
 429                          MI_DestinationOptions_Delete(&tempDestinationOptions);
 430                      }
 431                      MI_DestinationOptions_Delete(&protocolHandlerDestinationOptions);
 432                      ThunkHandle_Shutdown(genericHandle->thunkHandle, Session_Destructor);
 433                      session->reserved2 = 0;
 434                      session->ft = &g_sessionFT_OOM;
 435                      if (Session_RevertImpersonation(originalImpersonation) != MI_RESULT_OK)
 436                      {
 437                          TerminateProcess(GetCurrentProcess(), -1);
 438                      }
 439                      return returnCode;
 440                  }
 441              
 442 krisbash 1.1     if (tempDestinationOptions.ft != NULL)
 443                  {
 444                      MI_DestinationOptions_Delete(&tempDestinationOptions);
 445                  }
 446              
 447                  MI_DestinationOptions_Delete(&protocolHandlerDestinationOptions);
 448              
 449                  /* Fix up clients function table to point to us*/
 450                  session->ft = &g_sessionFT;
 451              
 452                  sessionObject->clientSessionPtr = session;  /*for debug logging only*/
 453              
 454                  /* Copy client handle */
 455                  sessionObject->sessionNode.clientHandle = *(GenericHandle*)session;
 456              
 457                  trace_MIClient_SessionCreate(application, session, sessionObject);
 458              
 459                  if (Session_RevertImpersonation(originalImpersonation) != MI_RESULT_OK)
 460                  {
 461                      TerminateProcess(GetCurrentProcess(), -1);
 462                  }
 463 krisbash 1.1 
 464                  return returnCode;
 465              }
 466              
 467              _Success_(return == MI_RESULT_OK)
 468              MI_Result Session_RegisterOperation(_Inout_ MI_Session *session, _Inout_ ChildListNode *operation)
 469              {
 470                  GenericHandle *genericHandle = (GenericHandle *)session;
 471                  ThunkHandle *thunkHandle = NULL;
 472                  MI_Result errorReturn = MI_RESULT_OK;
 473              
 474                  ThunkHandle_FromGeneric(genericHandle, &thunkHandle);
 475                  if (thunkHandle)
 476                  {
 477                      SessionObject *sessionObject = (SessionObject*) thunkHandle->u.object;
 478                      errorReturn = ChildList_AddNode(&sessionObject->operationList, operation);
 479                      ThunkHandle_Release(thunkHandle);
 480                  }
 481                  else
 482                  {
 483                      errorReturn = MI_RESULT_FAILED;
 484 krisbash 1.1     }
 485              
 486                  return errorReturn;
 487              }
 488              
 489              _Success_(return == MI_RESULT_OK)
 490              MI_Result Session_UnregisterOperation(_Inout_ ThunkHandle *thunkHandle, _Inout_ ChildListNode *operation)
 491              {
 492                  SessionObject *sessionObject = (SessionObject*) thunkHandle->u.object;
 493                  ChildList_RemoveNode(&sessionObject->operationList, operation);
 494              
 495                  return MI_RESULT_OK;
 496              }
 497              
 498              
 499              /* Callback from protocol handler that Close has competed.  It is 
 500               * safe for us to finish closing things down now and then callback
 501               * to the client.
 502               */
 503              void MI_CALL Session_CloseCallback(_In_ void *completionContext)
 504              {
 505 krisbash 1.1     ThunkHandle *thunkHandle = (ThunkHandle*) completionContext;
 506                  SessionObject *sessionObject = (SessionObject*) thunkHandle->u.object;
 507              
 508                  /* Final callback */
 509                  if (sessionObject->sessionCloseCallback != NULL)
 510                  {
 511                      MI_CLIENT_IMPERSONATION_TOKEN currentImpersonationToken;
 512                      MI_Result impersonationResult = Session_ImpersonateClientInternal(sessionObject, &currentImpersonationToken);
 513              
 514                      if (impersonationResult == MI_RESULT_OK)
 515                      {
 516                          /* Client was async, so callback */
 517                          sessionObject->sessionCloseCallback(sessionObject->sessionCloseCallbackContext);
 518              
 519                          trace_MIClient_SessionCloseCompleted(sessionObject->clientSessionPtr, sessionObject);
 520              
 521                          if (Session_RevertImpersonation(currentImpersonationToken) != MI_RESULT_OK)
 522                          {
 523                              TerminateProcess(GetCurrentProcess(), -1);
 524                          }
 525                      }
 526 krisbash 1.1         /* Shutdown was holding open refcount until callback was called */
 527                      ThunkHandle_Release(thunkHandle);
 528                  }
 529                  else
 530                  {
 531                      /* Client was synchronous, so signal waiting thread */
 532                      sessionObject->sessionCloseCallbackCalled = 1;
 533                      CondLock_Broadcast((ptrdiff_t)sessionObject);
 534                  }
 535              }
 536              
 537              /* Shutdown of all child operations was successful so now
 538               * we need to call into the protocol handler to tell it 
 539               * to shutdown
 540               */
 541              void Session_AllOperationsShutdown(void *context)
 542              {
 543                  MI_CLIENT_IMPERSONATION_TOKEN originalImpersonation = INVALID_HANDLE_VALUE;
 544                  MI_Result miResult;
 545                  ThunkHandle *sessionThunk = (ThunkHandle*) context;
 546                  SessionObject *sessionObject = (SessionObject*) sessionThunk->u.object;
 547 krisbash 1.1     ProtocolHandlerCacheItem *protocolHandlerItem = sessionObject->protocolHandlerItem;
 548                  /* Call into protocol handler to initiate shutdown */
 549                  ProtocolHandlerCache_IncrementApiCount(protocolHandlerItem);
 550                  
 551                  miResult = Session_ImpersonateClientInternal(sessionObject, &originalImpersonation);
 552                  //If it is failed it is going to have to be best effort and hope it works!
 553                  sessionObject->protocolHandlerSession.ft->Close(&sessionObject->protocolHandlerSession, sessionThunk, Session_CloseCallback);
 554              
 555                  if ((miResult == MI_RESULT_OK) && (Session_RevertImpersonation(originalImpersonation) != MI_RESULT_OK))
 556                  {
 557                      TerminateProcess(GetCurrentProcess(), -1);
 558                  }
 559              
 560                  ProtocolHandlerCache_DecrementApiCount(protocolHandlerItem);
 561              
 562                  /* Close is async so do nothing else after this */
 563              }
 564              
 565              /* Trigger cancellation of all operations */
 566              void Session_CancelAllOperations(_Inout_ MI_Session *session)
 567              {
 568 krisbash 1.1     ThunkHandle *thunkHandle;
 569                  SessionObject *sessionObject;
 570              
 571                  ThunkHandle_FromGeneric((GenericHandle*)session, &thunkHandle);
 572                  if (thunkHandle == NULL)
 573                  {
 574                      /* Failed means version was wrong or object was shutdown */
 575                      return;
 576                  }
 577              
 578                  sessionObject = (SessionObject*) thunkHandle->u.object;
 579              
 580                  {
 581                      ChildListOutstandingHandles _smallBuffer[100];
 582                      ChildListOutstandingHandles* outstandingOperations = _smallBuffer;
 583                      ptrdiff_t outstandingOperationSize = sizeof(_smallBuffer)/sizeof(_smallBuffer[0]);
 584                      ptrdiff_t outstandingOperationCount;
 585              
 586                      int r = ChildList_Shutdown(&sessionObject->operationList);
 587                      if (r)
 588                      {
 589 krisbash 1.1             r = ChildList_GetCurrentList(&sessionObject->operationList, outstandingOperations, outstandingOperationSize, &outstandingOperationCount);
 590                          if (r == 0 && outstandingOperationCount > outstandingOperationSize)
 591                          {
 592                              outstandingOperations = (ChildListOutstandingHandles*) PAL_Malloc(outstandingOperationCount*sizeof(ChildListOutstandingHandles));
 593                              if (outstandingOperations == NULL)
 594                              {
 595                                  //TSASSERT(0, L"ignored memory allocation on purpose", TLINE);
 596                                  //Note that we cannot cancel the operations.  
 597                                  //It is completely up to the client to close all operations in this case and it will cause it to not respond if they do not
 598                              }
 599                              else
 600                              {
 601                                  outstandingOperationSize = outstandingOperationCount;
 602                                  r = ChildList_GetCurrentList(&sessionObject->operationList, outstandingOperations, outstandingOperationSize, &outstandingOperationCount);
 603                              }
 604                          }
 605              
 606                          /* Cancel all child operations */
 607                          if (r)
 608                          {
 609                  #ifdef _PREFAST_
 610 krisbash 1.1     //famous last words, but I am pretty sure this code is not an overflow. outstandingOperationCount has how many items are in it and it will never be more than 
 611                  //outstandingOperationSize if r is non-zero
 612                   #pragma prefast(push)
 613                   #pragma prefast(disable:26015) 
 614                  #endif
 615                              while (outstandingOperationCount)
 616                              {
 617                                  MI_Operation *operation = (MI_Operation*)&outstandingOperations[outstandingOperationCount-1].clientHandle;
 618                          
 619                                  /* Mode to next one as cancel may cause current operation to get deleted */
 620                                  outstandingOperationCount--;
 621              
 622                                  MI_Operation_Cancel(operation, MI_REASON_NONE);
 623                              }
 624                  #ifdef _PREFAST_
 625                   #pragma prefast(pop)
 626                  #endif
 627                          }
 628                          if (outstandingOperations != _smallBuffer)
 629                          {
 630                              PAL_Free(outstandingOperations);
 631 krisbash 1.1             }
 632                      }
 633                  }
 634                  ThunkHandle_Release(thunkHandle);
 635              }
 636              
 637              /* Client API MI_Session_Close method.
 638               */
 639              _Success_(return == MI_RESULT_OK)
 640              MI_Result MI_CALL Session_Close(
 641                  _In_     MI_Session *session,
 642                  _In_opt_ void *completionContext,
 643                  _In_opt_ void (MI_CALL *completionCallback)(_In_opt_ void *completionContext))
 644              {
 645                  GenericHandle *genericHandle = (GenericHandle *)session;
 646                  ThunkHandle *thunkHandle = NULL;
 647                  SessionObject *sessionObject = NULL;
 648                  MI_CLIENT_IMPERSONATION_TOKEN originalImpersonation = INVALID_HANDLE_VALUE;
 649              
 650                  trace_MISessionClose(__FUNCTION__, session, completionContext, (void*)completionCallback);
 651              
 652 krisbash 1.1     /* invalid parameter check, already closed, or out of memory during creation */
 653                  if ((session == NULL) || (genericHandle->thunkHandle == NULL))
 654                  {
 655                      if (completionCallback != NULL)
 656                      {
 657                          completionCallback(completionContext);
 658                      }
 659                      trace_MIInvalidSession(__FUNCTION__, session);
 660                      return MI_RESULT_INVALID_PARAMETER;
 661                  }
 662              
 663                  ThunkHandle_FromGeneric(genericHandle, &thunkHandle);
 664                  if (thunkHandle == NULL)
 665                  {
 666                      /* Failed means version was wrong or object was shutdown */
 667                      trace_MISessionInvalidThunkHandle(__FUNCTION__, session);
 668                      return MI_RESULT_INVALID_PARAMETER;
 669                  }
 670              
 671                  sessionObject = (SessionObject*) thunkHandle->u.object;
 672              
 673 krisbash 1.1     {
 674                      MI_Result securityResult = Session_AccessCheck(session, MI_T("close session"));
 675                      if (securityResult != MI_RESULT_OK)
 676                      {
 677                          ThunkHandle_Release(thunkHandle);
 678                          trace_MISession_AccessCheckFailed(__FUNCTION__, session);
 679                          return securityResult;
 680                      }
 681                  }
 682              
 683                  trace_MIClient_SessionClose(session, sessionObject);
 684              
 685                  /* Mark handle for shutdown */
 686                  if (ThunkHandle_Shutdown(thunkHandle, Session_Destructor))
 687                  {
 688                      MI_Result miResult =  Session_ImpersonateClientInternal(sessionObject, &originalImpersonation);
 689                      if (miResult != MI_RESULT_OK)
 690                      {
 691                          ThunkHandle_Release(thunkHandle);
 692                          return miResult;
 693                      }
 694 krisbash 1.1 
 695                      /* remember callback details */
 696                      if (completionCallback)
 697                      {
 698                          sessionObject->sessionCloseCallbackContext = completionContext;
 699                          sessionObject->sessionCloseCallback = completionCallback;
 700                      }
 701              
 702                      /* Cancel all child operations */
 703                      {
 704                          ChildListOutstandingHandles _smallBuffer[100];
 705                          ChildListOutstandingHandles* outstandingOperations = _smallBuffer;
 706                          ptrdiff_t outstandingOperationSize = sizeof(_smallBuffer)/sizeof(_smallBuffer[0]);
 707                          ptrdiff_t outstandingOperationCount;
 708              
 709                          int r = ChildList_Shutdown(&sessionObject->operationList);
 710                          if (r)
 711                          {
 712                              r = ChildList_GetCurrentList(&sessionObject->operationList, outstandingOperations, outstandingOperationSize, &outstandingOperationCount);
 713                              if (r == 0 && outstandingOperationCount > outstandingOperationSize)
 714                              {
 715 krisbash 1.1                     outstandingOperations = (ChildListOutstandingHandles*) PAL_Malloc(outstandingOperationCount*sizeof(ChildListOutstandingHandles));
 716                                  if (outstandingOperations == NULL)
 717                                  {
 718                                      //TSASSERT(0, L"ignored memory allocation on purpose", TLINE);
 719                                      //Note that we cannot cancel the operations.  
 720                                      //It is completely up to the client to close all operations in this case and it will cause it to not respond if they do not
 721                                  }
 722                                  else
 723                                  {
 724                                      outstandingOperationSize = outstandingOperationCount;
 725                                      r = ChildList_GetCurrentList(&sessionObject->operationList, outstandingOperations, outstandingOperationSize, &outstandingOperationCount);
 726                                  }
 727                              }
 728              
 729                              /* Cancel all child operations */
 730                              if (r)
 731                              {
 732                  #ifdef _PREFAST_
 733                  //famous last words, but I am pretty sure this code is not an overflow. outstandingOperationCount has how many items are in it and it will never be more than 
 734                  //outstandingOperationSize if r is non-zero
 735                   #pragma prefast(push)
 736 krisbash 1.1      #pragma prefast(disable:26015) 
 737                  #endif
 738                                  while (outstandingOperationCount)
 739                                  {
 740                                      MI_Operation *operation = (MI_Operation*)&outstandingOperations[outstandingOperationCount-1].clientHandle;
 741                          
 742                                      /* Mode to next one as cancel may cause current operation to get deleted */
 743                                      outstandingOperationCount--;
 744              
 745                                      MI_Operation_Cancel(operation, MI_REASON_NONE);
 746                                  }
 747                  #ifdef _PREFAST_
 748                   #pragma prefast(pop)
 749                  #endif
 750                              }
 751                              if (outstandingOperations != _smallBuffer)
 752                              {
 753                                  PAL_Free(outstandingOperations);
 754                              }
 755                          }
 756                          ChildList_RegisterShutdownCallback(&sessionObject->operationList, Session_AllOperationsShutdown, thunkHandle);
 757 krisbash 1.1         }
 758                      
 759                      /* Callback into the protocol handler happens asynchronously once all child operations are shutdown */
 760              
 761                      /* CALL IS ASYNC. NO MORE CODE HERE except for code to make close synchronous.  Anything else that is needed goes here: Session_CloseCallback */
 762              
 763                      if (completionCallback == NULL)
 764                      {
 765                          ptrdiff_t curSessionCloseCallbackCalled = sessionObject->sessionCloseCallbackCalled;
 766                          /* block until protocol handler calls back */
 767                          while (!curSessionCloseCallbackCalled)
 768                          {
 769                              trace_MIClient_SessionClose_WaitingOnOperations(session, sessionObject, sessionObject->operationList.childCount);
 770                              /* 0 is the current value of state, the value we don't want to see. */
 771                              CondLock_Wait((ptrdiff_t) sessionObject, &sessionObject->sessionCloseCallbackCalled, curSessionCloseCallbackCalled, CONDLOCK_DEFAULT_SPINCOUNT);
 772                              curSessionCloseCallbackCalled = sessionObject->sessionCloseCallbackCalled;
 773                          }
 774                          trace_MIClient_SessionCloseCompleted(session, sessionObject);
 775                          ThunkHandle_Release(thunkHandle);
 776                      }
 777                      else
 778 krisbash 1.1         {
 779                          /* ThunkHandle_Release(thunkHandle) happens in callback code */
 780                      }
 781              
 782                      if (Session_RevertImpersonation(originalImpersonation) != MI_RESULT_OK)
 783                      {
 784                          TerminateProcess(GetCurrentProcess(), -1);
 785                      }
 786                  }
 787                  else
 788                  {
 789                      /* Not the first call to Close so ignore this.  It is unlikely this will happen
 790                       * as the ThunkHandle_FromGeneric would generally fail but there is a small 
 791                       * race condition that could cause this to happen
 792                       */
 793                      ThunkHandle_Release(thunkHandle);
 794                  }
 795              
 796                  return MI_RESULT_OK;
 797              }
 798              
 799 krisbash 1.1 _Success_(return == MI_RESULT_OK)
 800              MI_Result MI_CALL Session_GetApplication(
 801                  _In_     MI_Session *session,
 802                  _Out_    MI_Application *application)
 803              {
 804                  GenericHandle *genericHandle = (GenericHandle*) session;
 805                  ThunkHandle * thunkHandle = NULL;
 806                  SessionObject *sessionObject;
 807              
 808                  if (application)
 809                  {
 810                      memset(application, 0, sizeof(MI_Application));
 811                  }
 812                  if ((session == NULL) || (application == NULL))
 813                  {
 814                      return MI_RESULT_INVALID_PARAMETER;
 815                  }
 816              
 817              
 818                  ThunkHandle_FromGeneric(genericHandle, &thunkHandle);
 819                  if (thunkHandle == NULL)
 820 krisbash 1.1     {
 821                      /* Failed means version was wrong or object was shutdown */
 822                      return MI_RESULT_INVALID_PARAMETER;
 823                  }
 824              
 825                  sessionObject = (SessionObject *) thunkHandle->u.object;
 826                  *application = sessionObject->clientApplication;
 827              
 828                  /* finished with object for now... */
 829                  ThunkHandle_Release(thunkHandle);
 830                  return MI_RESULT_OK;
 831              }
 832              
 833              /* Get a copy of the session destination options */
 834              void Session_GetDestinationOptions(_Inout_ MI_Session *session, _Out_ MI_DestinationOptions *destOptions)
 835              {
 836                  GenericHandle *genericHandle = (GenericHandle*) session;
 837                  ThunkHandle * thunkHandle = NULL;
 838                  SessionObject *sessionObject;
 839              
 840                  memset(destOptions, 0, sizeof(MI_DestinationOptions));
 841 krisbash 1.1 
 842                  ThunkHandle_FromGeneric(genericHandle, &thunkHandle);
 843                  if (thunkHandle == NULL)
 844                  {
 845                      /* Failed means version was wrong or object was shutdown */
 846                      return;
 847                  }
 848              
 849                  sessionObject = (SessionObject *) thunkHandle->u.object;
 850                  DestinationOptions_Duplicate(&sessionObject->clientDestinationOptions, destOptions);
 851                  /* finished with object for now... */
 852                  ThunkHandle_Release(thunkHandle);
 853              }
 854              
 855              /* From a client session get the transport session */
 856              _Success_(return==MI_RESULT_OK)
 857              MI_Result Session_GetProtocolHandlerSession(
 858                  _In_ MI_Session *clientSession, 
 859                  _Out_ MI_Session *protocolHandlerSession,
 860                  _Out_ ProtocolHandlerCacheItem **protocolHandlerItem)
 861              {
 862 krisbash 1.1     ThunkHandle *sessionThunk = NULL;
 863                  SessionObject *sessionObject = NULL;
 864              
 865                  ThunkHandle_FromGeneric((GenericHandle*)clientSession, &sessionThunk);
 866                  if (sessionThunk == NULL)
 867                  {
 868                      return MI_RESULT_FAILED;
 869                  }
 870              
 871                  sessionObject = (SessionObject *) sessionThunk->u.object;
 872                  *protocolHandlerSession = sessionObject->protocolHandlerSession;
 873                  *protocolHandlerItem = sessionObject->protocolHandlerItem;
 874                  /* release up sessionThunk */
 875                  ThunkHandle_Release(sessionThunk);
 876              
 877                  return MI_RESULT_OK;
 878              }
 879              
 880              _Success_(return==MI_RESULT_OK)
 881              MI_Result Session_GetProtocolHandlerApplication(
 882                  _In_ MI_Session *clientSession, 
 883 krisbash 1.1     _Out_ MI_Application *protocolHandlerApplication)
 884              {
 885                  ThunkHandle *sessionThunk = NULL;
 886                  SessionObject *sessionObject = NULL;
 887              
 888                  ThunkHandle_FromGeneric((GenericHandle*)clientSession, &sessionThunk);
 889                  if (sessionThunk == NULL)
 890                  {
 891                      return MI_RESULT_FAILED;
 892                  }
 893              
 894                  sessionObject = (SessionObject *) sessionThunk->u.object;
 895                  *protocolHandlerApplication = sessionObject->protocolHandlerItem->application;
 896              
 897                  /* release up sessionThunk */
 898                  ThunkHandle_Release(sessionThunk);
 899              
 900                  return MI_RESULT_OK;
 901              }
 902              
 903              _Success_(return == MI_RESULT_OK)
 904 krisbash 1.1 MI_Result Session_AccessCheck(_In_ MI_Session *session, _In_opt_z_ const MI_Char *operationName)
 905              {
 906                  ThunkHandle *sessionThunk = NULL;
 907                  SessionObject *sessionObject = NULL;
 908                  MI_Result r;
 909              
 910                  trace_MIEnter(__FUNCTION__, session);
 911              
 912                  /* NOTE: Access check may be called from Operat_Cancel or Operation_Close after the
 913                   * session has been closed.  Therefore do thunk and ignore Active bit on handle.
 914                   */
 915                  ThunkHandle_FromGeneric_ForCompletionCallback((GenericHandle*)session, &sessionThunk);
 916                  if (sessionThunk == NULL)
 917                  {
 918                      trace_MISession_InvalidSessionThunk(__FUNCTION__, session);
 919                      return MI_RESULT_INVALID_PARAMETER;
 920                  }
 921              
 922                  sessionObject = (SessionObject *) sessionThunk->u.object;
 923              
 924              #if defined(_MSC_VER)
 925 krisbash 1.1     {
 926                  MI_CLIENT_IMPERSONATION_TOKEN currentToken = INVALID_HANDLE_VALUE;
 927                  BOOL bRet;
 928                  DWORD windowsError = NO_ERROR;
 929              
 930                  bRet = OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE|TOKEN_READ|TOKEN_DUPLICATE, TRUE, &currentToken) ;
 931                  if (bRet == FALSE)
 932                  {
 933                      /*Not impersonating or out of memory*/
 934                      windowsError = GetLastError();
 935                      if (windowsError == ERROR_NO_TOKEN)
 936                      {
 937                          /*OK, so no token on thread so try process token instead*/
 938                          bRet = ImpersonateSelf(SecurityImpersonation);
 939                          if (bRet == FALSE)
 940                          {
 941                              /* failed */
 942                              windowsError = GetLastError();
 943                          }
 944                          else
 945                          {
 946 krisbash 1.1                 bRet = OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE|TOKEN_READ|TOKEN_DUPLICATE, TRUE, &currentToken) ;
 947                              if (bRet == FALSE)
 948                              {
 949                                  /* failed */
 950                                  windowsError = GetLastError();
 951                              }
 952                              else
 953                              {
 954                                  /*Now got the impersonated process token*/
 955                                  windowsError = NO_ERROR;
 956                              }
 957                              RevertToSelf();
 958                          }
 959                      }
 960                      else
 961                      {
 962                          /*Failed, either out of memory or anonymous token*/
 963                      }
 964                  }
 965                  else
 966                  {
 967 krisbash 1.1         /*Using impersonation token*/
 968                  }
 969              
 970                  if (bRet)
 971                  {
 972                      //Compare user SID
 973                      DWORD dwSize = sizeof(TOKEN_USER)+sizeof(SID)+(SID_MAX_SUB_AUTHORITIES*sizeof(DWORD));       
 974                      BYTE Array[sizeof(TOKEN_USER)+sizeof(SID)+(SID_MAX_SUB_AUTHORITIES*sizeof(DWORD))];
 975                      TOKEN_USER * pTokenUser = (TOKEN_USER *)Array;
 976              
 977                      if (!GetTokenInformation(currentToken,TokenUser,pTokenUser,dwSize,&dwSize))
 978                      {
 979                          windowsError = GetLastError();
 980                      }
 981                      else
 982                      {
 983                          if (!EqualSid(pTokenUser->User.Sid, sessionObject->clientSessionCreationTokenSID->User.Sid))
 984                          {
 985                              windowsError = ERROR_ACCESS_DENIED;
 986                          }
 987                      }
 988 krisbash 1.1         
 989                      CloseHandle(currentToken);
 990                  }
 991                  r = WindowsError_To_MI_Result(windowsError);
 992                  }
 993              #else
 994                  if ((getuid() == sessionObject->uid) && (getgid() == sessionObject->gid))
 995                  {
 996                      r = MI_RESULT_OK;
 997                  }
 998                  else
 999                  {
1000                      r = MI_RESULT_ACCESS_DENIED;
1001                  }
1002              #endif
1003              
1004                  /* release up sessionThunk */
1005                  ThunkHandle_Release(sessionThunk);
1006              
1007                  trace_MILeavingSessionWithOperation(__FUNCTION__, session, operationName);
1008                  return r;
1009 krisbash 1.1 }
1010              
1011              /*Impersonates based on who created the session, returning original thread token to call Session_RevertImpersonation with*/
1012              _Success_(return == MI_RESULT_OK)
1013              MI_Result Session_ImpersonateClient(_In_ MI_Session *session, _Out_ MI_CLIENT_IMPERSONATION_TOKEN *originalImpersonation)
1014              {
1015              #if defined(_MSC_VER)
1016                  ThunkHandle *sessionThunk = NULL;
1017                  SessionObject *sessionObject = NULL;
1018                  MI_Result ret = MI_RESULT_OK;
1019              
1020                  *originalImpersonation = INVALID_HANDLE_VALUE ;
1021              
1022                  /* There is a change we need to do this when the session has already been marked for close
1023                     however the session cannot go away until the operations have gone so probably OK
1024                     */
1025                  ThunkHandle_FromGeneric_ForCompletionCallback((GenericHandle*)session, &sessionThunk);
1026                  if (sessionThunk == NULL)
1027                  {
1028                      return MI_RESULT_FAILED;
1029                  }
1030 krisbash 1.1 
1031                  sessionObject = (SessionObject *) sessionThunk->u.object;
1032              
1033                  ret = Session_ImpersonateClientInternal(sessionObject, originalImpersonation);
1034              
1035                  /* release up sessionThunk */
1036                  ThunkHandle_Release(sessionThunk);
1037              
1038                  return ret;
1039              #else
1040                  return MI_RESULT_OK;
1041              #endif
1042              }
1043              
1044              /*Impersonates based on who created the session, returning original thread token to call Session_RevertImpersonation with*/
1045              MI_Result Session_ImpersonateClientInternal(_In_ SessionObject *sessionObject, _Out_ MI_CLIENT_IMPERSONATION_TOKEN *originalImpersonation)
1046              {
1047              #if defined(_MSC_VER)
1048                  MI_Result ret = MI_RESULT_OK;
1049              
1050                  *originalImpersonation = INVALID_HANDLE_VALUE ;
1051 krisbash 1.1 
1052                  /* Get the current impersonation token */
1053                  if (!OpenThreadToken(GetCurrentThread(),
1054                          TOKEN_IMPERSONATE, 
1055                          TRUE,
1056                          originalImpersonation))
1057                  {
1058                      DWORD error  =  GetLastError();
1059                      if ( error == ERROR_NO_TOKEN )
1060                      { 
1061                          /*thread is not impersonating, nothing to do*/
1062                          ret = MI_RESULT_OK;
1063                      }
1064                      else
1065                      {
1066                          ret = WindowsError_To_MI_Result(error);
1067                      }
1068                  }
1069                  if (ret == MI_RESULT_OK)
1070                  {
1071                      /*Good so far, now set the token to the session creation token */
1072 krisbash 1.1         if (SetThreadToken( NULL, sessionObject->clientSessionCreationToken) == FALSE)
1073                      {
1074                          /*Failed!  Not good.  Clean-up*/
1075                          ret = WindowsError_To_MI_Result(GetLastError());
1076                          CloseHandle(*originalImpersonation);
1077                          *originalImpersonation = INVALID_HANDLE_VALUE;
1078                      }
1079                  }
1080              
1081                  return ret;
1082              #else
1083                  *originalImpersonation = INVALID_HANDLE_VALUE;
1084                  return MI_RESULT_OK;
1085              #endif
1086              }
1087              
1088              //Reverts the impersonation token back to what it was before Session_ImpersonateClient was called
1089              _Success_(return == MI_RESULT_OK)
1090              MI_Result Session_RevertImpersonation(MI_CLIENT_IMPERSONATION_TOKEN originalImpersonation)
1091              {
1092              #if defined(_MSC_VER)
1093 krisbash 1.1     MI_Result ret = MI_RESULT_OK;
1094              
1095                  if (INVALID_HANDLE_VALUE == originalImpersonation)
1096                  {
1097                      originalImpersonation = NULL;
1098                  }
1099                  
1100                  
1101                  if (SetThreadToken( NULL, originalImpersonation) == FALSE)
1102                  {
1103                      //
1104                      // If we fail to re-attach the original token, we return FALSE. It is *** CRITICAL *** that the callee check the
1105                      // return as potential security issues may arise if they dont.
1106                      //
1107                      ret = WindowsError_To_MI_Result(GetLastError());
1108                  }
1109              
1110                  CloseHandle( originalImpersonation );
1111              
1112                  return ret;
1113              #else
1114 krisbash 1.1     return MI_RESULT_OK;
1115              #endif
1116              }
1117              
1118              const MI_SessionFT g_sessionFT_OOM = {
1119                  Session_Close,
1120                  NULL
1121              };
1122              
1123              const MI_SessionFT g_sessionFT = {
1124                  Session_Close,
1125                  Session_GetApplication,
1126                  Operation_Execute_GetInstance,
1127                  Operation_Execute_ModifyInstance,
1128                  Operation_Execute_CreateInstance,
1129                  Operation_Execute_DeleteInstance,
1130                  Operation_Execute_Invoke,
1131                  Operation_Execute_EnumerateInstances,
1132                  Operation_Execute_QueryInstances,
1133                  Operation_Execute_AssociatorInstances,
1134                  Operation_Execute_ReferenceInstances,
1135 krisbash 1.1     Operation_Execute_Subscribe,
1136                  Operation_Execute_GetClass,
1137                  Operation_Execute_EnumerateClasses,
1138                  Operation_Execute_TestConnection
1139              };

ViewCVS 0.9.2