/*!
  @file           vos97.c
  @author         RaymondR
  @brief          get SERVERDB and XSERVER status
  @see            

\if EMIT_LICENCE

    ========== licence begin  GPL
    Copyright (c) 2001-2005 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end



\endif
*/




/*
 * INCLUDE FILES
 */
//#include "gos00.h"
#include "heo00.h"
#include "heo46.h"
#include "geo007_1.h"   
#include "heo11.h"
#include "gos41.h"


#if defined (USER)
# include "gsp09.h"      /* nocheck */
#endif

/*
 *  DEFINES
 */
#define USE_REGISTRY

#define MOD__  "VOS97C : "
#define MF__   MOD__"UNDEFINED"

#define PARAM_SEARCH_KEY             "KERNELVERSION"
#define SEARCH_PATTERN               "*."
#define FILE_ATTRIBUTE               0
#define DEFAULT_SERVICE_BUF          16384

#define USE_SERVICE_MANAGER

/*
 *  MACROS
 */


/*
 *  LOCAL TYPE AND STRUCT DEFINITIONS
 */

/*
 * EXTERNAL VARIABLES
 */


/*
 *  EXPORTED VARIABLES
 */


/*
 * LOCAL VARIABLES
 */

 #if defined ( USE_SERVICE_MANAGER )
  static LPENUM_SERVICE_STATUS               lpessService           = NULL;
  static ULONG                               ulNumServices;
  static ULONG                               ulCurrService          = 0;
  static ULONG                               ulCurrServerType       = SERVER_TYPE_SERVERDB;
 #endif

 static WIN32_FIND_DATA                      FindData;
 static HANDLE                               FindHandle;

/*
 * LOCAL FUNCTION PROTOTYPES
 */
static VOID sql97_check_param_file ( PSZ    pszServerDB,
                                     PBOOL  pfOk );

#if defined (_WIN32) && defined ( USE_SERVICE_MANAGER )
 static BOOL sql97_get_next_db_gw( ULONG     ulServerType,
                                   PSZ       pszServerDB,
                                   PBOOL     pfActive );
#endif


/*
 * ========================== GLOBAL FUNCTIONS ================================
 */


#if defined (_WIN32) && defined ( USE_SERVICE_MANAGER )

#include "gsp09.h"

/*
  Function: os97_IsServiceRunning
  Description: Check if given service is running or start pending
  Arguments: hSCM [in] handle to service control manager
             serviceName [in] service name (not display name) of service to test
  Return value: TRUE if service is running or start pending, FALSE else
 */
static bool os97_IsServiceRunning(SC_HANDLE hSCM, 
                                  const char *serviceName)
{
    SERVICE_STATUS serviceStatus;
    SC_HANDLE hService;
    DWORD rc;
    bool result = false;

    hService = OpenService(hSCM, serviceName, SERVICE_QUERY_STATUS );
    if ( !hService )
    {
        rc = GetLastError();
        if ( rc != ERROR_SERVICE_DOES_NOT_EXIST )
        {
            MSGCD(( ERR_OPEN_SERVICE_MANAGER, rc ));
        }
    }
    else
    {
        if ( QueryServiceStatus( hService,         // handle of service
                                &serviceStatus  // address of service status structure
                               ) )
        {
            result = ( (serviceStatus.dwCurrentState == SERVICE_RUNNING) 
                    || (serviceStatus.dwCurrentState == SERVICE_START_PENDING) );  
        }
        if (!CloseServiceHandle(hService))
        {
            DWORD rc = GetLastError();
            MSGCD(( ERR_CLOSE_SERVICE_MANAGER, rc ));
        }
    }
    return result;
}

//--------------------------------------------------------

/*
  Function: os97_IsServiceRunning
  Description: Check if given service is running or start pending
  Arguments: hSCM [in] handle to service control manager
             serviceName [in] service name (not display name) of service to test
  Return value: TRUE if service is running or start pending, FALSE else
 */
tsp9_pgm_kind sqlDBSpeed( const tsp00_DbNamec szDbName )
{
    #undef MF__
    #define MF__ MOD__"sqlDBSpeed"
    SC_HANDLE hSCM;
    char serviceName[256];
    tsp9_pgm_kind runningKind = csp9_any_pgm;

    DBGIN;

    hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_QUERY_LOCK_STATUS);
    if ( !hSCM )
    {
        DWORD rc = GetLastError();
        if ( rc != ERROR_SERVICE_DOES_NOT_EXIST )
        {
            MSGCD(( ERR_OPEN_SERVICE_MANAGER, rc ));
        }
    }
    else
    {
        sprintf(serviceName, "%s%s", SERVICE_ID, szDbName);
        if ( os97_IsServiceRunning( hSCM, serviceName ) )
        {
            runningKind = csp9_fast_pgm;
        }
        else
        {
            sprintf(serviceName, "%s%s%s", SERVICE_ID, szDbName, SERVICE_SLOW_EXT);
            if ( os97_IsServiceRunning( hSCM, serviceName ) )
            {
                runningKind = csp9_slow_pgm;
            }
            else
            {
                sprintf(serviceName, "%s%s%s", SERVICE_ID, szDbName, SERVICE_QUICK_EXT);
                if ( os97_IsServiceRunning( hSCM, serviceName ) )
                {
                    runningKind = csp9_quick_pgm;
                }
                else
                {
                    sprintf(serviceName, "%s%s%s", SERVICE_ID, szDbName, SERVICE_TEST_EXT);
                    if ( os97_IsServiceRunning( hSCM, serviceName ) )
                    {
                        runningKind = csp9_test_pgm;
                    }
                }
            }
        }

        if (!CloseServiceHandle(hSCM))
        {
            DWORD rc = GetLastError();
            MSGCD(( ERR_CLOSE_SERVICE_MANAGER, rc ));
        }
    }

    DBGOUT;

    return runningKind;
}

//--------------------------------------------------------

 APIRET sql97_update ( PSZ    pszNodeName )
   {
   #undef  MF__
   #define MF__ MOD__"sql97_update"
   APIRET                 rc               = NO_ERROR;
   ULONG                  ulSize           = DEFAULT_SERVICE_BUF;
   ULONG                  ulRemaining      = 0;
   ULONG                  ulResumeHandle;
   SC_HANDLE              hScM;

   DBGIN;

   if ( sql02_get_platform_id() != VER_PLATFORM_WIN32_NT )
     {
     // --- Windows 95 - nothing to do !!!!!!!
     DBGOUT;
     return ( NO_ERROR );
     }

   // --- free old buffer
   if ( lpessService != NULL )
     {
     rc = FREE_MEM ( lpessService );

     lpessService = NULL;

     if ( rc != NO_ERROR )
       {
       DBGOUT;
       return( rc );
       }
     }



   for ( ;; )
     {
     if (!(hScM = OpenSCManager( pszNodeName, NULL, SC_MANAGER_ENUMERATE_SERVICE)))
       {
       rc = GetLastError();

       switch ( rc )
         {
         case ERROR_ACCESS_DENIED:      MSGCD (( ERR_ACCESS_DENIED ));
                                        break;
         case RPC_S_SERVER_UNAVAILABLE: MSGCD (( ERR_SERVER_NODE_UNKNOWN, pszNodeName ));
                                        break;
         default:                       MSGCD(( ERR_OPEN_SERVICE_MANAGER, rc ));
                                        break;
         }
       DBGOUT;
       return ( rc );
       }

     // --- allocate space for the result buffer
     rc = ALLOC_MEM ( &lpessService, ulSize );

     if ( rc != NO_ERROR )
       {
       lpessService = NULL;
       DBGOUT;
       return( rc );
       }

     ulCurrService    = (ULONG)UNDEF;
     ulNumServices    = 0;
     ulResumeHandle   = 0;

     // --- now we ask for the service entries
     if (!EnumServicesStatus( hScM, SERVICE_WIN32,
                              SERVICE_ACTIVE | SERVICE_INACTIVE,
                              lpessService, ulSize,
                              &ulRemaining, &ulNumServices,
                              &ulResumeHandle ))
       {
       rc = GetLastError ();

       if (( rc != NO_ERROR ) && ( rc != ERROR_MORE_DATA ))
         {
         FREE_MEM ( lpessService );
         lpessService = NULL;
         DBGOUT;
         return ( rc );
         }

       rc = FREE_MEM ( lpessService );

       lpessService = NULL;

       if ( rc != NO_ERROR )
         {
         DBGOUT;
         return( rc );
         }

       if (!CloseServiceHandle(hScM))
         {
         rc = GetLastError();
         MSGCD(( ERR_CLOSE_SERVICE_MANAGER, rc ));

         DBGOUT;
         return ( rc );
         }

       ulSize = ulSize + ulRemaining;
       }
     else
       break;
     }

    if (!CloseServiceHandle(hScM) && rc == NO_ERROR)
      {
      rc = GetLastError();
      MSGCD(( ERR_CLOSE_SERVICE_MANAGER, rc ));

      DBGOUT;
      return ( rc );
      }

   DBGOUT;
   return ( rc );
   }

#endif

/*------------------------------*/

APIRET sql97_first_db_gw_state ( ULONG     ulServerType,
                                 PSZ       pszServerDB,
                                 PBOOL     pfActive )
  {
  #undef  MF__
  #define MF__ MOD__"sql97_first_db_gw_state"
  PATHNAME        szSearchName;
  PSZ             pszFileName;
  tsp00_Pathc     pszConfigPath;
  BOOL            fValidParamFile;
  APIRET          rc                = NO_ERROR;
  ULONG           FindCount         = 1;
  HEV             hevSem            = 0;
  tsp01_RteError  RteError ;

  #if defined (_WIN32) && defined ( USE_SERVICE_MANAGER )
   if ( sql02_get_platform_id() == VER_PLATFORM_WIN32_NT )
     {
     ulCurrService    = 0;
     ulCurrServerType = ulServerType;

     if ( sql97_get_next_db_gw ( ulServerType, pszServerDB, pfActive ) )
       {
       DBGOUT;
       return( NO_ERROR );
       }

     DBGOUT;
     return ( ERROR_NO_MORE_FILES );
     }
  #endif

  *pfActive = FALSE;

  pszFileName = FindData.cFileName;


  /* PTS 1107043 */
  if ( !sqlGetIndependentConfigPath ( pszConfigPath, TERM_WITH_DELIMITER_EO01, &RteError ) )
  {
    MSGCD(( ERR_CANT_GET_CONFIG_PATH ))
	MSGCD(( ERR_RTE_ERROR, RteError.RteErrCode, RteError.RteErrText )) ;
	MSGCD(( ERR_OS_ERROR , RteError.OsErrCode,  RteError.OsErrText )) ;
    return ( !NO_ERROR ) ;
  }

  strcpy (szSearchName, pszConfigPath ) ;
  strcat (szSearchName, SEARCH_PATTERN);


   FindHandle = FindFirstFile(szSearchName, &FindData);

   if (FindHandle == INVALID_HANDLE_VALUE)
     {
     rc = GetLastError();
     }
   else
     CharUpper(FindData.cFileName);

  if ( rc == ERROR_PATH_NOT_FOUND )
    {
    MSGCD((ERR_WRONG_DBROOT_PATH, pszConfigPath));
    return ( rc );
    }
  else if ( rc == NO_ERROR )
    {
    do
      {
      if ( strrchr ( pszFileName, '.' ) != NULL )
        fValidParamFile = FALSE;
      else
        sql97_check_param_file ( pszFileName, &fValidParamFile );

      if ( fValidParamFile == FALSE )
        {
        #if defined(_WIN32)
         if (!FindNextFile(FindHandle, &FindData))
           {
           rc = GetLastError();
           FindClose(FindHandle);
           }
         else
           CharUpper(FindData.cFileName);
        #else
         rc = DosFindNext(FindHandle,           // --- Directory handle
                          (PVOID) &FindBuffer,  // --- Result buffer
                          sizeof(FindBuffer),   // --- Result buffer length
                          &FindCount);          // --- Number of entries to find

         if (( rc == ERROR_NO_MORE_FILES ) || ( !FindCount ))
           {
           rc = ERROR_NO_MORE_FILES;
           DosFindClose(FindHandle);
           }
        #endif
        }
      }
    while (( fValidParamFile == FALSE ) && ( rc == NO_ERROR ));


    if (( fValidParamFile == TRUE ) && ( rc == NO_ERROR ))
      {
      pszServerDB[MX_DBNAME] = '\0';
      strncpy ( pszServerDB, pszFileName, MX_DBNAME );

      rc = sql41c_open_event_sem ( &hevSem, SEM_COORD,
                                   pszFileName, ERROR_ACCESS_DENIED);

      if ((rc == NO_ERROR) || (rc == ERROR_ACCESS_DENIED))
        {
        *pfActive = TRUE;

        if (rc == NO_ERROR)
          sql41c_close_event_sem ( hevSem, "COORD" );
        rc = NO_ERROR;
        }
      else if ( rc == ERROR_SEM_NOT_FOUND )
        rc = NO_ERROR;
      }
    }


  DBGOUT;
  return ( rc );
  }

/*------------------------------*/

APIRET sql97_next_db_gw_state ( PSZ       pszServerDB,
                                PBOOL     pfActive )
  {
  #undef  MF__
  #define MF__ MOD__"sql97_next_db_gw_state"
  APIRET    rc        = NO_ERROR;
  ULONG     FindCount = 1;
  HEV       hevSem    = 0;
  BOOL      fValidParamFile;
  PSZ       pszFileName;

  #if defined (_WIN32) && defined ( USE_SERVICE_MANAGER )
   if ( sql02_get_platform_id() == VER_PLATFORM_WIN32_NT )
     {
     if ( lpessService == NULL )
       {
       DBGOUT;
       return ( ERROR_NO_MORE_FILES );
       }

     if ( sql97_get_next_db_gw ( ulCurrServerType, pszServerDB, pfActive ) )
       {
       DBGOUT;
       return( NO_ERROR );
       }

     DBGOUT;
     return ( ERROR_NO_MORE_FILES );
     }
  #endif

  *pfActive   = FALSE;

   pszFileName = FindData.cFileName;

  do
    {
     if (!FindNextFile(FindHandle, &FindData))
       {
       rc = GetLastError();
       FindClose(FindHandle);
       }

    if ( rc == NO_ERROR )
      {
      if ( strrchr ( pszFileName, '.' ) != NULL )
        fValidParamFile = FALSE;
      else
        sql97_check_param_file ( pszFileName, &fValidParamFile );
      }
    }
  while (( fValidParamFile == FALSE ) && ( rc == NO_ERROR ));


  if (( fValidParamFile == TRUE ) && ( rc == NO_ERROR ))
    {
    pszServerDB[MX_DBNAME] = '\0';
    strncpy ( pszServerDB, pszFileName, MX_DBNAME );

    rc = sql41c_open_event_sem ( &hevSem, SEM_COORD,
                                 pszFileName, ERROR_ACCESS_DENIED);

    if ((rc == NO_ERROR) || (rc == ERROR_ACCESS_DENIED))
      {
      *pfActive = TRUE;

      if (rc == NO_ERROR)
        sql41c_close_event_sem ( hevSem, "COORD" );
      rc = NO_ERROR;
      }
    else if ( rc == ERROR_SEM_NOT_FOUND )
      rc = NO_ERROR;
    }

  DBGOUT;
  return ( rc );
  }

/*------------------------------*/

APIRET sql97_xserver_state ( PSZ  pszNodeName, PBOOL  pfActive )
  {
  #undef  MF__
  #define MF__ MOD__"sql97_xserver_state"
  APIRET    rc     = NO_ERROR;
  HEV       hevSem = 0;
  #if defined (_WIN32) && defined ( USE_SERVICE_MANAGER )
   ULONG    ulCurrServ;
  #endif

 *pfActive   = FALSE;

  #if defined (_WIN32) && defined ( USE_SERVICE_MANAGER )
   if ( sql02_get_platform_id() == VER_PLATFORM_WIN32_NT )
     {
     for (ulCurrServ = 0; ulCurrServ < ulNumServices; ulCurrServ++ )
       {
       if (! strncmp( lpessService[ulCurrServ].lpServiceName, XSERV_TITLE,
                      sizeof(SERVICE_ID) - 1))
         {
         switch ( lpessService[ulCurrServ].ServiceStatus.dwCurrentState )
           {
           case SERVICE_START_PENDING:
           case SERVICE_RUNNING:
             *pfActive   = TRUE;
             break;
           default:
             *pfActive   = FALSE;
             break;
           }

         ulCurrServ++;

         DBGOUT;
         return( NO_ERROR );
         }
       }
     DBGOUT;
     return ( rc );
     }
  #endif

  // --- check SERVER
  rc = sql41c_open_event_sem ( &hevSem, SEM_XSERVER, "",
                               ERROR_ACCESS_DENIED);

  if (rc == ERROR_ACCESS_DENIED)
    {
    *pfActive = TRUE;
    rc        = NO_ERROR;
    }
  else if ( rc == ERROR_SEM_NOT_FOUND )
    {
    *pfActive = FALSE;
    rc        = NO_ERROR;
    }
  else if (rc == NO_ERROR)
    {
    sql41c_close_event_sem ( hevSem, XSERV_TITLE );
    *pfActive = TRUE;
    }
  else
    *pfActive = FALSE;

  DBGOUT;
  return ( rc );
  }


/*
 * ========================== LOCAL FUNCTIONS =================================
 */

static VOID sql97_check_param_file ( PSZ   pszServerDB,
                                     PBOOL pfValidParamFile )
  {
  #undef  MF__
  #define MF__ MOD__"sql97_check_param_file"
  tsp01_RteError          RteError ;
  tsp00_C64c              XpValueC ;

  DBGPAS;

  // --- display no error messages

  sql60_disable_message_output ();

  eo11GetParam (pszServerDB, PARAM_SEARCH_KEY, XpValueC, &RteError ) ;

  *pfValidParamFile = RteError.RteErrCode == RTE_NO_ERROR_SP01 ;

  sql60_enable_message_output();
  }

/*------------------------------*/

#if defined (_WIN32) && defined ( USE_SERVICE_MANAGER )

 static BOOL sql97_get_next_db_gw ( ULONG     ulServerType,
                                    PSZ       pszServerDB,
                                    PBOOL     pfActive )
   {
   #undef  MF__
   #define MF__ MOD__"sql97_get_next_db_gw"
   PSZ    pszServiceID;

   DBGIN;


   switch(ulServerType)
     {
     case SERVER_TYPE_ADABAS_SERVERDB :
       pszServiceID = ADABAS_SERVICE_ID;
       break;
     case SERVER_TYPE_ADABAS_GATEWAY :
       pszServiceID = ADABAS_SERVICE_ID_GW;
       break;
     case SERVER_TYPE_GATEWAY :
       pszServiceID = SERVICE_ID_GW;
       break;
     default:
       pszServiceID = SERVICE_ID;
       break;
     }

   for (; ulCurrService < ulNumServices; ulCurrService++ )
     {
     if (! strncmp( lpessService[ulCurrService].lpServiceName, pszServiceID,
                    strlen(pszServiceID)))
       {
       strncpy( pszServerDB, lpessService[ulCurrService].lpServiceName +
                strlen(pszServiceID), MX_DBNAME );

       switch ( lpessService[ulCurrService].ServiceStatus.dwCurrentState )
         {
         case SERVICE_START_PENDING:
         case SERVICE_RUNNING:
           *pfActive   = TRUE;
           break;
         default:
           *pfActive   = FALSE;
           break;
         }

       ulCurrService++;

       DBGOUT;
       return ( TRUE );
       }
     }

   DBGOUT;
   return ( FALSE );
   }

#endif

/*
 * =============================== END ========================================
 */

