STDMETHODIMP InterfaceDatabase::BeginTransaction()
{
   try
   {
      if (!config_)
         return GetAccessDenied();

      if (!GetIsServerAdmin())
         return GetAccessDenied();
   
      HRESULT hRes = EnsureDatabaseConnectivity_();
      if (hRes != S_OK)
         return hRes;
   
      HM::String sErrorMessage;
      conn_ = db_manager_->BeginTransaction(sErrorMessage);
   
      if (!conn_)
      {
         return COMError::GenerateError(sErrorMessage);
      }
   
      return S_OK;
   }
   catch (...)
   {
      return COMError::GenerateGenericMessage();
   }
}
STDMETHODIMP InterfaceDatabase::UtilGetFileNameByMessageID(hyper lMessageID, BSTR *Output)
{
   try
   {
      if (!GetIsServerAdmin())
         return GetAccessDenied();
   
      HRESULT hRes = EnsureDatabaseConnectivity_();
      if (hRes != S_OK)
         return hRes;
   
      HM::String sSQL;
      sSQL.Format(_T("select messagefilename from hm_messages where messageid = %d"), lMessageID);
   
      std::shared_ptr<HM::DALRecordset> pRS = db_manager_->OpenRecordset(HM::SQLCommand(sSQL));
      if (!pRS)
         return S_OK;
   
      HM::String sRetVal = "";
      if (!pRS->IsEOF())
         sRetVal = pRS->GetStringValue("messagefilename");
   
   
      *Output = sRetVal.AllocSysString();
   
      return S_OK;
   }
   catch (...)
   {
      return COMError::GenerateGenericMessage();
   }
}
STDMETHODIMP InterfaceDatabase::get_CurrentVersion(long *pVal)
{
   try
   {
      if (!config_)
         return GetAccessDenied();

      /*
         Server administration privileges should not be required for this function. Reason is that
         user should be able to determine whether a database upgrade is needed without entering his
         password. Because we don't want the user to enter his password during every installation
         unless there's changes in the database.
      */
   
      HRESULT hRes = EnsureDatabaseConnectivity_();
      if (hRes != S_OK)
         return hRes;
   
      *pVal = db_manager_->GetCurrentDatabaseVersion();
      return S_OK;
   }
   catch (...)
   {
      return COMError::GenerateGenericMessage();
   }
}
STDMETHODIMP InterfaceApplication::get_Rules(IInterfaceRules **pVal)
{
    try
    {
        if (!authentication_->GetIsServerAdmin())
            return authentication_->GetAccessDenied();

        HRESULT hResult = EnsureDatabaseConnectivity_();
        if (hResult != S_OK)
            return hResult;

        CComObject<InterfaceRules >* pItem = new CComObject<InterfaceRules >();
        pItem->SetAuthentication(authentication_);

        std::shared_ptr<HM::Rules> pRules = std::shared_ptr<HM::Rules>(new HM::Rules(0));

        if (pRules)
        {
            pRules->Refresh();
            pItem->Attach(pRules);
            pItem->AddRef();
            *pVal = pItem;
        }

        return S_OK;
    }
    catch (...)
    {
        return COMError::GenerateGenericMessage();
    }
}
STDMETHODIMP InterfaceApplication::get_Domains(IInterfaceDomains **pVal)
{
    try
    {
        if (!authentication_->GetIsAuthenticated())
            return authentication_->GetAccessDenied();

        HRESULT hResult = EnsureDatabaseConnectivity_();
        if (hResult != S_OK)
            return hResult;


        CComObject<InterfaceDomains>* pInterfaceDomains = new CComObject<InterfaceDomains>;

        pInterfaceDomains->SetAuthentication(authentication_);
        pInterfaceDomains->Refresh();

        pInterfaceDomains->AddRef();
        *pVal = pInterfaceDomains;

        return S_OK;
    }
    catch (...)
    {
        return COMError::GenerateGenericMessage();
    }
}
STDMETHODIMP InterfaceApplication::get_BackupManager(IInterfaceBackupManager **pVal)
{
    try
    {
        if (!authentication_->GetIsServerAdmin())
            return authentication_->GetAccessDenied();

        HRESULT hResult = EnsureDatabaseConnectivity_();
        if (hResult != S_OK)
            return hResult;

        CComObject<InterfaceBackupManager>* pInterfaceBackupManager = new CComObject<InterfaceBackupManager>;
        pInterfaceBackupManager->SetAuthentication(authentication_);
        if (!pInterfaceBackupManager->LoadSettings())
            return COMError::GenerateError("Backup manager not available");

        pInterfaceBackupManager->AddRef();
        *pVal = pInterfaceBackupManager;

        return S_OK;
    }
    catch (...)
    {
        return COMError::GenerateGenericMessage();
    }
}
STDMETHODIMP InterfaceDatabase::ExecuteSQLWithReturn(BSTR sSQLStatement, long *uniqueID)
{
   try
   {
      if (!config_)
         return GetAccessDenied();

      if (!GetIsServerAdmin())
         return GetAccessDenied();
   
      if (uniqueID)
         *uniqueID = 0;
   
      HRESULT hRes = EnsureDatabaseConnectivity_();
      if (hRes != S_OK)
         return hRes;
   
      HM::String sStatement = sSQLStatement;
   
      HM::String sErrorMessage;
      if (conn_)
      {
         // Execute in the transaction we've started.
         __int64 value = 0;
         if (conn_->TryExecute(HM::SQLCommand(sStatement), sErrorMessage, &value, 0) == HM::DALConnection::DALSuccess)
         {
            if (uniqueID)
               *uniqueID = (long) value;
   
               return S_OK;
         }
      }
      else
      {
         __int64 value = 0;
   
         if (db_manager_->Execute(HM::SQLCommand(sStatement), &value, 0, sErrorMessage))
         {
            if (uniqueID)
               *uniqueID = (long) value;
   
            return S_OK;
         }
   
      }
   
      return COMError::GenerateError("Execution of SQL statement failed. Error: " + sErrorMessage);
   }
   catch (...)
   {
      return COMError::GenerateGenericMessage();
   }
}
STDMETHODIMP InterfaceDatabase::get_RequiresUpgrade(VARIANT_BOOL *pVal)
{
   try
   {
      if (!config_)
         return GetAccessDenied();

      HRESULT hRes = EnsureDatabaseConnectivity_();
      if (hRes != S_OK)
         return hRes;
      
      bool bUpgradeRequired = config_->GetRequiredDBVersion() > db_manager_->GetCurrentDatabaseVersion();
   
      *pVal = bUpgradeRequired ? VARIANT_TRUE : VARIANT_FALSE;
   
      return S_OK;
   }
   catch (...)
   {
      return COMError::GenerateGenericMessage();
   }
}
STDMETHODIMP InterfaceDatabase::ExecuteSQLScript(BSTR sFilename)
{
   try
   {
      if (!config_)
         return GetAccessDenied();

      if (!GetIsServerAdmin())
         return GetAccessDenied();
   
      HRESULT hRes = EnsureDatabaseConnectivity_();
      if (hRes != S_OK)
         return hRes;
   
      HM::String sErrorMessage;
      if (conn_)
      {
         HM::SQLScriptRunner scriptRunner;
         if (!scriptRunner.ExecuteScript(conn_, sFilename, sErrorMessage))
         {
            return COMError::GenerateError("Execution of SQL statements failed. Error: " + sErrorMessage);
         }
      }
      else
      {
         if (!db_manager_->ExecuteScript(sFilename, sErrorMessage))
         {
            return COMError::GenerateError("Execution of SQL statements failed. Error: " + sErrorMessage);
         }
      }
   
      return S_OK;
   }
   catch (...)
   {
      return COMError::GenerateGenericMessage();
   }
}
STDMETHODIMP InterfaceApplication::get_Links(IInterfaceLinks **pVal)
{
    try
    {
        if (!authentication_->GetIsServerAdmin())
            return authentication_->GetAccessDenied();

        HRESULT hResult = EnsureDatabaseConnectivity_();
        if (hResult != S_OK)
            return hResult;

        CComObject<InterfaceLinks>* pItem = new CComObject<InterfaceLinks >();
        pItem->SetAuthentication(authentication_);
        pItem->AddRef();
        *pVal = pItem;

        return S_OK;
    }
    catch (...)
    {
        return COMError::GenerateGenericMessage();
    }
}