@python -x "%~f0" %* & goto :EOF
#
# CheckNetworkSettings
#
# - check for Enable DNS for Windows Resolution setting
# - check for lower case host name
# - check protocol binding order of network adapters
# - optionally reboot if problems found
#
# Note this is all very dependent on assumptions about undocumented 
# (or poorly documented) NT registry settings. If Microsoft were to change them, 
# it might break this, but I doubt if they'd do that because it would probably
# break a zillion other programs also
#

import os
import re
import socket
import sys
import string
import struct
import time
from types import *

import winerror
import win32con
import win32api
import win32pipe
import win32file
#import win32security
import strptime

import windll
advapi32 = windll.module( 'advapi32' )

from com.creo.araxi.AraxiRegistry import AraxiRegistry
from com.creo.win32.Registry import RegistryKey
from com.creo.araxi import DIAG

EXIT_SUCCESS = 0
EXIT_FAILURE = 1

TRUE = (0 == 0)
FALSE = (0 == 1)

RESERVED = 0

OFF = 0
ON = 1

# Intel network cards should be using a driver no earlier than
# this date on W2K
LatestNetworkDriverDate = '1-7-2000'

# Length of time (in seconds) a secondary should keep polling 
# the Araxi service on the primary, waiting for it to start.
WaitForPrimaryTimeout = 900
PollFreq = 15

# Location of the ini file which lists which system network checks are
# enabled or disabled.
inifile = None

# Flags that are set externally by an *.ini file to indicate which system
# checks should be performed.  By default, all the checks are turned ON.
kAdaptiveTechSettingCheck = ON
kCriticalUpdateCheck = ON
kDNSServerSetupCheck = ON    
kDLTDriversCheck = ON         
kDriverDateCheck = ON        
kEnableDnsForWindowsResolutionSettingCheck = ON
kHostNameCheck = ON   
kPrimaryNodeNameCheck = ON        
kMaintModeCheck = ON  
kNetBEUICheck = ON                   
kNetBiosSettingCheck = ON 
kOrbacusIPAddressCheck = ON
kPrimaryRunningCheck = ON 
kProtocolBindingOrderCheck = ON
kServicePackLevelCheck = ON
kSystemPathCheck = ON        
kTCPIPBindingOrderCheck = ON         
kTempVarsCheck = ON      
kTimeSyncCheck = ON 
kCreateRebootFlag = ON
kRunOnceFlag = ON


# -----------------------------------------------------------------------------
# annoying error message box that stays in front and can be popped up by faceless service
def Alert( msg, style=win32con.MB_OK ):
    flags = style | win32con.MB_ICONSTOP | win32con.MB_SETFOREGROUND | win32con.MB_SERVICE_NOTIFICATION
    title = 'Prinergy System Configuration Error'
    return win32api.MessageBox( 0, msg, title, flags )

# -----------------------------------------------------------------------------
# annoying error message box that stays in front and can be popped up by faceless service
def AlertWarning( msg, style=win32con.MB_OK ):
    flags = style | win32con.MB_ICONQUESTION | win32con.MB_SETFOREGROUND | win32con.MB_SERVICE_NOTIFICATION
    title = 'Prinergy System Configuration Warning'
    return win32api.MessageBox( 0, msg, title, flags )
                    
# -----------------------------------------------------------------------------

# reboot, forcing apps to close
def Reboot():
    #response = raw_input( 'Are you really really sure you want to reboot? (y/n) ' )
    #if response != 'y':
    #    return

    hProcess = win32api.GetCurrentProcess()
    privs = win32con.TOKEN_ADJUST_PRIVILEGES | win32con.TOKEN_QUERY
    #hToken = win32security.OpenProcessToken( hProcess, privs )
    tokbuf = windll.membuf( 4 )
    bSuccess = advapi32.OpenProcessToken( hProcess, privs, tokbuf )
    if not bSuccess:
        errcode = win32api.GetLastError()
        raise win32api.error( errcode, 'LookupPrivilegeValue', win32api.FormatMessage( errcode ) )
    (hToken,) = struct.unpack( 'I', tokbuf.mb.read() )
    #print hToken
    
    #localnode = win32api.GetComputerName()
    #luid = win32security.LookupPrivilegeValue( localnode, win32con.SE_SHUTDOWN_NAME )
    #print luid, type(luid)
    #bDontDisableAll = 0
    #TOKEN_PRIVILEGES = [ ( luid, win32con.SE_PRIVILEGE_ENABLED ) ]
    #win32security.AdjustTokenPrivileges( hToken, 0, TOKEN_PRIVILEGES )
    
    luidbuf = windll.membuf( 8 )
    privname = windll.cstring( win32con.SE_SHUTDOWN_NAME )
    bSuccess = advapi32.LookupPrivilegeValue( 0, privname, luidbuf )
    #print bSuccess
    if not bSuccess:
        errcode = win32api.GetLastError()
        raise win32api.error( errcode, 'LookupPrivilegeValue', win32api.FormatMessage( errcode ) )
    
    ( luid_lo, luid_hi ) = struct.unpack( 'II', luidbuf.mb.read() )
    #print luid_lo, luid_hi
    newprivs = windll.membuf( 16 )
    newprivs.mb.write( struct.pack( 'IIII', 1, luid_lo, luid_hi, win32con.SE_PRIVILEGE_ENABLED ) )
    bSuccess = advapi32.AdjustTokenPrivileges( hToken, FALSE, newprivs, 0, 0, 0 )
    #print bSuccess
    if not bSuccess:
        errcode = win32api.GetLastError()
        raise win32api.error( errcode, 'AdjustTokenPrivileges', win32api.FormatMessage( errcode ) )
     
    optionalmessage = None
    timeout = 0
    bForceClose = TRUE
    bRebootAfterShutdown = TRUE
    win32api.InitiateSystemShutdown( None, optionalmessage, timeout, bForceClose, bRebootAfterShutdown )


# -------------------------------------------------------------------

def DetermineIniFile():

    # Locate the checknetworkconfig.ini file.  If the user chooses to
    # provide his/her own ini file, he/she may do so by specifying
    # the path to the file using the "-f" option.  Otherwise, the default
    # ini file is found at %ARAXIHOME%\CreoAraxi\bin\checknetworkconfig.ini
    # If the file doesn't exist, default settings are used.
    
    global inifile
    
    inifile = None
    argc = len( sys.argv )
    i = 1
    while i < argc:
        arg = sys.argv[i]
        if arg == '-f':
            i = i + 1
            if i >= argc:
               print 'option -f requires argument'
               raise SystemExit(1)
            userIniFile = win32api.GetFullPathName( sys.argv[i] )
            if os.path.isfile(userIniFile):
                inifile = userIniFile
            else:
                print '%s: file not found' % userIniFile
        else:
            print 'Usage: preplicated [-f inifile]'
        i = i + 1
        
    if not inifile:
        # check if default ini file 
        # %ARAXIHOME%\CreoAraxi\bin\checknetworkconfig.ini exists
        araxiHome = str( win32api.GetEnvironmentVariable( 'ARAXIHOME' ) )
        if araxiHome is not None:
            defaultIniFile = os.path.join( araxiHome, 'CreoAraxi', 'bin', 'checknetworkconfig.ini' )
            if os.path.isfile(defaultIniFile):
                inifile = defaultIniFile
    if inifile:
        DIAG_LOGDEBUG(TRUE, 'inifile:', inifile)
        
    # Keep going with defaults even if no .ini file is found.
  
    
# -----------------------------------------------------------------------------

def GetConfigVal(section, entry, default):

    # Reads the checknetworkconfig.ini file and returns the value for
    # the specified parameter.  Note that the full path to the .ini file
    # must be specified, otherwise the call tries to look for the file
    # in the system directory.
    
    global inifile
        
    if inifile:
        value = win32api.GetProfileVal(section, entry, default, inifile)
    else:
        value = default
        
    return value 

# -----------------------------------------------------------------------------
#
#   Get a list of GUIDs for all enabled Network cards
#
def GetEnabledNetworkCardList( ):

    networkCardList = []
    enabledNetworkCardList = []
    
    # Open the network cards reg key
    try:
        hkey = win32api.RegOpenKey( win32con.HKEY_LOCAL_MACHINE,
                                    "Software\\microsoft\\Windows NT\\CurrentVersion\\NetworkCards",
                                    RESERVED,
                                    win32con.KEY_READ)

    except win32api.error, err:
        print
        if err[0] == winerror.ERROR_ACCESS_DENIED:
            print err[2]
            sys.exit( 1 )
        else:
            sys.stdout.write( '\a' )
            msg = """\
No network cards were found in the registry.

Please re-install the network card."""

            response = Alert( msg, win32con.MB_OK)
            print 'ERROR: Network card not found in registry'
            return [], [], FALSE

    # Iterate through each entry and create a list of network card [GUID,description] pairs
    numkeys, numvals, modtime = win32api.RegQueryInfoKey( hkey )
    for i in range( numkeys ):
        subkeyname = win32api.RegEnumKey( hkey, i )
        hsubkey = win32api.RegOpenKey( hkey, subkeyname, 0, win32con.KEY_READ)
        networkCardGUID, regtype = win32api.RegQueryValueEx( hsubkey, 'ServiceName' )
        assert regtype == win32con.REG_SZ

        networkCardDesc, regtype = win32api.RegQueryValueEx( hsubkey, 'Description' )
        assert regtype == win32con.REG_SZ

        networkCardList.append([networkCardGUID, networkCardDesc])

    # Read the Device Classes reg key for network cards
    try:
        hkey = win32api.RegOpenKey( win32con.HKEY_LOCAL_MACHINE,
                                    "SYSTEM\\CurrentControlSet\\Control\\DeviceClasses\\{ad498944-762f-11d0-8dcb-00c04fc3358c}",
                                    RESERVED,
                                    win32con.KEY_READ)

    except win32api.error, err:
        print
        if err[0] == winerror.ERROR_ACCESS_DENIED:
            print err[2]
            sys.exit( 1 )

    # Iterate through each "Device Registered Interface" GUID 
    numDevicekeys, numDevicevals, modDevicetime = win32api.RegQueryInfoKey( hkey )
    for i in range( numDevicekeys ):
    
        subkeyname = win32api.RegEnumKey( hkey, i )
        hsubkey = win32api.RegOpenKey( hkey, subkeyname, 0, win32con.KEY_READ)

        # Iterate through the keys directly below and check for a network card
        numkeys, numvals, modtime = win32api.RegQueryInfoKey( hsubkey )
        for i in range( numkeys ):
            networkCardGUIDkey = win32api.RegEnumKey( hsubkey, i )

            # Determine whether it's a network card by searching for one of the network card GUIDs
            for networkCard in networkCardList:

                networkCardGUID = networkCard[0]
                if (string.find(networkCardGUIDkey, networkCardGUID) >= 0):

                    # If it's a network card, check the ...control\linked reg key to see whether it's enabled
                    controlPath = networkCardGUIDkey + '\\Control'
                    try:
                        hNetworkCardGUIDkey = win32api.RegOpenKey( hsubkey, controlPath, 0, win32con.KEY_READ)
                        bEnabled, regtype = win32api.RegQueryValueEx( hNetworkCardGUIDkey, 'Linked' )
                        assert regtype == win32con.REG_DWORD

                    except win32api.error, err:
                        print
                        if err[0] == winerror.ERROR_ACCESS_DENIED:
                            print err[2]
                            sys.exit( 1 )
                        bEnabled = FALSE    

                    # If it's enabled, add this GUID to the list of enabled network card GUID's
                    if (bEnabled):
                        enabledNetworkCardList.append(networkCard)
                
    return enabledNetworkCardList, TRUE

# -----------------------------------------------------------------------------
#
# Make sure TCP/IP is the first protocol bound to the following services: 
#    File and Printer Sharing for Microsoft Networks (LanmanServer) and
#    Client for Microsoft Networks (LanmanWorkstation)
#
def CheckProtocolBindingOrder(networkCardGUIDList):

    # Note:  This function changes the 

    print 'Checking protocol binding order . . .',
    errorFound = FALSE

    rootkey = win32con.HKEY_LOCAL_MACHINE

    # loop through LanmanServer and LanmanWorkstation, checking the 
    # linkage, export and route reg keys.  Ensure that the network card
    # TCP/IP protocols are bound first, and NetBios is last

    serviceList = ['lanmanserver', 'lanmanworkstation']
    serviceRegKeyList = ['bind', 'export', 'route']

    errMsgShown = FALSE
    fixOk = FALSE
    for service in serviceList:

        for serviceRegKey in serviceRegKeyList:

            hkey, pcolList, res = GetServiceProtocolList(service, serviceRegKey)
            if (not res):
                continue

            # Entries in the 'route' reg key are slightly different than the others,
            # so they use a different network card TCPIP protocol list
            if (serviceRegKey == 'route'):
                firstProtocols = []
                for networkCardGUID in networkCardGUIDList:
                    tcpipGUID = '"Tcpip" "' + networkCardGUID
                    firstProtocols.append(tcpipGUID)
            else:
                firstProtocols = []
                for networkCardGUID in networkCardGUIDList:
                    tcpipGUID = 'Tcpip_' + networkCardGUID
                    firstProtocols.append(tcpipGUID)
            lastProtocols = ['NetbiosSmb']

            # Reorder the protocol list such that firstProtocols are at the beginning
            # of the list and lastProtocols are at the end
            bChanged, newList = ReorderList(pcolList, firstProtocols, lastProtocols)

            # If the order was changed, prompt for permission, then set registry
            if (bChanged):
                if (not errMsgShown):
                    fixOk = ProtocolErrorMsg()
                    errMsgShown = TRUE

                if (fixOk):
                    win32api.RegSetValueEx( hkey, serviceRegKey, RESERVED, win32con.REG_MULTI_SZ, newList )

    # if there was a problem and the user said it was ok to fix, return false so that
    # there will be a reboot
    if (fixOk and errMsgShown):
        print 'fixed.'
        return FALSE
    
    # if there was a problem but the user did NOT want to fix it, return true so that 
    # there will NOT be a reboot
    if (errMsgShown):
        print 'ERROR.'
        return TRUE

    # otherwise, there were no problems so no reboot necessary
    print 'ok.'
    return TRUE

# -----------------------------------------------------------------------------
def ReorderList(list, firstItems, lastItems):

    # Returns the 'list' sequence, reordered such that items containing one of the
    # strings in 'firstItems' are at the beginning and items containing one of the
    # strings in 'lastItems' are at the end.  Also returns a boolean indicating 
    # whether the list was changed.
    
    firstList = []
    lastList = []
    otherList = []
    
    for x in list:
        bAdded = FALSE
        if (type(x) is StringType):
            for item in firstItems:
                if (string.find(x, item) >= 0):
                    firstList.append(x)
                    bAdded =TRUE
                    break

            if (not bAdded):
                for item in lastItems:
                    if (string.find(x, item) >= 0):
                        lastList.append(x)
                        bAdded =TRUE
                        break

            if (not bAdded):
                otherList.append(x)

    returnList = firstList + otherList + lastList
    
    # Check whether list was changed
    i = 0
    while i < len(list):
        if (list[i] != returnList[i]):
            return TRUE, returnList
        i = i + 1

    return FALSE, returnList
    

# -----------------------------------------------------------------------------
#
def GetServiceProtocolList(service, serviceRegKey):

    hkey = None
    pcolList = []
    regKey = 'System\\CurrentControlSet\\Services\\' + service + '\\Linkage'
    try:
        hkey = win32api.RegOpenKey( win32con.HKEY_LOCAL_MACHINE,
                                    regKey,
                                    RESERVED,
                                    win32con.KEY_READ | win32con.KEY_WRITE)
    except win32api.error, err:
        if err[0] == winerror.ERROR_ACCESS_DENIED:
            print err[2]
            sys.exit( 1 )
        else:
            return hkey, pcolList, FALSE

    pcolList, regtype = win32api.RegQueryValueEx( hkey, serviceRegKey )
    assert regtype == win32con.REG_MULTI_SZ

    return hkey, pcolList, TRUE


# -----------------------------------------------------------------------------
#
def ProtocolErrorMsg():
    sys.stdout.write( '\a' )
    msg = """\
One or more network protocols are not configured correctly.
        
Proper binding order of network protocols is required for optimum performance of Prinergy.

TCP/IP should be the first protocol and NetBios should be the last protocol 
in the binding order for:

         Client for Microsoft Networks
         File and Printer Sharing for Microsoft Networks

Click OK to change the protocol binding order to match the above criteria.

"""
    response = Alert( msg, win32con.MB_OKCANCEL )
    if response == win32con.IDOK:
        return TRUE
    else:
        return FALSE


# -----------------------------------------------------------------------------
#
# Make sure the network card is the first bound to the TCP/IP service
#
def CheckTCPIPBindingOrder(networkCardGUIDList):

    print 'Checking TCPIP binding order . . .',
    errorFound = FALSE

    rootkey = win32con.HKEY_LOCAL_MACHINE

    firstProtocols = networkCardGUIDList
    lastProtocols = ['NetbiosSmb']
    serviceRegKeyList = ['bind', 'export', 'route']

    errMsgShown = FALSE
    fixOk = FALSE
    for serviceRegKey in serviceRegKeyList:

        hkey, pcolList, res = GetServiceProtocolList('tcpip', serviceRegKey)
        if (not res):
            msg = 'TCP/IP service not found in registry'
            response = Alert( msg, win32con.MB_OK )
            print 'ERROR.'
            return FALSE

        # Reorder the protocol list such that firstProtocols are at the beginning
        # of the list and lastProtocols are at the end
        bChanged, newList = ReorderList(pcolList, firstProtocols, lastProtocols)

        # If the order is wrong, prompt for permission, then fix it
        if (bChanged):
            if (not errMsgShown):
                fixOk = TCPIPProtocolErrorMsg()
                errMsgShown = TRUE

            if (fixOk):
                win32api.RegSetValueEx( hkey, serviceRegKey, RESERVED, win32con.REG_MULTI_SZ, newList )

    # if there was a problem and the user said it was ok to fix, return false so that
    # there will be a reboot
    if (fixOk and errMsgShown):
        print 'fixed.'
        return FALSE
    
    # if there was a problem but the user did NOT want to fix it, return true so that 
    # there will NOT be a reboot
    if (errMsgShown):
        print 'ERROR.'
        return TRUE

    # otherwise, there were no problems so no reboot necessary
    print 'ok.'
    return TRUE

# -----------------------------------------------------------------------------
#
def TCPIPProtocolErrorMsg():
    sys.stdout.write( '\a' )
    msg = """\
A TCP/IP adapter is not first in the binding order under the TCP/IP service.

This setting is required for correct operation of Prinergy.

Click OK to move the TCP/IP adapter to the front of the binding order.

"""
    response = Alert( msg, win32con.MB_OKCANCEL )
    if response == win32con.IDOK:
        return TRUE
    else:
        return FALSE

# -----------------------------------------------------------------------------
#
# Make sure NetBEUI protocol is not associated wtih enabled network cards
#
def CheckNetBEUI( networkCardGUIDList ):

    print 'Checking for NetBEUI Protocol  . . .',
    
    errMsgShown = FALSE
    netBEUIEnabled = FALSE
    
    serviceRegKeyList = ['bind', 'export', 'route']
    
    for serviceRegKey in serviceRegKeyList:

        hkey, pcolList, res = GetServiceProtocolList('Nbf', serviceRegKey)
        if (not res):
            print 'ok.'
            return TRUE

        for networkCardGUID in networkCardGUIDList: 
            for item in pcolList:
                if (string.find(item, networkCardGUID) >= 0 ):
                    netBEUIEnabled = TRUE

        if (netBEUIEnabled):
            if (not errMsgShown):
                NetBEUIProtocolErrorMsg()
                errMsgShown = TRUE

    # if netBEUI is enabled, this check results in a Warning    
    if (netBEUIEnabled):
        print 'WARNING.'
        return FALSE

    # otherwise, check results in ok
    print 'ok.'
    
    return TRUE    
             
    
# -----------------------------------------------------------------------------
#
def NetBEUIProtocolErrorMsg():
    sys.stdout.write( '\a' )
    msg = """\
The NetBEUI protocol for the Local Area Connection is enabled 
on this machine.

The NetBEUI protocol seriously degrades the performance of Prinergy.

To ensure that Prinergy will run properly, it is recommended that
this protocol be disabled.  This can be done as follows
 
1) Select Network and Dial-up Connections in the Control Panel
2) Right click on Local Area Connection
3) Select Properties
4) Uncheck "NetBEUI Protocol" in the Components list
5) Click OK


Click OK to continue."""

    response = AlertWarning( msg, win32con.MB_OK )

# -----------------------------------------------------------------------------
#
# Make sure this checkbox is on, otherwise Orbix stuff misbehaves
#
def CheckEnableDnsForWindowsResolutionSetting( ):

    print 'Checking TCP/IP Enable DNS for Windows Resolution setting . . .',
    try:
        hkeyNetBTParameters = win32api.RegOpenKey( win32con.HKEY_LOCAL_MACHINE,
                                     "System\\CurrentControlSet\\Services\\NetBT\\Parameters",
                                     RESERVED,
                                     win32con.KEY_READ | win32con.KEY_WRITE )
    except win32api.error, err:
        print
        if err[0] == winerror.ERROR_ACCESS_DENIED:
            print err[2]
            sys.exit( 1 )
        else:
            print 'Enable DNS for Windows Resolution not found - ok.'
            return TRUE

    try:
        EnableDNS, regtype = win32api.RegQueryValueEx( hkeyNetBTParameters, 'EnableDNS' )
        assert regtype == win32con.REG_DWORD

    except:
        print 'Enable DNS for Windows Resolution not found - ok.'
        return TRUE

    if not EnableDNS:
        sys.stdout.write( '\a' )
        msg = """\
The TCP/IP Control Panel setting Enable DNS for Windows Resolution is NOT enabled.
 
This setting is required for correct operation of Prinergy.

Click OK to correct this setting now."""

        response = Alert( msg, win32con.MB_OKCANCEL )
        if response == win32con.IDOK:
            win32api.RegSetValueEx( hkeyNetBTParameters, 'EnableDNS', RESERVED, win32con.REG_DWORD, 1 )
            print 'fixed.'
        else:
            print 'ERROR.'
        return FALSE
    else:
        print 'ok.'
    return TRUE

# -----------------------------------------------------------------------------
#
# Make sure hostname is all lowercase, otherwise Orbix stuff misbehaves
#
def CheckHostName( ):

    print 'Checking TCP/IP host name . . .',
    try:
        hkey = win32api.RegOpenKey( win32con.HKEY_LOCAL_MACHINE, r'System\CurrentControlSet\Services\Tcpip\Parameters', 0, win32con.KEY_READ|win32con.KEY_WRITE )
    except win32api.error, err:
        print
        if err[0] == winerror.ERROR_ACCESS_DENIED:
            print err[2]
            sys.exit( 1 )
        else:
            sys.stdout.write( '\a' )
            msg = """\
A TCP/IP registry key was not found in the Services registry.

This service is required for correct operation of Prinergy.

Please re-install the TCP/IP service."""

            response = Alert( msg, win32con.MB_OK)
            print 'ERROR: TCP/IP damaged or not installed'
            return FALSE

    # Win2K machines have 'NV HostName' in registry that replaces
    # 'HostName' on reboot.  So, have to check this one too.
    hostNameOk = FixHostName(hkey, 'HostName')
    if hostNameOk:
        hostNameOk = FixHostName(hkey, 'NV HostName')
        if hostNameOk:
            print 'ok.'

    return hostNameOk

# -----------------------------------------------------------------------------
def FixHostName(hkey, regHostName):
    HostName, t = win32api.RegQueryValueEx( hkey, regHostName )
    assert t == win32con.REG_SZ
    errors = 0
    for ch in HostName:
        if ch in string.uppercase:
            errors = errors + 1
            break
    #print errors, 'error(s) found'
    if errors:
        sys.stdout.write( '\a' )
        msg = '''\
The TCP/IP host name is incorrectly configured.

Prinergy requires the host name to be all lower case.

Click OK to correct this setting now.'''

        response = Alert( msg, win32con.MB_OKCANCEL )
        if response == win32con.IDOK:
            node = win32api.GetComputerName()    
            hostname = string.lower( node )
            win32api.RegSetValueEx( hkey, 'HostName', RESERVED, win32con.REG_SZ, hostname )
            win32api.RegSetValueEx( hkey, 'NV HostName', RESERVED, win32con.REG_SZ, hostname )
            print 'fixed.'
        else:
            print 'ERROR.'
        return FALSE

    return TRUE

# -----------------------------------------------------------------------------
#
# Make sure PrimaryNodeName is all uppercase, otherwise Orbacus stuff misbehaves
#
def FixPrimaryNodeName( ):

    print 'Checking Primary Node name . . .',
    try:
        araxiReg = AraxiRegistry()
        systemReg = RegistryKey( araxiReg.Root(), 'System', win32con.KEY_READ | win32con.KEY_WRITE )
        primaryNode = systemReg.GetValue('PrimaryNodeName')
        primaryNodeUCase = string.upper(primaryNode)
    except win32api.error, err:
        print err[2]
        sys.exit( 1 )

    # Make sure PrimaryNodeName is in all uppercase
    if primaryNode != primaryNodeUCase:
        print 'PrimaryNodeName ', primaryNode, ' is not all upper case.'
        print 'Fixing Primary Node name . . .',
	systemReg.SetValue( 'PrimaryNodeName', primaryNodeUCase, win32con.REG_SZ  )	
	print 'fixed.'
    else:
	print 'ok.'
	
    return TRUE

                
# -----------------------------------------------------------------------------
#
# Make sure Adaptive Technology is off, otherwise get bizarre/annoying/intermittent network-related problems
#
def CheckAdaptiveTechSetting( networkCardGUID ):

    print 'Checking Adaptive Technology setting for network adaptor . . .',
    try:
        hkey = win32api.RegOpenKey( win32con.HKEY_LOCAL_MACHINE,
                                    "System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",
                                    RESERVED,
                                    win32con.KEY_READ | win32con.KEY_WRITE )
    except win32api.error, err:
        print
        if err[0] == winerror.ERROR_ACCESS_DENIED:
            print err[2]
            sys.exit( 1 )
        else:
            print 'Setting not found in registry - ok.'
            return TRUE

    # Iterate through the list of driver reg keys to find the TCP/IP GUID
    numkeys, numvals, modtime = win32api.RegQueryInfoKey( hkey )
    for i in range( numkeys ):
        subkeyname = win32api.RegEnumKey( hkey, i )

        hsubkey = win32api.RegOpenKey( hkey, subkeyname, 0, win32con.KEY_READ | win32con.KEY_WRITE )

        driverGUID, t = win32api.RegQueryValueEx( hsubkey, 'NetCfgInstanceId' )
        assert t == win32con.REG_SZ

        if (driverGUID == networkCardGUID):
            tcpipKey = hsubkey
            break

    try:
        adaptiveTech, regtype = win32api.RegQueryValueEx( tcpipKey, 'UcodeSW' )
        assert regtype == win32con.REG_SZ

    except:
            print 'Setting not found in registry - ok.'
            return TRUE

    if (adaptiveTech == '1'):
        sys.stdout.write( '\a' )
        msg = """\
The Adaptive Technology setting for a Network Adaptor is ON.  

This setting is required to be OFF for correct operation of Prinergy.

Click OK to turn Adaptive Technology OFF."""

        response = Alert( msg, win32con.MB_OKCANCEL )
        if response == win32con.IDOK:
            win32api.RegSetValueEx( tcpipKey, 'UcodeSW', RESERVED, win32con.REG_SZ, '0' )
            win32api.FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM)
            print 'fixed.'
        else:
            print 'ERROR.'
        return FALSE
    else:
        print 'ok.'
    return TRUE

# -----------------------------------------------------------------------------

#
# Make sure 'Enable NetBIOS over TCP/IP' is set in WINS tab
#
def CheckNetBiosSetting( networkCardGUID ):
    print 'Checking NetBIOS options in WINS . . .',

    tcpipGUID = 'Tcpip_' + networkCardGUID
    try:
        tcpipInterface = "SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters\\Interfaces\\" + tcpipGUID
        hkey = win32api.RegOpenKey( win32con.HKEY_LOCAL_MACHINE,
                                    tcpipInterface,
                                    RESERVED,
                                    win32con.KEY_READ | win32con.KEY_WRITE )

    except win32api.error, err:
        print
        if err[0] == winerror.ERROR_ACCESS_DENIED:
            print err[2]
            sys.exit( 1 )
        else:
            'Netbios reg key not found - ok.'
            return TRUE

    NetBIOS, regtype = win32api.RegQueryValueEx( hkey, 'NetbiosOptions' )
    assert regtype == win32con.REG_DWORD

    if (not NetBIOS == 1):
        sys.stdout.write( '\a' )
        msg = """\
NetBIOS over TCP/IP for WINS has not been enabled on a network
adapter in this machine.  

This setting is required for correct operation of Prinergy.

Click OK to enable NetBIOS over TCP/IP."""

        response = Alert( msg, win32con.MB_OKCANCEL )
        if response == win32con.IDOK:
            win32api.RegSetValueEx( hkey, 'NetbiosOptions', RESERVED, win32con.REG_DWORD, 1 )
            print 'fixed.'
        else:
            print 'ERROR.'
        return FALSE
    else:
        print 'ok.'
    return TRUE

# -----------------------------------------------------------------------------

#
# Make sure Network driver is up to date, if the network card is familiar (i.e. Intel)
#
def CheckDriverDate( networkCardGUID ):

    print 'Checking network driver date . . .',
    try:
        hkey = win32api.RegOpenKey( win32con.HKEY_LOCAL_MACHINE,
                                    "System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",
                                    RESERVED,
                                    win32con.KEY_READ | win32con.KEY_WRITE )
    except win32api.error, err:
        print
        if err[0] == winerror.ERROR_ACCESS_DENIED:
            print err[2]
            sys.exit( 1 )
        else:
            print 'Registry error.  Date not checked.'
            return TRUE

    # Iterate through the list of driver reg keys to find the TCP/IP GUID
    numkeys, numvals, modtime = win32api.RegQueryInfoKey( hkey )
    for i in range( numkeys ):
        subkeyname = win32api.RegEnumKey( hkey, i )

        hsubkey = win32api.RegOpenKey( hkey, subkeyname, 0, win32con.KEY_READ )

        driverGUID, t = win32api.RegQueryValueEx( hsubkey, 'NetCfgInstanceId' )
        assert t == win32con.REG_SZ

        if (driverGUID == networkCardGUID):
            tcpipKey = hsubkey
            break

    try:
        hNdiKey = win32api.RegOpenKey( hsubkey, 'Ndi', 0, win32con.KEY_READ )
        serviceName, t = win32api.RegQueryValueEx( hNdiKey, 'Service' )
        hkey = win32api.RegOpenKey( win32con.HKEY_LOCAL_MACHINE,
                                    "SYSTEM\\CurrentControlSet\\Services\\" + serviceName,
                                    RESERVED,
                                    win32con.KEY_READ)
    except win32api.error, err:
        print
        if err[0] == winerror.ERROR_ACCESS_DENIED:
            print err[2]
            sys.exit( 1 )
        else:
            print 'Registry error.  Date not checked.'
            return TRUE

    driverName, regtype = win32api.RegQueryValueEx( hkey, 'ImagePath' )
    if (string.find(string.lower(driverName), 'e100bnt5') >= 0):

        networkDriverDate, regtype = win32api.RegQueryValueEx( tcpipKey, 'DriverDate' )
        assert regtype == win32con.REG_SZ

        dtNetworkDriverDate = strptime.strptime(networkDriverDate, '%m-%d-%Y')
        dtLatestNetworkDriverDate = strptime.strptime(LatestNetworkDriverDate, '%m-%d-%Y')

        if dtNetworkDriverDate < dtLatestNetworkDriverDate:
            sys.stdout.write( '\a' )
            msg = 'The driver for an Intel network card is out of date.  You should be using a driver\nno older than ' + LatestNetworkDriverDate + '.\n\nPlease update the network driver and restart your computer before running Prinergy.'

            response = Alert( msg, win32con.MB_OK)
            print 'ERROR.'
            return FALSE
        else:
            print 'ok.'
    else:
        print 'Driver e100bnt5.sys not used - ok.'

    return TRUE

# -----------------------------------------------------------------------------
# Make sure TEMP and TMP env. vars for the account running the Araxi service
# point to the same place.
#
# Dec-09-2002: Today it was noticed that this part of the code does not 
# function in certain cases where the profile is like "ARAXI.SERVERNAME" or 
# "ARAXI.000".  This is broken since it was first implemented 
# in 2.0.3 (June-2000).  This is still outstanding in case it turns out to 
# become a requirement.
#
def CheckTempVars( ):

    chktmpvarDebug = FALSE

    print 'Checking TEMP and TMP environment variables . . .',
    if chktmpvarDebug:
        print '\nDebugging in CheckTempVars'

    # -------------------------------------------
    # Retrieve the current values of TEMP and TMP
    # -------------------------------------------

    # First, get the account name for the Araxi service from the registry
    try:
        hkey = win32api.RegOpenKey( win32con.HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\Araxi", RESERVED, win32con.KEY_READ)

    except win32api.error, err:
        if err[0] == winerror.ERROR_ACCESS_DENIED:
            print err[2]
            sys.exit( 1 )
        else:
            print 'Araxi service not found - Temp environment variables for Araxi service not checked.'
            return FALSE

    araxiUserName, regtype = win32api.RegQueryValueEx( hkey, 'ObjectName' )
    assert regtype == win32con.REG_SZ
    win32api.RegCloseKey( hkey )

    loc = string.rfind(araxiUserName, '\\')
    araxiUserName = araxiUserName[loc+1:]

    # Second, find the user profile in the registry for the Araxi service account
    try:
        hkey = win32api.RegOpenKey( win32con.HKEY_LOCAL_MACHINE, "Software\Microsoft\Windows NT\CurrentVersion\ProfileList", 0, win32con.KEY_READ )
    except win32api.error, err:
        if err[0] == winerror.ERROR_ACCESS_DENIED:
            print err[2]
            sys.exit( 1 )
        else:
            print 'NT Profile list not found - Temp environment variables for Araxi service not checked.'
            return FALSE

    # Third, iterate through the list of profile image paths until 
    # one is found that ends with the Araxi service account name
    bAraxiUserFound = FALSE
    numkeys, numvals, modtime = win32api.RegQueryInfoKey( hkey )
    for i in range( numkeys ):
        subkeyname = win32api.RegEnumKey( hkey, i )

        hsubkey = win32api.RegOpenKey( hkey, subkeyname, 0, win32con.KEY_READ )

        profileImagePath, t = win32api.RegQueryValueEx( hsubkey, 'ProfileImagePath' )
        assert t == win32con.REG_EXPAND_SZ

        loc = string.rfind(profileImagePath, '\\')
        profileName = profileImagePath[loc+1:]

        if (string.lower(profileName) == string.lower(araxiUserName)):
            araxiUserSID = subkeyname
            bAraxiUserFound = TRUE
            break

    win32api.RegCloseKey( hkey )

    # Fourth, load the hive for the Araxi service user registry
    hProcess = win32api.GetCurrentProcess()
    privs = win32con.TOKEN_ADJUST_PRIVILEGES | win32con.TOKEN_QUERY
    tokbuf = windll.membuf( 4 )
    bSuccess = advapi32.OpenProcessToken( hProcess, privs, tokbuf )
    if not bSuccess:
        errcode = win32api.GetLastError()
        raise win32api.error( errcode, 'LookupPrivilegeValue', win32api.FormatMessage( errcode ) )
    (hToken,) = struct.unpack( 'I', tokbuf.mb.read() )
    
    luidbuf = windll.membuf( 8 )
    privname = windll.cstring( win32con.SE_RESTORE_NAME )
    bSuccess = advapi32.LookupPrivilegeValue( 0, privname, luidbuf )
    if not bSuccess:
        errcode = win32api.GetLastError()
        raise win32api.error( errcode, 'LookupPrivilegeValue', win32api.FormatMessage( errcode ) )
    
    ( luid_lo, luid_hi ) = struct.unpack( 'II', luidbuf.mb.read() )
    newprivs = windll.membuf( 16 )
    newprivs.mb.write( struct.pack( 'IIII', 1, luid_lo, luid_hi, win32con.SE_PRIVILEGE_ENABLED ) )
    bSuccess = advapi32.AdjustTokenPrivileges( hToken, FALSE, newprivs, 0, 0, 0 )
    if not bSuccess:
        errcode = win32api.GetLastError()
        raise win32api.error( errcode, 'AdjustTokenPrivileges', win32api.FormatMessage( errcode ) )
         
    rootkey = win32con.HKEY_USERS
   
    # Fifth, find registry hive file for the Araxi service account and load it
    userProfilePath = os.environ['USERPROFILE']
    tok = string.rfind(userProfilePath, '\\')
    profilePath = userProfilePath[0:tok]
    araxiUserProfile = profilePath + '\\' + araxiUserName + '\\' + 'NTUSER.DAT'
    if (os.path.exists(araxiUserProfile)):
        try:
            ret = win32api.RegLoadKey(rootkey, araxiUserSID, araxiUserProfile)
    
        except win32api.error, err:
            if err[0] == winerror.ERROR_ACCESS_DENIED:
                print err[2]
                sys.exit( 1 )
    
    # Sixth, get the TEMP and TMP env. vars for the Araxi service account
    try:
        rootkey = win32con.HKEY_USERS

        if (bAraxiUserFound):
            hkey = win32api.RegOpenKey( rootkey, araxiUserSID + "\\Environment", 0, win32con.KEY_READ | win32con.KEY_WRITE )
        else:
            hkey = win32api.RegOpenKey( rootkey, ".DEFAULT\\Environment", 0, win32con.KEY_READ | win32con.KEY_WRITE )

    except win32api.error, err:
        if err[0] == winerror.ERROR_ACCESS_DENIED:
            print err[2]
            sys.exit( 1 )
        else:
            print 'No environment variables found for account running Araxi service - Temp environment variables for Araxi service not checked.'
            return FALSE

    envTemp, regtype = win32api.RegQueryValueEx( hkey, 'TEMP' )
    envTemp = win32api.ExpandEnvironmentStrings( envTemp )

    envTmp, regtype = win32api.RegQueryValueEx( hkey, 'TMP' )
    envTmp = win32api.ExpandEnvironmentStrings( envTmp )

    if chktmpvarDebug:
        print 'DEBUG: envTemp=', envTemp
        print 'DEBUG: envTmp =', envTmp

    # -------------------------------------------
    # Get the desired temp path
    # -------------------------------------------

    desiredTempPath = ''

    # First, get the list of shares
    try:
        hkeyShares = win32api.RegOpenKey( win32con.HKEY_LOCAL_MACHINE, 'SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Shares', 0, win32con.KEY_READ)
    except win32api.error, err:
        if err[0] == winerror.ERROR_ACCESS_DENIED:
            print err[2]
            sys.exit( 1 )
        else:
            print 'AraxiTemp share not found in registry - Temp environment variables for Araxi service not checked.'
            return FALSE

    # Second, iterate through all the shares until one is found that starts with 'AraxiTemp'
    numkeys, numvals, modtime = win32api.RegQueryInfoKey( hkeyShares )
    for i in range( numvals ):
        subkeyName = win32api.RegEnumValue( hkeyShares, i )

        if (string.find(subkeyName[0], "AraxiTemp") > -1):

            # Take the drive letter from the 'AraxiTemp' share name (it's the last letter in the share name,
            # eg. AraxiTemp_Gorgon_F) and set the temp env. vars to use this drive
            araxiTempName = subkeyName[0]
            araxiTempDrive = araxiTempName[len(araxiTempName)-1:]
            desiredTempPath = araxiTempDrive + ':\\Temp'
            break

    # Third, make sure we found the AraxiTemp drive
    if not araxiTempDrive:
        #  (something seriously wrong if get to here - Prinergy not installed?)
        print 'AraxiTemp drive cannot be determined - Temp environment variables for Araxi service not checked.'
        return FALSE

    if chktmpvarDebug:
        print 'DEBUG: desiredTempPath=', desiredTempPath

    # Fourth, make sure the temp drive letter points at something
    if (not os.path.exists(araxiTempDrive + ':\\')):
        #  Did a user re-assign this share name to a different drive?
        print 'AraxiTemp drive names a non-existent drive - Temp environment variables for Araxi service not checked.'
        return FALSE


    # --------------------------------
    # Count our available hard drives
    # --------------------------------

    driveCount = 0
    for i in string.split(win32api.GetLogicalDriveStrings(), '\000'):
        if win32file.GetDriveType(i) == win32con.DRIVE_FIXED:
            driveCount = driveCount+1
    if chktmpvarDebug:
        print 'DEBUG: driveCount=', driveCount


    # --------------------------------
    # Do the TMP & TEMP var checking
    # --------------------------------

    needToChangeVars = FALSE

    msgPreamble = 'The TEMP and/or TMP user environment variables for the Araxi service account '
    msgPostamble = '\n\nClick OK to have both of these environment variables set to the temp folder on the AraxiTemp volume.'

    # TMP & TEMP should be set
    if (not envTmp) or (not envTemp):
        # This should never be the case
        needToChangeVars = TRUE
        msg = ' are not configured.  This will cause problems.'
        if chktmpvarDebug:
            print 'DEBUG: (not envTmp) or (not envTemp)'

    # TMP & TEMP should be the same
    elif string.lower(envTmp) != string.lower(envTemp):
        needToChangeVars = TRUE
        msg = ' are not configured the same.  This may cause problems.'
        if chktmpvarDebug:
            print 'DEBUG: not TMP & TEMP the same'

    # If we have more than 2 drives, TMP & TEMP should not point
    #   to the system drive (if our AraxiTemp share
    #   has been configured for a non-system drive).
    elif driveCount > 2:
        systemDrive = os.environ['SystemDrive']
        if chktmpvarDebug:
            print 'DEBUG: systemDrive=', systemDrive
        if string.upper(systemDrive[0]) == string.upper(envTmp[0]):
            # TMP/TEMP are pointing to the system drive
            if chktmpvarDebug:
                print 'DEBUG: TMP/TEMP are pointing to the system drive'

            if string.upper(desiredTempPath[0]) == string.upper(systemDrive[0]):
                # nothing we can do here - the AraxiTemp share has been configured for the system drive
                # (Perhaps the user added other drives after Prinergy was installed)
                if chktmpvarDebug:
                    print 'DEBUG: the AraxiTemp share has been placed on the system drive'
            else:
                # the AraxiTemp share has been placed on a non-system drive - we want to go there too
                needToChangeVars = TRUE
                msg = ' have been configured to use a folder on the system drive.  This configuration will degrade performance.'
                if chktmpvarDebug:
                    print 'DEBUG: the AraxiTemp share has been placed on a non-system drive'

    if chktmpvarDebug:
        print 'DEBUG: needToChangeVars=', needToChangeVars


    # ---------------------------------------------
    # Ask & set the temp env. vars in the Registry
    # ---------------------------------------------

    if needToChangeVars:

        # Ask user whether to proceed to set the vars
        sys.stdout.write( '\a' )
        msg1 = msgPreamble + msg + msgPostamble
        response = Alert( msg1, win32con.MB_OKCANCEL )
        if response != win32con.IDOK:
            print 'ERROR.'
            return FALSE

        # set the vars
        envTmp  = desiredTempPath
        envTemp = desiredTempPath

        win32api.RegSetValueEx( hkey, 'TEMP', RESERVED, win32con.REG_SZ, envTmp )
        win32api.RegSetValueEx( hkey, 'TMP',  RESERVED, win32con.REG_SZ, envTemp )

        win32api.RegCloseKey( hkey )

        if chktmpvarDebug:
            print 'DEBUG: updated Registry'

    # -----------------------------------------------------
    # make sure temp folders exist and create if they don't
    # -----------------------------------------------------

    if chktmpvarDebug:
        print 'DEBUG: envTemp=', envTemp
        print 'DEBUG: envTmp =', envTmp

    if (not os.path.exists(envTemp)):
        os.makedirs(envTemp)
    if (not os.path.exists(envTmp)):
        os.makedirs(envTmp)

    if needToChangeVars:
        print 'fixed.'
        return FALSE   # might need to force a reboot

    print 'ok.'
    return TRUE

# -----------------------------------------------------------------------------
#
# Make sure 'Critical Update Notification' is not installed
#
def CheckCriticalUpdate( ):

    print 'Checking for Critical Update Notification . . .',
    try:
        criticalUpdateKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Critical Update"
        hkey = win32api.RegOpenKey( win32con.HKEY_LOCAL_MACHINE,
                                    criticalUpdateKey,
                                    RESERVED,
                                    win32con.KEY_READ)

    except win32api.error, err:
        print 'ok.'
        return TRUE

    sys.stdout.write( '\a' )
    msg = """\
Microsoft Windows Critical Update Notification has been installed 
on this machine.

This software interferes with the operation of the Task Scheduler
service, which is used to do system backups.

To ensure that system backups will run properly, it is recommended that
this software be removed.  This can be done using Add/Remove Programs 
in the control panel.

Click OK to continue."""

    response = Alert( msg, win32con.MB_OK )
    print 'ERROR.'
    return FALSE


# -----------------------------------------------------------------------------
#
# Make sure time syncronization with primary is setup properly
#
def CheckTimeSync( ):
    print 'Checking time synchronization with primary . . . ',

    node = win32api.GetComputerName()
    node = string.upper(node)

    araxiReg = AraxiRegistry()
    systemReg = RegistryKey( araxiReg.Root(), 'System' )
    primaryNode = systemReg.GetValue('PrimaryNodeName')
    primaryNode = string.upper(primaryNode)

    if (node == primaryNode):
        print 'Primary node. Not required.'
        return
    else:

        bNetTimeFound = FALSE
        bNetTimeRemoved = FALSE
        cmdLine = 'at'
        res = os.popen(cmdLine, "r")
        output = res.readlines()
        for line in output:
            line = string.lower(line)
            if (string.find(line, 'net time') >= 0):
                bNetTimeFound = TRUE
                start = string.find(line, '\\\\')
                end = string.find(line, '/')
                synchNode = line[start+2:end]
                synchNode = string.upper(synchNode)

                # If the current 'at' command synchronizes the time with
                # the wrong primary server, remove it
                if (synchNode != primaryNode):
                    line = string.lstrip(line)
                    atIndex = line[0:2]
                    cmdLine = 'at %s /d' % atIndex
                    res = os.popen(cmdLine, "r")
                    bNetTimeRemoved = TRUE                    

        # Recreate the 'at' command to synchronize the time with the primary
        if (not bNetTimeFound or bNetTimeRemoved):
            cmdLine = 'at 03:00 /every:M,T,W,Th,F,S,Su net time \\\\%s /set /y' % primaryNode
            res = os.popen(cmdLine, "r")
            output = res.readlines()
            for line in output:
                line = string.lower(line)
                if (string.find(line, 'added a new job') >= 0):
                    print 'ok.'
                    return TRUE
            print 'Error.'
            return FALSE
                
        print 'ok.'
        return TRUE

# -----------------------------------------------------------------------------
# Check whether Maintenance Mode is enabled
#
def CheckMaintMode( ):
    print 'Checking Maintenance Mode . . . ',

    try:
        araxiReg = AraxiRegistry('', win32con.KEY_READ | win32con.KEY_WRITE)
        systemReg = RegistryKey( araxiReg.Root(), 'System', win32con.KEY_READ | win32con.KEY_WRITE )
    except win32api.error, err:
        errMsg = err[2]
        print 'Error accessing registry key %s in the "Araxi" registry tree: %s' % ( 'System', errMsg )
        sys.exit(0)

    # Ok if MaintenanceMode reg key doesn't exist
    try:
        maintMode = systemReg.GetValue('MaintenanceMode')

    except:
        print 'ok.'
        return TRUE

    maintMode = string.lower(maintMode)
    if (maintMode == 'on'):
        sys.stdout.write( '\a' )
        msg = """\
Prinergy is currently in Maintenance Mode.

The system operates as usual in this mode, except that no Oracle or system 
backups will be performed.

Maintenance mode can be toggled on or off from the System Configuration
window in the Prinergy Administrator (under Tools->Configure System).

Please ensure that no servers are in the process of being upgraded before 
turning off Maintenance Mode.

Click OK to continue."""

        response = AlertWarning( msg, win32con.MB_OK )
        print 'WARNING.'
        return TRUE
    else:
        print 'ok.'
    return TRUE


# -----------------------------------------------------------------------------
# Checks if there are any file in %AraxiHome%\CreoAraxi\Setup\RunOnce directory.
# If there are any files, then the file will be launched, and if successful the
# will be deleted. 
#
def CheckRunOnceNeedsToRun():
    print 'Checking RunOnce directory . . . ',

    # retrieve AraxiHome path
    try:
        araxiHome = os.environ['AraxiHome']
    except Exception, err:
        raise 'ERROR - "AraxiHome" environment variable not found.  Detail: %s' % err

    runOnceDir = os.path.join(araxiHome, 'CreoAraxi', 'Setup', 'RunOnce' )
    if os.path.isdir( runOnceDir ):
        # Runonce Directory exists
        fileList = os.listdir( runOnceDir )
        for eachFile in fileList:
            fileToLaunch = os.path.join( runOnceDir, eachFile )
            if os.path.isfile(fileToLaunch):
            
                try:
                    result = os.system(fileToLaunch)
                    try:
                        SetFileReadOnlyFlagImp( fileToLaunch, readonly=FALSE )
                        win32api.DeleteFile( fileToLaunch )
                    except:
                        print 'Failed to delete file %s' % fileToLaunch
                except:
                    print 'Failed to execute %s' % fileToLaunch
            
    return TRUE   
# ----------------------------------------------------------------------------
def GetServiceState(node, serviceName):
    state = 'UNKNOWN'
    rootkey = win32con.HKEY_LOCAL_MACHINE
    subkey = "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"
    
    creoKey, creoDir = GetKeyValue(rootkey, subkey, 'CREOHOME')
    expandedCreoDir = win32api.ExpandEnvironmentStrings(creoDir)                                                                                      
    scPath = os.path.join(expandedCreoDir, 'support', 'bin', 'sc')
    
    cmdLine = scPath + ' \\\\' + node + ' query ' + serviceName
    res = os.popen(cmdLine, "r")
    output = res.readlines()
    for line in output:
        if (string.find(line, 'STATE              :') > -1):
            line = string.strip(line)
            loc = string.rfind(line, ' ')
            state = line[loc:]
            state = string.strip(state)

    return state

# -----------------------------------------------------------------------------
#
# Make sure primary is running
#
def CheckPrimaryRunning():

    print 'Checking that primary is running (if this is a secondary). . . ',
    node = win32api.GetComputerName()
    node = string.upper(node)

    try:
        araxiReg = AraxiRegistry()
        systemReg = RegistryKey( araxiReg.Root(), 'System' )
        primaryNode = systemReg.GetValue('PrimaryNodeName')
        primaryNode = string.upper(primaryNode)

    except win32api.error, err:
        print err[2]
        sys.exit( 1 )


    if (node == primaryNode):
        print 'primary.'
    else:

        try:
            nTimeout = systemReg.GetValue('StartupTimeout')
        except win32api.error, err:
            if err[0] == winerror.ERROR_ACCESS_DENIED:
                print err[2]
                sys.exit( 1 )
            else:
                nTimeout = WaitForPrimaryTimeout

        if (nTimeout == 0):
            print 'check disabled.'
            return TRUE
    
        state = ''      
        while (nTimeout > 0 and state != 'RUNNING'):
            state = GetServiceState(primaryNode, 'Araxi')
    
            if (state != 'RUNNING'):
                DIAG_LOGWARN('Waiting for primary server to start.')
                DIAG_LOGWARN('Secondary server will not continue startup until primary is running.')
                time.sleep(PollFreq)
                nTimeout = nTimeout - PollFreq
    
        if (state == 'RUNNING'):
            print 'ok.'
        else:
            DIAG_LOGERR('This server has timed out waiting for the primary server to start.  It will continue starting now.')
            DIAG_LOGERR('In order for Prinergy to function properly, this server should be restarted after the primary server has started.')
            print 'ERROR.'

    return TRUE

# -----------------------------------------------------------------------
def ChangeKeyValue(hkey, value, newData, dataType, msg):

    # This function changes the data for the value of a specified key in the
    # registry.  Permission to change the registry values is requested before
    # actually changing the registry value.
   
    # Ask for permission to change the registry value.
    sys.stdout.write('\a')
    msg = msg + '\n\n Click OK to correct this problem now.'
    response = Alert(msg, win32con.MB_OKCANCEL)
    
    if response == win32con.IDOK:
        # Update the registry.  Return FALSE to force the system to
        # reboot.
        win32api.RegSetValueEx(hkey, value, RESERVED, dataType, newData)
        return TRUE
    else:
        return FALSE

# -----------------------------------------------------------------------
def CheckDLTDrivers():

    # This function checks to see if any of the DLT drivers are Microsoft
    # DLT drivers.  If there are, an error message is returned listing all
    # the tape drivers that have the Microsoft DLT drivers.

    print 'Checking for Microsoft DLT Drivers . . .',
    
    msg = ""
 
    # Get the handle and the value of the specified key from the registry.
    try:   
        key, value = GetKeyValue(win32con.HKEY_LOCAL_MACHINE,
                                 "SYSTEM\\CurrentControlSet\\Services\\dlttape\\Enum",
                                 'Count')

        # Generate a list of all the tape drivers that are using the
        # Microsoft DLT driver.  Raise a warning to notify which tape
        # drivers use the Microsoft DLT driver.
        for count in range(value):
            valData, valType = win32api.RegQueryValueEx(key, `count`)
            assert valType == win32con.REG_SZ    
            
            # To avoid redundant code and for simplicity's sake,
            # part of the error message that will be displayed
            # will be generated here.  This will put the list of
            # tape drivers into columnar format.
            tapeDrive = GetDLTName(valData)
            msg = msg + "\t" + tapeDrive + "\n"
        
        sys.stdout.write('\a')
        msg = """\
The following tape drives are detected to have the Microsoft DLT driver
installed:\n"""\
+ msg + """\
To ensure that Prinergy operates correctly, please install the Quantum 
tape driver for these tape drives.  Contact the Creo Response Centre
for help if necessary."""

        response = Alert(msg, win32con.MB_OK)
        print 'ERROR - Microsoft DLT drivers detected.'
        return FALSE
        
    except:
        # If the dlt\Enum key or the Count value is not found, this means
        # that there are no Microsoft DLT drivers installed.  This case
        # is the same as the case where Count < 0.
        print 'Microsoft DLT drivers not found - no need to check any further.'
        return TRUE

##################
# helper function GetHostIPaddress, get's host name or ip address and ensures that it will returns one of its ip addresses
def GetHostIPaddress( host ):
    # Check to see if the Orbacus host value is currently storing an IP address or a host name.
    if string.find( host, '.' ) == -1:
        # This indicates that a host name is being stored.
        name, alias, hostIp = socket.gethostbyname_ex( host )
        newIp = hostIp[0]
    else:
        # This indicates that the IP address is being stored.
        # Compare this IP addres with the IP address of the machine
        # to see if the address has changed.
        machineName = socket.gethostname()
        machine, machineAlias, machineIp = socket.gethostbyname_ex(machineName)
        if host in machineIp: # check if the current ip is still being used
            return host       # if so, don't change it
#        for ip in machineIp:
#            if ip in machineIp:
#                newIp = ip
#                return newIp
        # wasn't in list just return the first ip
        newIp = machineIp[0]
    return newIp
# end helper function GetHostIPaddress
##################


##################
# helper function ReplaceHostNameToHostIPinOrbacusParamString
# looks for 'lookFor' within the string delimited by 'paramDelimiter', then
# threats the part after the string passed as lookFor as a host.
# If the host is not an IP address, it will be replaced by the host's IP.
# The return string will then be reconstructed with the IP instead of the host name.
# parameterString, the Orbacus parameter string, which we usually get from the registry.
# paramDelimiter, default ' --' : the registry value should be a list of parameters separated by paramDelimiter
# lookFor, default 'host ' : identifies what parameter within the registry value that identifies the host name or the host ip address
#
# NOTE 1: The spaces in paramDelimiter, and lookFor are important
# NOTE 2: Leading and trailing whitespaces will be removed during this conversion from all parameters as well.

def ReplaceHostNameToHostIPinOrbacusParamString( parameterString, lookFor='host ', paramDelimiter=' --' ):

    print 'Checking Orbacus IP Address . . .',
    parameterList = string.split( parameterString, paramDelimiter )
    newParameterList = []

    # find the parameter that starts with lookFor
    for ListItem in parameterList:

        ListItem = string.strip( ListItem )
        position = string.find( ListItem, lookFor )

        if position == 0:
            # if we've found it, get the IP address for that host
            hostParameter = ListItem[ len(lookFor): ]
            hostIP = GetHostIPaddress( hostParameter )

            # replace the list item that contains the host name with a list item with the IP address
            ListItem = lookFor + hostIP

            print "Using IP address %s for host %s" % ( hostIP, hostParameter )

        elif position <> -1:
            raise Exception( "Invalid configuration string detected in %s" % parameterString )

        # append the resultin ListItem to the new endpoint list
        newParameterList.append( ListItem )

    # rebuild the parameter sring from the list
    newparameterString = string.join( newParameterList, paramDelimiter )
    return newparameterString

# end helper function ReplaceHostNameToHostIPinOrbacusParamString
##################


# -----------------------------------------------------------------------
# This function receives a list of IP addresses and checks to see if at
# least one of the addresses are stored in the registry.  If not, the
# current IP address stored in the registry is over-written.
def CheckOrbacusIpAddress():

    # Retrieve the IP address from the registry
    try:
        hkey, endpointString = GetKeyValue(win32con.HKEY_LOCAL_MACHINE,
                                 "SOFTWARE\\OOC\\Properties\\ooc\\orb\\oa",
                                 'endpoint')
        endpointString = ReplaceHostNameToHostIPinOrbacusParamString( endpointString )
        win32api.RegSetValueEx(hkey, 'endpoint', RESERVED, win32con.REG_SZ, endpointString)

        hkey, endpointString = GetKeyValue(win32con.HKEY_LOCAL_MACHINE,
                                 "SOFTWARE\\OOC\\Properties\\ooc\\imr",
                                 'admin_endpoint')

        endpointString = ReplaceHostNameToHostIPinOrbacusParamString( endpointString )
        win32api.RegSetValueEx(hkey, 'admin_endpoint', RESERVED, win32con.REG_SZ, endpointString)

        hkey, endpointString = GetKeyValue(win32con.HKEY_LOCAL_MACHINE,
                                 "SOFTWARE\\OOC\\Properties\\ooc\\imr",
                                 'forward_endpoint')

        endpointString = ReplaceHostNameToHostIPinOrbacusParamString( endpointString )
        win32api.RegSetValueEx(hkey, 'forward_endpoint', RESERVED, win32con.REG_SZ, endpointString)

        hkey, endpointString = GetKeyValue(win32con.HKEY_LOCAL_MACHINE,
                                 "SOFTWARE\\OOC\\Properties\\ooc\\imr",
                                 'slave_endpoint')

        endpointString = ReplaceHostNameToHostIPinOrbacusParamString( endpointString )
        win32api.RegSetValueEx(hkey, 'slave_endpoint', RESERVED, win32con.REG_SZ, endpointString)

        # Update HKLM\SOFTWARE\OOC\Properties\ooc\orb\service\IMR to ensure it references this machine
        # This key will have the following format: corbaloc::CHICKEN:49100/IMR
        
        hkey, endpointString = GetKeyValue(win32con.HKEY_LOCAL_MACHINE,
                                 "SOFTWARE\\OOC\\Properties\\ooc\\orb\\service",
                                 'IMR')

        # Find the start and end locations.
        startPosition = string.find( endpointString, '::' )
        startPosition = startPosition + 2
        endPosition   = string.find( endpointString, ':', startPosition)
        
        # Determine the preamble and postamble.
        preamble      = endpointString[ 0:startPosition ]
        postamble     = endpointString[ endPosition: ]
        hostParameter = endpointString[ startPosition:endPosition ]
        
        # Get the local machine's name.
        currentHost = socket.gethostname()
        currentHost = string.upper(currentHost)
        
        # Create the new IMR entry.
        newEntry = preamble + currentHost + postamble

        print 'Checking Orbacus IP Address . . . Updating the IMR entry to "%s"' % newEntry  
        
        # Write the new entry to the registry.        
        win32api.RegSetValueEx(hkey, 'IMR', RESERVED, win32con.REG_SZ, newEntry)

        print 'ok'

        # Update HKLM\SOFTWARE\OOC\Properties\ooc\orb\service\NameService to ensure it references this machine
        # This key will have the following format: corbaloc::CHICKEN:49101/%AB%AC%AB0_RootPOA%00forward%00%00%AB%AC%AB0NameService%00RootContextPOA%00%00NameService
        
        hkey, endpointString = GetKeyValue(win32con.HKEY_LOCAL_MACHINE,
                                 "SOFTWARE\\OOC\\Properties\\ooc\\orb\\service",
                                 'NameService')

        # Find the start and end locations.
        startPosition = string.find( endpointString, '::' )
        startPosition = startPosition + 2
        endPosition   = string.find( endpointString, ':', startPosition)
        
        # Determine the preamble and postamble.
        preamble      = endpointString[ 0:startPosition ]
        postamble     = endpointString[ endPosition: ]
        hostParameter = endpointString[ startPosition:endPosition ]
               
        # Create the new NameService entry.
        newEntry = preamble + currentHost + postamble

        print 'Checking Orbacus IP Address . . . Updating the NameService entry to "%s"' % newEntry  
        
        # Write the new entry to the registry.        
        win32api.RegSetValueEx(hkey, 'NameService', RESERVED, win32con.REG_SZ, newEntry)

        print 'ok'

        return TRUE

    except Exception, err:
        print 'ERROR - Could not check Orbacus IP address.  Cause: %s' % err
        return FALSE
 
# -----------------------------------------------------------------------
def CheckServicePackLevel():

    # This function is used to check the service pack level.  If the service
    # pack level is not greater than or equal to 1, a warning is raised.
    
    print 'Checking Service Pack Level . . .',
 
    # Get the handle and the value to a specified key from the registry. 
    try:  
        key, value = GetKeyValue(win32con.HKEY_LOCAL_MACHINE,
                                 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
                                 'CSDVersion')

        print 'service pack level 1 or greater found.'
        return TRUE

    except:
        # This case is the same as the case where the service pack level
        # is less than Service Pack level 1.
        sys.stdout.write('\a')
        msg = """\
Service pack level 1 or greater is not detected.

Prinergy requires Windows 2000 service pack level 1 or greater."""
        response = Alert(msg, win32con.MB_OK)
        print 'ERROR - Service pack level 1 or greater not detected.'
        return FALSE


# -----------------------------------------------------------------------
def CheckSystemPath():
    
    # This function is used to check the system path to ensure that 
    # AdobeExtreme\bin, CreoAraxi\support\bin, and CreoAraxi\binare the last 
    # ones in PATH (we're interested to have them after PrintConsole\bin).  
    # If not, permission is requested from the user to change the order of the 
    # system path.
    
    rootkey = win32con.HKEY_LOCAL_MACHINE
    subkey = "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"
    result = FALSE
    
    print 'Checking system path order . . .',
    
    # retrieve the system path from the registry to get the actual one, 
    # insteadof getting it from the OS environment strings which may not 
    # be up to date.
    try:
        hkey, sysPath = GetKeyValue(rootkey, subkey, 'PATH')
        expandedSysPath = win32api.ExpandEnvironmentStrings(sysPath)
    except Exception, err:
        raise 'ERROR - system path not found.  Detail: %s' % err
    
    # retrieve AraxiHome
    try:
        araxiHome = os.environ['AraxiHome']
    except Exception, err:
        raise 'ERROR - "AraxiHome" environment variable not found.  Detail: %s' % err
    
    # Construct AdobeExtreme\bin, CreoAraxi\bin, and CreoAraxi\support\bin 
    # from AraxiHome.
    adobeExtremeBin = os.path.join( araxiHome, 'AdobeExtreme', 'bin' )
    creoAraxiSupportBin = os.path.join( araxiHome, 'CreoAraxi', 'support', 'bin' )
    creoAraxiBin = os.path.join( araxiHome, 'CreoAraxi', 'bin' )
    
    # it's easier to work with lists than it is with strings, so let's split it.
    pathList = string.split( expandedSysPath, ';' )
    newPathList = pathList
    
    # first mark all occurrences of the Prinergy paths for deletion in newPathList
    prinergyPaths = [ string.upper( adobeExtremeBin ), string.upper( creoAraxiBin ), string.upper( creoAraxiSupportBin ) ]
    for pathItem in newPathList:
        if string.upper( pathItem ) in prinergyPaths:
                newPathList[ newPathList.index( pathItem ) ] = ''  # mark for deletion
    
    # delete empty items
    newPathList = filter( None, newPathList )
    
    # add all Prinergy paths to the end of newPathList
    newPathList.extend( [ adobeExtremeBin, creoAraxiBin, creoAraxiSupportBin ] )
    
    # check to see if everything but the last 3 items are still untouched.  
    # if so, we don't have to write any changes to the registry, since we're 
    # not attempting to perform any repair actions, we're just trying to 
    # re-order the path.
    if pathList[:-3] == newPathList[:-3]:
        print 'System path order is ok.'
        # no reboot necessary, return true
        result = TRUE
    else:
        newPath = string.join( newPathList, ';' )
        msg = "The current system path is set incorrectly, and may result in unexpected behavior."
        # write the new path back to the registry if user is okay with it.
        if ChangeKeyValue(hkey, 'PATH', newPath, win32con.REG_EXPAND_SZ, msg):
            # user said "yes", and the new path was written,
            print 'fixed.  System path order has now been corrected.'
            # return false to make it ask for reboot at the end
            result = FALSE
        else:
            # user said "no".
            print 'WARNING - system path order has not been corrected.'
            # no reboot necessary, return true
            result = TRUE
    
    return result


# -----------------------------------------------------------------------
def CheckDDNSSetup():

    # This function deselects all the "Register this connection with DNS"
    # flags for TCP/IP connections.  The purpose of deselecting the
    # "Register this connection with DNS" option is to avoid having DHCP
    # clients inccorectly setup to use DDNS which could cause the DNS
    # root server to flood.
    
    print 'Checking dynamic DNS setup . . . ',
    
    msg = ""
    deselectDDNSList = []
    enabledGUIDList = []

    # Get a list of all the enabled network cards.    
    enabledGUIDList, result = GetEnabledNetworkCardList()
        
    if result == TRUE:
        # Iterate through each of the enabled network card GUIDs.
        for enabledGUID in enabledGUIDList:
            try:
                key, value = GetKeyValue(win32con.HKEY_LOCAL_MACHINE,
                                         "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\" + enabledGUID[0],
                                         'DisableDynamicUpdate')

                # Check to see if "Register this connection with DNS" is
                # equalled to 0 or 1.  If equalled to 0, need to change
                # the registry value so that it is equal to 1.                                         
                if value == 0:
                    deselectDDNSList.append(key)
                    msg = msg + "\t" + enabledGUID[1] + "\n"
            except:
                print 'No TCP/IP interface found for network card ' + enabledGUID[1]
                
        if len(deselectDDNSList) == 0:
            # None of the enabled network cards have "Register this
            # connection with DNS" selected.
            print 'ok - server not configured to use dynamic DNS.'           
            return TRUE
        else:         
            # Ask for permission to change the DisableDynamicUpdate
            # value in the registry.
            sys.stdout.write('\a')
            msg = """\
Prinergy will now disable DynamicDNS on the following network 
card(s):
    %s

The DynamicDNS option is normally not required and to avoid improper 
use, Prinergy will disable this feature.  Please press 'OK' to accept.

However, if you require this feature you may cancel now and disable 
this check via the checknetworkconfig.ini file.
""" % msg
            response = AlertWarning(msg, win32con.MB_OKCANCEL)
        
            if response == win32con.IDOK:
                # Update the registry for each of the enabled network
                # cards.
                for deselectDDNS in deselectDDNSList:
                    win32api.RegSetValueEx(deselectDDNS, 'DisableDynamicUpdate', RESERVED, win32con.REG_DWORD, 1)
                print 'fixed - server is no longer configured to use dynamic DNS.'
                return TRUE
            else:
                print 'WARNING - server is still configured to use dynamic DNS.'
                return FALSE
    else:
        print 'No network cards found - no need to check any further.'
        return TRUE
 

# -----------------------------------------------------------------------
def CreateRebootFlag():
    # This function will create a dummy file in CreoAraxi\Support\patches\Admin 
    # directory.  When ppu and pudates sees this file it will ask the user to 
    # make sure and reboot the server before performing an update.
    
    # The runonce registry will be set to remove this file.
    print 'Checking Reboot Flag . . . '
    # Get the araxihome share path
    try:
        araxiHome = os.environ['AraxiHome']
    except Exception, err:
        raise 'ERROR - "AraxiHome" environment variable not found.  Detail: %s' % err

    patchesAdminDirectory = os.path.join(araxiHome, 'CreoAraxi', 'Support', 'patches', 'admin' )
    if not os.path.isdir (  patchesAdminDirectory ):
        raise 'ERROR - Could not find directory %s.' % patchesAdminDirectory
        
    rebootFile = 'ppuRebootCheck.txt'
   
    try:  
        if not os.path.isfile(os.path.join(patchesAdminDirectory, rebootFile)):
            CreateBlankFile( os.path.join(patchesAdminDirectory, rebootFile))
    except:
        raise 'ERROR - Could not create file %s.' % os.path.join(patchesAdminDirectory, rebootFile)
        
    # Traverse the runonce registry to see if the delete command has already been added
    runonce = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE,
                               "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
                               RESERVED,
                               win32con.KEY_READ | win32con.KEY_WRITE)
                                   
    num, val, date = win32api.RegQueryInfoKey(runonce)
    bFound = FALSE
    for s in range(val):
        delCmd = win32api.RegEnumValue(runonce, s)
        if string.upper(delCmd[0]) == 'DELETEPPUREBOOTFLAG':
            bFound = TRUE
            break;     
         
    if not bFound:
        win32api.RegSetValueEx( runonce, 'DeletePPURebootFlag', RESERVED, win32con.REG_EXPAND_SZ, r'CMD /c Del %AraxiHome%\CreoAraxi\support\patches\admin\ppuRebootCheck.txt' )
              
# -----------------------------------------------------------------------
def GetDLTName(valData):

    # This function determines the name of the DLT tape driver.  The tape
    # drive is always there because the calling function is responsible
    # for making sure that a tape drive is detected. 
        
    # Need to strip the last three digits from valData - this will
    # tell us the SCSI bus number, the Target ID and the Logical
    # Unit ID.  
    lastThree = valData[-3:]
    
    busNo = 'Scsi Bus ' + lastThree[0]
    targetId = 'Target Id ' + lastThree[1]
    logicalUnitId = 'Logical Unit Id ' + lastThree[2]
    
    # Get the key to the device map to look at the contents of the SCSI component.
    scsi = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE,
                               "HARDWARE\\DEVICEMAP\\Scsi",
                               RESERVED,
                               win32con.KEY_READ)
                                   
    num, val, date = win32api.RegQueryInfoKey(scsi)
    for s in range(num):
        port = win32api.RegEnumKey(scsi, s)
        pkey = win32api.RegOpenKey(scsi, port, RESERVED, win32con.KEY_READ)
        pnum, pval, pdate = win32api.RegQueryInfoKey(pkey)   
        for p in range(pnum):
            bus = win32api.RegEnumKey(pkey, p)
            if bus == busNo:
                bkey = win32api.RegOpenKey(pkey, bus, RESERVED, win32con.KEY_READ)
                bnum, bval, bdate = win32api.RegQueryInfoKey(bkey)
                
                for b in range(bnum):
                    target = win32api.RegEnumKey(bkey, b)
                    if target == targetId:
                        lkey = win32api.RegOpenKey(bkey, target, RESERVED, win32con.KEY_READ)
                        lnum, lval, ldate = win32api.RegQueryInfoKey(lkey)
                        
                        for l in range(lnum):
                            logical = win32api.RegEnumKey(lkey, l)
                            if logical == logicalUnitId:                                
                                # Found the driver - get its name.
                                tkey = win32api.RegOpenKey(lkey, logical, RESERVED, win32con.KEY_READ)
                                tapeName, tapeType = win32api.RegQueryValueEx(tkey, 'DeviceName')
                                return tapeName
    return ""
              
# -----------------------------------------------------------------------
def GetKeyValue(hkey, subkey, value):

    # This function is used to check the registry for a particular key value
    # (as specified by the calling function).

    # Retrieve the key from the registry.
    try:
        key = win32api.RegOpenKey(hkey,
                                  subkey,
                                  RESERVED,
                                  win32con.KEY_READ | win32con.KEY_WRITE)
        
    except win32api.error, err:
        if err[0] == winerror.ERROR_ACCESS_DENIED:
            print err[2]
            sys.exit(1)
        else:
            raise
        
    # Access the key value
    try:
        data, keyType = win32api.RegQueryValueEx(key, value)
        
    except win32api.error, err:
        if err[0] == winerror.ERROR_ACCESS_DENIED:
            print err[2]
            sys.exit(1)
        else:
            raise

    return key, data
    

# -----------------------------------------------------------------------
def SearchList(stringToFind, listToSearch):

    # This function looks for the location of the string specified by the
    # user in the list and returns the list index of the string.

    for i in range(len(listToSearch)):
        # To make the search through the list case insensitive, compare
        # the capitalized versions of the string to find and the current
        # item in the list that is being checked against.
        if  string.upper(listToSearch[i]) == string.upper(stringToFind):
            return i
    
    return -1
            
# -----------------------------------------------------------------------------
def StartupCheck():

    # WARNING: THE SCRIPT BELOW IS LAUNCHED WITHOUT WAITING FOR A RETURN
    # Because the script might generate a warning message box, and we don't want
    # system startup to have to wait for someone to acknowledge this msg box 
    # (possibly on a secondary server, possibly in another room, or another 
    # building), the script below is launched and processing continues without 
    # waiting for it to return.
    
    cmdLine = 'StartupCheck.cmd'
    win32pipe.popen4(cmdLine, 't')

# -----------------------------------------------------------------------------
def CreateBlankFile( fullfilename ):
   # Creates a blank file
    fNew = open( fullfilename, 'w' )
    fNew.write( '# Empty File\n' ) 
    fNew.close()

#----------------------------------------------------------------------------
# SetFileReadOnlyFlagImp
#
def SetFileReadOnlyFlagImp( filename, readonly=TRUE ):
    fileAttr = None
    try:
        if os.path.isfile( filename ):
            fileAttr = win32file.GetFileAttributes( filename )
            if readonly:
                win32file.SetFileAttributes( filename, fileAttr | win32file.FILE_ATTRIBUTE_READONLY )
            else:
                win32file.SetFileAttributes( filename, fileAttr & ~win32file.FILE_ATTRIBUTE_READONLY )
    except:
        fileAttr = None
    return fileAttr 

# -----------------------------------------------------------------------------
def GetNetworkChecks():

    # This function looks for the checknetworkconfig.ini file and reads it to see
    # which checks need to be performed.

    # Network check flags.
    global kAdaptiveTechSettingCheck                 
    global kCriticalUpdateCheck                      
    global kDNSServerSetupCheck                      
    global kDLTDriversCheck                          
    global kDriverDateCheck                          
    global kEnableDnsForWindowsResolutionSettingCheck
    global kHostNameCheck
    global kPrimaryNodeNameCheck                      
    global kMaintModeCheck                           
    global kNetBEUICheck                             
    global kNetBiosSettingCheck                    
    global kOrbacusIPAddressCheck                    
    global kPrimaryRunningCheck                      
    global kProtocolBindingOrderCheck                
    global kServicePackLevelCheck                    
    global kSystemPathCheck                          
    global kTCPIPBindingOrderCheck                   
    global kTempVarsCheck                            
    global kTimeSyncCheck   
    global kCreateRebootFlag  
    global kRunOnceFlag
        
    DetermineIniFile();
    
    # Read in the values as listed in checknetworkconfig.ini.  If 
    # checknetworkconfig.ini doesn't exist or doesn't have the check listed,
    # set the check to its default value (ON).
    
    print 'In GetNetworkChecks' 
    
    kAdaptiveTechSettingCheck = GetConfigVal('Checks', 'AdaptiveTechSetting', ON)
    kCriticalUpdateCheck = GetConfigVal('Checks', 'CriticalUpdates', ON)
    kDNSServerSetupCheck = GetConfigVal('Checks', 'DDNSSetup', ON)
    kDLTDriversCheck = GetConfigVal('Checks', 'DLTDrivers', ON)
    kDriverDateCheck = GetConfigVal('Checks', 'DriverDate', ON)
    kEnableDnsForWindowsResolutionSettingCheck = GetConfigVal('Checks', 'EnableDnsForWindowsResolutionSetting', ON)
    kHostNameCheck = GetConfigVal('Checks', 'HostName', ON)
    kPrimaryNodeNameCheck = GetConfigVal('Checks', 'PrimaryNodeName', ON)
    kMaintModeCheck = GetConfigVal('Checks', 'MaintenanceMode', ON)
    kNetBEUICheck = GetConfigVal('Checks', 'NetBEUI', ON)
    kNetBiosSettingCheck = GetConfigVal('Checks', 'NetBiosSetting', ON)
    kOrbacusIPAddressCheck = GetConfigVal('Checks', 'OrbacusIPAddress', ON)
    kPrimaryRunningCheck = GetConfigVal('Checks', 'PrimaryRunning', ON)
    kProtocolBindingOrderCheck = GetConfigVal('Checks', 'ProtocolBindingOrder', ON)
    kServicePackLevelCheck = GetConfigVal('Checks', 'ServicePackLevel', ON)
    kSystemPathCheck = GetConfigVal('Checks', 'SystemPath', ON)
    kTCPIPBindingOrderCheck = GetConfigVal('Checks', 'TCPIPBindingOrder', ON)
    kTempVarsCheck = GetConfigVal('Checks', 'TempVariables', ON)
    kTimeSyncCheck = GetConfigVal('Checks', 'TimeSynchronization', ON)
    kCreateRebootFlag = GetConfigVal('Checks', 'CreateRebootFlag', ON)
    kRunOnceFlag = GetConfigVal('Checks', 'RunOnceFlag', ON)
    
# -----------------------------------------------------------------------------
def CheckNetworkSettings():

    # Network check flags.
    global kAdaptiveTechSettingCheck                 
    global kCriticalUpdateCheck                      
    global kDNSServerSetupCheck                      
    global kDLTDriversCheck                          
    global kDriverDateCheck                          
    global kEnableDnsForWindowsResolutionSettingCheck
    global kHostNameCheck
    global kPrimaryNodeNameCheck
    global kMaintModeCheck                           
    global kNetBEUICheck                             
    global kNetBiosSettingCheck                      
    global kOrbacusIPAddressCheck                    
    global kPrimaryRunningCheck                      
    global kProtocolBindingOrderCheck                
    global kServicePackLevelCheck                    
    global kSystemPathCheck                          
    global kTCPIPBindingOrderCheck                   
    global kTempVarsCheck                            
    global kTimeSyncCheck                            
    global kCreateRebootFlag

    driverDateOk = TRUE
    networkAdaptorOk = TRUE
    netBiosOk = TRUE
    bindingsOk = TRUE
    TCPIPBindingsOk = TRUE
    DLTDriversOk = TRUE
    OrbacusIpAddressOk = TRUE
    ServicePackLevelOk = TRUE
    systemPathOk = TRUE
    dnsServerSetupOk = TRUE
    enableDnsOk = TRUE
    hostNameOk = TRUE
    primaryNodeNameOk = TRUE
    
# make sure we can connect to the registry before proceeding. When a server
# starts up, there is a time period when this script is running but the registry
# is not available yet. The following code waits until the registy is 'up'
    connectedToRegistry = FALSE
    connectToRegistryTimeout = 60
    connectPollFreq = 5
    while (connectToRegistryTimeout > 0 and connectedToRegistry == FALSE):
        try:
            AraxiRegistry()
            connectedToRegistry = TRUE

        except win32api.error, err:
            DIAG_LOGINFO('Exception caught connecting to registry, retrying')
            time.sleep(connectPollFreq)
            connectToRegistryTimeout = connectToRegistryTimeout - connectPollFreq

    if (connectedToRegistry == FALSE):
        DIAG_LOGERR('Could not connect to registry since retries exhausted - exiting.')
        sys.exit( EXIT_FAILURE )

    networkCardList, res = GetEnabledNetworkCardList()
    if (res):
        networkCardGUIDList = []
        for networkCard in networkCardList:
            print '\nNetwork card: %s' % networkCard[1]
            networkCardGUID = networkCard[0]
            networkCardGUIDList.append(networkCardGUID)
            if (kDriverDateCheck):            
                print '    ',
                if (not CheckDriverDate(networkCardGUID)):
                    driverDateOk = FALSE
            if (kAdaptiveTechSettingCheck):
                print '    ',
                if (not CheckAdaptiveTechSetting(networkCardGUID)):
                    networkAdaptorOk = FALSE
            if (kNetBiosSettingCheck):
                print '    ',
                if (not CheckNetBiosSetting(networkCardGUID)):
                    netBiosOk = FALSE
                
        print ''
        if (kProtocolBindingOrderCheck):
            bindingsOk = CheckProtocolBindingOrder(networkCardGUIDList)
        if (kTCPIPBindingOrderCheck):
            TCPIPBindingsOk = CheckTCPIPBindingOrder(networkCardGUIDList)
        
        # the netBEUI check does NOT change any settings, so will not require a reboot.
        if (kNetBEUICheck):
            netBEUIOk = CheckNetBEUI(networkCardGUIDList)
    
    if (kTimeSyncCheck):                        
        try:
            timeSyncOk = CheckTimeSync( )
        except Exception, err:
            print '*** exception: %s\n' % err
            DIAG_LOGERR('Error in checknetworkconfig.CheckTimeSync: %s' % err)

    if (kTempVarsCheck):
        try:
            tempVarsOk = CheckTempVars( )
        except Exception, err:
            print '*** exception: %s\n' % err
            DIAG_LOGERR('Error in checknetworkconfig.CheckTempVars: %s' % err)

    if (kMaintModeCheck):
        try:
            maintModeOk = CheckMaintMode( )
        except Exception, err:
            print '*** exception: %s\n' % err
            DIAG_LOGERR('Error in checknetworkconfig.CheckMaintMode: %s' % err)

    if (kCriticalUpdateCheck):
        try:
            noCriticalUpdates = CheckCriticalUpdate( )
        except Exception, err:
            print '*** exception: %s\n' % err
            DIAG_LOGERR('Error in checknetworkconfig.CheckCriticalUpdate: %s' % err)

    if (kEnableDnsForWindowsResolutionSettingCheck):
        try:
            enableDnsOk = CheckEnableDnsForWindowsResolutionSetting()
        except Exception, err:
            print '*** exception: %s\n' % err
            DIAG_LOGERR('Error in checknetworkconfig.CheckEnableDnsForWindowsResolutionSetting: %s' % err)

    if (kHostNameCheck): 
        try:
            hostNameOk = CheckHostName()
        except Exception, err:
            print '*** exception: %s\n' % err
            DIAG_LOGERR('Error in checknetworkconfig.CheckHostName: %s' % err)

    if (kPrimaryNodeNameCheck): 
        try:
            primaryNodeNameOk = FixPrimaryNodeName()
        except Exception, err:
            print '*** exception: %s\n' % err
            DIAG_LOGERR('Error in checknetworkconfig.FixPrimaryNodeName: %s' % err)

    if (kPrimaryRunningCheck):
        try:
            primaryRunningOk = CheckPrimaryRunning()
        except Exception, err:
            print '*** exception: %s\n' % err
            DIAG_LOGERR('Error in checknetworkconfig.CheckPrimaryRunning: %s' % err)

    if (kDLTDriversCheck):
        try:
            DLTDriversOk = CheckDLTDrivers()
        except Exception, err:
            print '*** exception: %s\n' % err
            DIAG_LOGERR('Error in checknetworkconfig.CheckDLTDrivers: %s' % err)
    
    if (kOrbacusIPAddressCheck):        
        try:
            OrbacusIpAddressOk = CheckOrbacusIpAddress()
        except Exception, err:
            print '*** exception: %s\n' % err
            DIAG_LOGERR('Error in checknetworkconfig.CheckOrbacusIpAddress: %s' % err)

    if (kServicePackLevelCheck):
        try:
            ServicePackLevelOk = CheckServicePackLevel()
        except Exception, err:
            print '*** exception: %s\n' % err
            DIAG_LOGERR('Error in checknetworkconfig.CheckServicePackLevel: %s' % err)
    
    if (kSystemPathCheck):           
        try:
            systemPathOk = CheckSystemPath()
        except Exception, err:
            print '*** exception: %s\n' % err
            DIAG_LOGERR('Error in checknetworkconfig.CheckSystemPath: %s' % err)

    if (kDNSServerSetupCheck):
        try:
            dnsServerSetupOk = CheckDDNSSetup()
        except Exception, err:
            print '*** exception: %s\n' % err
            DIAG_LOGERR('Error in checknetworkconfig.CheckDDNSSetup: %s' % err)

    if (kCreateRebootFlag):
        try:
            CreateRebootFlag()
        except Exception, err:
            print '*** exception: %s\n' % err
            DIAG_LOGERR('Error in checknetworkconfig.CreateRebootFlag: %s' % err)

    if (kRunOnceFlag):
        try:
            CheckRunOnceNeedsToRun()
        except Exception, err:
            print '*** exception: %s\n' % err
            DIAG_LOGERR('Error in checknetworkconfig.RunOnceFlag: %s' % err)


            
    if enableDnsOk and hostNameOk and networkAdaptorOk and driverDateOk and bindingsOk and\
       TCPIPBindingsOk and systemPathOk and dnsServerSetupOk:
        pass
    else:
        # probably we should only reboot if corrections were made, but in the
        # case of fixing binding order, we don't really know if the user went
        # to the control panel and actually fixed it properly, so always ask 
        # if any errors were found. Perhaps we could loop to check again?
        sys.stdout.write( '\a' )
        response = Alert( """\
One or more network settings were incorrect.

Restart the system now?""", win32con.MB_YESNO )
        if response == win32con.IDYES:
            Reboot()
        else:
            sys.exit( EXIT_FAILURE )

# -----------------------------------------------------------------------------

if __name__ == '__main__':
    StartupCheck()
    GetNetworkChecks()
    CheckNetworkSettings()
