/*++

Copyright (c) 1995  Microsoft Corporation

Module Name:

   util.c

Abstract:

   Contains general functions.

Author:

    Sanjay Anand (SanjayAn)  Nov. 14, 1995

Environment:

    User mode

Revision History:

    Sanjay Anand (SanjayAn) Nov. 14, 1995
        Created

--*/
#include "defs.h"

#define  CONV_LOG_FILE_NAME TEXT("%SystemRoot%\\System32\\jetconv.exe")
#define  CONV_MSGFILE_SKEY  TEXT("EventMessageFile")

HANDLE  EventlogHandle = NULL;

NTSTATUS
JCRegisterEventSrc()
/*++

Routine Description:

    This routine registers JetConv as an eventsource.

Arguments:

    None.

Return Value:

    None.

--*/
{
    TCHAR   temp[] = "JetConv";
    TCHAR   logName[MAX_PATH]=JCONV_LOG_KEY_PREFIX;
    TCHAR   Buff[MAX_PATH];
    LONG    RetVal = ERROR_SUCCESS;
    HKEY    LogRoot;
    DWORD   NewKeyInd;
    DWORD   dwData;

    strcat(logName, temp);

    //
    // Create the registry keys so we can register as an event source
    //

    RetVal =  RegCreateKeyEx(
                HKEY_LOCAL_MACHINE,        //predefined key value
                logName,                //subkey for JetConv
                0,                        //must be zero (reserved)
                TEXT("Class"),                //class -- may change in future
                REG_OPTION_NON_VOLATILE, //non-volatile information
                KEY_ALL_ACCESS,                //we desire all access to the keyo
                NULL,                         //let key have default sec. attributes
                &LogRoot,                //handle to key
                &NewKeyInd                //is it a new key (out arg) -- not
                                        //looked at
                );


    if (RetVal != ERROR_SUCCESS)
    {
        MYDEBUG(("RegCreateKeyEx failed %lx for %s\n", RetVal, logName));
        return(RetVal);
    }


    /*
        Set the event id message file name
    */
    lstrcpy(Buff, CONV_LOG_FILE_NAME);

    /*
       Add the Event-ID message-file name to the subkey
    */
    RetVal = RegSetValueEx(
                        LogRoot,            //key handle
                        CONV_MSGFILE_SKEY,   //value name
                        0,                    //must be zero
                        REG_EXPAND_SZ,            //value type
                        (LPBYTE)Buff,
                        (lstrlen(Buff) + 1) * sizeof(TCHAR)   //length of value data
                         );

    if (RetVal != ERROR_SUCCESS)
    {
        MYDEBUG(("RegSetValueEx failed %lx for %s", RetVal, Buff));
        return(RetVal);
    }

    /*
     Set the supported data types flags
    */
    dwData = EVENTLOG_ERROR_TYPE       |
            EVENTLOG_WARNING_TYPE     |
            EVENTLOG_INFORMATION_TYPE;


    RetVal = RegSetValueEx (
                        LogRoot,            //subkey handle
                        TEXT("TypesSupported"),  //value name
                        0,                    //must be zero
                        REG_DWORD,            //value type
                        (LPBYTE)&dwData,    //Address of value data
                        sizeof(DWORD)            //length of value data
                          );

    if (RetVal != ERROR_SUCCESS)
    {
        MYDEBUG(("RegSetValueEx failed %lx for TypesSupported on %s", RetVal, logName));
        return(RetVal);
    }

    /*
    * Done with the key.  Close it
    */
    RetVal = RegCloseKey(LogRoot);

    if (RetVal != ERROR_SUCCESS)
    {
        MYDEBUG(("RegCloseKey failed %lx\n", RetVal));
        return(RetVal);
    }

    //
    // Register JetConv as an event source
    //
    strcpy(logName, temp);

    if (!(EventlogHandle = RegisterEventSource( NULL,
                                                logName))) {
        MYDEBUG(("RegisterEventSource failed %lx\n", GetLastError()));
        return STATUS_UNSUCCESSFUL;
    } else {
        MYDEBUG(("RegisterEventSource succeeded\n"));
        return STATUS_SUCCESS;
    }
}

NTSTATUS
JCDeRegisterEventSrc()
/*++

Routine Description:

    This routine deregisters eventsources corresponding to those service that
    are installed in the system.

Arguments:

    None.

Return Value:

    NtStatus.

--*/
{
    if (EventlogHandle) {
        if (!DeregisterEventSource(EventlogHandle)) {
            MYDEBUG(("DeregisterEventSource failed:  %lx for %s", GetLastError()));
            return STATUS_UNSUCCESSFUL;
        } else {
            return STATUS_SUCCESS;
        }
    }
}

VOID
JCLogEvent(
    DWORD EventId,
    LPSTR MsgTypeString1,
    LPSTR MsgTypeString2 OPTIONAL,
    LPSTR MsgTypeString3 OPTIONAL
    )

/*++

Routine Description:

    This routine logs an entry in the eventlog.

Arguments:

    EventId - the event identifier

    MsgTypeString1 - string to be output

    MsgTypeString2 - string2 to be output (OPTIONAL)

Return Value:

    None.

--*/
{
    LPSTR   Strings[3];
    WORD    numStr;

    Strings[0] = MsgTypeString1;
    Strings[1] = MsgTypeString2;
    Strings[2] = MsgTypeString3;

    if (MsgTypeString3) {
        numStr = 3;
    } else if (MsgTypeString2) {
        numStr = 2;
    } else {
        numStr = 1;
    }


    if( !ReportEvent(
            EventlogHandle,
            (WORD)EVENTLOG_INFORMATION_TYPE,
            0,            // event category
            EventId,
            NULL,
            numStr,
            0,
            Strings,
            NULL) ) {

        MYDEBUG(("ReportEvent failed %ld.", GetLastError() ));
    }

    return;
}


VOID
JCReadRegistry(
    IN  PSERVICE_INFO   pServiceInfo
    )
/*++

Routine Description:

    This routine reads the registry to determine which of the service
    among WINS, DHCP and RPL are installed. For those installed, it
    fills in the ServiceInfo structure.

Arguments:

    pServiceInfo - Pointer to the service information struct.

Return Value:

    None.

--*/

{
    HKEY    hkey ;
    SERVICES    i ;
    DWORD   type ;
    DWORD   size = 0 ;
    DWORD   error;
    TCHAR   tempPath[MAX_PATH];
    TCHAR   servicePath[MAX_PATH];
    TCHAR   parametersPath[MAX_PATH];
    TCHAR   dbfilePath[MAX_PATH];
    TCHAR   dbfileName[MAX_PATH];
    TCHAR   backupFilePath[MAX_PATH];
    TCHAR   logfilePath[MAX_PATH];

    for ( i = 0; i < NUM_SERVICES; i++) {

        switch (i) {
        case WINS:
            strcpy(servicePath, WINS_REGISTRY_SERVICE_PATH);
            strcpy(parametersPath, WINS_REGISTRY_PARAMETERS_PATH);
            strcpy(dbfilePath, WINS_REGISTRY_DBFILE_PATH);
            strcpy(logfilePath, WINS_REGISTRY_LOGFILE_PATH);
            strcpy(backupFilePath, WINS_REGISTRY_BACKUP_PATH);

            break;

        case DHCP:
            strcpy(servicePath, DHCP_REGISTRY_SERVICE_PATH);
            strcpy(parametersPath, DHCP_REGISTRY_PARAMETERS_PATH);
            strcpy(dbfilePath, DHCP_REGISTRY_DBFILE_PATH);
            strcpy(dbfileName, DHCP_REGISTRY_DBFILE_NAME);
            // strcpy(logfilePath, DHCP_REGISTRY_LOGFILE_PATH);
            strcpy(backupFilePath, DHCP_REGISTRY_BACKUP_PATH);

            break;

        case RPL:
            strcpy(servicePath, RPL_REGISTRY_SERVICE_PATH);
            strcpy(parametersPath, RPL_REGISTRY_PARAMETERS_PATH);
            strcpy(dbfilePath, RPL_REGISTRY_DBFILE_PATH);

            // no such path
            // strcpy(logfilePath, RPL_REGISTRY_LOGFILE_PATH);
            // strcpy(backupFilePath, RPL_REGISTRY_BACKUP_PATH);

            break;
        }

        //
        // Check if service is installed -  if the service name key is
        // present, it is installed.
        //
        if ((error = RegOpenKey(HKEY_LOCAL_MACHINE,
                                servicePath,
                                &hkey)) != ERROR_SUCCESS) {

            MYDEBUG(("RegOpenKey %s returned error: %lx\n", pServiceInfo[i].ServiceName, error));
            MYDEBUG(("%s not installed\n", pServiceInfo[i].ServiceName));
            pServiceInfo[i].Installed = FALSE;
            continue;
        }

        pServiceInfo[i].Installed = TRUE;
        size = MAX_PATH;

        if ((error = JCRegisterEventSrc()) != ERROR_SUCCESS) {
            MYDEBUG(("JCRegisterEventSrc failed\n"));
            pServiceInfo[i].Installed = FALSE;
            continue;
        }

        //
        // Open the parameters key
        //
        if ((error = RegOpenKeyEx(  HKEY_LOCAL_MACHINE,
                                    parametersPath,
                                    0,
                                    KEY_ALL_ACCESS,
                                    &hkey)) != ERROR_SUCCESS) {

            MYDEBUG(("RegOpenKeyEx %s\\Parameters returned error: %lx\n", pServiceInfo[i].ServiceName, error));

        } else {
            //
            // Read in the path to the Dbase file.
            //
            size = MAX_PATH;
            if ((error = RegQueryValueEx(hkey,
                                         dbfilePath,
                                         NULL,
                                         &type,
                                         pServiceInfo[i].DBPath,
                                         &size)) != ERROR_SUCCESS) {

                MYDEBUG(("RegQueryValueEx of %s dbpath failed: %lx\n", pServiceInfo[i].ServiceName, error));

                //
                // If no path parameter, it shd be in %systemroot%\system32\<service> - the path was initialized to
                // the default.
                //
                MYDEBUG(("%s dbfile path not present; assuming it is in %s\n",
                                            pServiceInfo[i].ServiceName, pServiceInfo[i].DBPath));
            } else {

                pServiceInfo[i].DefaultDbPath = FALSE;

                //
                // DHCP splits the name and path
                //
                if (i == DHCP) {
                    TCHAR   dhcpDBFileName[MAX_PATH];

                    //
                    // Copy this path to the logfilepath too.
                    //
                    strcpy(pServiceInfo[i].LogFilePath, pServiceInfo[i].DBPath);

                    //
                    // Read the name too
                    //
                    size = MAX_PATH;
                    if ((error = RegQueryValueEx(hkey,
                                                 dbfileName,
                                                 NULL,
                                                 &type,
                                                 dhcpDBFileName,
                                                 &size)) != ERROR_SUCCESS) {

                        MYDEBUG(("RegQueryValueEx of %s dbName failed: %lx\n", pServiceInfo[i].ServiceName, error));

                        //
                        // If no path parameter, it shd be in %systemroot%\system32\<service> - the path was initialized to
                        // the default.
                        //
                        MYDEBUG(("%s dbfile name not present; assuming it is dhcp.mdb\n",
                                                    pServiceInfo[i].ServiceName));

                        strcat(pServiceInfo[i].DBPath, TEXT("\\dhcp.mdb"));

                    } else {
                        strcat(pServiceInfo[i].DBPath, TEXT("\\"));
                        strcat(pServiceInfo[i].DBPath, dhcpDBFileName);
                    }
                } else if (i == RPL) {

                    //
                    // Copy this path to the logfilepath too.
                    //
                    strcpy(pServiceInfo[i].LogFilePath, pServiceInfo[i].DBPath);

                    //
                    // Copy this path to the backuppath too
                    //
                    strcpy(pServiceInfo[i].BackupPath, pServiceInfo[i].DBPath);
                    strcat(pServiceInfo[i].BackupPath, TEXT("\\backup"));

                    //
                    // The DBFile is always called rplsvc.mdb
                    //
                    strcat(pServiceInfo[i].DBPath, TEXT("\\rplsvc.mdb"));
                }

            }

            //
            // Read in the path to the Log file.
            // In case of RPL, no such paths exist.
            // Assume they are in the same directory as the database files.
            //
            if (i != RPL) {

                //
                // DHCP has no logfilepath
                //
                if (i != DHCP) {
                    size = MAX_PATH;
                    if ((error = RegQueryValueEx(hkey,
                                                 logfilePath,
                                                 NULL,
                                                 &type,
                                                 pServiceInfo[i].LogFilePath,
                                                 &size)) != ERROR_SUCCESS) {

                        MYDEBUG(("RegQueryValueEx of %s logfilepath failed: %lx\n", pServiceInfo[i].ServiceName, error));

                        //
                        // If no path parameter, it shd be in %systemroot%\system32\<service> - the path was initialized to
                        // the default.
                        //
                        MYDEBUG(("%s logfile path not present; assuming it is in %s\n",
                                                    pServiceInfo[i].ServiceName, pServiceInfo[i].LogFilePath));
                    } else {
                        pServiceInfo[i].DefaultLogFilePath = FALSE;
                    }
                }

                //
                // Read in the path to the backup file.
                //

                size = MAX_PATH;
                if ((error = RegQueryValueEx(hkey,
                                             backupFilePath,
                                             NULL,
                                             &type,
                                             pServiceInfo[i].BackupPath,
                                             &size)) != ERROR_SUCCESS) {

                    MYDEBUG(("RegQueryValueEx of %s BackupPath failed: %lx\n", pServiceInfo[i].ServiceName, error));

                    //
                    // If no path parameter, it shd be in %systemroot%\system32\<service> - the path was initialized to
                    // the default.
                    //
                    MYDEBUG(("%s backupfile path not present; assuming it is in %s\n",
                                                pServiceInfo[i].ServiceName, pServiceInfo[i].BackupPath));
                }
            }
        }

        //
        // Expand the environment variables in the path.
        //
        strcpy(tempPath, pServiceInfo[i].DBPath);

        if ((size = ExpandEnvironmentStrings( tempPath,
                                              pServiceInfo[i].DBPath,
                                              MAX_PATH)) == 0) {
            error = GetLastError();
            MYDEBUG(("ExpandEnvironmentVaraibles %s returned error: %lx\n", pServiceInfo[i].ServiceName, error));
        }

        SystemDrive[0] = pServiceInfo[i].DBPath[0];
        SystemDrive[1] = pServiceInfo[i].DBPath[1];
        SystemDrive[2] = pServiceInfo[i].DBPath[2];
        SystemDrive[3] = '\0';

        MYDEBUG(("pServiceInfo[i].DbasePath: %s\n", pServiceInfo[i].DBPath));

        //
        // Expand the environment variables in the log file path.
        //
        strcpy(tempPath, pServiceInfo[i].LogFilePath);

        if ((size = ExpandEnvironmentStrings( tempPath,
                                              pServiceInfo[i].LogFilePath,
                                              MAX_PATH)) == 0) {
            error = GetLastError();
            MYDEBUG(("ExpandEnvironmentVaraibles %s returned error: %lx\n", pServiceInfo[i].ServiceName, error));
        }

        MYDEBUG(("pServiceInfo[i].LogFilePath: %s\n", pServiceInfo[i].LogFilePath));

        //
        // Expand the environment variables in the backup file path.
        //
        strcpy(tempPath, pServiceInfo[i].BackupPath);

        if ((size = ExpandEnvironmentStrings( tempPath,
                                              pServiceInfo[i].BackupPath,
                                              MAX_PATH)) == 0) {
            error = GetLastError();
            MYDEBUG(("ExpandEnvironmentVaraibles %s returned error: %lx\n", pServiceInfo[i].ServiceName, error));
        }

        MYDEBUG(("pServiceInfo[i].BackupPath: %s\n", pServiceInfo[i].BackupPath));
    }
}

VOID
JCGetMutex (
    IN HANDLE hMutex,
    IN DWORD To
    )
/*++

Routine Description:

    This routine waits on a mutex object.

Arguments:

    hMutex - handle to mutex

    To - time to wait

Return Value:

    None.

--*/
{
    if (WaitForSingleObject (hMutex, To) == WAIT_FAILED) {
        MYDEBUG(("WaitForSingleObject failed: %lx\n", GetLastError()));
    }
}

VOID
JCFreeMutex (
    IN HANDLE hMutex
    )

/*++

Routine Description:

    This routine releases a mutex.

Arguments:

    hMutex - handle to mutex

Return Value:

    None.

--*/
{
    if (!ReleaseMutex(hMutex)) {
        MYDEBUG(("ReleaseMutex failed: %lx\n", GetLastError()));
    }
}