;====================================================================================
;====================================================================================
;
; OEMSetup.inf
;
; Function.
;  Installation Script for Express-Link by IP Metrics
;  Software, Inc.
;
;
; History.
;  01 March     1998 BBT            Initial writing.
;
;  24 March     1998 BBT            Fixed several bugs.
;
;  14 April     1998 B. Dolecheck   Added SNMP Install & Removal.
;
;  13 May       1998 B. Dolecheck   Corrected problems with AppleTalk.
;
;  24 May       1998 B. Dolecheck   Changed driver to NDIS Transport and
;                                   removed dup cards in list.
;
;  27 May       1998 B. Dolecheck   Removed unnecessary commas so UI parses
;                                   correct.
;
;  29 September 1998 B. Dolecheck   Modifications for D-Link Corporation.
;
;  21 October   1998 B. Dolecheck   Added ConnectTest registry entry.
;
;  28 April     1999 B. Dolecheck   Added detection of the RollUp Hotfix for
;                                   SP4 instead of the TCPIP hotfix.
;
;  10 May       1999 B. Dolecheck   Added detection of SP5.
;
;  14 October   1999 M. Reyero      No longer call the CheckVersionInfo during
;                                   configuration.
;
;  19 July      2000 B. Dolecheck   Added registry entry 'ValidateRoute'.
;
;  20 February  2001 B. Dolecheck   Changed the titles to D-Link Server Card.
;
;  Copyright (c) 1997-2001 IP Metrics Software, Inc.
;                          All Rights Reserved.
;====================================================================================
;====================================================================================

[Identification]
    OptionType = NetTransport

[LanguagesSupported]
    ENG

[Options]
    ExpressLink

[OptionsTextENG]
    ExpressLink = "D-Link Server Card Load Balancing and Failover Software"

[FileConstants]
    UtilityInf                       = "UTILITY.INF"
    SubroutineInf                    = "SUBROUTN.INF"
    TransportSoftwareType            = "transport"
    AdapterSoftwareType              = "driver"
    Exit_Code                        = 0
    NetEventDLL                      = "%SystemRoot%\System32\ExpressLnk_Msgs.dll"

    Manufacturer                     = "D-Link Corp"
    ProductMajorVersion              = "1"
    ProductMinorVersion              = "0"
    ProductVersion                   = $(ProductMajorVersion)"."$(ProductMinorVersion)

    GroupNumber                      = "1"
    GroupName                        = "Test Group #1"
    BaseGroupTitle                   = "New Segment"
    BaseGroupName                    = "Group0"

    MaxFailures                      = "3"   ; Maximum times a NIC can fail is.
    MaxFailuresTimePeriod            = "60"  ; 3 times in 60 minutes before being declared faulty.
    NoTrafficTimePeriod              = "120" ; 120 secs w/o traffic causes last adapter to be pulled.
    ConnectTesting                   = "1"   ; Check connection status at init time.
    LoadBalancing                    = "1"   ; Turn on load balancing by default.
    ValidateRoute                    = "0"   ; Do not validate route to default gateway.

    TransportProductSoftwareName     = "ExpressLink"
    AdapterProductSoftwareName       = "ExpressLinkMP"
    AdapterProductHardwareName       = "ExpressLinkMP"

    ProductSoftwareImagePath         = "\SystemRoot\System32\drivers\ExpressLnk.sys"

    TransportNetRuleSoftwareType     = "expressLink expressLink"
    TransportNetRuleSoftwareClass    = {"expressLink ndisTransport"}
    TransportNetRuleSoftwareUse      = $(TransportSoftwareType)" yes none"
    TransportNetRuleSoftwareBindForm = """expressLink"" yes yes container"
    TransportNetRuleSoftwareBindable = {"expressLink ndisDriver non non 100"}

    AdapterNetRuleSoftwareType       = "expLnkArSys ndisDriver expLnkArDriver"
    AdapterNetRuleSoftwareUse        = $(AdapterSoftwareType)
    AdapterNetRuleSoftwareBindForm   = """expLnkArSys"" yes no container"
    AdapterNetRuleSoftwareClass      = {"expLnkArDriver basic"}
    AdapterNetRuleSoftwareBindable   = {"expLnkArDriver expLnkArAdapter non exclusive 100"}

    AdapterNetRuleHardwareType       = "expLnkAr expLnkArAdapter"
    AdapterNetRuleHardwareBindForm   = " yes yes container"
    AdapterNetRuleHardwareClass      = {"expLnkArAdapter basic"}
    AdapterNetRuleHardwareBlock      = {"expressLink expLnkArAdapter"}

    TransportProductKeyName          = $(!NTN_SoftwareBase)"\"$(Manufacturer)"\"$(TransportProductSoftwareName)"\CurrentVersion"
    TransportParamKeyName            = $(!NTN_ServiceBase)"\"$(TransportProductSoftwareName)"\Parameters"
    TransportServiceKeyName          = $(!NTN_ServiceBase)"\"$(TransportProductSoftwareName)
    TransportLinkageKeyName          = $(!NTN_ServiceBase)"\"$(TransportProductSoftwareName)"\Linkage"

    AdapterProductKeyName            = $(!NTN_SoftwareBase)"\"$(Manufacturer)"\"$(AdapterProductSoftwareName)"\CurrentVersion"
    AdapterParamKeyName              = $(!NTN_ServiceBase)"\"$(AdapterProductSoftwareName)"\Parameters"
    AdapterServiceKeyName            = $(!NTN_ServiceBase)"\"$(AdapterProductSoftwareName)
    AdapterLinkageKeyName            = $(!NTN_ServiceBase)"\"$(AdapterProductSoftwareName)"\Linkage"

    TransportSignature               = "ExpressLink_Virtual_Adapter"

    NcpaBase                         = $(!NTN_SoftwareBase)"\Microsoft\NCPA\CurrentVersion"
    TcpIpServiceBase                 = $(!NTN_ServiceBase)"\TcpIp"
    ATServiceKeyName                 = $(!NTN_ServiceBase)"\AppleTalk"
    NwLnkNbServiceKeyName            = $(!NTN_ServiceBase)"\NwlnkNb"

    SNMPServiceKeyName               = $(!NTN_ServiceBase)"\SNMP"
    SNMPPathLocation                 = $(TransportProductKeyName)"\SnmpAgent"
    SNMPFileName                     = "ExpressLnk_Snmp.dll"
    SNMPFileLocation                 = $(!STF_WINDOWSSYSPATH)"\"$(SNMPFileName)

[FileConstantsENG]
    ProCaption                          = "D-Link Server Card Setup"
    ProCancel                           = "Cancel"
    ProCancelMsg                        = "Windows NT Networking is not correctly installed.  "+
                                          "Are you sure you want to cancel copying files?"
    ProCancelCap                        = "Network Setup Message"
    ProText1                            = "Copying:"
    ProText2                            = "To:"
    FunctionTitle                       = "ExpressLink Driver"
    TransportProductSoftwareDescription = "The D-Link Server Card transport driver is used for failover and load balancing network traffic."
    TransportProductSoftwareDisplayName = "D-Link Server Card Transport"
    TransportProductSoftwareTitle       = "D-Link Server Card Transport"
    AdapterProductSoftwareDescription   = "D-Link Server Card miniport adapter, which is used for failover and load balancing network traffic."
    AdapterProductSoftwareDisplayName   = "D-Link Server Card Miniport Adapter"
    AdapterProductSoftwareTitle         = "D-Link Server Card Miniport Adapter"
    ProductHardwareDescription          = "D-Link Server Card virtual adapter, which is used for failover and load balancing network traffic."
    ProductHardwareDisplayName          = "D-Link Server Card Virtual Adapter"
    ProductHardwareTitle                = "D-Link Server Card Virtual Adapter"
    ShellCodeErrorTitle                 = "Error: ExpressLink Driver"
    ShellCodeErrorText                  = "Shell Code Error."

[GeneralConstants]
    from                = ""
    to                  = ""
    ExitCodeOk          = 0
    ExitCodeCancel      = 1
    ExitCodeFatal       = 2
    KeyNull             = ""
    MAXIMUM_ALLOWED     = 33554432
    RegistryErrorIndex  = NO_ERROR
    KeyProduct          = ""
    KeyParameters       = ""
    TRUE                = 1
    FALSE               = 0
    NoTitle             = 0
    ExitState           = "Active"
    OldVersionExisted   = $(FALSE)
    DriverPath          = $(!STF_NTPATH)\drivers
    NDIS_HotFix_Ver     = "Service Pack 3"
    TCPIP_HotFix_Ver    = "Service Pack 4"

[Source Media Descriptions]
    1 = "D-Link Server Card Installation Disk", TAGFILE = disk1

[Files-Inf]
    1, OEMSETUP.INF, SIZE=999, RENAME=$(InfName)

[Files-Dialog]
    1, ExplDlg.dll,   SIZE=999
    1, ExplDlg.hlp,   SIZE=999
    1, ExplDlg.cnt,   SIZE=999
    1, ExplGraph.dll, SIZE=999

[Files-Platform-Drivers]
    1, ExpressLnk.SYS , SIZE=999

[Files-MsgDLL]
    1, ExpressLnk_Msgs.DLL , SIZE=999

[Files-SnmpDLL]
    1, ExpressLnk_Snmp.DLL , SIZE=999

[DialogConstantsENG]
    Help                = "&Help"
    Exit                = "Cancel"
    OK                  = "OK"
    HelpContext         = ""
    Continue            = "Continue"
    Cancel              = "Cancel"

;==================================================================
;==================================================================
; Data Section - OS Versions Supported.
;
[VersionsSupported]
    Ver0 = "Service Pack 3"
    Ver1 = "Service Pack 4"
    Ver2 = "Service Pack 5"
    Ver3 = "Service Pack 6"

;==================================================================
;==================================================================
; Data Section - Registry Info for Adapter Search.
;
[RegBaseInfo]
    AdapterNumber         = "1"
    AdapterRegBase        = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards\"
    NDISHotFixRegBase     = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Hotfix\Q156655"
    NDISTEHotFixRegBase   = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Hotfix\Q216108"
    TCPIPHotFixRegBase    = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\SP4\Hotfix\Q195725"
    RollUpHotFixRegBase   = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\SP4\Hotfix\Q195734"
    TermSrvRegBase        = "SYSTEM\CurrentControlSet\Control\Terminal Server"
    NumProcossorRegBase   = "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
    AvailableAdaptersList = {}
    AllAdaptersInfo       = {}
    ServiceBase           = $(!NTN_ServiceBase)"\"
    ParameterBase         = "\Parameters"
    TcpipBase             = "\Parameters\Tcpip"
    ExpressLinkBase        = "\Parameters\ExpressLink"
    NetRulesBase          = "\NetRules"

;==================================================================
;==================================================================
; Data Section - Known Bindable Transports.
;
[TransportNames]
    Transport0 = lanmanServer
    Transport1 = lanmanWorkstation
    Transport2 = ipxTransport
    Transport3 = tcpipTransport
    Transport4 = netbtTransport
    Transport5 = nbfTransport
    Transport6 = netBiosTransport
    Transport7 = appletalktransport

;==================================================================
;==================================================================
; Data Section - Modified Item Notes.
;
[ItemNotesENG]
    Set-Subst LF = "\n"
    UpdatedText = "Member of the D-Link for "$(UpdateSegmentName)$(LF)$(LF)

;==================================================================
;==================================================================
; Data Section - Text Messages.
;
[ErrorMessagesENG]
    WrongOSVersion       = "The D-Link Server Card interface requires a minumum of WindowsNT 4.0 Service Pack 3 (SP3) before installation. "+
                           "Please consult the ReadMe or SetupGuide for further information.  This installation will now exit."
    WrongSPVersion       = "D-Link Server Card Load Balancing and Failover software has not been tested on this Service Pack release. "+
                           "You can contact D-Link Software to check if this Service Pack release has been verified yet. "$(!LF)$(!LF)+
                           "Would you like to continue?"
    AlreadyInstalled       = "A version of this transport is already installed on this system.  "+
                             "In order to update, lease remove and then reinstall."
    ExpressLinkNotLoaded    = "The D-Link Server Card Transport is not currently running.  "+
                             "The Status Display will not be available."
    CannotRemoveFrom0      = "This Segment contains no accessible adapters."
    MustRemoveTransport    = "To uninstall this adapter, remove '"$(TransportProductSoftwareDescription)"' from under the Protocols tab."
    NoTCP                  = "In order to use the D-Link Server Card interface, the TCP/IP protocol stack must be installed."
    CannotConfigure        = "In order to modify the configuration, select the D-Link Server Card transport on the protocols tab."
    NoAdapterToAdd         = "There are no adapters available to add"
    NoNetRules             = "The NetRules subkey was not found for ExpressLink"
    NoInfName              = "The InfName values was not found for ExpressLink"
    NoSNMP                 = "The Windows NT SNMP Service is currently not installed. Therefore the D-Link Server Card "+
                             "SNMP agent will not be installed. If you would like to add this functionality later, "+
                             "first install the Windows NT SNMP Service and then update the D-Link Server Card Transport via "+
                             "the Update button."
    NoNDISHotFix         = "The NDIS Hotfix has not been installed on this computer. This fix corrects "+
                           "problems between NDIS and Intermediate Drivers. It is highly recommended that "+
                           "this Hotfix be installed from the following ftp site: "$(!LF)+
                           "ftp://ftp.microsoft.com/bussys/winnt/winnt-public/fixes/usa/nt40/hotfixes-postSP3/ndis-fix"$(!LF)$(!LF)+
                           "Would you like to continue?"
    NoRollUpHotFix       = "The RollUp Hotfix has not been installed on this computer. This fix corrects "+
                           "problems between TCP/IP and Intermediate Drivers. It is highly recommended that "+
                           "this Hotfix be installed from the following ftp site: "$(!LF)+
                           "ftp://ftp.microsoft.com/bussys/winnt/winnt-public/fixes/usa/nt40/hotfixes-postSP4/roll-up"$(!LF)$(!LF)+
                           "Would you like to continue?"
    NoNDISTEHotFix         = "This version of WindowsNT Terminal Server Edition requires a newer version of NDIS. "+
                             "Please contact D-Link for further information on this issue. "+
						     "Please review the ReadMe.txt file for additional information before rebooting!"
    UnassignedAdapters   = "Currently there are adapters unassigned to D0Link Load Balancing and Failover Software. "+
                           "All Adapters must be assigned to an array. "+
			               "Would you like to assign them now?"

;==================================================================
;==================================================================
; Data Section - Default Configuration Parameters.
;
[DefaultParametersENG]
    NoneSelected          = ""
    Group0List            = {}
    GroupTitleList        = { $(BaseGroupTitle) }
    GroupNameList         = { $(BaseGroupName) }
    GroupAdapterList      = { $(Group0List) }


;==================================================================
;==================================================================
; Data Section - Null out Status Display.
;
[NullStats]
    StatBytesIn     = 0
    StatBytesOut    = 0
    StatPacketsIn   = 0
    StatPacketsOut  = 0
    CurrentStatsLbl = ""
    EditTextIn      = { $(StatBytesIn), $(StatBytesOut), $(StatPacketsIn), $(StatPacketsOut), $(CurrentStatsLbl) }

;==================================================================
;==================================================================
; Data Section - Set Debug Display Level.
;
[DebugLevel]
    !DebugOutputControl = 1

;==================================================================
;==================================================================
; Data Section - Variables for Dialog DLL.
;
[DllInformation]
    DllName  = ExplDlg.dll

;==================================================================
;==================================================================
; Detect Current Date.
;
[CurrentDate]
    Now = {} ? $(!LIBHANDLE) GetSystemDate

;==================================================================
;==================================================================
; Identify Major Options Supported by INF File.
;
; $($R0)  = Status.
; $($R1)  = .inf option type(s).
; $($R2)  = Installation media description.
;
[Identify]
    Read-Syms DebugLevel
    Read-Syms Identification

    Set Status     = STATUS_SUCCESSFUL
    Set Identifier = $(OptionType)
    Set Media      = #("Source Media Descriptions", 1, 1)

    Return $(Status) $(Identifier) $(Media)

;==================================================================
;==================================================================
; Return INF File Supported Options.
;
; $($0)  =  Target Language.
; $($1)  =  Target Platform.
;
; $($R0) =  Status.
; $($R1) =  List of .inf options.
; $($R2) =  Description of .inf options.
;
[ReturnOptions]
    Read-Syms DebugLevel

    Set OptionList     = {}
    Set OptionTextList = {}
    Set LanguageList   = ^(LanguagesSupported, 1)
    Set PlatformList   = ^(PlatformsSupported, 1)

    IfContains(i) $($0) Not-In $(LanguageList)
        Set Status = STATUS_NOLANGUAGE
    Else
        Set Status = STATUS_SUCCESSFUL
        Set OptionList     = ^(Options, 1)
        Set OptionTextList = ^(OptionsText$($0), 1)
    EndIf

    Return $(Status) $(OptionList) $(OptionTextList)

;==================================================================
;==================================================================
; Install Option.
;
;
; $($0) =  Language to use
; $($1) =  OptionID to install
; $($2) =  SourceDirectory
; $($3) =  AddCopy  (YES | NO)
; $($4) =  DoCopy   (YES | NO)
; $($5) =  DoConfig (YES | NO)
;
; $($R0) = STATUS
;
;
[InstallOption]
    Set Status   = STATUS_FAILED
    Set Option   = $($1)
    Set SrcDir   = $($2)
    Set AddCopy  = $($3)
    Set DoCopy   = $($4)
    Set DoConfig = $($5)

    Read-Syms DebugLevel

    Read-Syms GeneralConstants
    Read-Syms FileConstants
    Read-Syms RegBaseInfo
    Read-Syms ErrorMessages$(!STF_LANGUAGE)

    Set LanguageList = ^(LanguagesSupported, 1)

    IfContains(i) $($0) NOT-IN $(LanguageList)
        Return STATUS_NOLANGUAGE
    EndIf

    Set-Title  $(FunctionTitle)

    EndWait


    IfStr(i) $(!NTN_InstallMode)      == DeInstall
        Set StartLabel = RemoveTransport
    Else-IfStr(i) $(!NTN_InstallMode) == Update
        Set StartLabel = UpdateTransport
        Shell "" CheckVersionInfo
        IfStr(i) $($R0) != STATUS_SUCCESSFUL
            Return $($R0)
        EndIf
    Else-IfStr(i) $(!NTN_InstallMode) == Bind
        Set StartLabel = BindTransport
    Else-IfStr(i) $(!NTN_InstallMode) == Configure
        Set StartLabel = ConfigureTransport
        ;Shell "" CheckVersionInfo
        ;IfStr(i) $($R0) != STATUS_SUCCESSFUL
        ;    Return $($R0)
        ;EndIf
    Else
        Set StartLabel = InstallTransport
    EndIf

    ;Debug-Output "ExpressLink: Executing "$(StartLabel)
    Set Path = $(!STF_PLATFORM)

    GoTo $(StartLabel)

;======================================================
;======================================================
UpdateTransport = +
    Read-Syms FileConstants
    Read-Syms GeneralConstants
    Read-Syms ErrorMessages$(!STF_LANGUAGE)

    set FinalStatus = "STATUS_SUCCESSFUL"

    ;----------------------------------------------------
    ; Setup the variable so the inf functions will know
    ; where to find the source files and the new INF file
    ;----------------------------------------------------
    Set InfDir      = $(SrcDir)

    Shell "" StripTrailSlash $(SrcDir)
    Set Temp   = $(SrcDir)"\"$(Path)
    Set SrcDir = $(Temp)

    ; First determine the installed name of the .INF file so the new version can
    ; overwrite the existing one.
    set NetRulesName = $(TransportProductKeyName)"\NetRules"
    OpenRegKey $(!REG_H_LOCAL) "" $(NetRulesName) $(MAXIMUM_ALLOWED) KeyProduct
    ifint $(RegLastError) != $(!REG_ERROR_SUCCESS)
        Shell "" DoFatalMessage $(NoNetRules)
        set FinalStatus = CANNOT_FIND_COMPONENT_SERVICE
    else
        set SubKeyName = "InfName"
        GetRegValue $(KeyProduct) $(SubKeyName) InfNameList
        ifint $(RegLastError) != $(!REG_ERROR_SUCCESS)
            Shell "" DoFatalMessage $(NoInfName)
            set FinalStatus = CANNOT_FIND_COMPONENT_SERVICE
        else
            set InfName = *($(InfNameList), 4)
            ;Debug-Output "InfName: "$(InfName)
        endif
        CloseRegKey $(NetRulesHKey)
    endif

    ;-------------------------------------------------------------
    ; Check to see if the ConnectTest registry entry exists. If it
    ; does not then we will need to create it. This entry is used
    ; to inform the driver that if status indications are in place 
    ; and the entry is set to 1, then the driver must query the
    ; connection status to determine if the adapter should be 
    ; removed from the array. Setting it to zero turns it off.
    ;-------------------------------------------------------------
    OpenRegKey $(!REG_H_LOCAL) "" $(TransportParamKeyName) $(MAXIMUM_ALLOWED) KeyParameters

    IfStr(i) $(KeyParameters) != $(KeyNull)
        Set ConnectTestList = {}
        GetRegValue $(KeyParameters) "ConnectTest" ConnectTestList

        IfStr(i) $(ConnectTestList) == {}
            SetRegValue $(KeyParameters) {"ConnectTest", $(NoTitle), $(!REG_VT_DWORD), $(ConnectTesting)}
        EndIf
    EndIf

    ;-------------------------------------------------------------
    ; Check to see if the LoadBalance registry entry exists. If it
    ; does not then we will need to create it. This entry is used
    ; to turn on/off load balancing within the driver.
    ;-------------------------------------------------------------
    IfStr(i) $(KeyParameters) != $(KeyNull)
        Set LBTestList = {}
        GetRegValue $(KeyParameters) "LoadBalance" LBTestList

        IfStr(i) $(LBTestList) == {}
            SetRegValue $(KeyParameters) {"LoadBalance", $(NoTitle), $(!REG_VT_DWORD), $(LoadBalancing)}
        EndIf
    EndIf

    ;-------------------------------------------------------------
    ; Check to see if the ValidateRoute registry entry exists. If
    ; it does not then we will need to create it. This entry is
    ; used to validate the route to the default gateway.
    ;-------------------------------------------------------------
    IfStr(i) $(KeyParameters) != $(KeyNull)
        Set VRTestList = {}
        GetRegValue $(KeyParameters) "ValidateRoute" VRTestList

        IfStr(i) $(VRTestList) == {}
            SetRegValue $(KeyParameters) {"ValidateRoute", $(NoTitle), $(!REG_VT_DWORD), $(ValidateRoute)}
        EndIf
 
        CloseRegKey $(KeyParameters)
    EndIf

    install "Install-Update"
    install InstallSNMPagent

    Return $(FinalStatus)


;==================================================================
;==================================================================
;  Install New Transport.
;
;  $($R0)  Status.
;
InstallTransport = +
    Read-Syms FileConstants
    Read-Syms GeneralConstants
    Read-Syms FileConstants$(!STF_LANGUAGE)
    Read-Syms ErrorMessages$(!STF_LANGUAGE)

    ;-----------------------------------------------------------------------------
    ; Check to see if this computer has the SNMP installed. If not then
    ; we need to warn the user that our SNMP service will not be used.
    ;-----------------------------------------------------------------------------
    OpenRegKey $(!REG_H_LOCAL) "" $(SNMPServiceKeyName) $(!REG_KEY_CREATE_SUB_KEY) SNMPHandle
    IfStr $(SNMPHandle) == $(KeyNull)
       ;Debug-Output "The SNMP Service is not installed."
       Shell "" DoNonFatalMessage $(NoSNMP) NONFATAL
    EndIf

    Set OldVersionExisted = FALSE

    OpenRegKey $(!REG_H_LOCAL) "" $(TransportProductKeyName) $(MAXIMUM_ALLOWED) KeyProduct

    IfStr $(KeyProduct) != $(KeyNull)
        CloseRegKey $(KeyProduct)
        Shell "" DoFatalMessage $(AlreadyInstalled)
        Return STATUS_FAILED
    EndIf

    IfStr(i) $(DoCopy) == "YES"
        Shell $(UtilityInf) DoAskSource $(!STF_CWDDIR) $(SrcDir) YES

        IfInt $($ShellCode) != $(!SHELL_CODE_OK)
            Shell "" DoShellErrorMessage
            Return STATUS_FAILED
        Else-IfStr(i) $($R0) == STATUS_FAILED
            Shell "" DoRegistryMessage DoFatalMessage ASK_SOURCE_FAIL
            Return STATUS_FAILED
        Else-IfStr(i) $($R0) == STATUS_USERCANCEL
            Return STATUS_USERCANCEL
        EndIf

        Set SrcDir = $($R1)
    EndIf

    Shell "" StripTrailSlash $(SrcDir)
    Set PlatformDir  = $($R0)"\"$(!STF_PLATFORM)
    Set InfDir       = $($R0)"\"
    Shell "" StripTrailSlash $(PlatformDir)
    Set DialogDir = $(PlatformDir)"\"

    ;Shell "" TestTCP
    ;IfStr(i) $($R0) != STATUS_SUCCESSFUL
    ;    Return $($R0)
    ;EndIf

    Read-Syms DefaultParameters$(!STF_LANGUAGE)

    Shell "" CheckVersionInfo
    IfStr(i) $($R0) != STATUS_SUCCESSFUL
        Return $($R0)
    EndIf

    Shell "" DoAdapterDialog

    IfStr(i) $($R0) != STATUS_SUCCESSFUL
        Return $($R0)
    EndIf

    Shell "" AddTransportComponent $(OldVersionExisted)

    IfStr(i) $($R0) != STATUS_SUCCESSFUL
        Return $($R0)
    EndIf

    IfStr(i) $(OldVersionExisted) == FALSE
        install "Install-Option"
  
        IfStr(i) $(STF_INSTALL_OUTCOME) != STF_SUCCESS
            Shell "" DoRegistryMessage DoFatalMessage UNABLE_COPY_FILE
            Return STATUS_FAILED
        EndIf

        Shell "" AddInfToReview
    EndIf

    install InstallSNMPagent
    
    Return STATUS_SUCCESSFUL

;==================================================================
;==================================================================
;  Configure Existing Transport.
;
;  $($R0)  Status.
;
ConfigureTransport = +
    Read-Syms FileConstants
    Read-Syms GeneralConstants
    Read-Syms FileConstants$(!STF_LANGUAGE)
    Read-Syms ErrorMessages$(!STF_LANGUAGE)

    Set OldVersionExisted = TRUE

    IfStr(i) $(!NTN_RegBase) != $(TransportProductKeyName)
        Shell "" DoFatalMessage $(CannotConfigure)
        Return STATUS_FAILED
    EndIf


    IfStr(i) $(ProductKeyName) == $(!NTN_RegBase)
        Shell "" DoRegistryMessage DoNonFatalMessage CANNOT_CONFIGURE_SOFTWARE STATUS
        Return STATUS_SUCCESSFUL
    EndIf

    IfStr(i) $(KeyProduct) == $(KeyNull)
        OpenRegKey $(!REG_H_LOCAL) "" $(!NTN_RegBase) $(MAXIMUM_ALLOWED) KeyProduct
        IfStr(i) $(KeyProduct) == $(KeyNull)
            Shell "" DoRegistryErrorMessage DoFatalMessage CANNOT_FIND_COMPONENT_SERVICE
            Return STATUS_FAILED
        EndIf
    EndIf

    Shell $(UtilityInf) FindService $(KeyProduct)

    IfInt $($ShellCode) != $(!SHELL_CODE_OK)
       Shell "" DoShellErrorMessage
       Return STATUS_FAILED
    EndIf

    IfStr(i) $($R0) != NO_ERROR
        Shell "" DoRegistryErrorMessage DoFatalMessage $($R0)
        Return STATUS_FAILED
    EndIf

    CloseRegKey $($R1)
    CloseRegKey $($R2)

    Shell "" DoAdapterDialog

    IfStr(i) $($R0) != STATUS_SUCCESSFUL
        Return $($R0)
    EndIf

    Return STATUS_SUCCESSFUL

;==================================================================
;==================================================================
;  Bind Transport.
;
;  $($R0)  Status.
;
BindTransport =+
    Read-Syms FileConstants
    Read-Syms GeneralConstants
    Read-Syms FileConstants$(!STF_LANGUAGE)
    Read-Syms ErrorMessages$(!STF_LANGUAGE)

    Set OldVersionExisted = TRUE

	;
	; If Netbios/IPX is loaded then set the keepalive timer down
	; so that failover will happen quicker.
	;

    ;  Try to open the NwlnkNb service key to see if it exists.
    OpenRegKey $(!REG_H_LOCAL) "" $(NwLnkNbServiceKeyName) $(!REG_KEY_CREATE_SUB_KEY) NwLnkNbHandle
    ifstr $(NwLnkNbHandle) == $(KeyNull)
       Debug-Output "The NwLnkNb Service is not installed."
       goto ContinueBind
    endif

    ;  Open the key for the Parameters and if successful, change the keepalive timer.
    OpenRegKey $(NwLnkNbHandle) "" "Parameters" $(!REG_KEY_ALL_ACCESS) ParamsHandle
    ifstr $(ParamsHandle) != $(KeyNull)
       SetRegValue $(ParamsHandle) {"KeepaliveTimeout", 0, $(!REG_VT_DWORD), "15"}
       CloseRegKey $(ParamsHandle)
    endif

    CloseRegKey $(NwLnkNbHandle)

;;;;;

ContinueBind = +

    ;
    ;   If this is the binding review for the Transport Driver...
    ;
    ifstr(i) $(!NTN_RegBase) == $(TransportProductKeyName)
        ;
        ; Check to see if there are any unassigned adapters
        ;
        Shell "" AllAdaptersAssigned
        IfStr(i) $($R0) != STATUS_SUCCESSFUL
            Shell "" DoShellDialog "NICExpress" $(UnassignedAdapters) 3 1 1
            IfStr(i) $($R0) == "YES"
                Shell "" AssignAdaptersToArray

                IfStr(i) $($R0) == STATUS_SUCCESSFUL
                   Shell "" AllAdaptersAssigned
                EndIf
            EndIf
        EndIf

        ;
        ;  Open the Linkage Key, \SYSTEM\CurrentControlSet\Services\ExpressLink\Linkage
        ;  and obtain the Bind value.  AllBindList includes 
        ;  "\Device\adapter1 \Device\adapter2 ..." 
        ;
        OpenRegKey $(!REG_H_LOCAL) "" $(TransportLinkageKeyName) $(MAXIMUM_ALLOWED) TransportLinkageKey

        ifstr(i) $(TransportLinkageKey) != ""
            GetRegValue $(TransportLinkageKey) "Bind" BindList
            Set AllBindList = *($(BindList),4)
            CloseRegKey $(TransportLinkageKey)
        else
            set RegistryErrorIndex = $(RegLastError)
            Debug-Output "ExpressLink: failed to open Linkage Key for "$(TransportServiceKeyName)
            Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
            Return STATUS_FAILED
        endif

        ;
        ;  Each card is identified as "\Device\adapterX" in AllBindList.
        ;  Create CardList containing "adapter1 adapter2..."
        ;  For each entry in AllBindList do the following:
        ;       put entry in BindInfo as "\ Device \ adapterX"
        ;       determine size of BindInfo, ie 4
        ;       CardName is the 4th element in the list, ie adapterX
        ;       Add CardName to CardList
        ;  
        ;
        set CardList = {}
        ForListDo $(AllBindList)
            Split-String $($), "\", BindInfo
            QueryListSize BindListSize $(BindInfo)
            set CardName = *($(BindInfo),$(BindListSize))
            set CardList = >($(CardList),$(CardName))
            endif
        EndForListDo
    
        ; 
        ;  Create a new list, AdapterList, which is a subset of CardList.  
        ;  AdapterList excludes any virtual adapters.  To determine a 
        ;  virtual adapter, check in \SYSTEM\CurrentControlSet\Services\adapterX\Parameters
        ;  for each entry in CardList.  If a "Signature" exists with a 
        ;  value of ExpressLink_Virtual_Adapter, then do not add entry
        ;  to AdapterList.  The AdapterList also does NOT any adapters that
        ;  were not selected for binding.  To determine a bindable adapter,
        ;  check in 
        ;  \SYSTEM\CurrentControlSet\Services for each entry in AdapterList.
        ;  Only if the ExpressLink key exists and the GroupNumber is NOT 0,
        ;  then add the adapter to AdapterList.  If the GroupNumber is 0, go
        ;  to next entry in list.
        ;
        ;  For every entry that should be eliminated, store its index in
        ;  the EliminatorList.
        ;
        set EliminatorList = {}
        set Index          = 1
        set AdapterList    = {}
        ForListDo $(CardList)
            Set RegKeyName = $(!NTN_ServiceBase)"\"$($)"\Parameters"

            OpenRegKey $(!REG_H_LOCAL) "" $(RegKeyName) $(MAXIMUM_ALLOWED) ExpressLinkKey

            ifstr(i) $(ExpressLinkKey) != KeyNull
                GetRegValue $(ExpressLinkKey) "Signature" SignatureValue
                ifstr(i) *($(SignatureValue),4) == $(TransportSignature)
                    CloseRegKey $(ExpressLinkKey)
                    set EliminatorList = >($(EliminatorList),$(Index))
                    goto continueCardList
                endif
                CloseRegKey $(ExpressLinkKey)
            endif

            Set RegKeyName = $(!NTN_ServiceBase)"\"$($)"\Parameters\ExpressLink"
            OpenRegKey $(!REG_H_LOCAL) "" $(RegKeyName) $(MAXIMUM_ALLOWED) ExpressLinkKey

            ifstr(i) $(ExpressLinkKey) == ""
                set EliminatorList = >($(EliminatorList),$(Index))
                goto continueAdapterList
            else
                set AdapterGroupNumber = {}
                GetRegValue $(ExpressLinkKey) "GroupNumber" AdapterGroupNumber
                ifstr(i) $(AdapterGroupNumber) == {}
                    set EliminatorList = >($(EliminatorList),$(Index))
                    goto continueAdapterList
                endif

                ifint *($(AdapterGroupNumber),4) == 0
                    set EliminatorList = >($(EliminatorList),$(Index))
                    goto continueAdapterList
                endif
            endif

            set AdapterList = >($(AdapterList),$($))

continueAdapterList = +

            CloseRegKey $(ExpressLinkKey)

continueCardList = +

            set-add Index = $(Index), 1
            
        EndForListDo

        ; 
        ;  Get entries in \SYSTEM\CurrentControlSet\Services\ExpressLink\Linkage
        ;  for Bind, Export and Route.
        ;

        OpenRegKey $(!REG_H_LOCAL) "" $(TransportLinkageKeyName) $(MAXIMUM_ALLOWED) TransportLinkageKey

        ifstr(i) $(TransportLinkageKey) != ""
            GetRegValue $(TransportLinkageKey) "Bind" BindList
            Set OldBindList = *($(BindList),4)

            GetRegValue $(TransportLinkageKey) "Export" ExportList
            Set OldExportList = *($(ExportList),4)

            GetRegValue $(TransportLinkageKey) "Route" RouteList
            Set OldRouteList = *($(RouteList),4)

            CloseRegKey $(TransportLinkageKey)
        else
            set RegistryErrorIndex = $(RegLastError)
            Debug-Output "ExpressLink: failed to open Linkage Key for "$(TransportServiceKeyName)
            CloseRegKey $(TransportLinkageKey)
            Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
            Return STATUS_FAILED
        endif

        ifstr(i) $(EliminatorList) == {}
            set NewBindList     = $(OldBindList)
            set NewExportList   = $(OldExportList)
            set NewRouteList    = $(OldRouteList)
            goto createBindExportRoute
        endif

        ;
        ;  Determine the number of entries in the EliminatorList and the 
        ;  old lists like OldBindList.
        ;
        set MaxNumberEliminatorList = 0
        ForListDo $(EliminatorList)
            set-add MaxNumberEliminatorList = $(MaxNumberEliminatorList), 1
        EndForListDo

        ;
        ;  Create new lists for Bind, Export and Route by eliminating
        ;  entries that are invalid.  Invalid entries are based on
        ;  indices in the EliminatorList.
        ;
        set LastRemoveIndex      = 0
        set NumberEliminatorList = 0
        set NewBindList          = {}
        set NewExportList        = {}
        set NewRouteList         = {}
        ForListDo $(EliminatorList)
            set RemoveIndex = $($)
            set-add NumberEliminatorList = $(NumberEliminatorList), 1

            set Index = 1
            ForListDo $(OldBindList)
                ifint $(Index) > $(LastRemoveIndex)
                    ifint $(Index) < $(RemoveIndex)
                        set NewBindList = >($(NewBindList),$($))
                    else
                        ifint $(Index) > $(RemoveIndex)
                            ifint $(NumberEliminatorList) == $(MaxNumberEliminatorList)
                                set NewBindList = >($(NewBindList),$($))
                            endif
                        endif
                    endif
                endif
                set-add Index = $(Index), 1
            EndForListDo

            set Index = 1
            ForListDo $(OldExportList)
                ifint $(Index) > $(LastRemoveIndex)
                    ifint $(Index) < $(RemoveIndex)
                        set NewExportList = >($(NewExportList),$($))
                    else
                        ifint $(Index) > $(RemoveIndex)
                            ifint $(NumberEliminatorList) == $(MaxNumberEliminatorList)
                                set NewExportList = >($(NewExportList),$($))
                            endif
                        endif
                    endif
                endif
                set-add Index = $(Index), 1
            EndForListDo

            set Index = 1
            ForListDo $(OldRouteList)
                ifint $(Index) > $(LastRemoveIndex)
                    ifint $(Index) < $(RemoveIndex)
                        set NewRouteList = >($(NewRouteList),$($))
                    else
                        ifint $(Index) > $(RemoveIndex)
                            ifint $(NumberEliminatorList) == $(MaxNumberEliminatorList)
                                set NewRouteList = >($(NewRouteList),$($))
                            endif
                        endif
                    endif
                endif
                set-add Index = $(Index), 1
            EndForListDo
                        
            set LastRemoveIndex = $(RemoveIndex)

        EndForListDo

createBindExportRoute = +

        ; 
        ;  Now modify entries in \SYSTEM\CurrentControlSet\Services\ExpressLink\Linkage
        ;  for Bind, Export and Route.
        ;

        OpenRegKey $(!REG_H_LOCAL) "" $(TransportLinkageKeyName) $(MAXIMUM_ALLOWED) TransportLinkageKey

        ifstr(i) $(TransportLinkageKey) != ""
        	set NewValueList = {{"Bind",$(NoTitle),$(!REG_VT_MULTI_SZ),$(NewBindList)},+
        			   {"Export",$(NoTitle),$(!REG_VT_MULTI_SZ),$(NewExportList)},+
        			   {"Route",$(NoTitle),$(!REG_VT_MULTI_SZ),$(NewRouteList)}}

        	Shell  $(UtilityInf), AddValueList, $(TransportLinkageKey), $(NewValueList)
        	ifint $($ShellCode) != $(!SHELL_CODE_OK)
        	    CloseRegKey $(TransportLinkageKey)
        	    Shell "" DoShellErrorMessage
                Debug-Output "ExpressLink: failed modifying services\ExpressLink\linkage, 1"
                Return STATUS_FAILED
        	endif

        	set RegistryErrorIndex = $($R0)

        	Ifstr(i) $(RegistryErrorIndex) != NO_ERROR
        	    CloseRegKey $(TransportLinkageKey)
                Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
                Debug-Output "ExpressLink: failed modifying services\ExpressLink\linkage, 2"
                Return STATUS_FAILED
        	endif
        	CloseRegKey $(TransportLinkageKey)
        else
            set RegistryErrorIndex = $(RegLastError)
            Debug-Output "ExpressLink: failed to open Linkage Key for "$(TransportServiceKeyName)
            Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
            Return STATUS_FAILED
        endif

doneBindExportRoute = +

        QueryListSize ListSize $(NewBindList)
        Set TempBindList = {}

        ForListDo $(NewBindList)
            Set WrkCard = $($)
            QueryListSize TempSize $(TempBindList)

            ifint $(TempSize) == 0
                set TempBindList = >($(TempBindList),$(WrkCard))
            else
                Set AddToList = 1
                ForListDo $(TempBindList)
                    Set TempWrkCard = $($)
                    ifstr(i) $(TempWrkCard) == $(WrkCard)
                       Set AddToList = 0
                    endif
                EndForListDo
                
                ifint $(AddToList) == 1
                    set TempBindList = >($(TempBindList),$(WrkCard))
                endif
            endif
        EndForListDo

        QueryListSize ListSize $(TempBindList)

        OpenRegKey $(!REG_H_LOCAL) "" $(TransportParamKeyName) $(MAXIMUM_ALLOWED) KeyParameters

        IfStr(i) $(KeyParameters) != $(KeyNull)
            SetRegValue $(KeyParameters) {"NumAdapters", $(NoTitle), $(!REG_VT_DWORD), $(ListSize)}
            CloseRegKey $(KeyParameters)
        Else
            Debug-Output "ExpressLink: Failed to open Transport Parameters Key = "$(RegLastError)
        EndIf
    EndIf

    Shell "" NotifyTheProtocols
    
    Return STATUS_SUCCESSFUL



;==================================================================
;==================================================================
;  Remove Transport.
;
;  $($R0)  Status.
;
RemoveTransport =+
    Read-Syms FileConstants
    Read-Syms GeneralConstants
    Read-Syms FileConstants$(!STF_LANGUAGE)
    Read-Syms RegBaseInfo
    Read-Syms DllInformation
    Read-Syms ErrorMessages$(!STF_LANGUAGE)

    IfStr(i) $(!NTN_RegBase) != $(TransportProductKeyName)
        Shell "" DoFatalMessage $(MustRemoveTransport)
        Return STATUS_FAILED
    EndIf

    Shell "" DeleteInfFromReview

    ;
    ;--  Load the Helper DLL.
    ;
    Set DllName = $(!STF_WINDOWSSYSPATH)\$(DllName)
    LoadLibrary $(DiskName) $(DllName) ResourceHandle

    ;
    ;--  Build lists of Real and Virtual Adapters.
    ;   
    Shell "" CreateAvailableList


    ;
    ;--  First pass clear of Real Adapters.
    ;
    Set Dummy = {"", 0, 0, 0, 0, "Group0", {}}
    Set DummyAdaptersList = {$(Dummy)}

    Set NewList = {}
    ForListDo $(AllAdaptersInfo)
        Set AdapterInfo = $($)

        Set AdapterServiceName     = *($(AdapterInfo), 1)
        Set AdapterDescription     = *($(AdapterInfo), 2)
        Set AdapterManufacturer    = *($(AdapterInfo), 3)
        Set AdapterProductName     = *($(AdapterInfo), 4)
        Set AdapterMACAddress      = *($(AdapterInfo), 6)
        Set AdapterIPAddress       = *($(AdapterInfo), 7)
        Set AdapterBusInfo         = *($(AdapterInfo), 8)
        Set AdapterProtocolInfo    = *($(AdapterInfo), 10)
        Set AdapterOldTitle        = *($(AdapterInfo), 12)
        Set AdapterOldDescription  = *($(AdapterInfo), 13)

        Set AdapterGroupName       = "Group0"
        Set AdapterTitle           = $(AdapterOldTitle)
        Set AdapterDescription     = $(AdapterOldDescription)
        Set AdapterDeviceName      = ""
        Set AdapterUseProtocolInfo = 0

        Set AdapterInfo = {$(AdapterServiceName),   +
                           $(AdapterDescription),   +
                           $(AdapterManufacturer),  +
                           $(AdapterProductName),   +
                           $(AdapterTitle),         +
                           $(AdapterMACAddress),    +
                           $(AdapterIPAddress),     +
                           $(AdapterBusInfo),       +
                           $(AdapterGroupName),     +
                           $(AdapterProtocolInfo),  +
                           $(AdapterDeviceName),    +
                           $(AdapterOldTitle),      +
                           $(AdapterOldDescription) +
                           $(AdapterUseProtocolInfo)}

        Set NewList = >($(NewList), $(AdapterInfo))
    EndForListDo

    Set AllAdaptersInfo = $(NewList)

;---------------------------------------------------------------------------------------

    ;Debug-Output "ExpressLink:  DummyAdaptersList: "$(DummyAdaptersList)
    ;Debug-Output "ExpressLink:    AllAdaptersInfo: "$(AllAdaptersInfo)
    ;Debug-Output "ExpressLink:  AllGroupsNameList: "$(AllGroupsNameList)
    ;Debug-Output "ExpressLink: AllGroupsTitleList: "$(AllGroupsTitleList)

;---------------------------------------------------------------------------------------

    Shell "" UpdateRealAdapters $(DummyAdaptersList) $(AllAdaptersInfo) $(AllGroupsNameList) $(AllGroupsTitleList)

    ;
    ;--  Second Pass clear out identifiers for Real Adapters.
    ;
    ForListDo $(AllAdaptersInfo)
        Set AdapterInfo = $($)
        Set AdapterServiceName = *($(AdapterInfo), 1)
        Set ParameterKeyName = $(ServiceBase)$(AdapterServiceName)$(ParameterBase)

        OpenRegKey $(!REG_H_LOCAL) "" $(ParameterKeyName) $(MAXIMUM_ALLOWED) KeyParameter

        IfStr $(KeyParameter) != $(KeyNull)
            DeleteRegTree $(KeyParameter) $(TransportProductSoftwareName)
            CloseRegKey $(KeyParameter)
        EndIf
    EndForListDo

    ;
    ;--  Remove all Virtual Adapters.
    ;
    ForListDo $(VirtualAdaptersList)
        Set NextAdapter = $($)
        Shell "" DeleteVirtualMAC $(NextAdapter)
    EndForListDo

    ;
    ;--  Remove our SNMP agent.
    ;
    install RemoveSNMPagent

    ;
    ;--  Remove the Transport itself.
    ;
    Shell $(UtilityInf), RemoveSoftwareComponent, $(Manufacturer), +
        $(TransportProductSoftwareName)

    ;
    ;-- Remove files
    ;
    Set FileList = ^(Files-Dialog, 2)
    Shell "" RemoveFiles $(!STF_WINDOWSSYSPATH) $(FileList) $(ResourceHandle)

    Set FileList = ^(Files-MsgDLL, 2)
    Shell "" RemoveFiles $(!STF_WINDOWSSYSPATH) $(FileList) $(ResourceHandle)

    Set FileList = ^(Files-SnmpDLL, 2)
    Shell "" RemoveFiles $(!STF_WINDOWSSYSPATH) $(FileList) $(ResourceHandle)

    Set FileList = ^(Files-Agent, 2)
    Shell "" RemoveFiles $(!STF_WINDOWSSYSPATH) $(FileList) $(ResourceHandle)

    Set FileList = ^(Files-Platform-Drivers, 2)
    Shell "" RemoveFiles $(!STF_WINDOWSSYSPATH)\drivers $(FileList) $(ResourceHandle)

    FreeLibrary $(ResourceHandle)
    Return STATUS_SUCCESSFUL

[Install-Option]
    Set STF_VITAL = ""

    IfStr(i) $(AddCopy) == "YES"
        AddSectionFilesToCopyList Files-Platform-Drivers $(PlatformDir) $(!STF_WINDOWSSYSPATH)\drivers
        AddSectionFilesToCopyList Files-MsgDLL           $(PlatformDir) $(!STF_WINDOWSSYSPATH)
        AddSectionFilesToCopyList Files-SnmpDLL          $(PlatformDir) $(!STF_WINDOWSSYSPATH)
        AddSectionFilesToCopyList Files-Dialog           $(PlatformDir) $(!STF_WINDOWSSYSPATH)
    EndIf

    IfStr(i) $(DoCopy) == "YES"
        Set !STF_NCPA_FLUSH_COPYLIST = TRUE
        CopyFilesInCopyList
    EndIf

    Exit

[Install-Update]
    Set STF_VITAL        = ""
    Set STF_OVERWRITE    = "VERIFYSOURCEOLDER"

    AddSectionFilesToCopyList Files-Platform-Drivers $(SrcDir) $(!STF_WINDOWSSYSPATH)\drivers
    AddSectionFilesToCopyList Files-MsgDLL           $(SrcDir) $(!STF_WINDOWSSYSPATH)
    AddSectionFilesToCopyList Files-SnmpDLL          $(SrcDir) $(!STF_WINDOWSSYSPATH)
    AddSectionFilesToCopyList Files-Dialog           $(SrcDir) $(!STF_WINDOWSSYSPATH)
    AddSectionFilesToCopyList Files-Inf              $(InfDir) $(!STF_WINDOWSSYSPATH)

    IfStr(i) $(DoCopy) == "YES"
        Set !STF_NCPA_FLUSH_COPYLIST = TRUE
        CopyFilesInCopyList
    EndIf

   Exit

;==================================================================
;==================================================================
; Retrieve System Error Message and Display.
;
; $($0)  = Display Routine.
; $($1)  = Text String.
; $($2)  = Severity Level.
;
; $($R0) = Action.
;
[DoRegistryMessage]
    Read-Syms FileConstants

    Set Routine  = $($0)
    Set Text     = $($1)
    Set Severity = $($2)

    IfStr(i) $(Text) == ""
        Set Text = "SETUP_FAIL"
    EndIf
    
    Shell $(UtilityInf) RegistryErrorString $(Text)

    IfInt $($ShellCode) != $(!SHELL_CODE_OK)
        Shell "" DoShellErrorMessage
        Return STATUS_FAILED
    EndIf

    Set Text = $($R0)

    Shell "" $(Routine) $(Text) $(Severity)

    Return $($R0)

;==================================================================
;==================================================================
; Display Warning Message.
;
; $($0)  = Text String.
;
; $($R0) = Action.
;
[DoWarningMessage]
    Read-Syms FileConstants

    Shell $(SubroutineInf) SetupMessage $(!STF_LANGUAGE) "WARNING" $($0)

    Return $($R1)

;==================================================================
;==================================================================
; Display NonFatal Error Message.
;
; $($0)  = Text String.
; $($1)  = Severity Level.
;
; $($R0) = Action.
;
[DoNonFatalMessage]
    Read-Syms FileConstants

    Set Severity = $($1)
    Set Error    = $($0)

    Shell $(SubroutineInf) SetupMessage $(!STF_LANGUAGE) $(Severity) $(Error)

    Return $($R1)

;==================================================================
;==================================================================
; Display Fatal Error Message.
;
; $($0) = Text String.
;
;
[DoFatalMessage] 
    Read-Syms FileConstants

    Set Error = $($0)

    Shell $(SubroutineInf) SetupMessage $(!STF_LANGUAGE) "FATAL" $(Error)

    IfInt $($ShellCode) != $(!SHELL_CODE_OK)
        Shell "" DoShellErrorMessage
        Return
    EndIf

    Return

;==================================================================
;==================================================================
; Display Shell Error Message.
;
;
[DoShellErrorMessage]
    Read-Syms FileConstantsENG

    Set DlgType      = "MessageBox"
    Set STF_MB_TITLE = $(ShellCodeErrorTitle)
    Set STF_MB_TEXT  = $(ShellCodeErrorText)
    Set STF_MB_TYPE  = 1
    Set STF_MB_ICON  = 3
    Set STF_MB_DEF   = 1

    ui start "Error Message"

    Return

;==================================================================
;==================================================================
; Display Shell Dialog.
;
; $($0)  = Dialog Title.
; $($1)  = Text Message.
; $($2)  = Buttons:
;            1  OK button
;            2  OK and Cancel buttons
;            3  Yes and No buttons
;            4  Yes, No, and Cancel buttons
;            5  Retry and Cancel buttons
;            6  Abort, Retry, and Ignore buttons
; $($3)  = Icon:
;            1  No icon
;            2  Info icon
;            3  Stop icon
;            4  ? icon
;            5  ! icon
; $($4)  = Specifies the default button (1, 2, or 3).
;
; $($R0) = Action taken by user: "ABORT", "CANCEL", "IGNORE", "NO", "OK", "RETRY", or "YES".
:
[DoShellDialog]
    Set DlgType      = "MessageBox"
    Set STF_MB_TITLE = $($0)
    Set STF_MB_TEXT  = $($1)
    Set STF_MB_TYPE  = $($2)
    Set STF_MB_ICON  = $($3)
    Set STF_MB_DEF   = $($4)

    ui start "Message"

    Return $(DLGEVENT)

[NotifyTheProtocols]
    Read-Syms DllInformation
    Read-Syms DialogConstants$(!STF_LANGUAGE)
    Read-Syms FileConstants$(!STF_LANGUAGE)
    Read-Syms GeneralConstants
    Read-Syms FileConstants
    Read-Syms ErrorMessages$(!STF_LANGUAGE)

    Set-Subst LF = "\n"

    IfStr(i) $(!p:OldVersionExisted) == FALSE
        Set DllName = $(!p:DialogDir)$(DllName)
    EndIf

    LoadLibrary $(DiskName) $(DllName) ResourceHandle

    LibraryProcedure ReturnCode $(ResourceHandle) NotifyAllProtocols

    FreeLibrary $(ResourceHandle)
    Return STATUS_SUCCESSFUL

[AllAdaptersAssigned]
    Read-Syms FileConstants$(!STF_LANGUAGE)
    Read-Syms FileConstants
    Read-Syms DllInformation
    Read-Syms GeneralConstants
    Read-Syms ErrorMessages$(!STF_LANGUAGE)
    Read-Syms DialogConstants$(!STF_LANGUAGE)


    OpenRegKey $(!REG_H_LOCAL) "" $(TransportLinkageKeyName) $(MAXIMUM_ALLOWED) TransportLinkageKey

    ifstr(i) $(TransportLinkageKey) != ""
        GetRegValue $(TransportLinkageKey) "Bind" BindList
        Set AllBindList = *($(BindList),4)
        CloseRegKey $(TransportLinkageKey)
    else
        set RegistryErrorIndex = $(RegLastError)
        Debug-Output "NICExpress: failed to open Linkage Key for "$(TransportServiceKeyName)
        Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
        Return STATUS_FAILED
    endif

    ;
    ;  Each card is identified as "\Device\adapterX" in AllBindList.
    ;  Create CardList containing "adapter1 adapter2..."
    ;  For each entry in AllBindList do the following:
    ;       put entry in BindInfo as "\ Device \ adapterX"
    ;       determine size of BindInfo, ie 4
    ;       CardName is the 4th element in the list, ie adapterX
    ;       Add CardName to CardList
    ;  
    ;
    set CardList = {}
    ForListDo $(AllBindList)
        Split-String $($), "\", BindInfo
        QueryListSize BindListSize $(BindInfo)
        set CardName = *($(BindInfo),$(BindListSize))
        set CardList = >($(CardList),$(CardName))
    EndForListDo

    ;    
    ;  Create a new list, AdapterList, which is a subset of CardList.  
    ;  AdapterList excludes any virtual adapters.  To determine a 
    ;  virtual adapter, check in \SYSTEM\CurrentControlSet\Services\adapterX\Parameters
    ;  for each entry in CardList.  If a "Signature" exists with a 
    ;  value of NICExpress_Virtual_Adapter, then do not add entry
    ;  to AdapterList.  The AdapterList also does NOT any adapters that
    ;  were not selected for binding.  To determine a bindable adapter,
    ;  check in 
    ;  \SYSTEM\CurrentControlSet\Services for each entry in AdapterList.
    ;  Only if the NICExpress key exists and the GroupNumber is NOT 0,
    ;  then add the adapter to AdapterList.  If the GroupNumber is 0, go
    ;  to next entry in list.
    ;
    ;  For every entry that should be eliminated, store its index in
    ;  the EliminatorList.
    ;
    set EliminatorList = {}
    set Index          = 1
    set AdapterList    = {}
    ForListDo $(CardList)
        Set RegKeyName = $(!NTN_ServiceBase)"\"$($)"\Parameters"

        OpenRegKey $(!REG_H_LOCAL) "" $(RegKeyName) $(MAXIMUM_ALLOWED) NICExpressKey

        ifstr(i) $(NICExpressKey) != KeyNull
            GetRegValue $(NICExpressKey) "Signature" SignatureValue
            ifstr(i) *($(SignatureValue),4) == $(TransportSignature)
                CloseRegKey $(NICExpressKey)
                goto IncrementTheIndex
            endif
            CloseRegKey $(NICExpressKey)
        endif

        Set RegKeyName = $(!NTN_ServiceBase)"\"$($)"\Parameters\NICExpress"
        OpenRegKey $(!REG_H_LOCAL) "" $(RegKeyName) $(MAXIMUM_ALLOWED) NICExpressKey

        ifstr(i) $(NICExpressKey) == ""

            Set ParameterKeyName = $(!NTN_ServiceBase)"\"$($)"\Parameters"

            OpenRegKey $(!REG_H_LOCAL) "" $(ParameterKeyName) $(MAXIMUM_ALLOWED) KeyParameter

            IfStr $(KeyParameter) != $(KeyNull)
               ;
               ;--  Get the media type of the NIC we are investigating
               ;
               Set MediaTypeList = {}
               GetRegValue $(KeyParameter) "MediaType" MediaTypeList
               Set MediaType = *($(MediaTypeList), 4)

               ;
               ; We will only add to our eliminator list if the adapters match
               ; the media NICExpress is installed as (Ethernet or TokenRing)!
               ;
               IfStr $(!NetworkSelected) == NICExpress_Ethernet
                  IfInt $(MediaType) == 1
                     set EliminatorList = >($(EliminatorList),$(Index))
                  EndIf
               Else-IfStr $(!NetworkSelected) == NICExpress_TokenRing
                  IfInt $(MediaType) == 2
                     set EliminatorList = >($(EliminatorList),$(Index))
                  EndIf
               EndIf
               CloseRegKey $(KeyParameter)
            EndIf

            goto CloseNICExpressRegistry
        else
            set AdapterGroupNumber = {}
            GetRegValue $(NICExpressKey) "GroupNumber" AdapterGroupNumber
            ifstr(i) $(AdapterGroupNumber) == {}

                Set ParameterKeyName = $(!NTN_ServiceBase)"\"$($)"\Parameters"

                OpenRegKey $(!REG_H_LOCAL) "" $(ParameterKeyName) $(MAXIMUM_ALLOWED) KeyParameter

                IfStr $(KeyParameter) != $(KeyNull)
                   ;
                   ;--  Get the media type of the NIC we are investigating
                   ;
                   Set MediaTypeList = {}
                   GetRegValue $(KeyParameter) "MediaType" MediaTypeList
                   Set MediaType = *($(MediaTypeList), 4)

                   ;
                   ; We will only add to our eliminator list if the adapters match
                   ; the media NICExpress is installed as (Ethernet or TokenRing)!
                   ;
                   IfStr $(!NetworkSelected) == NICExpress_Ethernet
                      IfInt $(MediaType) == 1
                         set EliminatorList = >($(EliminatorList),$(Index))
                      EndIf
                   Else-IfStr $(!NetworkSelected) == NICExpress_TokenRing
                      IfInt $(MediaType) == 2
                         set EliminatorList = >($(EliminatorList),$(Index))
                      EndIf
                   EndIf
                   CloseRegKey $(KeyParameter)
                EndIf

                goto CloseNICExpressRegistry
            endif

            ifint *($(AdapterGroupNumber),4) == 0

                Set ParameterKeyName = $(!NTN_ServiceBase)"\"$($)"\Parameters"

                OpenRegKey $(!REG_H_LOCAL) "" $(ParameterKeyName) $(MAXIMUM_ALLOWED) KeyParameter

                IfStr $(KeyParameter) != $(KeyNull)
                   ;
                   ;--  Get the media type of the NIC we are investigating
                   ;
                   Set MediaTypeList = {}
                   GetRegValue $(KeyParameter) "MediaType" MediaTypeList
                   Set MediaType = *($(MediaTypeList), 4)

                   ;
                   ; We will only add to our eliminator list if the adapters match
                   ; the media NICExpress is installed as (Ethernet or TokenRing)!
                   ;
                   IfStr $(!NetworkSelected) == NICExpress_Ethernet
                      IfInt $(MediaType) == 1
                         set EliminatorList = >($(EliminatorList),$(Index))
                      EndIf
                   Else-IfStr $(!NetworkSelected) == NICExpress_TokenRing
                      IfInt $(MediaType) == 2
                         set EliminatorList = >($(EliminatorList),$(Index))
                      EndIf
                   EndIf
                   CloseRegKey $(KeyParameter)
                EndIf

                goto CloseNICExpressRegistry
            endif
       endif

       set AdapterList = >($(AdapterList),$($))

CloseNICExpressRegistry = +

       CloseRegKey $(NICExpressKey)

IncrementTheIndex = +

       set-add Index = $(Index), 1
            
    EndForListDo

    Ifstr(i) $(EliminatorList) == {}
       Return STATUS_SUCCESSFUL
    Endif

    Return STATUS_FAILED


[AssignAdaptersToArray]
    Shell "" DoAdapterDialog

    IfStr(i) $($R0) != STATUS_SUCCESSFUL
        Return STATUS_FAILED
    EndIf

    Return STATUS_SUCCESSFUL

;==================================================================
;==================================================================
; Perform Adapter Configuration Dialog.
;
;
;
[DoAdapterDialog]
    Read-Syms DllInformation
    Read-Syms DialogConstants$(!STF_LANGUAGE)
    Read-Syms FileConstants$(!STF_LANGUAGE)
    Read-Syms GeneralConstants
    Read-Syms FileConstants
    Read-Syms ErrorMessages$(!STF_LANGUAGE)

    Set-Subst LF = "\n"

    IfStr(i) $(!p:OldVersionExisted) == FALSE
        Set DllName = $(!p:DialogDir)$(DllName)
    EndIf

    LoadLibrary $(DiskName) $(DllName) ResourceHandle

    LibraryProcedure DriverIsLoaded $(ResourceHandle) TestDriverLoaded

    Shell "" CreateAvailableList

    ;------------------------------------------------------------------------------
    ; Call the function to send data to the user interface
    ;------------------------------------------------------------------------------
    Set ReturnCode = ""
    Set NoParm     = ""
    ;Debug-Output "ExpressLink:  Calling DoDialog"
    ;Debug-Output "ExpressLink:  AAI: "$(AllAdaptersInfo)
    ;Debug-Output "ExpressLink:  VAL: "$(VirtualAdaptersList)
    ;LibraryProcedure ReturnCode  $(ResourceHandle) DoSerialNumDialog  $(NoParm)

    ;IfStr(i) $(ReturnCode) == "FALSE"
    ;    FreeLibrary $(ResourceHandle)
    ;	Return STATUS_SUCCESSFUL
    ;EndIf
    
    Set ReturnCode = ""
    LibraryProcedure ReturnCode  $(ResourceHandle) DoDialog  $(AllAdaptersInfo) $(VirtualAdaptersList) $(AllGroupsTitleList) $(AllGroupsNameList)

    ;------------------------------------------------------------------------------
    ;------------------------------------------------------------------------------
    IfStr(i) $(ReturnCode) == "FALSE"
        FreeLibrary $(ResourceHandle)
        Return STATUS_USERCANCEL
    EndIf

    LibraryProcedure VirtualAdaptersList $(ResourceHandle) GetInfo 1
    LibraryProcedure AllAdaptersInfo     $(ResourceHandle) GetInfo 0
    LibraryProcedure AllGroupsNameList   $(ResourceHandle) GetInfo 3
    LibraryProcedure AllGroupsTitleList  $(ResourceHandle) GetInfo 2


    ;Debug-Output "ExpressLink:  VirtualAdaptersList: "$(VirtualAdaptersList) ; 1
    ;Debug-Output "ExpressLink:      AllAdaptersInfo: "$(AllAdaptersInfo)     ; 2
    ;Debug-Output "ExpressLink:    AllGroupsNameList: "$(AllGroupsNameList)   ; 3
    ;Debug-Output "ExpressLink:   AllGroupsTitleList: "$(AllGroupsTitleList)  ; 4

    Set AdaptersAdded    = 0
    Set AdaptersDeleted  = 0
    Set AdaptersModified = 0
    Set NewList = {}

    ForListDo $(VirtualAdaptersList)
        Set VirtualAdapter = $($)
        IfInt *($(VirtualAdapter), 3) == 1
            Set-Add AdaptersAdded = $(AdaptersAdded), 1
            Set TmpGroupName = *($(VirtualAdapter), 6 )
            Set Index = 0
            Set AdapterIndex = 0

            ; Loop thru the groups name list and compare the name
            ; against our TmpGroupName so we can get the offset
            ForListDo $(AllGroupsNameList)
               Set AllGroupsName = $($)

               ; When we find the match we will set the adapter index
               Set CurrName = *($(AllGroupsName), 1)
               IfStr $(TmpGroupName) == $(CurrName)
                  Set-Add AdapterIndex = $(Index), 0
               EndIf
             
               ; Only increment the counter if we have not set the adapter index
               IfInt AdapterIndex == 0
                  Set-Add Index = $(Index), 1
               EndIf
            EndForListDo

            ; Now go get the actual group name
            Set Index = 0
            Set TheGroupTitle = ""
            ForListDo $(AllGroupsTitleList)
               Set AllGroupsTitle = $($)
               
               ; Match the index numbers and we have our title
               IfInt $(Index) == $(AdapterIndex)
                  Set TheGroupTitle = *($(AllGroupsTitle), 1)
               EndIf

               Set-Add Index = $(Index), 1
            EndForListDo

            Shell "" AddMACComponent $(VirtualAdapter) $(TheGroupTitle)
            Set VirtualAdapter = $($R1)
        EndIf
        IfInt *($(VirtualAdapter), 5) == 1
            Set-Add AdaptersModified = $(AdaptersModified), 1
        EndIf
        Set NewList = >($(NewList), $(VirtualAdapter))
    EndForListDo
    Set VirtualAdaptersList = $(NewList)

    ; Now loop through the virtual adapters and delete the necessary ones
    ForListDo $(VirtualAdaptersList)
        Set VirtualAdapter = $($)
        IfInt *($(VirtualAdapter), 4) == 1
            Set-Add AdaptersDeleted = $(AdaptersDeleted), 1
            Shell "" DeleteVirtualMAC $(VirtualAdapter)
        EndIf
    EndForListDo

    Set Dummy = {"", 0, 0, 0, 0, "Group0", {}}
    Set VirtualAdaptersList = >($(VirtualAdaptersList), $(Dummy))

    ;Debug-Output "ExpressLink:  VirtualAdaptersList: "$(VirtualAdaptersList) ; 1
    ;Debug-Output "ExpressLink:      AllAdaptersInfo: "$(AllAdaptersInfo)     ; 2
    ;Debug-Output "ExpressLink:    AllGroupsNameList: "$(AllGroupsNameList)
    ;Debug-Output "ExpressLink:   AllGroupsTitleList: "$(AllGroupsTitleList)


    Shell "" UpdateRealAdapters $(VirtualAdaptersList) $(AllAdaptersInfo) $(AllGroupsNameList) $(AllGroupsTitleList)
    Shell "" UpdateVirtualAdapters $(VirtualAdaptersList) $(AllAdaptersInfo)

    FreeLibrary $(ResourceHandle)
    Return STATUS_SUCCESSFUL

;==================================================================
;==================================================================
; Create List of Available Adapters.
;
;
;
[CreateAvailableList]
    Read-Syms GeneralConstants
    Read-Syms FileConstants
    Read-Syms RegBaseInfo

    Set AdapterNumber         = "1"
    Set AvailableAdaptersList = {}
    Set AllAdaptersInfo       = {}
    Set VirtualAdaptersList   = {}
    Set GroupTitle0           = $(BaseGroupTitle)
    Set Group0                = TRUE
    Set MaxAdapterNumber      = "0"

;  Open the key for the NetCards and calculate the Max Adapter Number.
    OpenRegKey $(!REG_H_LOCAL) "" $(AdapterRegBase) $(MAXIMUM_ALLOWED) NetCardKey

    EnumRegKey $(NetCardKey) KeyList

    forlistdo $(KeyList)
        set NextKey = $($)
        set KeyName = *($(NextKey), 1)
        ifint $(KeyName) > $(MaxAdapterNumber)
            set MaxAdapterNumber = $(KeyName)
        endif
    endforlistdo

    set-add MaxAdapterNumber = $(MaxAdapterNumber), 1

    CloseRegKey $(NetCardKey)

FindAvailableCards =+

    Set NextAdapterName = $(AdapterRegBase)$(AdapterNumber)

    OpenRegKey $(!REG_H_LOCAL) "" $(NextAdapterName) $(MAXIMUM_ALLOWED) KeyAdapter

    IfStr $(KeyAdapter) != $(KeyNull)
        Set ValueName = ""
        Set ValueData = ""
        Set ValueStr  = ""
        Set ValueList = {}

        EnumRegValue $(KeyAdapter) ValueList

        ForListDo $(ValueList)
            Set ValueItem = $($)
            Set ValueName = *($(ValueItem),1)
            Set ValueData = *($(ValueItem),4)

            IfStr(i) $(ValueName) == "Description"
                Set AdapterDescription = $(ValueData)
            Else-IfStr(i) $(ValueName) == "Manufacturer"
                Set AdapterManufacturer = $(ValueData)
            Else-IfStr(i) $(ValueName) == "ProductName"
                Set AdapterProductName = $(ValueData)
            Else-IfStr(i) $(ValueName) == "ServiceName"
                Set AdapterServiceName = $(ValueData)
            Else-IfStr(i) $(ValueName) == "Title"
                Set AdapterTitle = $(ValueData)
            EndIf

        EndForListDo

        CloseRegKey $(KeyAdapter)

        Set RulesBase = $(NextAdapterName)$(NetRulesBase)
        Set OldBlock  = ""
        Set BlockList = {}

        OpenRegKey $(!REG_H_LOCAL) "" $(RulesBase) $(MAXIMUM_ALLOWED) KeyNetRules

        IfStr(i) $(KeyNetRules) != $(KeyNull)
            GetRegValue $(KeyNetRules) "block" BlockList
            Set OldBlock = *($(BlockList), 4)
            CloseRegKey $(KeyNetRules)
        EndIf

        ;
        ;--  Get Bus and Slot Information.
        ;
        Set BusNumber  = ""
        Set BusType    = ""
        Set SlotNumber = ""

        Set ParameterKeyName = $(ServiceBase)$(AdapterServiceName)$(ParameterBase)

        OpenRegKey $(!REG_H_LOCAL) "" $(ParameterKeyName) $(MAXIMUM_ALLOWED) KeyParameter

        IfStr $(KeyParameter) != $(KeyNull)
            ;
            ;--  Verify that this is an Ethernet-type device.
            ;
            Set MediaTypeList = {}
            GetRegValue $(KeyParameter) "MediaType" MediaTypeList
            Set MediaType = *($(MediaTypeList), 4)

            IfInt $(MediaType) != 1
                CloseRegKey $(KeyParameter)
                GoTo FindNextAvailable
            EndIf

            ;
            ;--  Check for (our) Virtual Adapters.
            ;
            Set SignatureList = {}
            GetRegValue $(KeyParameter) "Signature" SignatureList
            Set Signature = *($(SignatureList), 4)

            IfStr(i) $(Signature) == $(TransportSignature)
                Set AdapterProtocolInfo = {}

                Set VirtualAdapter = {$(AdapterServiceName),+
                                      $(AdapterNumber),     +
                                      0,                    +
                                      0,                    +
                                      0,                    +
                                      0                     +
                                      $(AdapterProtocolInfo)}

                Set VirtualAdaptersList = >($(VirtualAdaptersList), $(VirtualAdapter))
                CloseRegKey $(KeyParameter)
                GoTo FindNextAvailable
            EndIf

            ;
            ;-- Make sure that we are dealing with D-Link cards
            ;
            Debug-Output "Adapter Manufacturer: "$(AdapterManufacturer)

            IfStr $(AdapterManufacturer) != "D-LinkCorporation"
                Debug-Output "This card isn't a D-Link, Finding Next Adapter"
                CloseRegKey $(KeyParameter)
                GoTo FindNextAvailable
            EndIf
	
            ;
            ;--  Collect information for Real adapters.
            ;
            Set BusTypeList = {}
            GetRegValue $(KeyParameter) "BusType" BusTypeList
            Set BusType = *($(BusTypeList),4)

            Set BusNumberList = {}
            GetRegValue $(KeyParameter) "BusNumber" BusNumberList
            Set BusNumber = *($(BusNumberList),4)

            Set SlotNumberList = {}
            GetRegValue $(KeyParameter) "SlotNumber" SlotNumberList
            Set SlotNumber = *($(SlotNumberList),4)

            CloseRegKey $(KeyParameter)

            IfStr(i) $(SlotNumber) != ""
                Set SlotNumber = " Slot "$(SlotNumber)
            EndIf

            IfInt $(BusType) == 0
                Set BusType = "Jazz-Internal Bus "
            Else-IfInt $(BusType) == 1
                Set BusType = "ISA Bus "
            Else-IfInt $(BusType) == 2
                Set BusType = "EISA Bus "
            Else-IfInt $(BusType) == 3
                Set BusType = "MCA Bus "
            Else-IfInt $(BusType) == 4
                Set BusType = "TCChannel Bus "
            Else-IfInt $(BusType) == 5
                Set BusType = "PCI Bus "
            Else
                Set BusType = "Unknown Bus "
            EndIf

            Set AdapterBusInfo = $(BusType)$(BusNumber)$(SlotNumber)
        Else
            GoTo FindNextAvailable
        EndIf

        ;
        ;--  Get the IP address for this guy.
        ;
        Set AdapterIPAddress = ""
        Set TcpIpKeyName = $(ServiceBase)$(AdapterServiceName)$(TcpipBase)

        OpenRegKey $(!REG_H_LOCAL) "" $(TcpIpKeyName) $(MAXIMUM_ALLOWED) KeyTcpIp

        IfStr $(KeyTcpIp) != $(KeyNull)
            Set AdapterProtocolInfo = {}
            EnumRegValue $(KeyTcpIp) AdapterProtocolInfo

            Set AddressList = {}
            GetRegValue $(KeyTcpIp) "IPAddress" AddressList
            Set AdapterIPAddress = *($(AddressList),4)
            CloseRegKey $(KeyTcpIp)
        EndIf

        ;
        ;--  Get the Adapter's Permanent MAC Address.
        ;
        Set AdapterMACAddress = ""
        LibraryProcedure AdapterMACAddress $(!p:ResourceHandle) GetMACAddress $(AdapterServiceName)

        ;
        ;--  Get Transport-Specific Info.
        ;
        Set AdapterGroupName   = ""
        Set AdapterGroupNumber = ""
        Set AdapterDeviceName  = ""

        Set ExpressLinkKeyName = $(ServiceBase)$(AdapterServiceName)$(ExpressLinkBase)

        OpenRegKey $(!REG_H_LOCAL) "" $(ExpressLinkKeyName) $(MAXIMUM_ALLOWED) KeyExpressLink

        IfStr $(KeyExpressLink) != $(KeyNull)
            Set GroupNoList = {}
            GetRegValue $(KeyExpressLink) "GroupNumber" GroupNoList
            Set AdapterGroupNumber = *($(GroupNoList),4)

            Set GroupTitleList = {}
            GetRegValue $(KeyExpressLink) "GroupName" GroupTitleList
            Set GroupTitle = *($(GroupTitleList),4)
            Set GroupTitle$(AdapterGroupNumber) = $(GroupTitle)
            Set Group$(AdapterGroupNumber) = TRUE

            Set DeviceNameList = {}
            GetRegValue $(KeyExpressLink) "Device" DeviceNameList
            Set AdapterDeviceName = *($(DeviceNameList),4)

            Set OldTitleList = {}
            GetRegValue $(KeyExpressLink) "OldTitle" OldTitleList
            Set AdapterOldTitle = *($(OldTitleList),4)

            Set OldDescriptionList = {}
            GetRegValue $(KeyExpressLink) "OldDescription" OldDescriptionList
            Set AdapterOldDescription = *($(OldDescriptionList),4)

            Set UseProtocolInfoList = {}
            GetRegValue $(KeyExpressLink) "UseProtocolInfo" UseProtocolInfoList
            Set AdapterUseProtocolInfo = *($(UseProtocolInfoList),4)

            CloseRegKey $(KeyExpressLink)
        Else
            Set AdapterOldTitle        = $(AdapterTitle)
            Set AdapterOldDescription  = $(AdapterDescription)
            Set AdapterUseProtocolInfo = 0

            Set GroupNumber = 0
            Set GroupName   = "New Segment"

            CreateRegKey $(!REG_H_LOCAL) {$(ExpressLinkKeyName),$(NoTitle),GenericClass} "" $(MAXIMUM_ALLOWED) "" KeyExpressLink
            IfStr(i) $(KeyExpressLink) != $(KeyNull)
                IfStr(i) $(OldBlock) != ""
                    SetRegValue $(KeyExpressLink) {"OldBlock", $(NoTitle), $(!REG_VT_MULTI_SZ), $(BlockValue)}
                EndIf

                Set NewValueList = {{Device,          $(NoTitle), $(!REG_VT_SZ),       $(DeviceName)     },       +
                                    {AdapterNumber,   $(NoTitle), $(!REG_VT_SZ),       $(AdapterNumber)  },       +
                                    {InstanceNumber,  $(NoTitle), $(!REG_VT_DWORD),    $(AdapterNumber)  },       +
                                    {GroupNumber,     $(NoTitle), $(!REG_VT_DWORD),    $(GroupNumber)    },       +
                                    {GroupName,       $(NoTitle), $(!REG_VT_SZ),       $(GroupName)      },       +
                                    {OldTitle,        $(NoTitle), $(!REG_VT_SZ),       $(AdapterOldTitle)},       +
                                    {OldDescription,  $(NoTitle), $(!REG_VT_SZ),       $(AdapterOldDescription)}, +
                                    {UseProtocolInfo, $(NoTitle), $(!REG_VT_DWORD),    $(AdapterUseProtocolInfo)}}

                Shell $(UtilityInf), AddValueList, $(KeyExpressLink), $(NewValueList)
                CloseRegKey $(KeyExpressLink)

                Set RegistryErrorIndex = $($R0)

                IfStr $(RegistryErrorIndex) != NO_ERROR
                    Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
                    Return STATUS_FAILED
                EndIf
            EndIf
        EndIf

        IfStr(i) $(AdapterGroupNumber) == ""
            Set AdapterGroupName = "Group0"
        Else
            Set AdapterGroupName = "Group"$(AdapterGroupNumber)
        EndIf

        ;
        ;--  Build List of Adapter Resources available.
        ;
        Set AvailableAdaptersList = >($(AvailableAdaptersList), $(AdapterTitle))

        ;
        ; Remove the commas from required strings so our UI parsing routine
        ; won't barf a lung
        ;

        Shell "" StripTheComma $(AdapterDescription)
        Set AdapterDescription = $($R0)

        Shell "" StripTheComma $(AdapterManufacturer)
        Set AdapterManufacturer = $($R0)
        
        Shell "" StripTheComma $(AdapterTitle)
        Set AdapterTitle = $($R0)

        Set AdapterInfo = {$(AdapterServiceName),   +
                           $(AdapterDescription),   +
                           $(AdapterManufacturer),  +
                           $(AdapterProductName),   +
                           $(AdapterTitle),         +
                           $(AdapterMACAddress),    +
                           $(AdapterIPAddress),     +
                           $(AdapterBusInfo),       +
                           $(AdapterGroupName),     +
                           $(AdapterProtocolInfo),  +
                           $(AdapterDeviceName),    +
                           $(AdapterOldTitle),      +
                           $(AdapterOldDescription) +
                           $(AdapterUseProtocolInfo)}

        Set AllAdaptersInfo = >($(AllAdaptersInfo), $(AdapterInfo))

    EndIf

FindNextAvailable =+
    Set-Add AdapterNumber = $(AdapterNumber), 1

    IfInt $(AdapterNumber) < $(MaxAdapterNumber)
        GoTo FindAvailableCards
    EndIf

    ;
    ;--  Finish Virtual Adapters List.
    ;
    ForListDo $(AllAdaptersInfo)
        Set RealAdapterInfo  = $($)
        Set AdapterGroupName = *($(RealAdapterInfo), 9)
        Set MACName          = *($(RealAdapterInfo), 11)

        IfStr(i) $(AdapterGroupName) != "Group0"
            Set NewList = {}

            ForListDo $(VirtualAdaptersList)
                Set VirtualAdapterInfo = $($)
                Set VirtualAdapterName = *($(VirtualAdapterInfo), 1)

                IfStr(i) $(VirtualAdapterName) == $(MACName)

                    Set AdapterServiceName  = *($(VirtualAdapterInfo), 1)
                    Set AdapterNumber       = *($(VirtualAdapterInfo), 2)
                    Set AdapterProtocolInfo = *($(VirtualAdapterInfo), 7)

                    Set VirtualAdapterInfo = {$(AdapterServiceName),+
                                              $(AdapterNumber),     +
                                              0,                    +
                                              0,                    +
                                              0,                    +
                                              $(AdapterGroupName),  +
                                              $(AdapterProtocolInfo)}
                EndIf

                Set NewList = >($(NewList), $(VirtualAdapterInfo))
            EndForListDo

            Set VirtualAdaptersList = $(NewList)
        EndIf
    EndForListDo

    Set AllGroupsTitleList = {}
    Set AllGroupsNameList  = {}

    IfStr(i) $(Group0) == TRUE
        Set AllGroupsTitleList = >($(AllGroupsTitleList), $(GroupTitle0))
        Set AllGroupsNameList  = >($(AllGroupsNameList), "Group0")
    EndIf

    IfStr(i) $(Group1) == TRUE
        Set AllGroupsTitleList = >($(AllGroupsTitleList), $(GroupTitle1))
        Set AllGroupsNameList  = >($(AllGroupsNameList), "Group1")
    EndIf

    IfStr(i) $(Group2) == TRUE
        Set AllGroupsTitleList = >($(AllGroupsTitleList), $(GroupTitle2))
        Set AllGroupsNameList  = >($(AllGroupsNameList), "Group2")
    EndIf

    IfStr(i) $(Group3) == TRUE
        Set AllGroupsTitleList = >($(AllGroupsTitleList), $(GroupTitle3))
        Set AllGroupsNameList  = >($(AllGroupsNameList), "Group3")
    EndIf

    IfStr(i) $(Group4) == TRUE
        Set AllGroupsTitleList = >($(AllGroupsTitleList), $(GroupTitle4))
        Set AllGroupsNameList  = >($(AllGroupsNameList), "Group4")
    EndIf

    IfStr(i) $(Group5) == TRUE
        Set AllGroupsTitleList = >($(AllGroupsTitleList), $(GroupTitle5))
        Set AllGroupsNameList  = >($(AllGroupsNameList), "Group5")
    EndIf

    IfStr(i) $(Group6) == TRUE
        Set AllGroupsTitleList = >($(AllGroupsTitleList), $(GroupTitle6))
        Set AllGroupsNameList  = >($(AllGroupsNameList), "Group6")
    EndIf

    IfStr(i) $(Group7) == TRUE
        Set AllGroupsTitleList = >($(AllGroupsTitleList), $(GroupTitle7))
        Set AllGroupsNameList  = >($(AllGroupsNameList), "Group7")
    EndIf

    IfStr(i) $(Group8) == TRUE
        Set AllGroupsTitleList = >($(AllGroupsTitleList), $(GroupTitle8))
        Set AllGroupsNameList  = >($(AllGroupsNameList), "Group8")
    EndIf

    IfStr(i) $(Group9) == TRUE
        Set AllGroupsTitleList = >($(AllGroupsTitleList), $(GroupTitle9))
        Set AllGroupsNameList  = >($(AllGroupsNameList), "Group9")
    EndIf

    Set !p:AvailableAdaptersList = $(AvailableAdaptersList)
    Set !p:AllAdaptersInfo       = $(AllAdaptersInfo)
    Set !p:VirtualAdaptersList   = $(VirtualAdaptersList)
    Set !p:AllGroupsTitleList    = $(AllGroupsTitleList)
    Set !p:AllGroupsNameList     = $(AllGroupsNameList)
    ;Debug-Output "ExpressLink: AllGroupsTitleList: "$(AllGroupsTitleList)
    ;Debug-Output "ExpressLink: AllGroupsNameList : "$(AllGroupsNameList)

    Return

;==================================================================
;==================================================================
; Check System Version Information.
;
;
;
[CheckVersionInfo]
    Read-Syms DllInformation
    Read-Syms FileConstants$(!STF_LANGUAGE)
    Read-Syms GeneralConstants
    Read-Syms ErrorMessages$(!STF_LANGUAGE)
    Read-Syms RegBaseInfo

    Set-Subst LF = "\n"

    IfStr(i) $(!p:OldVersionExisted) == FALSE
        Set DllName = $(!p:DialogDir)$(DllName)
    Else
        Set DllName = $(!STF_WINDOWSSYSPATH)\$(DllName)
    EndIf

    LoadLibrary $(DiskName) $(DllName) ResourceHandle

    LibraryProcedure OsInfo $(ResourceHandle) GetOSVER

    FreeLibrary $(ResourceHandle)

    Split-String OsInfo "," $(OsInfo)

    Set MajorVersion = *($(OsInfo), 1)
    Set MinorVersion = *($(OsInfo), 2)
    Set BuildNumber  = *($(OsInfo), 3)
    Set PlatformId   = *($(OsInfo), 4)
    Set CSDVersion   = *($(OsInfo), 5)

    IfStr $(MajorVersion) != "4"
        Shell "" DoFatalMessage $(WrongOSVersion)
        Return STATUS_FAILED
    EndIf

    Set VersionList  = ^(VersionsSupported, 1)

    IfContains(i) $(CSDVersion) Not-In $(VersionList)
        Shell "" DoShellDialog "Un-Tested Service Pack" $(WrongSPVersion) 3 4 1
        IfStr(i) $($R0) == "NO"
            Return STATUS_FAILED
        EndIf
    EndIf


    ; Is this Terminal Server Edition?
    ;
    Set TermSrv = "FALSE"     ; Default is no!

    OpenRegKey $(!REG_H_LOCAL) "" $(TermSrvRegBase) $(MAXIMUM_ALLOWED) TermSrvKey
    IfStr $(TermSrvKey) != $(KeyNull)
        Set TermSrv = "TRUE"                        ; Yep, it is loaded!
        CloseRegKey $(TermSrvKey)
    EndIf


    ; Determine if this is a multi-processor box so we can determine if we need to warn
    ; the user about needing the RollUp (TCPIP) Hotfix.
    ;
    Set MultiProc = "FALSE"     ; Default is no!

    OpenRegKey $(!REG_H_LOCAL) "" $(NumProcossorRegBase) $(MAXIMUM_ALLOWED) RegKey
    GetRegValue $(RegKey) "NUMBER_OF_PROCESSORS" NumProcList
    Ifint *($(NumProcList), 4) > 1
        Set MultiProc = "TRUE"     ; There are more than processors loaded.
    EndIf
    CloseRegKey $(RegKey)


    ; If this is SP3 then verify that the proper NDIS Hotfix is installed.
    IfStr(i) $(CSDVersion) == $(NDIS_HotFix_Ver)

        ; If this is Terminal Server Edition, then check for Hotfix Q216108
        IfStr $(TermSrv) == "TRUE"
            OpenRegKey $(!REG_H_LOCAL) "" $(NDISTEHotFixRegBase) $(MAXIMUM_ALLOWED) HotFixKey
            IfStr $(HotFixKey) == $(KeyNull)
                Shell "" DoShellDialog "NDIS HotFix Not Loaded" $(NoNDISTEHotFix) 3 3 2
                IfStr(i) $($R0) == "NO"
                    Return STATUS_FAILED
                EndIf
            Else
                CloseRegKey $(HotFixKey)
            EndIf

        ; This must be regular NT, so check for Hotfix Q156655
        Else
            OpenRegKey $(!REG_H_LOCAL) "" $(NDISHotFixRegBase) $(MAXIMUM_ALLOWED) HotFixKey

            IfStr $(HotFixKey) == $(KeyNull)
                Shell "" DoShellDialog "NDIS HotFix Not Loaded" $(NoNDISHotFix) 3 3 2
                IfStr(i) $($R0) == "NO"
                    Return STATUS_FAILED
                EndIf
            Else
                CloseRegKey $(HotFixKey)
            EndIf
        EndIf

    EndIf


    ; If this is SP4, a MultiProcessor and not TSE then verify that the RollUp (Q195734) or TCP/IP Hotfix (Q195725) is installed.
    IfStr(i) $(CSDVersion) == $(TCPIP_HotFix_Ver)
        IfStr $(MultiProc) == "TRUE"
            IfStr $(TermSrv) == "FALSE"
                OpenRegKey $(!REG_H_LOCAL) "" $(TCPIPHotFixRegBase) $(MAXIMUM_ALLOWED) HotFixKey
                IfStr $(HotFixKey) == $(KeyNull)
                    OpenRegKey $(!REG_H_LOCAL) "" $(RollUpHotFixRegBase) $(MAXIMUM_ALLOWED) RUHotFixKey
                    IfStr $(RUHotFixKey) == $(KeyNull)
                        Shell "" DoShellDialog "RollUp HotFix Not Loaded" $(NoRollUpHotFix) 3 3 2
                        IfStr(i) $($R0) == "NO"
                            Return STATUS_FAILED
                        EndIf
                    Else
                        CloseRegKey $(RUHotFixKey)
                    EndIf
                Else
                    CloseRegKey $(HotFixKey)
                EndIf
            EndIf
        EndIf
    EndIf

    Return STATUS_SUCCESSFUL

;==================================================================
;==================================================================
; Add required component keys to Registry to configure Transport.
;
; $($0) = OldVersionExisted  TRUE|FALSE
;
[AddTransportComponent]
    Read-Syms FileConstants
    Read-Syms GeneralConstants
    Read-Syms FileConstants$(!STF_LANGUAGE)
    Read-Syms ErrorMessages$(!STF_LANGUAGE)

    Set OldVersionExisted = $($0)

    Detect CurrentDate

    Shell $(UtilityInf), AddSoftwareComponent, $(Manufacturer), +
                                               $(TransportProductSoftwareName), +
                                               $(TransportProductSoftwareName), +
                                               $(TransportProductSoftwareDisplayName), $(STF_CONTEXTINFNAME), +
                                               $(ProductSoftwareImagePath), "transport", "TDI", {}, "",+
                                               $(NetEventDLL)

    Set RegistryErrorIndex = $($R0)

    IfStr(i) $(RegistryErrorIndex) !=  NO_ERROR
        CloseRegKey $($R1)
        CloseRegKey $($R2)
        CloseRegKey $($R3)
        CloseRegKey $($R4)
        CloseRegKey $($R5)

        Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
        Return STATUS_FAILED
    EndIf

    Set SoftProductKey      = $($R1)
    Set SoftNetRuleKey      = $($R2)
    Set SoftServiceKey      = $($R3)
    Set SoftParameterKey    = $($R4)
    Set SoftLinkageKey      = $($R5)

    Set NewValueList = {{SoftwareType,$(NoTitle),$(!REG_VT_SZ),$(TransportSoftwareType)},+
                       {MajorVersion,$(NoTitle),$(!REG_VT_DWORD),$(ProductMajorVersion)},+
                       {MinorVersion,$(NoTitle),$(!REG_VT_DWORD),$(ProductMinorVersion)},+
                       {Title,$(NoTitle),$(!REG_VT_SZ),$(TransportProductSoftwareTitle)},+
                       {Description,$(NoTitle),$(!REG_VT_SZ),$(TransportProductSoftwareDescription)},+
                       {ServiceName,$(NoTitle),$(!REG_VT_SZ),$(TransportProductSoftwareName)},+
                       {Review,$(NoTitle),$(!REG_VT_DWORD),1},+
                       {InstallDate,$(NoTitle),$(!REG_VT_DWORD),*($(Now),1)}}

    Shell  $(UtilityInf), AddValueList, $(SoftProductKey), $(NewValueList)

    Set RegistryErrorIndex = $($R0)

    IfStr $(RegistryErrorIndex) != NO_ERROR
        CloseRegKey $(SoftProductKey)
        CloseRegKey $(SoftNetRuleKey)
        CloseRegKey $(SoftServiceKey)
        CloseRegKey $(SoftParameterKey)
        CloseRegKey $(SoftLinkageKey)

        Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
        Return STATUS_FAILED
    EndIf

    Set NewValueList = {{type,$(NoTitle),$(!REG_VT_SZ),$(TransportNetRuleSoftwareType)}, +
                        {use,$(NoTitle),$(!REG_VT_SZ),$(TransportNetRuleSoftwareUse)}, +
                        {class,$(NoTitle),$(!REG_VT_MULTI_SZ),$(TransportNetRuleSoftwareClass)}, +
                        {bindform,$(NoTitle),$(!REG_VT_SZ),$(TransportNetRuleSoftwareBindForm)}, +
                        {bindable,$(NoTitle),$(!REG_VT_MULTI_SZ),$(TransportNetRuleSoftwareBindable)}, +
                        {InfOption,$(NoTitle),$(!REG_VT_SZ),$(TransportProductSoftwareName)}}

    Shell  $(UtilityInf), AddValueList, $(SoftNetRuleKey), $(NewValueList)

    Set RegistryErrorIndex = $($R0)

    IfStr $(RegistryErrorIndex) != NO_ERROR
        CloseRegKey $(SoftProductKey)
        CloseRegKey $(SoftNetRuleKey)
        CloseRegKey $(SoftServiceKey)
        CloseRegKey $(SoftParameterKey)
        CloseRegKey $(SoftLinkageKey)

        Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
        Return STATUS_FAILED
    EndIf

    Set NewValueList = {{DebugLevel,            $(NoTitle), $(!REG_VT_DWORD), 0                        }, +
                        {DebugMask,             $(NoTitle), $(!REG_VT_DWORD), 0                        }, +
                        {StatusPacketsOn,       $(NoTitle), $(!REG_VT_DWORD), 0                        }, +
                        {MaxDownCnt,            $(NoTitle), $(!REG_VT_DWORD), $(MaxFailures)           }, +
                        {MaxTimeInterval,       $(NoTitle), $(!REG_VT_DWORD), $(MaxFailuresTimePeriod) }, +
                        {NoTrafficTimeInterval, $(NoTitle), $(!REG_VT_DWORD), $(NoTrafficTimePeriod)   }, +
                        {LoadBalance,           $(NoTitle), $(!REG_VT_DWORD), $(LoadBalancing)         }, +
                        {ValidateRoute,         $(NoTitle), $(!REG_VT_DWORD), $(ValidateRoute)         }, +
						{ConnectTest,           $(NoTitle), $(!REG_VT_DWORD), $(ConnectTesting)        }   }

    Shell  $(UtilityInf), AddValueList, $(SoftParameterKey), $(NewValueList)

    Set RegistryErrorIndex = $($R0)

    IfStr $(RegistryErrorIndex) != NO_ERROR
        CloseRegKey $(SoftProductKey)
        CloseRegKey $(SoftNetRuleKey)
        CloseRegKey $(SoftServiceKey)
        CloseRegKey $(SoftParameterKey)
        CloseRegKey $(SoftLinkageKey)

        Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
        Return STATUS_FAILED
    EndIf

    CloseRegKey $(SoftProductKey)
    CloseRegKey $(SoftNetRuleKey)
    CloseRegKey $(SoftServiceKey)
    CloseRegKey $(SoftParameterKey)
    CloseRegKey $(SoftLinkageKey)

    Return STATUS_SUCCESSFUL

;==================================================================
;==================================================================
; Add required component keys to Registry to configure Adapter.
;
; $($0)  = Virtual Adapter
; $($1)  = The Adapters group title
:
; $($R0) = Status
; $($R1) = Updated Virtual Adapter Structure
;
;
[AddMACComponent]
    Read-Syms FileConstants
    Read-Syms GeneralConstants
    Read-Syms RegBaseInfo
    Read-Syms FileConstants$(!STF_LANGUAGE)
    Read-Syms ErrorMessages$(!STF_LANGUAGE)

    Detect CurrentDate

    Set OldVersionExisted = FALSE
    Set VirtualAdapter = $($0)
    Set TheGroupsTitle = $($1)

    Set AdapterAdded        = *($(VirtualAdapter), 3)
    Set AdapterDeleted      = *($(VirtualAdapter), 4)
    Set AdapterModified     = *($(VirtualAdapter), 5)
    Set AdapterGroupName    = *($(VirtualAdapter), 6)
    Set AdapterProtocolInfo = *($(VirtualAdapter), 7)

    OpenRegKey $(!REG_H_LOCAL) "" $(AdapterProductKeyName) $(MAXIMUM_ALLOWED) KeyProduct

    IfStr $(KeyProduct) == $(KeyNull)
        Shell $(UtilityInf), AddSoftwareComponent, $(Manufacturer), +
                                                   $(AdapterProductSoftwareName), +
                                                   $(AdapterProductSoftwareName), +
                                                   $(AdapterProductSoftwareDisplayName), $(STF_CONTEXTINFNAME), +
                                                   $(ProductSoftwareImagePath), "kernel", "NDIS", {}, "",+
                                                   $(NetEventDLL)

        Set RegistryErrorIndex = $($R0)

        IfStr(i) $(RegistryErrorIndex) !=  NO_ERROR
            CloseRegKey $($R1)
            CloseRegKey $($R2)
            CloseRegKey $($R3)
            CloseRegKey $($R4)
            CloseRegKey $($R5)

            Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
            Return STATUS_FAILED
        EndIf

        Set SoftProductKey      = $($R1)
        Set SoftNetRuleKey      = $($R2)
        Set SoftServiceKey      = $($R3)
        Set SoftParameterKey    = $($R4)
        Set SoftLinkageKey      = $($R5)

        Set NewValueList = {{SoftwareType, $(NoTitle), $(!REG_VT_SZ),    $(AdapterSoftwareType)},+
                           {MajorVersion,  $(NoTitle), $(!REG_VT_DWORD), $(ProductMajorVersion)},+
                           {MinorVersion,  $(NoTitle), $(!REG_VT_DWORD), $(ProductMinorVersion)},+
                           {Title,         $(NoTitle), $(!REG_VT_SZ),    $(AdapterProductSoftwareTitle)},+
                           {Description,   $(NoTitle), $(!REG_VT_SZ),    $(AdapterProductSoftwareDescription)},+
                           {ServiceName,   $(NoTitle), $(!REG_VT_SZ),    $(AdapterProductSoftwareName)},+
                           {InstallDate,   $(NoTitle), $(!REG_VT_DWORD), *($(Now),1)}}

        Shell  $(UtilityInf), AddValueList, $(SoftProductKey), $(NewValueList)

        Set RegistryErrorIndex = $($R0)

        IfStr $(RegistryErrorIndex) != NO_ERROR
            CloseRegKey $(SoftProductKey)
            CloseRegKey $(SoftNetRuleKey)
            CloseRegKey $(SoftServiceKey)
            CloseRegKey $(SoftParameterKey)
            CloseRegKey $(SoftLinkageKey)

            Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
            Return STATUS_FAILED
        EndIf

        Set NewValueList = {{type,$(NoTitle),$(!REG_VT_SZ),$(AdapterNetRuleSoftwareType)}, +
                            {use,$(NoTitle),$(!REG_VT_SZ),$(AdapterNetRuleSoftwareUse)}, +
                            {class,$(NoTitle),$(!REG_VT_MULTI_SZ),$(AdapterNetRuleSoftwareClass)}, +
                            {bindform,$(NoTitle),$(!REG_VT_SZ),$(AdapterNetRuleSoftwareBindForm)}, +
                            {bindable,$(NoTitle),$(!REG_VT_MULTI_SZ),$(AdapterNetRuleSoftwareBindable)}, +
                            {InfOption,$(NoTitle),$(!REG_VT_SZ),$(Option)}}
        Shell  $(UtilityInf), AddValueList, $(SoftNetRuleKey), $(NewValueList)

        Set RegistryErrorIndex = $($R0)

        IfStr $(RegistryErrorIndex) != NO_ERROR
            CloseRegKey $(SoftProductKey)
            CloseRegKey $(SoftNetRuleKey)
            CloseRegKey $(SoftServiceKey)
            CloseRegKey $(SoftParameterKey)
            CloseRegKey $(SoftLinkageKey)

            Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
            Return STATUS_FAILED
        EndIf
            
        CloseRegKey $(SoftProductKey)
        CloseRegKey $(SoftNetRuleKey)
        CloseRegKey $(SoftServiceKey)
        CloseRegKey $(SoftParameterKey)
        CloseRegKey $(SoftLinkageKey)
    Else
        CloseRegKey $(KeyProduct)
        Set OldVersionExisted = TRUE
    EndIf

    ;
    ;--  Create the HARDWARE\Netcard region and its corresponding service
    ;
    Shell $(UtilityInf), AddHardwareComponent, +
        $(AdapterProductHardwareName), +
        $(STF_CONTEXTINFNAME), +
        $(AdapterProductKeyName)

    IfInt $($ShellCode) != $(!SHELL_CODE_OK)
        Debug-Output "ExpressLink: ShellCode error."
        Shell "" DoShellErrorMessage
        Return STATUS_FAILED
    EndIf

    Set RegistryErrorIndex = $($R0)
    IfStr(i) $(RegistryErrorIndex) !=  NO_ERROR
        Debug-Output "ExpressLink: Failed to Add Hardware Component"
        CloseRegKey $($R1)
        CloseRegKey $($R2)
        CloseRegKey $($R3)
        Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
        Return STATUS_FAILED
    EndIf
                

    ;
    ;   At this point:
    ;     $R1  Registry key variable for HARDWARE\Netcard\(n)
    ;     $R2  Registry key variable for HARDWARE\Netcard\(n)\\NetRules
    ;     $R3  Registry key handle for <service>\Parameters key
    ;     $R4  Adapter number assigned to adapter
    ;     $R5  Service name generated by combining svc name with adapter number
    ;
    Set KeyParameters   = $($R3)
    Set KeyAdapterRules = $($R2)
    Set AdapterNumber   = $($R4)
    Set NewServiceName  = $($R5)

    Set NewValueList = {{Manufacturer,$(NoTitle),$(!REG_VT_SZ),$(Manufacturer)},+
                        {Title,$(NoTitle),$(!REG_VT_SZ),"["$($R4)"] "$(ProductHardwareTitle)" ["$(TheGroupsTitle)"]"},+
                        {Description,$(NoTitle),$(!REG_VT_SZ),$(ProductHardwareDescription)},+
                        {ProductName,$(NoTitle),$(!REG_VT_SZ),$(AdapterProductHardwareName)},+
                        {ServiceName,$(NoTitle),$(!REG_VT_SZ),$($R5)},+
                        {Hidden,$(NoTitle),$(!REG_VT_DWORD),1},+
                        {InstallDate,$(NoTitle),$(!REG_VT_DWORD),*($(Now),1)}}

    Shell  $(UtilityInf), AddValueList, $($R1), $(NewValueList)

    IfInt $($ShellCode) != $(!SHELL_CODE_OK)
        Debug-Output "ExpressLink: ShellCode error"
        Shell "" DoShellErrorMessage
        Return STATUS_FAILED
    EndIf
    CloseRegKey $($R1)
            
    Set TempProdName = """"$(AdapterProductHardwareName)$(AdapterNumber)""""
    Set TempBindForm = $(TempProdName)$(AdapterNetRuleHardwareBindForm)
    Set NewValueList = {{type,$(NoTitle),$(!REG_VT_SZ),$(AdapterNetRuleHardwareType)},+
                        {bindform,$(NoTitle),$(!REG_VT_SZ),$(TempBindForm)}, +
                        {class,$(NoTitle),$(!REG_VT_MULTI_SZ),$(AdapterNetRuleHardwareClass)}, +
                        {block,$(NoTitle),$(!REG_VT_MULTI_SZ),$(AdapterNetRuleHardwareBlock)}, +
                        {InfOption,$(NoTitle),$(!REG_VT_SZ),$(Option)}}

    Shell  $(UtilityInf), AddValueList, $(KeyAdapterRules), $(NewValueList)

    IfInt $($ShellCode) != $(!SHELL_CODE_OK)
        Debug-Output "ExpressLink: ShellCode error."
        Shell "" DoShellErrorMessage
        Return STATUS_FAILED
    EndIf

    Set RegistryErrorIndex = $($R0)

    IfStr(i) $(RegistryErrorIndex) != NO_ERROR
        Debug-Output "ExpressLink: Registry error: add value list."
        CloseRegKey $(KeyParameters)
        CloseRegKey $(KeyAdapterRules)
        Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
        Return STATUS_FAILED
    EndIf

    CloseRegKey $(KeyAdapterRules)
    
    Set NewValueList = {{MediaType,$(NoTitle),$(!REG_VT_DWORD),1},                      +
                        {InstanceNumber,$(NoTitle),$(!REG_VT_DWORD),$(AdapterNumber) }, +
                        {Signature,$(NoTitle),$(!REG_VT_SZ),$(TransportSignature) }}

    Shell  $(UtilityInf), AddValueList, $(KeyParameters), $(NewValueList)


    Set TcpInfo = *($(VirtualAdapter), 7)
    IfStr(i) $(TcpInfo) != {}
        Set TcpKeyName = $(!NTN_ServiceBase)"\"$(NewServiceName)$(TcpipBase)

        CreateRegKey $(!REG_H_LOCAL) {$(TcpKeyName),$(NoTitle),GenericClass} "" $(MAXIMUM_ALLOWED) "" TcpIpKey

        IfStr(i) $(TcpIpKey) == ""
            Set RegistryErrorIndex = $(RegLastError)
            Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
            CloseRegKey $(KeyParameters)
            Return STATUS_FAILED
        EndIf

        Shell  $(UtilityInf), AddValueList, $(TcpIpKey), $(TcpInfo)
        CloseRegKey $(TcpIpKey)

        IfInt $($ShellCode) != $(!SHELL_CODE_OK)
            Debug-Output "ExpressLink: ShellCode error."
            Shell "" DoShellErrorMessage
            Return STATUS_FAILED
        EndIf

        Set RegistryErrorIndex = $($R0)

        IfStr(i) $(RegistryErrorIndex) != NO_ERROR
            Debug-Output "ExpressLink: Registry error: Add value list"
            Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
            Return STATUS_FAILED
        EndIf
    EndIf

    CloseRegKey $(KeyParameters)

    IfInt $($ShellCode) != $(!SHELL_CODE_OK)
        Debug-Output "ExpressLink: ShellCode error."
        Shell "" DoShellErrorMessage
        Return STATUS_FAILED
    EndIf

    Set RegistryErrorIndex = $($R0)

    IfStr(i) $(RegistryErrorIndex) != NO_ERROR
        Debug-Output "ExpressLink: Registry error: Add value list"
        Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
        Return STATUS_FAILED
    EndIf

    Set VirtualAdapter = {$(NewServiceName),   +
                          $(AdapterNumber),    +
                          $(AdapterAdded),     +
                          $(AdapterDeleted),   +
                          0,                   +
                          $(AdapterGroupName), +
                          $(AdapterProtocolInfo)}

    Return STATUS_SUCCESSFUL $(VirtualAdapter)

;==================================================================
;==================================================================
; Update ProtocolInfo for Virtual Adapters.
;
; $($0)  = Virtual Adapters List
; $($1)  = Available Adapters List
;
;
[UpdateVirtualAdapters]
    Read-Syms FileConstants
    Read-Syms GeneralConstants
    Read-Syms RegBaseInfo
    Read-Syms FileConstants$(!STF_LANGUAGE)
    Read-Syms ErrorMessages$(!STF_LANGUAGE)

    Set VirtualAdaptersList = $($0)
    Set RealAdaptersList    = $($1)

    ForListDo $(RealAdaptersList)
        Set AdapterInfo = $($)
        IfInt *($(AdapterInfo), 14) == 1
            Set NewVirtualAdaptersList = {}
            Set GroupName = *($(AdapterInfo), 9)
            Set ProtocolInfo = *($(AdapterInfo), 10)
            Set DummyProtocol = {}

            ForListDo $(VirtualAdaptersList)
                Set VirtualAdapter = $($)
                IfStr(i) $(GroupName) == *($(VirtualAdapter), 6)
                    Set AdapterServiceName  = *($(VirtualAdapter), 1)
                    Set AdapterNumber       = *($(VirtualAdapter), 2)
                    Set AdapterAdded        = *($(VirtualAdapter), 3)
                    Set AdapterDeleted      = *($(VirtualAdapter), 4)
                    Set AdapterModified     = *($(VirtualAdapter), 5)
                    Set AdapterGroupName    = *($(VirtualAdapter), 6)
                    Set AdapterProtocolInfo = *($(VirtualAdapter), 7)

                    IfStr(i) $(AdapterProtocolInfo) == {}
                        Set AdapterProtocolInfo = $(ProtocolInfo)
                    Else-IfStr(i) $(AdapterProtocolInfo) == ""
                        Set AdapterProtocolInfo = $(DummyProtocol)
                    Else
                        Set NewIPAddress      = {}
                        Set NewSubnetMask     = {}
                        Set NewDefaultGateway = {}
                        Set GatewayList       = {}
                        Set IPList            = {}
                        Set SubnetList        = {}

                        ForListDo $(ProtocolInfo)
                            Set ValueItem = $($)
                            Set ValueName = *($(ValueItem),1)
                            Set ValueData = *($(ValueItem),4)

                            IfStr(i) $(ValueName) == "IPAddress"
                                Set IPList       = $(ValueItem)
                                Set NewIPAddress = $(ValueData)
                            Else-IfStr(i) $(ValueName) == "SubnetMask"
                                Set SubnetList    = $(ValueItem)
                                Set NewSubnetMask = $(ValueData)
                            Else-IfStr(i) $(ValueName) == "DefaultGateway"
                                Set GatewayList       = $(ValueItem)
                                Set NewDefaultGateway = $(ValueData)
                            EndIf
                        EndForListDo

                        Set OldIPAddress      = {}
                        Set OldSubnetMask     = {}
                        Set OldDefaultGateway = {}

                        ForListDo $(AdapterProtocolInfo)
                            Set ValueItem = $($)
                            Set ValueName = *($(ValueItem),1)
                            Set ValueData = *($(ValueItem),4)

                            IfStr(i) $(ValueName) == "IPAddress"
                                Set IPList       = $(ValueItem)
                                Set OldIPAddress = $(ValueData)
                            Else-IfStr(i) $(ValueName) == "SubnetMask"
                                Set SubnetList    = $(ValueItem)
                                Set OldSubnetMask = $(ValueData)
                            Else-IfStr(i) $(ValueName) == "DefaultGateway"
                                Set GatewayList       = $(ValueItem)
                                Set OldDefaultGateway = $(ValueData)
                            EndIf
                        EndForListDo

                        IfStr(i) $(GatewayList) != {}
                            Set DefaultGateway = {}

                            ForListDo $(OldDefaultGateway)
                                Set NextItem = $($)
                                Set DefaultGateway = >($(DefaultGateway), $(NextItem))
                            EndForListDo

                            ForListDo $(NewDefaultGateway)
                                Set NextItem = $($)
                                Set DefaultGateway = >($(DefaultGateway), $(NextItem))
                            EndForListDo

                            Set GateWayList = {*($(GatewayList), 1), +
                                               *($(GatewayList), 2), +
                                               *($(GatewayList), 3), +
                                               $(DefaultGateway)}
                        EndIf

                        IfStr(i) $(IPList) != {}
                            Set IPAddress = {}

                            ForListDo $(OldIPAddress)
                                Set NextItem = $($)
                                Set IPAddress = >($(IPAddress), $(NextItem))
                            EndForListDo

                            ForListDo $(NewIPAddress)
                                Set NextItem = $($)
                                Set IPAddress = >($(IPAddress), $(NextItem))
                            EndForListDo

                            Set IPList = {*($(IPList), 1), +
                                          *($(IPList), 2), +
                                          *($(IPList), 3), +
                                          $(IPAddress)}
                        EndIf

                        IfStr(i) $(SubnetList) != {}
                            Set SubnetMask = {}

                            ForListDo $(OldSubnetMask)
                                Set NextItem = $($)
                                Set SubnetMask = >($(SubnetMask), $(NextItem))
                            EndForListDo

                            ForListDo $(NewSubnetMask)
                                Set NextItem = $($)
                                Set SubnetMask = >($(SubnetMask), $(NextItem))
                            EndForListDo

                            Set SubnetList = {*($(SubnetList), 1), +
                                              *($(SubnetList), 2), +
                                              *($(SubnetList), 3), +
                                              $(SubnetMask)}
                        EndIf

                        Set NewInfoList = {}
                        ForListDo $(AdapterProtocolInfo)
                            Set ValueItem = $($)
                            Set ValueName = *($(ValueItem),1)
                            Set ValueData = *($(ValueItem),4)
                            IfStr(i) $(ValueName) == "IPAddress"
                                Set NewInfoList = >($(NewInfoList), $(IPList))
                            Else-IfStr(i) $(ValueName) == "DefaultGateway"
                                Set NewInfoList = >($(NewInfoList), $(GatewayList))
                            Else-IfStr(i) $(ValueName) == "SubnetMask"
                                Set NewInfoList = >($(NewInfoList), $(SubnetList))
                            Else
                                Set NewInfoList = >($(NewInfoList), $(ValueItem))
                            EndIf
                        EndForListDo
                        Set AdapterProtocolInfo = $(NewInfoList)
                    EndIf

                    Set VirtualAdapter = {$(AdapterServiceName),+
                                          $(AdapterNumber),     +
                                          $(AdapterAdded),      +
                                          $(AdapterDeleted),    +
                                          $(AdapterModified),   +
                                          $(AdapterGroupName),  +
                                          $(AdapterProtocolInfo)}
                EndIf

                Set NewVirtualAdaptersList = >($(NewVirtualAdaptersList), $(VirtualAdapter))
            EndForListDo

            Set VirtualAdaptersList = $(NewVirtualAdaptersList)
        EndIf

    EndForListDo

    ForListDo $(VirtualAdaptersList)
        Set VirtualAdapter = $($)
        Set AdapterServiceName = *($(VirtualAdapter), 1)
        Set AdapterProtocolInfo = *($(VirtualAdapter), 7)
        Set AdapterGroupName = *($(VirtualAdapter), 6)
        IfStr(i) $(AdapterGroupName) != "Group0"
            Set TcpIpKeyName = $(ServiceBase)$(AdapterServiceName)$(TcpipBase)

            OpenRegKey $(!REG_H_LOCAL) "" $(TcpIpKeyName) $(MAXIMUM_ALLOWED) KeyTcpIp

            IfStr(i) $(KeyTcpIp) == $(KeyNull)
                CreateRegKey $(!REG_H_LOCAL) {$(TcpIpKeyName),$(NoTitle),GenericClass} "" $(MAXIMUM_ALLOWED) "" KeyTcpIp
            EndIf

            IfStr $(KeyTcpIp) != $(KeyNull)
                Shell $(UtilityInf), AddValueList, $(KeyTcpIp), $(AdapterProtocolInfo)
                CloseRegKey $(KeyTcpIp)
            Else
                Debug-Output "ExpressLink: failed to open \Parameters\TcpIp Key for "$(AdapterServiceName)
            EndIf
        EndIf
    EndForListDo

    Return

;==================================================================
;==================================================================
; Update ExpressLink parameters for Adapters.
;
; $($0)  = Virtual Adapters List
; $($1)  = Available Adapters List
; $($2)  = All Groups Name List
; $($3)  = All Groups Title List
;
;
; $($R0) = Status
;
;
[UpdateRealAdapters]
    Read-Syms FileConstants
    Read-Syms GeneralConstants
    Read-Syms RegBaseInfo
    Read-Syms FileConstants$(!STF_LANGUAGE)
    Read-Syms ErrorMessages$(!STF_LANGUAGE)

    Set VirtualAdaptersList = $($0)
    Set RealAdaptersList    = $($1)
    Set AllGroupsNameList   = $($2)
    Set AllGroupsTitleList  = $($3)
    Set BlockList           = ^(TransportNames, 1)

;;;;;

;  Delete any non virtual adapters out from under the AppleTalk\Adapters subkey so that
;  AppleTalk won't get pissed off and bluescreen the box!

;  Try to open the AppleTalk service key to see if it exists.
   OpenRegKey $(!REG_H_LOCAL) "" $(ATServiceKeyName) $(!REG_KEY_CREATE_SUB_KEY) ATHandle
   ifstr $(ATHandle) == $(KeyNull)
      ;Debug-Output "The AppleTalk is not installed."
      goto ContinueUpdate
   endif

;  Open the key for the Adapters.
   OpenRegKey $(ATHandle) "" "Adapters" $(!REG_KEY_ALL_ACCESS) ATAdaptersHandle

   ifstr $(ATAdaptersHandle) != $(KeyNull)
      EnumRegKey $(ATAdaptersHandle) KeyList

      forlistdo $(KeyList)
          set NextKey = $($)
          set KeyName = *($(NextKey), 1)

          Split-String $(KeyName) "0123456789" SubKeyName

          ifstr *($(SubKeyName), 1) != $(AdapterProductHardwareName)
             ;Debug-Output "AppleTalk - deleting "$(KeyName)
             DeleteRegTree $(ATAdaptersHandle) $(KeyName)
          endif
      endforlistdo

      CloseRegKey $(ATAaptersHandle)
   endif

   CloseRegKey $(ATHandle)

;;;;;

ContinueUpdate = +

    ForListDo $(RealAdaptersList)
        Set NextAdapter = $($)
        Set GroupName = *($(NextAdapter), 9)

        ForListDo $(VirtualAdaptersList)
            Set VirtualAdapter = $($)

            IfStr(i) $(GroupName) == *($(VirtualAdapter), 6)
                Set TransportInfoBase = $(ServiceBase)*($(NextAdapter), 1)$(ExpressLinkBase)

                OpenRegKey $(!REG_H_LOCAL) "" $(TransportInfoBase) $(MAXIMUM_ALLOWED) TransportInfoKey

                IfStr(i) $(TransportInfoKey) == $(KeyNull)
                    CreateRegKey $(!REG_H_LOCAL) {$(TransportInfoBase),$(NoTitle),GenericClass} "" $(MAXIMUM_ALLOWED) "" TransportInfoKey
                    IfStr(i) $(TransportInfoKey) == $(KeyNull)
                        Set RegistryErrorIndex = $(RegLastError)
                        Debug-Output "ExpressLink: failed to open \Parameters\ExpressLink Key for "*($(NextAdapter), 1)
                        Shell "" DoRegistryMessage DoFatalMessage $(RegistryErrorIndex)
                        Return STATUS_FAILED
                    EndIf
                EndIf

                Set GroupNumber = *($(VirtualAdapter), 6)
                Set Index = 1
                ForListDo $(AllGroupsNameList)
                    Set NextGroup = $($)
                    IfStr(i) $(NextGroup) == $(GroupNumber)
                        Set GroupName = *($(AllGroupsTitleList), $(Index))
                    EndIf
                    Set-Add Index = $(Index), 1
                EndForListDo

                Split-String $(GroupNumber) "0123456789" GroupNumber
                QueryListSize ListSize $(GroupNumber)

                Set GroupNumber            = *($(GroupNumber), $(ListSize))
                Set DeviceName             = *($(VirtualAdapter), 1)
                Set AdapterNumber          = *($(VirtualAdapter), 2)
                Set AdapterUseProtocolInfo = *($(NextAdapter), 14)

                Set NewValueList = {{Device,          $(NoTitle), $(!REG_VT_SZ),    $(DeviceName)    }, +
                                    {AdapterNumber,   $(NoTitle), $(!REG_VT_SZ),    $(AdapterNumber) }, +
                                    {InstanceNumber,  $(NoTitle), $(!REG_VT_DWORD), $(AdapterNumber) }, +
                                    {GroupNumber,     $(NoTitle), $(!REG_VT_DWORD), $(GroupNumber)   }, +
                                    {GroupName,       $(NoTitle), $(!REG_VT_SZ),    $(GroupName)     }, +
                                    {UseProtocolInfo, $(NoTitle), $(!REG_VT_DWORD), $(AdapterUseProtocolInfo)}}

                Shell $(UtilityInf), AddValueList, $(TransportInfoKey), $(NewValueList)

                CloseRegKey $(TransportInfoKey)

                ;
                ;--  Modify the Title for this adapter.
                ;
                Set AdapterId = *($(NextAdapter), 5)
                Split-String $(AdapterId) "[]" AdapterId
                Set AdapterId = *($(AdapterId), 2)

                Set AdapterBase = $(AdapterRegBase)$(AdapterId)
                Set AdapterTitle = *($(NextAdapter), 5)
                Set AdapterDescription = *($(NextAdapter), 2)

                OpenRegKey $(!REG_H_LOCAL) "" $(AdapterBase) $(MAXIMUM_ALLOWED) AdapterBaseKey
                IfStr(i) $(AdapterBaseKey) != $(KeyNull)
                    SetRegValue $(AdapterBaseKey) {"Title", $(NoTitle), $(!REG_VT_SZ), $(AdapterTitle)}
                    SetRegValue $(AdapterBaseKey) {"Description", $(NoTitle), $(!REG_VT_SZ), $(AdapterDescription)}
                    CloseRegKey $(AdapterBaseKey)
                EndIf

                ;
                ;--  Modify the NetRules for this adapter.
                ;
                Set AdapterRulesBase = $(AdapterRegBase)$(AdapterId)$(NetRulesBase)

                OpenRegKey $(!REG_H_LOCAL) "" $(AdapterRulesBase) $(MAXIMUM_ALLOWED) AdapterRulesKey

                IfStr(i) $(AdapterRulesKey) != $(KeyNull)
                    IfInt $(GroupNumber) == 0
                        DeleteRegValue $(AdapterRulesKey) "block"
                    Else
                        GetRegValue $(AdapterRulesKey) "type" TypeList

                        Set CardType = *($(TypeList),4)
                        Split-String $(CardType) " " CardType
                        Set CardType = *($(CardType), 3)

                        Set NewBlockList = {}

                        ForListDo $(BlockList)
                            Set NextTransport = $($)
                            Set NewBlockList = >($(NewBlockList), $(NextTransport)" "$(CardType))
                        EndForListDo

                        SetRegValue $(AdapterRulesKey) {"block", $(NoTitle), $(!REG_VT_MULTI_SZ), $(NewBlockList)}
                    EndIf
                    CloseRegKey $(AdapterRulesKey)
                EndIf


            EndIf
        EndForListDo

    EndForListDo

    Return STATUS_SUCCESSFUL

;==================================================================
;==================================================================
; Notify NCPA that a Bindings Review is required.
;
;
[SetBindingReview]
    Read-Syms GeneralConstants
    Read-Syms FileConstants

    OpenRegKey $(!REG_H_LOCAL) "" $(NcpaBase) $(MAXIMUM_ALLOWED) NcpaKey
    IfStr(i) $(NcpaKey) != KeyNull
        SetRegValue $(NcpaKey) {"BindRestart",$(NoTitle),$(!REG_VT_DWORD),1}
        CloseRegKey $(NcpaKey)
    Else
        Debug-Output "ExpressLink: failed to open "$(RegKey)
    EndIf

    Return

;==================================================================
;==================================================================
; Test to verify that TCP\IP is installed on this system.
;
;
[TestTCP]
    Read-Syms GeneralConstants
    Read-Syms FileConstants
    Read-Syms FileConstants$(!STF_LANGUAGE)
    Read-Syms ErrorMessages$(!STF_LANGUAGE)

    Set DeleteFlag     = 0
    Set DeleteFlagInfo = {}
    Set ReturnStatus   = STATUS_SUCCESSFUL

    OpenRegKey $(!REG_H_LOCAL) "" $(TcpIpServiceBase) $(MAXIMUM_ALLOWED) KeyTcpIp

    IfStr(i) $(KeyTcpIp) == $(KeyNull)
        Set ReturnStatus = STATUS_FAILED
    Else
        GetRegValue $(KeyTcpIp),"DeleteFlag", DeleteFlagList
        Set DeleteFlag = *($(DeleteFlagList), 4)
        CloseRegKey $(KeyTcpIp)

        IfInt $(DeleteFlag) == 1
            Set ReturnStatus = STATUS_FAILED
        EndIf
    EndIf

    IfStr(i) $(ReturnStatus) == STATUS_FAILED
        Debug-Output "ExpressLink: TCP is not installed"
        Shell "" DoFatalMessage $(NoTCP)
        Return STATUS_FAILED
    Else
        Return STATUS_SUCCESSFUL
    EndIf

;==================================================================
;==================================================================
; Second Pass Bindings Review.
;
; $($0) =  Language to use
; $($1) =  OptionID to install
; $($2) =  SourceDirectory
; $($3) =  AddCopy  (YES | NO)
; $($4) =  DoCopy   (YES | NO)
; $($5) =  DoConfig (YES | NO)
;
;
[BindingsReview]
    Read-Syms DebugLevel
    Read-Syms GeneralConstants
    Read-Syms FileConstants

    Set Option   = $($1)
    Set SrcDir   = $($2)
    Set AddCopy  = $($3)
    Set DoCopy   = $($4)
    Set DoConfig = $($5)

    Set LanguageList = ^(LanguagesSupported, 1)

    IfContains(i) $($0) NOT-IN $(LanguageList)
        Return STATUS_NOLANGUAGE
    EndIf

    Set-Title  $(FunctionTitle)


    Return STATUS_SUCCESSFUL

;==================================================================
;==================================================================
; Set up INF for Second Pass Bindings Review.
;
[AddInfToReview]
    Read-Syms FileConstants
    Read-Syms GeneralConstants

    OpenRegKey $(!REG_H_LOCAL) "" $(NcpaBase) $(MAXIMUM_ALLOWED) KeyNcpa

    IfStr(i) $(KeyNcpa) == $(KeyNull)
        Debug-Output "ExpressLink: Failed to open NCPA key"
        Shell "" DoRegistryMessage DoFatalMessage $(RegLastError)
        Return STATUS_FAILED
    EndIf


    Set ReviewListInfo = {}
    Set ReviewList     = {}
    Set NewReviewList  = {$(!NTN_Infname)}

    GetRegValue $(KeyNcpa) "ReviewPrograms" ReviewListInfo

    IfStr(i) $(ReviewListInfo) != "{}"
        Set ReviewList = *($(ReviewListInfo), 4)
    EndIf

    ForListDo $(ReviewList)
        IfStr(i) $($) != $(!NTN_Infname)
            Set NewReviewList = >($(NewReviewList), $($))
        EndIf
    EndForListDo

    SetRegValue $(KeyNcpa) {ReviewPrograms, 0, $(!REG_VT_MULTI_SZ), $(NewReviewList)}
    CloseRegKey $(KeyNcpa)

    return STATUS_SUCCESSFUL

;==================================================================
;==================================================================
; Remove INF from Second Pass Bindings Review List.
;
[DeleteInfFromReview]
    Read-Syms FileConstants
    Read-Syms GeneralConstants

    OpenRegKey $(!REG_H_LOCAL) "" $(NcpaBase) $(MAXIMUM_ALLOWED) KeyNcpa

    IfStr(i) $(KeyNcpa) == $(KeyNull)
        Debug-Output "ExpressLink: Failed to open NCPA key"
        Shell "" DoRegistryMessage DoFatalMessage $(RegLastError)
        Return STATUS_FAILED
    EndIf


    Set ReviewListInfo = {}
    Set ReviewList     = {}
    Set NewReviewList  = {}

    GetRegValue $(KeyNcpa) "ReviewPrograms" ReviewListInfo

    IfStr(i) $(ReviewListInfo) != "{}"
        Set ReviewList = *($(ReviewListInfo), 4)
    EndIf

    ForListDo $(ReviewList)
        IfStr(i) $($) != $(!NTN_Infname)
            Set NewReviewList = >($(NewReviewList), $($))
        EndIf
    EndForListDo

    SetRegValue $(KeyNcpa) {ReviewPrograms, 0, $(!REG_VT_MULTI_SZ), $(NewReviewList)}
    CloseRegKey $(KeyNcpa)

    return STATUS_SUCCESSFUL

;==================================================================
;==================================================================
; Delete a virtual MAC.
;
;
; $($0)  =  VirtualAdapter structure.
;
[DeleteVirtualMAC]
    Read-Syms FileConstants
    Read-Syms GeneralConstants
    Read-Syms RegBaseInfo

    Set VirtualAdapter = $($0)

    Set AdapterNo      = *($(VirtualAdapter), 2)
    Set AdapterRegBase = $(AdapterRegBase)$(AdapterNo)

    Shell $(UtilityInf), RemoveHardwareComponent, $(Manufacturer), +
                        $(AdapterProductSoftwareName), $(AdapterRegBase)

    IfInt $($ShellCode) != $(!SHELL_CODE_OK)
        Shell "" DoShellErrorMessage
    EndIf

    Return


[StripTheComma]
    Split-String $($0) "," InList
    QueryListSize InListSize, $(InList)

    Ifint $(InListSize) <= 1
        Return $($0)
    Endif

    Set NewString = ""
    ForListDo $(InList)
        ifint $(#) < $(InListSize)
            ifstr $($) != ","
                Set NewString = $(NewString)$($)
            endif
        else-ifstr $($) != ","
            Set NewString = $(NewString)$($)
        endif
    EndForListDo
    Return $(NewString)


[StripTrailSlash]
    Split-String $($0) "\" InList
    QueryListSize InListSize, $(InList)
    Ifint $(InListSize) <= 1
        Return $($0)
    Endif
    Set NewString = ""
    ForListDo $(InList)
        ifint $(#) < $(InListSize)
            Set NewString = $(NewString)$($)
        else-ifstr $($) != "\"
            Set NewString = $(NewString)$($)
        endif
    EndForListDo
    Return $(NewString)


;==================================================================
;==================================================================
; Install and Remove our SNMP Extension Agent.
;
;

[InstallSNMPagent]

;  Try to open the SNMP service key to verify that it already exists.
   OpenRegKey $(!REG_H_LOCAL) "" $(SNMPServiceKeyName) $(!REG_KEY_CREATE_SUB_KEY) SNMPHandle
   ifstr $(SNMPHandle) == $(KeyNull)
      ;Debug-Output "The SNMP Service is not installed."
      ;Shell "" DoWarningMessage $(NoSNMP)
      exit 
   endif

;  Open the key for the ExtensionAgents.
   OpenRegKey $(SNMPHandle) "" "Parameters\ExtensionAgents" $(!REG_KEY_ALL_ACCESS) SNMPExtensionHandle
   EnumRegValue $(SNMPExtensionHandle) SNMPExtValueList
   ifint $(!RegLastError) != 0
      CloseRegKey $(SNMPHandle)
      exit
   endif

;  See if there is already an entry for our SNMP Agent.
   set MaxSNMPIndex = "0"
   ForListDo $(SNMPExtValueList)
      set CurrentSNMPVal = *($($), 4)
      ifstr(i) $(CurrentSNMPVal) == $(SNMPPathLocation)
         CloseRegKey $(SNMPExtensionHandle)
         CloseRegKey $(SNMPHandle)
         exit
      endif

;     Set the index to largest index number read so far.
;     This handles string ordering of index numbers (ie. 10 before 2).
      ifint *($($), 1) > $(MaxSNMPIndex)
         set MaxSNMPIndex = *($($), 1)
      endif
   EndForListDo

;  Add new entry index 1 greater than the largest found in the list.
   set-add MaxSNMPIndex = $(MaxSNMPIndex), 1

   SetRegValue $(SNMPExtensionHandle) {$(MaxSNMPIndex), 0, $(!REG_VT_SZ), $(SNMPPathLocation)}
   ifint $(!RegLastError) != 0
      Shell "subroutn.inf" SetUpMessage $(!STF_LANGUAGE) NONFATAL "Could not create Registry entry for SNMP ExtensionAgent."
      exit
   endif

;  Close the keys.
   CloseRegKey $(SNMPExtensionHandle)
   CloseRegKey $(SNMPHandle)

;  Open the TransportProductKeyName key.
   OpenRegKey $(!REG_H_LOCAL) "" $(TransportProductKeyName) $(!REG_KEY_CREATE_SUB_KEY) KeyProduct
   ifstr $(KeyProduct) == $(KeyNull)
      exit
   endif

;  If the SnmpAgent key doesn't exists, then create it.
   OpenRegKey $(!REG_H_LOCAL) "" $(SNMPPathLocation) $(!REG_KEY_SET_VALUE) SNMPAgentHandle
   ifstr $(SNMPAgentHandle) == $(KeyNull)
      CreateRegKey $(KeyProduct) {"SnmpAgent", 0, GenericClass} "" $(!REG_KEY_SET_VALUE) "" SNMPAgentHandle
      ifstr $(SNMPAgentHandle) == $(KeyNull)
         Debug-Output "Could not create SnmpAgent subkey."
         exit
      endif
   endif

;  Set the Pathname value under the SnmpAgent subkey.
   SetRegValue $(SNMPAgentHandle) {"Pathname", 0, $(!REG_VT_SZ), $(SNMPFileLocation)}
   ifint $(!RegLastError) != 0
      Debug-Output "Could not create Pathname value under SnmpAgent subkey."
      exit
   endif

;  Close the keys and exit.
   CloseRegKey $(SNMPAgentHandle)
   CloseRegKey $(KeyProduct)

   exit 


[RemoveSNMPagent]
	
;  Try to open the SNMP service key to verify that it already exists.
   OpenRegKey $(!REG_H_LOCAL) "" $(SNMPServiceKeyName) $(!REG_KEY_CREATE_SUB_KEY) SNMPHandle
   ifstr $(SNMPHandle) == $(KeyNull)
      ;Debug-Output "The SNMP Service is not installed."
      exit 
   endif

;  Open the key for the ExtensionAgents.
   OpenRegKey $(SNMPHandle) "" "Parameters\ExtensionAgents" $(!REG_KEY_ALL_ACCESS) SNMPExtensionHandle
   EnumRegValue $(SNMPExtensionHandle) SNMPExtValueList
   ifint $(!RegLastError) != 0
      exit
   endif

;  Search through the lists of values and remove us from the registry.
   ForListDo $(SNMPExtValueList)
      set CurrentSNMPVal = *($($), 4)
      set CurrentSNMPValName = *($($), 1)
      ifstr(i) $(CurrentSNMPVal) == $(SNMPPathLocation)
         ;Debug-Output "Removing our value from under ExtensionAgent subkey."
         DeleteRegValue $(SNMPExtensionHandle) $(CurrentSNMPValName)
      endif
   EndForListDo

;  Open the TransportProductKeyName key and delete the SnmpAgent subkey.
   OpenRegKey $(!REG_H_LOCAL) "" $(TransportProductKeyName) $(!REG_KEY_ALL_ACCESS) KeyProduct
   ifstr $(KeyProduct) == $(KeyNull)
      exit
   endif

   DeleteRegTree $(KeyProduct) "SnmpAgent"

;  Close the keys and exit.
   CloseRegKey $(SNMPExtensionHandle)
   CloseRegKey $(SNMPHandle)
   CloseRegKey $(KeyProduct)

   exit


;==================================================================
;==================================================================
; Remove (delete) the specified file(s) from the given list and
; from the given path.
;
;

[RemoveFiles]

   ForListDo $($1)
      Set NextFile = $($)
      Set FileName = *($(NextFile), 1)
      LibraryProcedure ReturnCode $($2) DelFile $($0)\$(FileName)
   EndForListDo

   Return
