Exemplo n.º 1
0
/**
  Update the variable region with Variable information.

  @param[in] AuthVariableInfo       Pointer AUTH_VARIABLE_INFO structure for
                                    input of the variable.

  @retval EFI_SUCCESS               The update operation is success.
  @retval EFI_INVALID_PARAMETER     Invalid parameter.
  @retval EFI_WRITE_PROTECTED       Variable is write-protected.
  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.

**/
EFI_STATUS
EFIAPI
VariableExLibUpdateVariable (
  IN AUTH_VARIABLE_INFO     *AuthVariableInfo
  )
{
  VARIABLE_POINTER_TRACK    Variable;

  FindVariable (AuthVariableInfo->VariableName, AuthVariableInfo->VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
  return UpdateVariable (
           AuthVariableInfo->VariableName,
           AuthVariableInfo->VendorGuid,
           AuthVariableInfo->Data,
           AuthVariableInfo->DataSize,
           AuthVariableInfo->Attributes,
           AuthVariableInfo->PubKeyIndex,
           AuthVariableInfo->MonotonicCount,
           &Variable,
           AuthVariableInfo->TimeStamp
           );
}
Exemplo n.º 2
0
/**
  Update platform mode.

  @param[in]  VirtualMode             The current calling mode for this function.
  @param[in]  Global                  The context of this Extended SAL Variable Services Class call.
  @param[in]  Mode                    SETUP_MODE or USER_MODE.

**/
VOID
UpdatePlatformMode (
  IN  BOOLEAN                   VirtualMode,
  IN  ESAL_VARIABLE_GLOBAL      *Global,
  IN  UINT32                    Mode
  )
{
  EFI_STATUS              Status;
  VARIABLE_POINTER_TRACK  Variable;
  UINT32                  VarAttr;

  Status = FindVariable (
             Global->VariableName[VirtualMode][VAR_SETUP_MODE], 
             Global->GlobalVariableGuid[VirtualMode], 
             &Variable, 
             &Global->VariableGlobal[VirtualMode],
             Global->FvbInstance
             );
  ASSERT_EFI_ERROR (Status);

  mPlatformMode  = Mode;
  VarAttr        = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
  Status         = UpdateVariable (
                     Global->VariableName[VirtualMode][VAR_SETUP_MODE],
                     Global->GlobalVariableGuid[VirtualMode],
                     &mPlatformMode,
                     sizeof(UINT8),
                     VarAttr,
                     0,
                     0,
                     VirtualMode,
                     Global,
                     &Variable
                     );
  ASSERT_EFI_ERROR (Status);
}
Exemplo n.º 3
0
/**
  Process variable with key exchange key for verification.

  @param[in]  VariableName                The name of Variable to be found.
  @param[in]  VendorGuid                  The variable vendor GUID.
  @param[in]  Data                        The data pointer.
  @param[in]  DataSize                    The size of Data found. If size is less than the
                                          data, this value contains the required size.
  @param[in]  VirtualMode                 The current calling mode for this function.
  @param[in]  Global                      The context of this Extended SAL Variable Services Class call.
  @param[in]  Variable                    The variable information which is used to keep track of variable usage.
  @param[in]  Attributes                  The attribute value of the variable.

  @retval EFI_INVALID_PARAMETER           Invalid parameter.
  @retval EFI_SECURITY_VIOLATION          The variable did NOT pass the validation 
                                          check carried out by the firmware. 
  @retval EFI_SUCCESS                     The variable passed validation successfully.

**/
EFI_STATUS
ProcessVarWithKek (
  IN  CHAR16                               *VariableName,
  IN  EFI_GUID                             *VendorGuid,
  IN  VOID                                 *Data,
  IN  UINTN                                DataSize,
  IN  BOOLEAN                              VirtualMode,
  IN  ESAL_VARIABLE_GLOBAL                 *Global,
  IN  VARIABLE_POINTER_TRACK               *Variable,
  IN  UINT32                               Attributes OPTIONAL
  )
{
  EFI_STATUS                      Status;
  VARIABLE_POINTER_TRACK          KekVariable;
  EFI_SIGNATURE_LIST              *KekList;
  EFI_SIGNATURE_DATA              *KekItem;
  UINT32                          KekCount;
  EFI_VARIABLE_AUTHENTICATION     *CertData;
  EFI_CERT_BLOCK_RSA_2048_SHA256  *CertBlock;
  BOOLEAN                         IsFound;
  UINT32                          Index;
  VARIABLE_HEADER                 VariableHeader;
  BOOLEAN                         Valid;

  KekList = NULL;
  ZeroMem (&VariableHeader, sizeof (VARIABLE_HEADER));

  if (mPlatformMode == USER_MODE) {
    if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {
      //
      // In user mode, should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute.
      //
      return EFI_INVALID_PARAMETER;
    }

    CertData  = (EFI_VARIABLE_AUTHENTICATION *) Data;
    CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);
    if (Variable->CurrPtr != 0x0) {
      Valid = IsValidVariableHeader (
                Variable->CurrPtr, 
                Variable->Volatile, 
                &Global->VariableGlobal[VirtualMode], 
                Global->FvbInstance, 
                &VariableHeader
                );
      ASSERT (Valid);

      if (CertData->MonotonicCount <= VariableHeader.MonotonicCount) {
        //
        // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
        //
        return EFI_SECURITY_VIOLATION;
      }
    }
    //
    // Get KEK database from variable.
    //
    Status = FindVariable (
               Global->VariableName[VirtualMode][VAR_KEY_EXCHANGE_KEY], 
               Global->GlobalVariableGuid[VirtualMode], 
               &KekVariable, 
               &Global->VariableGlobal[VirtualMode],
               Global->FvbInstance
               );
    ASSERT_EFI_ERROR (Status);

    ZeroMem (Global->KeyList, MAX_KEYDB_SIZE);
    GetVariableDataPtr (
      KekVariable.CurrPtr,
      KekVariable.Volatile,
      &Global->VariableGlobal[VirtualMode],
      Global->FvbInstance,
      (CHAR16 *) Global->KeyList
      );
    //
    // Enumerate all Kek items in this list to verify the variable certificate data.
    // If anyone is authenticated successfully, it means the variable is correct!
    //
    KekList   = (EFI_SIGNATURE_LIST *) Global->KeyList;
    IsFound   = FALSE;
    KekCount  = (KekList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - KekList->SignatureHeaderSize) / KekList->SignatureSize;
    KekItem   = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekList + sizeof (EFI_SIGNATURE_LIST) + KekList->SignatureHeaderSize);
    for (Index = 0; Index < KekCount; Index++) {
      if (CompareMem (KekItem->SignatureData, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {
        IsFound = TRUE;
        break;
      }
      KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekItem + KekList->SignatureSize);
    }

    if (!IsFound) {
      return EFI_SECURITY_VIOLATION;
    }

    Status = VerifyDataPayload (VirtualMode, Global, Data, DataSize, CertBlock->PublicKey);
    if (!EFI_ERROR (Status)) {
      Status = UpdateVariable (
                 VariableName, 
                 VendorGuid, 
                 (UINT8*)Data + AUTHINFO_SIZE, 
                 DataSize - AUTHINFO_SIZE, 
                 Attributes, 
                 0, 
                 CertData->MonotonicCount, 
                 VirtualMode,
                 Global,
                 Variable
                 );
    }
  } else {
    //
    // If in setup mode, no authentication needed.
    //
    Status = UpdateVariable (
               VariableName, 
               VendorGuid, 
               Data, 
               DataSize, 
               Attributes, 
               0, 
               0, 
               VirtualMode,
               Global,
               Variable
               );
  }

  return Status;
}
Exemplo n.º 4
0
/**
  Process variable with platform key for verification.

  @param[in]  VariableName                The name of Variable to be found.
  @param[in]  VendorGuid                  The variable vendor GUID.
  @param[in]  Data                        The data pointer.
  @param[in]  DataSize                    The size of Data found. If size is less than the
                                          data, this value contains the required size.
  @param[in]  VirtualMode                 The current calling mode for this function.
  @param[in]  Global                      The context of this Extended SAL Variable Services Class call.
  @param[in]  Variable                    The variable information which is used to keep track of variable usage.
  @param[in]  Attributes                  The attribute value of the variable.
  @param[in]  IsPk                        Indicates whether to process pk.

  @retval EFI_INVALID_PARAMETER           Invalid parameter.
  @retval EFI_SECURITY_VIOLATION          The variable does NOT pass the validation 
                                          check carried out by the firmware. 
  @retval EFI_SUCCESS                     The variable passed validation successfully.

**/
EFI_STATUS
ProcessVarWithPk (
  IN  CHAR16                    *VariableName,
  IN  EFI_GUID                  *VendorGuid,
  IN  VOID                      *Data,
  IN  UINTN                     DataSize,
  IN  BOOLEAN                   VirtualMode,
  IN  ESAL_VARIABLE_GLOBAL      *Global,
  IN  VARIABLE_POINTER_TRACK    *Variable,
  IN  UINT32                    Attributes OPTIONAL,
  IN  BOOLEAN                   IsPk
  )
{
  EFI_STATUS                  Status;
  VARIABLE_POINTER_TRACK      PkVariable;
  EFI_SIGNATURE_LIST          *OldPkList;
  EFI_SIGNATURE_DATA          *OldPkData;
  EFI_VARIABLE_AUTHENTICATION *CertData;
  VARIABLE_HEADER             VariableHeader;
  BOOLEAN                     Valid;

  OldPkList = NULL;
  ZeroMem (&VariableHeader, sizeof (VARIABLE_HEADER));

  if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
    //
    // PK and KEK should set EFI_VARIABLE_NON_VOLATILE attribute.
    //
    return EFI_INVALID_PARAMETER;
  }

  if (mPlatformMode == USER_MODE) {
    if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {
      //
      // In user mode, PK and KEK should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute.
      //
      return EFI_INVALID_PARAMETER;
    }

    CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;

    if (Variable->CurrPtr != 0x0) {
      Valid = IsValidVariableHeader (
                Variable->CurrPtr, 
                Variable->Volatile, 
                &Global->VariableGlobal[VirtualMode], 
                Global->FvbInstance, 
                &VariableHeader
                );
      ASSERT (Valid);

      if (CertData->MonotonicCount <= VariableHeader.MonotonicCount) {
        //
        // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
        //
        return EFI_SECURITY_VIOLATION;
      }
    }
    //
    // Get platform key from variable.
    //
    Status = FindVariable (
               Global->VariableName[VirtualMode][VAR_PLATFORM_KEY], 
               Global->GlobalVariableGuid[VirtualMode], 
               &PkVariable, 
               &Global->VariableGlobal[VirtualMode],
               Global->FvbInstance
               );
    ASSERT_EFI_ERROR (Status);

    ZeroMem (Global->KeyList, MAX_KEYDB_SIZE);
    GetVariableDataPtr (
      PkVariable.CurrPtr,
      PkVariable.Volatile,
      &Global->VariableGlobal[VirtualMode],
      Global->FvbInstance,
      (CHAR16 *) Global->KeyList
      );

    OldPkList = (EFI_SIGNATURE_LIST *) Global->KeyList;
    OldPkData = (EFI_SIGNATURE_DATA *) ((UINT8 *) OldPkList + sizeof (EFI_SIGNATURE_LIST) + OldPkList->SignatureHeaderSize);
    Status    = VerifyDataPayload (VirtualMode, Global, Data, DataSize, OldPkData->SignatureData);
    if (!EFI_ERROR (Status)) {
      Status = UpdateVariable (
                 VariableName, 
                 VendorGuid, 
                 (UINT8*)Data + AUTHINFO_SIZE, 
                 DataSize - AUTHINFO_SIZE, 
                 Attributes, 
                 0, 
                 CertData->MonotonicCount, 
                 VirtualMode, 
                 Global,
                 Variable
                 );

      if (!EFI_ERROR (Status)) {
        //
        // If delete PK in user mode, need change to setup mode.
        //
        if ((DataSize == AUTHINFO_SIZE) && IsPk) {
          UpdatePlatformMode (VirtualMode, Global, SETUP_MODE);
        }
      }
    }
  } else {
    Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, 0, 0, VirtualMode, Global, Variable);
    //
    // If enroll PK in setup mode, need change to user mode.
    //
    if ((DataSize != 0) && IsPk) {
      UpdatePlatformMode (VirtualMode, Global, USER_MODE);
    }
  }

  return Status;
}
Exemplo n.º 5
0
/**
  Initializes for authenticated varibale service.

  @retval EFI_SUCCESS           The function successfully executed.
  @retval EFI_OUT_OF_RESOURCES  Failed to allocate enough memory resources.

**/
EFI_STATUS
AutenticatedVariableServiceInitialize (
  VOID
  )
{
  EFI_STATUS              Status;
  VARIABLE_POINTER_TRACK  Variable;
  UINT8                   VarValue;
  UINT32                  VarAttr;
  UINTN                   DataSize;
  UINTN                   CtxSize;
  VARIABLE_HEADER         VariableHeader;
  BOOLEAN                 Valid;

  ZeroMem (&VariableHeader, sizeof (VARIABLE_HEADER));

  mVariableModuleGlobal->AuthenticatedVariableGuid[Physical] = &gEfiAuthenticatedVariableGuid;
  mVariableModuleGlobal->CertRsa2048Sha256Guid[Physical]     = &gEfiCertRsa2048Sha256Guid;
  mVariableModuleGlobal->ImageSecurityDatabaseGuid[Physical] = &gEfiImageSecurityDatabaseGuid;

  //
  // Initialize hash context.
  //
  CtxSize   = Sha256GetContextSize ();
  mVariableModuleGlobal->HashContext[Physical] = AllocateRuntimePool (CtxSize);
  ASSERT (mVariableModuleGlobal->HashContext[Physical] != NULL);
  //
  // Check "AuthVarKeyDatabase" variable's existence. 
  // If it doesn't exist, create a new one with initial value of 0 and EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set. 
  //
  Status = FindVariable (
             mVariableModuleGlobal->VariableName[Physical][VAR_AUTH_KEY_DB], 
             &gEfiAuthenticatedVariableGuid, 
             &Variable, 
             &mVariableModuleGlobal->VariableGlobal[Physical],
             mVariableModuleGlobal->FvbInstance
             );

  if (Variable.CurrPtr == 0x0) {
    VarAttr       = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
    VarValue      = 0;
    mPubKeyNumber = 0;
    Status        = UpdateVariable (
                      mVariableModuleGlobal->VariableName[Physical][VAR_AUTH_KEY_DB],
                      &gEfiAuthenticatedVariableGuid,
                      &VarValue,
                      sizeof(UINT8),
                      VarAttr,
                      0,
                      0,
                      FALSE,
                      mVariableModuleGlobal,
                      &Variable
                      );
    if (EFI_ERROR (Status)) {
      return Status;
    }
  } else {
    //
    // Load database in global variable for cache.
    //
    Valid = IsValidVariableHeader (
              Variable.CurrPtr, 
              Variable.Volatile, 
              &mVariableModuleGlobal->VariableGlobal[Physical], 
              mVariableModuleGlobal->FvbInstance, 
              &VariableHeader
              );
    ASSERT (Valid);

    DataSize  = DataSizeOfVariable (&VariableHeader);
    ASSERT (DataSize <= MAX_KEYDB_SIZE);
    GetVariableDataPtr (
      Variable.CurrPtr,
      Variable.Volatile,
      &mVariableModuleGlobal->VariableGlobal[Physical],
      mVariableModuleGlobal->FvbInstance,
      (CHAR16 *) mVariableModuleGlobal->PubKeyStore
      );

    mPubKeyNumber = (UINT32) (DataSize / EFI_CERT_TYPE_RSA2048_SIZE);
  }
  //
  // Check "SetupMode" variable's existence. 
  // If it doesn't exist, check PK database's existence to determine the value.
  // Then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set. 
  //
  Status = FindVariable (
             mVariableModuleGlobal->VariableName[Physical][VAR_SETUP_MODE], 
             &gEfiGlobalVariableGuid, 
             &Variable, 
             &mVariableModuleGlobal->VariableGlobal[Physical],
             mVariableModuleGlobal->FvbInstance
             );

  if (Variable.CurrPtr == 0x0) {
    Status = FindVariable (
               mVariableModuleGlobal->VariableName[Physical][VAR_PLATFORM_KEY], 
               &gEfiGlobalVariableGuid, 
               &Variable, 
               &mVariableModuleGlobal->VariableGlobal[Physical],
               mVariableModuleGlobal->FvbInstance
               );
    if (Variable.CurrPtr == 0x0) {
      mPlatformMode = SETUP_MODE;
    } else {
      mPlatformMode = USER_MODE;
    }

    VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
    Status  = UpdateVariable (
                mVariableModuleGlobal->VariableName[Physical][VAR_SETUP_MODE],
                &gEfiGlobalVariableGuid,
                &mPlatformMode,
                sizeof(UINT8),
                VarAttr,
                0,
                0,
                FALSE,
                mVariableModuleGlobal,
                &Variable
                );
    if (EFI_ERROR (Status)) {
      return Status;
    }
  } else {
    GetVariableDataPtr (
      Variable.CurrPtr,
      Variable.Volatile,
      &mVariableModuleGlobal->VariableGlobal[Physical],
      mVariableModuleGlobal->FvbInstance,
      (CHAR16 *) &mPlatformMode
      );
  }
  //
  // Check "SignatureSupport" variable's existence. 
  // If it doesn't exist, then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set. 
  //
  Status = FindVariable (
             EFI_SIGNATURE_SUPPORT_NAME, 
             &gEfiGlobalVariableGuid, 
             &Variable, 
             &mVariableModuleGlobal->VariableGlobal[Physical],
             mVariableModuleGlobal->FvbInstance
             );

  if (Variable.CurrPtr == 0x0) {
    VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
    Status  = UpdateVariable (
                EFI_SIGNATURE_SUPPORT_NAME,
                &gEfiGlobalVariableGuid,
                mSignatureSupport,
                SIGSUPPORT_NUM * sizeof(EFI_GUID),
                VarAttr,
                0,
                0,
                FALSE,
                mVariableModuleGlobal,
                &Variable
                );
  }

  return Status;
}
Exemplo n.º 6
0
/**
  Add public key in store and return its index.

  @param[in]  VirtualMode             The current calling mode for this function.
  @param[in]  Global                  The context of this Extended SAL Variable Services Class call.
  @param[in]  PubKey                  The input pointer to Public Key data.

  @return                             The index of new added item.

**/
UINT32
AddPubKeyInStore (
  IN  BOOLEAN                   VirtualMode,
  IN  ESAL_VARIABLE_GLOBAL      *Global,
  IN  UINT8                     *PubKey
  )
{
  EFI_STATUS              Status;
  BOOLEAN                 IsFound;
  UINT32                  Index;
  VARIABLE_POINTER_TRACK  Variable;
  UINT8                   *Ptr;

  if (PubKey == NULL) {
    return 0;
  }

  Status = FindVariable (
             Global->VariableName[VirtualMode][VAR_AUTH_KEY_DB],
             Global->AuthenticatedVariableGuid[VirtualMode],
             &Variable,
             &Global->VariableGlobal[VirtualMode],
             Global->FvbInstance
             );
  ASSERT_EFI_ERROR (Status);
  //
  // Check whether the public key entry does exist.
  //
  IsFound = FALSE;
  for (Ptr = Global->PubKeyStore, Index = 1; Index <= mPubKeyNumber; Index++) {
    if (CompareMem (Ptr, PubKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {
      IsFound = TRUE;
      break;
    }
    Ptr += EFI_CERT_TYPE_RSA2048_SIZE;
  }

  if (!IsFound) {
    //
    // Add public key in database.
    //
    if (mPubKeyNumber == MAX_KEY_NUM) {
      //
      // Notes: Database is full, need enhancement here, currently just return 0.
      //
      return 0;
    }

    CopyMem (Global->PubKeyStore + mPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);
    Index = ++mPubKeyNumber;
    //
    // Update public key database variable.
    //
    Status = UpdateVariable (
               Global->VariableName[VirtualMode][VAR_AUTH_KEY_DB],
               Global->AuthenticatedVariableGuid[VirtualMode],
               Global->PubKeyStore,
               mPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE,
               EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS,
               0,
               0,
               VirtualMode,
               Global,
               &Variable
               );
    ASSERT_EFI_ERROR (Status);
  }

  return Index;
}
Exemplo n.º 7
0
void VRSDClient::HandleDebuggingMessage(VMessage* pMessage)
{
  if(!pMessage || !m_pClientLanguageImplementation)
    return;

  // Handle debugging messages here

  switch(pMessage->GetMessageType())
  {
    case 'RSRN':
      HandleScriptReloadMessage(pMessage);
      break;

    case 'GCST':
      {
        // get the callstack from the scripting language implementation
        DynArray_cl<VRSDClientCallstackEntry> Callstack(16);
        unsigned int CallstackEntryCount = 0;
        
        m_pClientLanguageImplementation->GetCallstack(Callstack, CallstackEntryCount);
        
        // send it
        SendCallstack(Callstack, CallstackEntryCount);
      }

      break;

    case 'GGSY':
      {
        // get the global symbol collection from the scripting language implementation
        DynArray_cl<VRSDScriptSymbol> globalSymbols(32, VRSDScriptSymbol());
        unsigned int iGlobalSymbolCount = 0;

        m_pClientLanguageImplementation->GetGlobalSymbols(globalSymbols, iGlobalSymbolCount);

        // send it
        SendSymbols('GSYC', globalSymbols, iGlobalSymbolCount);
      }


      break;

    case 'GLSY':
      {
        // get the local symbol collection from the scripting language implementation
        DynArray_cl<VRSDScriptSymbol> localSymbols(16, VRSDScriptSymbol());
        unsigned int iLocalSymbolCount = 0;

        m_pClientLanguageImplementation->GetLocalSymbols(localSymbols, iLocalSymbolCount);

        // send it
        SendSymbols('LSYC', localSymbols, iLocalSymbolCount);
      }

      break;

    case 'GSFG':
      {
        // read the symbol name for which the subsymbols are requested
        char* pSymbolName = NULL;
        if(pMessage->ReadString(&pSymbolName))
        {
          // get the global symbol collection from the scripting language implementation
          DynArray_cl<VRSDScriptSymbol> globalSymbols(16, VRSDScriptSymbol());
          unsigned int iGlobalSymbolCount = 0;

          if(m_pClientLanguageImplementation->GetSubSymbolsForGlobal(pSymbolName, globalSymbols, iGlobalSymbolCount))
          {
            // send it
            SendSymbols('GSSC', globalSymbols, iGlobalSymbolCount, pSymbolName);
          }
        }
      }
      break;

    case 'GSFL':
      {
        // read the symbol name for which the subsymbols are requested
        char* pSymbolName = NULL;
        if(pMessage->ReadString(&pSymbolName))
        {
          // get the global symbol collection from the scripting language implementation
          DynArray_cl<VRSDScriptSymbol> localSymbols(16, VRSDScriptSymbol());
          unsigned int iLocalSymbolCount = 0;

          if(m_pClientLanguageImplementation->GetSubSymbolsForLocal(pSymbolName, localSymbols, iLocalSymbolCount))
          {
            // send it
            SendSymbols('LSSC', localSymbols, iLocalSymbolCount, pSymbolName);
          }
        }
      }
      break;

      // get userdata type (local / global)
    case 'GUDT':
    case 'LUDT':
      {
        // read first the variable name we should check
        char* pVariableName = NULL;
        if(!pMessage->ReadString(&pVariableName))
          break;

        char pUserDataTypeName[512];
        bool success;

        if(pMessage->GetMessageType() == 'GUDT')
          success = m_pClientLanguageImplementation->GetGlobalType(pVariableName, pUserDataTypeName);
        else
          success = m_pClientLanguageImplementation->GetLocalType(pVariableName, pUserDataTypeName);

        if(success)
        {
          VMessage msg('VUDT', (int)strlen(pUserDataTypeName) + 5);
          msg.Write(pUserDataTypeName);

          VMutexLocker lock(m_ConnectionMutex);
          if(m_pConnection)
            m_pConnection->Send(&msg);
        }
        else
        {
          // if no type is found submit that
          VMessage msg('VUDT', 5);
          msg.Write("");

          VMutexLocker lock(m_ConnectionMutex);
          if(m_pConnection)
            m_pConnection->Send(&msg);
        }
      }
      break;

    // update the value of a variable (non userdata = strings, bools, numbers)
    case 'LVCU':
    case 'GVCU':
      UpdateVariable(pMessage);
      break;

    // request for user data update
    case 'LUDU':
    case 'GUDU':
      UpdateUserDataVariable(pMessage);
      break;

    // request for local user data members
    case 'LUDM':
    case 'GUDM':
      HandleUserDataMemberRequest(pMessage);
      break;
  }
}