;-----------------------------------------------------------------------
;
; SETUPUTL.INF:  Various utility routines for setting up SNA Services.
;
;-----------------------------------------------------------------------
[Source Media Descriptions]
  1 = "Dummy"

[LanguagesSupported]
  ENG

[File Constants]
  !SNABinDir       = "system"

[Registry Constants]
  MaskAllAccess    = 33554432  ; 0x2000000
  MAXIMUM_ALLOWED  = 33554432  ; see winnt.h
  NoTitle          = 0
  RegErrorIndex    = NO_ERROR
  !RegLastError    = NO_ERROR
  KeyNull          = ""
  KeyInfo          = {}

  SNAGroup         = ""  ; was "SNA Services"
  SNAUser          = "LocalSystem"

  SYSTEM_ERROR_NORMAL       =  1

  SERVICE_SYSTEM_START      =  1
  SERVICE_AUTO_START        =  2
  SERVICE_DEMAND_START      =  3

  SERVICE_KERNEL_DRIVER     =  1
  SERVICE_DRIVER            =  3
  SERVICE_WIN32_OWN_PROCESS = 16

  LinkTypeList = { 3, 4, 10, 11 }  ; SDLC, X.25, DFT, TR (see [SNAServiceTypes] below)
  NapTypeList  = { 28, 29 }        ; CESCLIENTNAP, CESSERVERNAP

  CurrentControlSet  = "SYSTEM\CurrentControlSet"
  ServicesBaseName   = $(CurrentControlSet)"\Services"
  ServicesBaseHandle = ""

  PathRegKeyName   = "System\CurrentControlSet\Control"+
                     "\Session Manager\Environment"
  SetupRegKeyName  = "Software\Microsoft\SNA Server\2.0\Setup"
  SetupRegKeyPath  = +
  { +
    { "Software",     $(NoTitle), $(MaskAllAccess) } +
    { "Microsoft",    $(NoTitle), $(MaskAllAccess) } +
    { "SNA Server",   $(NoTitle), $(MaskAllAccess) } +
    { "2.0",          $(NoTitle), $(MaskAllAccess) } +
    { "Setup",        $(NoTitle), $(MaskAllAccess) } +
  }

  ;
  ; The SetupRegKeyValues list should have only three items; the fourth item
  ; (the value this key should receive) is tacked on later by UpdateRootDir.
  ;
  SetupRegKeyValues = +
  { +
    { "RootDir", $(NoTitle), $(!REG_VT_SZ) } +
    { "SetupMode", $(NoTitle), $(!REG_VT_SZ) } +
  }

  ;
  ; These guys are the tracing parameters for the various components.
  ; They are added under the Parameters key for the Nap, the Node, and
  ; each link service.
  ;
  NapTraceParams = +
  { +
    { "MessageTraceFile1", $(NoTitle), $(!REG_VT_SZ),         +
                             $(!SNATraceDir)"napmsg1.trc" }   +
    { "MessageTraceFile2", $(NoTitle), $(!REG_VT_SZ),         +
                             $(!SNATraceDir)"napmsg2.trc" }   +
    { "InternalTraceFile1",$(NoTitle), $(!REG_VT_SZ),         +
                             $(!SNATraceDir)"napint1.trc" }   +
    { "InternalTraceFile2",$(NoTitle), $(!REG_VT_SZ),         +
                             $(!SNATraceDir)"napint2.trc" }   +
    { "InternalMessageTraceState", $(NoTitle), $(!REG_VT_SZ), +
                             "off" } +
    { "FlipLength",        $(NoTitle), $(!REG_VT_DWORD), 500000 } +
    { "InternalTraceLevel",$(NoTitle), $(!REG_VT_DWORD), 20 } +
    { "FMITraceState",     $(NoTitle), $(!REG_VT_SZ), "off" } +
    { "PVITraceState",     $(NoTitle), $(!REG_VT_SZ), "off" } +
    { "TraceFlushing",     $(NoTitle), $(!REG_VT_SZ), "off" } +
    { "MaxRecordLength",   $(NoTitle), $(!REG_VT_DWORD), 65535 } +
    { "BufferAuditInterval",$(NoTitle),$(!REG_VT_DWORD), 4294967295 } +
  }

  ClientTraceParams =+
  { +
    { "APITraceFile1",      $(NoTitle), $(!REG_VT_SZ),         +
                              $(!SNATraceDir)"api1.trc"      } +
    { "APITraceFile2",      $(NoTitle), $(!REG_VT_SZ),         +
                              $(!SNATraceDir)"api2.trc"      } +
    { "MessageTraceFile1",  $(NoTitle), $(!REG_VT_SZ),         +
                              $(!SNATraceDir)"climsg1.trc"   } +
    { "MessageTraceFile2",  $(NoTitle), $(!REG_VT_SZ),         +
                              $(!SNATraceDir)"climsg2.trc"   } +
    { "InternalTraceFile1", $(NoTitle), $(!REG_VT_SZ),         +
                              $(!SNATraceDir)"client1.trc"   } +
    { "InternalTraceFile2", $(NoTitle), $(!REG_VT_SZ),         +
                              $(!SNATraceDir)"client2.trc"   } +
    { "InternalMessageTraceState", $(NoTitle), $(!REG_VT_SZ),  +
                             "off"                           } +
    { "FlipLength",         $(NoTitle), $(!REG_VT_DWORD), 500000 } +
    { "CSVTraceState",      $(NoTitle), $(!REG_VT_SZ), "Off" } +
    { "APPCTraceState",     $(NoTitle), $(!REG_VT_SZ), "Off" } +
    { "RUITraceState",      $(NoTitle), $(!REG_VT_SZ), "Off" } +
    { "FMITraceState",      $(NoTitle), $(!REG_VT_SZ), "Off" } +
    { "PVITraceState",      $(NoTitle), $(!REG_VT_SZ), "Off" } +
    { "HLLAPITraceState",   $(NoTitle), $(!REG_VT_SZ), "Off" } +
    { "CPICTraceState",     $(NoTitle), $(!REG_VT_SZ), "Off" } +
    { "TraceFlushing",      $(NoTitle), $(!REG_VT_SZ), "Off" } +
    { "COMTBLG",            $(NoTitle), $(!REG_VT_SZ), $(!SNARootDir)"\system\comtblg.dat" } +
    { "InternalTraceLevel", $(NoTitle), $(!REG_VT_DWORD),    20 } +
    { "MaxRecordLength",    $(NoTitle), $(!REG_VT_DWORD), 65535 } +
    { "SnamanagTraceLevel", $(NoTitle), $(!REG_VT_DWORD),    20 } +
  }

  NodeTraceParams = +
  { +
    { "MessageTraceFile1", $(NoTitle), $(!REG_VT_SZ),         +
                             $(!SNATraceDir)"nodemsg1.trc" }  +
    { "MessageTraceFile2", $(NoTitle), $(!REG_VT_SZ),         +
                             $(!SNATraceDir)"nodemsg2.trc" }  +
    { "InternalTraceFile1",$(NoTitle), $(!REG_VT_SZ),         +
                             $(!SNATraceDir)"nodeint1.trc" }  +
    { "InternalTraceFile2",$(NoTitle), $(!REG_VT_SZ),         +
                             $(!SNATraceDir)"nodeint2.trc" }  +
    { "InternalMessageTraceState", $(NoTitle), $(!REG_VT_SZ), +
                             "off" } +
    { "FlipLength",        $(NoTitle), $(!REG_VT_DWORD), 500000 } +
    { "InternalTraceLevel",$(NoTitle), $(!REG_VT_DWORD), 20 } +
    { "DLCTraceState",     $(NoTitle), $(!REG_VT_SZ), "off" } +
    { "FMITraceState",     $(NoTitle), $(!REG_VT_SZ), "off" } +
    { "PVITraceState",     $(NoTitle), $(!REG_VT_SZ), "off" } +
    { "SNATraceState",     $(NoTitle), $(!REG_VT_SZ), "off" } +
    { "TraceFlushing",     $(NoTitle), $(!REG_VT_SZ), "off" } +
    { "MaxRecordLength",   $(NoTitle), $(!REG_VT_DWORD), 65535 } +
  }

  LinkTraceParams = +
  { +
    { "MessageTraceFile1",   $(NoTitle), $(!REG_VT_SZ),         +
                               $(!SNATraceDir)"linkmsg1.trc" }  +
    { "MessageTraceFile2",   $(NoTitle), $(!REG_VT_SZ),         +
                               $(!SNATraceDir)"linkmsg2.trc" }  +
    { "ConnectionTraceFile1",$(NoTitle), $(!REG_VT_SZ),         +
                               $(!SNATraceDir)"connect1.trc" }  +
    { "ConnectionTraceFile2",$(NoTitle), $(!REG_VT_SZ),         +
                               $(!SNATraceDir)"connect2.trc" }  +
    { "InternalTraceFile1",  $(NoTitle), $(!REG_VT_SZ),         +
                               $(!SNATraceDir)"linkint1.trc" }  +
    { "InternalTraceFile2",  $(NoTitle), $(!REG_VT_SZ),         +
                               $(!SNATraceDir)"linkint2.trc" }  +
    { "InternalMessageTraceState", $(NoTitle), $(!REG_VT_SZ),   +
                               "off" }                          +
    { "FlipLength",        $(NoTitle), $(!REG_VT_DWORD), 500000 } +
    { "InternalTraceLevel",$(NoTitle), $(!REG_VT_DWORD), 20 }   +
    { "ConnectionTraceState",$(NoTitle), $(!REG_VT_SZ), "off" } +
    { "DLCTraceState",       $(NoTitle), $(!REG_VT_SZ), "off" } +
    { "TraceFlushing",       $(NoTitle), $(!REG_VT_SZ), "off" } +
    { "MaxRecordLength",     $(NoTitle), $(!REG_VT_DWORD), 65535 } +
  }

  NVAlertParams = +
  { +
    { "NMVTConfigFile", $(NoTitle), $(!REG_VT_SZ),               +
                          $(!SNARootDir)"\system\nvalert.ini" }  +
    { "TraceFileName",  $(NoTitle), $(!REG_VT_SZ),               +
                          $(!SNARootDir)"\traces\nvalert.trc" }  +
    { "Retries",        $(NoTitle), $(!REG_VT_DWORD),     7 }    +
    { "Timeout",        $(NoTitle), $(!REG_VT_DWORD), 10000 }    +
    { "TraceLevel",     $(NoTitle), $(!REG_VT_DWORD),    32 }    +
    { "FlipLength",        $(NoTitle), $(!REG_VT_DWORD), 500000 } +
  }

  NVRunParams = +
  { +
    { "TraceFileName",  $(NoTitle), $(!REG_VT_SZ),               +
                          $(!SNARootDir)"\traces\nvruncmd.trc" } +
    { "Timeout",        $(NoTitle), $(!REG_VT_DWORD), 30 }       +
    { "TraceLevel",     $(NoTitle), $(!REG_VT_DWORD), 32 }       +
    { "FlipLength",        $(NoTitle), $(!REG_VT_DWORD), 500000 } +
  }

[SNAServiceTypes]
;
; These all come from IWWSRC\SETALLOS.H
;
  CES21     =  1    ; 2.1 Node
  Node      =  1
  CES3270   =  2    ; 3270
  CESLINK   =  3    ; SDLC link (? - DCL)
  CESX25    =  4    ; X.25 Link
  CESQTP    =  5    ; Queued TP
  CESNQTP   =  6    ; Non-queued TP
  CESSRPI   =  7    ; SRPI
  CESADMIN  =  8    ; Admin
  CESCNMS   =  9    ; CNMS
  CESDFT    = 10    ; DFT Link
  CESTR     = 11    ; Token Ring Link
  CESASYNC  = 12    ; Async
  CESLU0    = 13    ; LU0
  CESCFG    = 14    ; Config
  CESCFGSRV = 15    ; Config Server
  CESCSV    = 16    ; CSV
  CESNETMN  = 17    ; NetMN
  SNANet    = 17
  CESNAP    = 18
  CESSTUB   = 19    ; Stub (COMSTUB.EXE)
  CESRANET  = 20    ; Old NAP (SnaBase)
  Nap       = 20
  CESRAREM  = 21
  CESRASPO  = 22
  CESRABUS  = 23
  CESADUTL  = 24
  CESNTADM  = 25
  CESOPTP   = 26
  CESCLIENTNAP = 28 ; New client & server nap types (June '93)
  CESSERVERNAP = 29
  NVRUNCMD  = 97    ; NetView RunCmd service
  NVALERT   = 98    ; NetView Alerter service
  DRIVER    = 99    ; Device Drivers


[LoadNCPALibrary]
  set !NCPA_HANDLE = ""
  LoadLibrary "NCPA Location" $(!STF_WINDOWSSYSPATH)\NCPA.CPL !NCPA_HANDLE
  exit

[LoadSetupLibrary]
  set !LIBHANDLE = ""
  LoadLibrary "SETUPDLL.DLL Location" $(!STF_WINDOWSSYSPATH)\SETUPDLL.DLL !LIBHANDLE
  exit

[LoadSvcLibrary]
  set !SVCLIBHANDLE = ""
  LoadLibrary "SVCLIB location" $(!SNARootDir)\SETUPSVC.DLL !SVCLIBHANDLE
  exit

[FreeNCPALibrary]
  FreeLibrary $(!NCPA_HANDLE)
  set !NCPA_HANDLE = ""
  exit

[FreeSetupLibrary]
  FreeLibrary $(!LIBHANDLE)
  set !LIBHANDLE = ""
  exit

[FreeSvcLibrary]
  FreeLibrary $(!SVCLIBHANDLE)
  set !SVCLIBHANDLE = ""
  exit


;-----------------------------------------------------------------------
; ROUTINE:      AddLinkServicePerfCounters
;
; DESCRIPTION:  Adds the performance counter strings for a link service.
;               Also maintains the indexes in Services\ServiceName\
;               Parameters\ExtraParameters
;
; ARGUMENTS:    $0   Language ID (009 for English)
;               $1   Service name of this link service
;
; RETURNS:      $R0  Status
;
;------------------------------------------------------------------------
[AddLinkServicePerfCounters]
  read-syms "Registry Constants"
  set Status = STATUS_FAILED

  ifstr(i) $($0) == ""
    goto EndALSPC
  else-ifstr(i) $($1) == ""
    goto EndASLPC
  endif

  set ServiceName = $($1)
  ;
  ; Get FirstPerformanceCounter from registry.
  ;
  OpenRegKey $(!REG_H_LOCAL) "" +
             "System\CurrentControlSet\Services\SnaServr\Parameters" +
             $(MaskAllAccess) SvcParamKey

  ifstr(i) $(SvcParamKey) == $(KeyNull)
    return STATUS_FAILED
  endif

  set FPCValue = {}
  GetRegValue $(SvcParamKey) "FirstPerformanceCounter" FPCValue
  CloseRegKey $(SvcParamKey)
  ifstr(i) $(FPCValue) == {}
    return STATUS_FAILED
  endif

  set FPC = *($(FPCValue),4)

  ;
  ; Build adapter name string and try to find it in the registry.
  ; If not found, then add our string, else just save the index.
  ;
  set AdapterString = "SNA Adapter "$(ServiceName)
  set AdapterHelp   = $(AdapterString)

  install LoadSvcLibrary
  ifstr(i) $(!SVCLIBHANDLE) != ""

    LibraryProcedure Result $(!SVCLIBHANDLE) +
      SNAFindCounterString $($0) $(AdapterString) Counter

    ifstr(i) $(Result) == "0"  ;not found in MULTI_SZ

      LibraryProcedure Result $(!SVCLIBHANDLE) +
        SNAAddPerfCounters $($0) Counters { $(AdapterString) }

      set LSCounterOffset = $(Result)

      LibraryProcedure Result $(!SVCLIBHANDLE) +
        SNAAddPerfCounters $($0) Help { $(AdapterHelp) }

    else
      set LSCounterOffset = $(Result)  ; 'twas found
    endif

    install FreeSvcLibrary
  endif

  ;
  ; Update link service's performance regentries.
  ;
  set SvcParamKey = $(KeyNull)

  OpenRegKey $(!REG_H_LOCAL) "" +
  "System\CurrentControlSet\Services\"$(ServiceName)"\Parameters\ExtraParameters" +
             $(MaskAllAccess) SvcParamKey ;re-use variable

  ifstr(i) $(SvcParamKey) != $(KeyNull)
    SetRegValue $(SvcParamKey) { "PerformanceObject", +
                                   $(NoTitle), $(!REG_VT_DWORD), $(LSCounterOffset) }
    SetRegValue $(SvcParamKey) { "FirstPerformanceCounter", +
                                   $(NoTitle), $(!REG_VT_DWORD), $(FPC) }
    CloseRegKey $(SvcParamKey)
  endif


EndASLPC =+
  return $(Status)


;-----------------------------------------------------------------------
; ROUTINE:      CreateSNARegEntry
;
; DESCRIPTION:  Creates entries for SNA Server in the registry tree.
;
; ARGUMENTS:    $0   Name of top-level registry node to use
;               $1   Product Name ("<name>_<version>_<instance>")
;
; RETURNS:      $R0  Status
;               $R1  Handle to top-level node
;               $R2  Handle to Product Name sub-key
;               $R3  Handle to Service Index sub-sub-key ("CurrentVersion")
;               $R4  Handle to NetRules sub-sub-sub-key
;
;------------------------------------------------------------------------
[CreateSNARegEntry]
  read-syms "Registry Constants"
  set Status   = STATUS_FAILED


  set TopLevelKey       = $(KeyNull)
  set ProductNameKey    = $(KeyNull)
  set ServiceIndexKey   = $(KeyNull)
  set NetRulesKey       = $(KeyNull)

  ifstr(i) $($0) == ""
    goto EndCreateSNARegEntry
  else-ifstr(i) $($1) == ""
    goto EndCreateSNARegEntry
  endif

;
; Open top-level key.
;
  OpenRegKey $(!REG_H_LOCAL) "" $($0) $(MaskAllAccess) TopLevelKey
  ifstr(i) $(TopLevelKey) == $(KeyNull)
    goto EndCreateSNARegEntry
  endif

;
; Create the Product Name key underneath the top-level key.
;
  OpenRegKey $(TopLevelKey) "" $($1) $(MaskAllAccess) ProductNameKey
  ifstr(i) $(ProductNameKey) == $(KeyNull)
    CreateRegKey $(TopLevelKey) +
                 { $($1), $(NoTitle), $(MaskAllAccess) } +
                 "" $(MaskAllAccess) "" ProductNameKey
    ifstr(i) $(ProductNameKey) == $(KeyNull)
      CloseRegKey $(TopLevelKey)
      set TopLevelKey = $(KeyNull)
      goto EndCreateSNARegEntry
    endif
  endif

;
; Create the "CurrentVersion" key (Service Index) underneath the Product Name key.
;
  OpenRegKey $(ProductNameKey) "" "CurrentVersion" $(MaskAllAccess) ServiceIndexKey
  ifstr(i) $(ServiceIndexKey) == $(KeyNull)
    CreateRegKey $(ProductNameKey) +
                 { "CurrentVersion", $(NoTitle), $(MaskAllAccess) } +
                 "" $(MaskAllAccess) "" ServiceIndexKey
    ifstr(i) $(ServiceIndexKey) == $(KeyNull)
      CloseRegKey $(ProductNameKey)
      CloseRegKey $(TopLevelKey)
      set ProductNameKey = $(KeyNull)
      set TopLevelKey    = $(KeyNull)
      goto EndCreateSNARegEntry
    endif
  endif

;
; Create the NetRules key underneath the Service Index key.
;
  OpenRegKey $(ServiceIndexKey) "" "NetRules" $(MaskAllAccess) NetRulesKey
  ifstr(i) $(NetRulesKey) == $(KeyNull)
    CreateRegKey $(ServiceIndexKey) +
                 { "NetRules", $(NoTitle), $(MaskAllAccess) } +
                 "" $(MaskAllAccess) "" NetRulesKey
    ifstr(i) $(NetRulesKey) == ""
        CloseRegKey $(ServiceIndexKey)
        CloseRegKey $(ProductNameKey)
        CloseRegKey $(TopLevelKey)
        set ServiceIndexKey = $(KeyNull)
        set ProductNameKey  = $(KeyNull)
        set TopLevelKey     = $(KeyNull)
        goto EndCreateSNARegEntry
    endif
  endif

  set Status = STATUS_SUCCESSFUL

EndCreateSNARegEntry =+
  return $(Status) $(TopLevelKey) +
                   $(ProductNameKey) +
                   $(ServiceIndexKey) +
                   $(NetRulesKey)


;-----------------------------------------------------------------------
; ROUTINE:      CreateSNAService
;
; DESCRIPTION:  Creates entries in the Service Control registry tree
;               for SNA Server.
;
; ARGUMENTS:    $0   Service name
;               $1   SNA Service type: see [SNAServiceTypes] above
;               $2   Image path
;               $3   Dependency list
;               $4   Parameter list, as per [AddValueList].  The
;                    "SNAServiceType" value will be automatically added.
;               $5   Extra parameter list (service-specific).
;               $6   Event Log message file.
;               $7   Event types supported (usually 0x07).
;               $8   Event Log Location
;
; RETURNS:      $R0  Status
;               $R1  Handle to top level service name key
;               $R2  Handle to "Parameters" sub-key
;               $R3  Handle to "ExtraParameters" sub-sub-key
;
;------------------------------------------------------------------------
[CreateSNAService]
  read-syms "File Constants"
  read-syms "Registry Constants"
  set Status = STATUS_FAILED

  set ServiceNameKey            = $(KeyNull)
  set SeriviceNameParamKey      = $(KeyNull)
  set SeriviceNameExtraParamKey = $(KeyNull)

  set CreateServiceType = ""

  ifstr(i) $($0) == ""
    goto EndCreateSNAService
  else
    set ServiceName = $($0)
  endif

  StartWait

  set SNAServiceType = $($1)
  set ImagePath      = $($2)
  set DependList     = $($3)
  set ParamList      = $($4)
  set ExtraParamList = $($5)
  set EventLogFile   = $($6)
  set EventTypes     = $($7)
  set EventLogLocal  = $($8)

  ifstr(i) $(DependList) == ""
    set DependList = {}
  endif
  ifstr(i) $(ParamList) == ""
    set ParamList = {}
  endif
  ifstr(i) $(ExtraParamList) == ""
    set ExtraParamList = {}
  endif

;
; Figure out our service type.
;
  ifstr(i) $(SNAServiceType) != ""
    set SNAServiceTypeDword = #( SNAServiceTypes, $(SNAServiceType), 1 )
  else
    goto EndCreateSNAService
  endif

  set CreateServiceType  = $(SERVICE_WIN32_OWN_PROCESS)
  set CreateServiceStart = $(SERVICE_DEMAND_START)
  set CreateServiceDesc  = "service"
  set SNAUser            = "LocalSystem"

; Old NAP type:
; -------------
; ifint $(SNAServiceTypeDword) == #( SNAServiceTypes, "CESRANET", 1 )
;   set CreateServiceStart = $(SERVICE_AUTO_START)

  ifcontains $(SNAServiceTypeDword) in $(NapTypeList)
    set CreateServiceStart = $(SERVICE_AUTO_START)

  else-ifint $(SNAServiceTypeDword) == #( SNAServiceTypes, "DRIVER", 1 )
    set CreateServiceType  = $(SERVICE_KERNEL_DRIVER)
    set CreateServiceStart = $(SERVICE_SYSTEM_START)
;;; set CreateServiceDesc  = "kernelautostart"
    set CreateServiceDesc  = "kernel"
    set SNAUser            = ""
    set SNAServiceType     = ""
    ; HACK until DCL recognizes 99 is driver and not service
  endif

;
; Determine ImagePath if necessary.
;
  ifcontains(i) $(SNAServiceTypeDword) in $(LinkTypeList)
    set ImagePath = $(!SNARootDir)"\"$(!SNABinDir)"\SNALINK.EXE"

  else-ifcontains(i) $(SNAServiceTypeDword) in $(NapTypeList)
    ; Nap
    set ImagePath = $(!SNARootDir)"\"$(!SNABinDir)"\SNABASE.EXE"

; Old NAP type:
; -------------
; else-ifint $(SNAServiceTypeDword) == #( SNAServiceTypes, "CESRANET", 1 )
;   ; Nap
;   set ImagePath = $(!SNARootDir)"\"$(!SNABinDir)"\SNABASE.EXE"

  else-ifint $(SNAServiceTypeDword) == #( SNAServiceTypes, "CES21", 1 )
    ; Node
    set ImagePath = $(!SNARootDir)"\"$(!SNABinDir)"\SNASERVR.EXE"

  else-ifint $(SNAServiceTypeDword) == #( SNAServiceTypes, "CESQTP", 1 )
    ; BounceTp
    set ImagePath = $(!SNARootDir)"\"$(!SNABinDir)"\BOUNCETP.EXE"

  else-ifint $(SNAServiceTypeDword) == #( SNAServiceTypes, "CESNETMN", 1 )
    ; SNAnet
    set ImagePath = $(!SNARootDir)"\"$(!SNABinDir)"\SNANMVT.EXE"

  else-ifint $(SNAServiceTypeDword) == #( SNAServiceTypes, "DRIVER", 1 )
    ; Link Driver

    ; HACK
    ifstr(i) $(ImagePath) == "DLC.SYS"
      set _DLC_ = YES
    else
      set _DLC_ = NO
    endif

    set TmpPath   = $(!SNARootDir)"\"$(!SNABinDir)"\"$(ImagePath)
    set ImagePath = $(TmpPath)

  endif

;
; Set UI name for SNA Server.  (Only used on NT builds >340)
;
  ifstr(i) $(ServiceName) == "SnaServr"
    set UiName = "SnaServer"
  else
    set UiName = $(ServiceName)
  endif

;
; All services depend on SnaBase.
;
; ; Old NAP type:
; ; -------------
; ifint $(SNAServiceTypeDword) == #( SNAServiceTypes, "CESRANET", 1 )
;   set OtherDepends = { "" }

  ifcontains(i) $(SNAServiceTypeDword) in $(NapTypeList)
    set OtherDepends = { "" }
  else-ifint $(SNAServiceTypeDword) == #( SNAServiceTypes, "DRIVER", 1 )
    set OtherDepends = { "" }
  else-ifcontains $(SNAServiceTypeDword) in $(LinkTypeList)
    set OtherDepends = { "" }
  else
    set OtherDepends = { "SnaBase" }
  endif

  set !NCPA_HANDLE = ""
  install LoadNCPALibrary
  ifstr(i) $(!NCPA_HANDLE) == ""
    goto EndCreateSNAService
  endif

  ifstr(i) $(_DLC_) == YES
    set SNAGroup = "TDI"
    set DependList = { "NDIS" }
  endif

  ifint $(!STF_NTBUILDNUM) <= 340
    shell $(!STF_WINDOWSSYSPATH)\UTILITY.INF CreateService +
          $(ServiceName) $(ImagePath) $(CreateServiceDesc) +
          $(SNAGroup) $(DependList) $(SNAUser) $(EventLogFile) +
          $(EventTypes) $(EventLogLocal)
  else
    shell $(!STF_WINDOWSSYSPATH)\UTILITY.INF CreateService +
          $(ServiceName) $(UiName) $(ImagePath) $(CreateServiceDesc) +
          $(SNAGroup) $(DependList) $(SNAUser) $(EventLogFile) +
          $(EventTypes) $(EventLogLocal)
  endif

  set ServiceNameKey        = $($R1)
  set ServiceNameParamKey   = $($R2)
  set ServiceNameLinkageKey = $($R3)

  install FreeNCPALibrary


SetSNAStuff =+
  set Status = STATUS_SUCCESSFUL

;
; If CreateService returned error 1073 (service already exists), as
; it will in the case when the user has accidentally or purposely
; deleted the service's registry keys, then it hasn't recreated the
; missing keys.  We'll now attempt to create them.
;

  ifstr(i) $(ServiceNameKey) == $(KeyNull)

    shell "" GetServiceBaseKey
    ifstr(i) $($R0) == STATUS_FAILED
      set Status = $($R0)
      goto EndCreateSNAService
    endif

    set ServiceBaseKey = $($R1)

    OpenRegKey $(ServiceBaseKey) "" $(ServiceName) +
               $(MAXIMUM_ALLOWED) ServiceNameKey

    ifstr(i) $(ServiceNameKey) == $(KeyNull)
      CreateRegKey $(ServiceBaseKey) +
                   {$(ServiceName),$(NoTitle),$(GenericClass)} +
                   "" $(MAXIMUM_ALLOWED) "" ServiceNameKey

      ifstr(i) $(ServiceNameKey) == $(KeyNull)
        set Status = STATUS_FAILED
        CloseRegKey $(ServiceBaseKey)
        goto EndCreateSNAService
      endif
    endif

    CloseRegKey $(ServiceBaseKey)

    ForListDo {"Linkage","Parameters"}

      OpenRegKey $(ServiceNameKey) "" $($) +
                 $(MAXIMUM_ALLOWED) TmpKey

      ifstr(i) $(TmpKey) == $(KeyNull)
        CreateRegKey $(ServiceNameKey) +
                     {$($),$(NoTitle),$(GenericClass)} +
                     "" $(MAXIMUM_ALLOWED) "" TmpKey

        ifstr(i) $(TmpKey) == $(KeyNull)
          set Status = STATUS_FAILED
          goto EndCreateSNAService
        endif
      endif

      ifstr(i) $($) == "Linkage"
        CloseRegKey $(TmpKey)
      else-ifstr(i) $($) == "Parameters"
        set ServiceNameParamKey = $(TmpKey)
      endif

    EndForListDo

  endif

;
; Since the CreateService wrapper function in nt\system\utility.inf only
; supports creation of a type 16 service with start type 3, and the NAP
; needs start type 2, we'll tweak the "Start" value in the registry if
; we're just now installing the NAP.
;
; Old NAP type:
; -------------
; ifint $(SNAServiceTypeDword) == #( SNAServiceTypes, "CESRANET", 1 )
;   SetRegValue $(ServiceNameKey) { "Start", $(NoTitle), $(!REG_VT_DWORD), 2 }

  ifcontains $(SNAServiceTypeDword) in $(NapTypeList)
    SetRegValue $(ServiceNameKey) { "Start", $(NoTitle), $(!REG_VT_DWORD), 2 }
  endif

;
; Add the "OtherDependencies" value under the Linkage key.
;
  ifstr(i) $(ServiceNameLinkageKey) != $(KeyNull)
    SetRegValue $(ServiceNameLinkageKey)  +
      { "OtherDependencies",  $(NoTitle), +
        $(!REG_VT_MULTI_SZ), $(OtherDepends) }
  endif

;
; Set up values under the Parameters key.
;
  set ParamsToAdd = {}
  ifstr(i) $(ServiceNameParamKey) != ""
    ifstr(i) $(SNAServiceType) != ""
      set ParamsToAdd = { +
        { "SNAServiceType", $(NoTitle), $(!REG_VT_DWORD), $(SNAServiceTypeDword) } +
                        }
    endif

    ifint $(SNAServiceTypeDword) == #( SNAServiceTypes, "CESQTP", 1 )
      set ParamsToAdd = >( $(ParamsToAdd), +
          { "CmdLineOptions", $(NoTitle), $(!REG_VT_SZ), "" } )
    endif

    ifint $(SNAServiceTypeDword) == #( SNAServiceTypes, "NVALERT", 1 )
      ForListDo $(NVAlertParams)
        set ParamsToAdd = >( $(ParamsToAdd), $($) )
      EndForListDo
    endif

    ifint $(SNAServiceTypeDword) == #( SNAServiceTypes, "NVRUNCMD", 1 )
      ForListDo $(NVRunParams)
        set ParamsToAdd = >( $(ParamsToAdd), $($) )
      EndForListDo
    endif

    ;
    ; Add tracing params
    ;
    set SNATraceParams = {}

; Old NAP type:
; -------------
;   ifint $(SNAServiceTypeDword) == #( SNAServiceTypes, "CESRANET", 1 )  ; Nap
;     set SNATraceParams = $(NapTraceParams)

    ifcontains(i) $(SNAServiceTypeDword) in $(NapTypeList)
      set SNATraceParams = $(NapTraceParams)
    else-ifint $(SNAServiceTypeDword) == #( SNAServiceTypes, "CES21", 1 )  ; Node
      set SNATraceParams = $(NodeTraceParams)
    else-ifcontains $(SNAServiceTypeDword) in $(LinkTypeList)
      set SNATraceParams = $(LinkTraceParams)
    endif

    ifstr(i) $(SNATraceParams) != {}
      ForListDo $(SNATraceParams)
        set ParamsToAdd = >( $(ParamsToAdd), $($) )
      EndForListDo
    endif

    ifstr(i) $(ParamList) != {}  ; Absorb caller-supplied parameters
      ForListDo $(ParamList)
        set ParamsToAdd = >( $(ParamsToAdd), $($) )
      EndForListDo
    endif

    shell "" AddValueList $(ServiceNameParamKey) $(ParamsToAdd)
  endif


  ;
  ; If we're creating the NAP (SnaBase), add a "Client" key underneath
  ; the "Parameters" key, which will contain its own tracing parameters.
  ;

  ; Old NAP type:
  ; -------------
  ; ifint $(SNAServiceTypeDword) == #( SNAServiceTypes, "CESRANET", 1 )
  ;   OpenRegKey $(ServiceNameParamKey) "" "Client" +
  ;              $(MAXIMUM_ALLOWED) ServiceNameClientKey

  ifcontains(i) $(SNAServiceTypeDword) in $(NapTypeList)
    OpenRegKey $(ServiceNameParamKey) "" "Client" +
               $(MAXIMUM_ALLOWED) ServiceNameClientKey

    ifstr(i) $(ServiceNameClientKey) == $(KeyNull)
      CreateRegKey $(ServiceNameParamKey) +
                   {"Client",$(NoTitle),$(GenericClass)} +
                   "" $(MAXIMUM_ALLOWED) "" ServiceNameClientKey
    endif
  endif

  set ParamsToAdd = {}
  ifstr(i) $(ClientTraceParams) != {}
    ForListDo $(ClientTraceParams)
      set ParamsToAdd = >( $(ParamsToAdd), $($) )
    EndForListDo
  endif

  shell "" AddValueList $(ServiceNameClientKey) $(ParamsToAdd)

  CloseRegKey $(ServiceNameClientKey)

;
; Create the ExtraParameters sub-key.
;
  set ServiceNameExtraParamKey = $(KeyNull)
  ifstr(i) $(ServiceNameParamKey) != $(KeyNull)

    OpenRegKey $(ServiceNameParamKey) "" "ExtraParameters" +
               $(MAXIMUM_ALLOWED) ServiceNameExtraParamKey

    ifstr(i) $(ServiceNameExtraParamKey) == $(KeyNull)
      CreateRegKey $(ServiceNameParamKey) +
                   {"ExtraParameters",$(NoTitle),$(GenericClass)} +
                   "" $(MAXIMUM_ALLOWED) "" ServiceNameExtraParamKey
    endif
  endif

  ifstr(i) $(ServiceNameExtraParamKey) != $(KeyNull)
    shell "" AddValueList $(ServiceNameExtraParamKey) $(ExtraParamList)
  endif


;
; Create performance monitor stuff if we're a link service.
;
  ifcontains(i) $(SNAServiceTypeDword) in $(LinkTypeList)

    ;
    ; Enumerate language keys under SW\MS\W.NT\CV\Perflib, and use the first.
    ;
    set TmpLangId = "009"
    OpenRegKey $(!REG_H_LOCAL), "", +
               "Software\Microsoft\Windows NT\CurrentVersion\Perflib", +
               $(!REG_KEY_READ), KeyPerflib
    ifstr(i) $(KeyPerflib) != $(KeyNull)
      EnumRegKey $(KeyPerflib) PerfLangKeyList
      ifstr(i) $(PerfLangKeyList) != {}
        set TmpLangId = *( *($(PerfLangKeyList),1), 1 )
        set PerfLangKeyList = {}
      endif
      CloseRegKey $(KeyPerflib)
    endif

    shell "" AddLinkServicePerfCounters $(TmpLangId) $(ServiceName)

  endif

;
; That's about it for creating a service!
;
  set Status = STATUS_SUCCESSFUL

EndCreateSNAService =+
  EndWait
  return $(Status) $(ServiceNameKey) +
                   $(ServiceNameParamKey) +
                   $(ServiceNameExtraParamKey)


;-----------------------------------------------------------------------
; ROUTINE:      EnumerateDrivers
;
; DESCRIPTION:  Returns a list of .INF files representing drivers that
;               are avilable to be installed.
;
; ARGUMENTS:    $0   Alternate source directory (optional).
;
; RETURNS:      $R0  Status
;               $R1  List of .INF files
;
;------------------------------------------------------------------------
[TheseInfFiles]
  InfFileList = {} ? $(!LIBHANDLE) FindFileInstances $(SrcDir)"*.inf"

[EnumerateDrivers]
  set Status          = STATUS_SUCCESSFUL
  set OtherDriverList = {}

  set SrcDir = $(!STF_CWDDIR)
  ifstr(i) $($0) != ""
    set SrcDir = $($0)
  endif

  install LoadSetupLibrary

  detect TheseInfFiles

  ForListDo $(InfFileList)

    set InfName = $($)

    LibraryProcedure ItExists $(!LIBHANDLE) CheckFileExistance +
                     $(SrcDir)$(InfName)

    ifstr(i) $(ItExists) == "Yes"

      shell $(SrcDir)$(InfName) ReturnSNAOptions
      set Status   = $($R0)
      set NameList = $($R1)
      set TextList = $($R2)

      ifint $($ShellCode) != 0
        goto LoopEnd1
      endif

      ifstr(i) $(Status) != STATUS_SUCCESSFUL
        goto LoopEnd1
      endif

      ForListDo $(NameList)
        set OtherDriverList = >( $(OtherDriverList), +
                                 { *( $(TextList), $(#) ), +
                                   $(InfName), +
                                   $($) } )
      EndForListDo
    endif

LoopEnd1 =+
  EndForListDo

EndEnumerateDrivers =+
  install FreeSetupLibrary
  return $(Status) $(OtherDriverList)



;-----------------------------------------------------------------------
; ROUTINE:      EnumSNAServices
;
; DESCRIPTION:  Returns a list of the names of all installed SNA services.
;
; ARGUMENTS:    $0   Service type to enumerate, as a string (see
;                    [SNAServiceTypes])
;
; RETURNS:      $R0  Status
;               $R1  List of all service names which are SNA services, and
;                    match the type given (if any).  Each entry in this
;                    list has the form:
;
;                          { "Service Name",
;                            "Title",
;                            "Type",
;                            "INF File Name",
;                            "INF File Option" }
;
;                    where "Service Name" is the name of the service as it
;                    appears in the registry tree, "Title" is a more
;                    descriptive title as stored under the Parameters key,
;                    and Type is the Dword value of the SNAServiceType key.
;
;------------------------------------------------------------------------
[EnumSNAServices]
  read-syms "Registry Constants"

  shell "" GetServiceBaseKey
  ifstr(i) $($R0) == STATUS_FAILED
    return STATUS_FAILED $(KeyNull)
  endif

  set SvcBaseKey = $($R1)
  set SNASvcList = {}

  ifstr(i) $($0) != ""
    ifstr(i) $($0) != "Link"
      set DesiredSvcDword = #( SNAServiceTypes, $($0), 1 )
    endif
  endif

  EnumRegKey $(SvcBaseKey) SvcList

  ForListDo $(SvcList)

    set SNASvcName = *( $($), 1 )

    OpenRegKey $(SvcBaseKey) "" $(SNASvcName) $(MaskAllAccess) TmpNameKey

    ifstr(i) $(TmpNameKey) != $(KeyNull)
      OpenRegKey $(TmpNameKey) "" "Parameters" $(MaskAllAccess) TmpParamKey

      ifstr(i) $(TmpParamKey) != $(KeyNull)
        set SNASvcTypeValue = ""
        GetRegValue $(TmpParamKey) "SNAServiceType" SNASvcTypeValue

        ifstr(i) $(SNASvcTypeValue) != ""  ; It's an SNA service
          set SNASvcTypeDword = *( $(SNASvcTypeValue), 4 )

          GetRegValue $(TmpParamKey) "Title" SNATitleValue
          set SNASvcTitle = ""
          ifstr(i) $(SNATitleValue) != {}
            set SNASvcTitle = *( $(SNATitleValue), 4 )
          endif

          GetRegValue $(TmpParamKey) "InfName" SNAInfNameValue
          set SNASvcInfName = ""
          ifstr(i) $(SNAInfNameValue) != {}
            set SNASvcInfName = *( $(SNAInfNameValue), 4 )
          endif

          GetRegValue $(TmpParamKey) "InfOption" SNAInfOptionValue
          set SNASvcInfOption = ""
          ifstr(i) $(SNAInfOptionValue) != {}
            set SNASvcInfOption = *( $(SNAInfOptionValue), 4 )
          endif

          set NewElement = { $(SNASvcName), +
                             $(SNASvcTitle), +
                             $(SNASvcTypeDword), +
                             $(SNASvcInfName), +
                             $(SNASvcInfOption) }

          ifstr(i) $($0) == ""  ; Enumerate ALL the SNA services
            set SNASvcList = >( $(SNASvcList), $(NewElement) )
          else-ifstr(i) $($0) == "Link"  ; Only enumerate Link services
            ifcontains(i) $(SNASvcTypeDword) in $(LinkTypeList)
              set SNASvcList = >( $(SNASvcList), $(NewElement) )
            endif
          else-ifstr(i) $($0) != ""
            ifstr(i) $(SNASvcTypeDword) == $(DesiredSvcDword)
              set SNASvcList = >( $(SNASvcList), $(NewElement) )
            endif
          endif
        endif  ; It's an SNA service

        CloseRegKey $(TmpParamKey)
      endif  ; Parameters key was opened

      CloseRegKey $(TmpNameKey)
    endif  ; Name key was opened

  EndForListDo

  return STATUS_SUCCESSFUL $(SNASvcList)


;-----------------------------------------------------------------------
; ROUTINE:      FindSNAProductServices
;
; DESCRIPTION:  Enumerates the Services and indices of a particular SNA product.
;
; ARGUMENTS:    $0   Name of top-level registry node to use
;               $1   Product Name ("<name>_<version>_<instance>")
;
; RETURNS:      $R0  Status
;               $R1  List of service indices for Product Name
;               $R2  List of service names for Product Name
;               $R3  List of service titles for Product Name
;               $R4  List of service descriptions for Product Name
;
;------------------------------------------------------------------------
[FindSNAProductServices]
  read-syms "Registry Constants"
  set Status = STATUS_FAILED
  set ServiceIndexList = {}
  set ServiceNameList  = {}
  set ServiceTitleList = {}
  set ServiceDescList  = {}

  ifstr(i) $($0) == ""
    goto EndFindSNAProductServices
  else-ifstr(i) $($1) == ""
    goto EndFindSNAProductServices
  endif

  ;
  ; Open the top-level registry key ("Software\Microsoft").
  ;
  OpenRegKey $(!REG_H_LOCAL) "" $($0) $(MaskAllAccess) TopLevelKey
  ifstr(i) $(TopLevelKey) == $(KeyNull)
    goto EndFindSNAProductServices
  endif

  ;
  ; Break up the Product Name into its component parts.
  ;
  Split-String $($1) "_" TmpList
  QueryListSize TmpListSize $(TmpList)

  ifint $(TmpListSize) == 1
    set NameStr = *( $(TmpList), 1 )
  else-ifint $(TmpListSize) >= 3
    set NameStr = *( $(TmpList), 1 )"_"*( $(TmpList), 3 )
  endif

  ;
  ; NameStr now has "<name>" or "<name>_<version>".  Enumerate all keys under
  ; TopLevel and search for those whose name matches NameStr.
  ;
  EnumRegKey $(TopLevelKey) KeyListAll

  set KeyListOur = {}
  ForListDo $(KeyListAll)
    Split-String *( $($), 1 ) "_" TmpList
    QueryListSize TmpListSize $(TmpList)

    ifint $(TmpListSize) == 5
      set TestStr  = *( $(TmpList), 1 )"_"*( $(TmpList), 3 )
      set Instance = *( $(TmpList), 5 )

      ifstr(i) $(TestStr) == $(NameStr)
        set KeyListOur = >( $(KeyListOur), *($($),1) )
        set ServiceIndexList = >( $(ServiceIndexList), $(Instance) )
      endif
    endif
  EndForListDo

  ;
  ; Using the list of indices we just got, look for the "ServiceName",
  ; "Title", and "Description" key under each, and produce a list of
  ; all these service names.  The names should match up with the indices,
  ; so if we have an index with no service name, use "<null>".
  ;
  ForListDo $(KeyListOur)
    OpenRegKey $(TopLevelKey) "" $($)"\CurrentVersion" $(MaskAllAccess) TmpIndexKey
    ifstr(i) $(TmpIndexKey) == ""
      set ServiceNameList  = >( $(ServiceNameList), "<null>" )
      set ServiceTitleList = >( $(ServiceTitleList), "<null>" )
      set ServiceDescList  = >( $(ServiceDescList), "<null>" )
    else
      GetRegValue $(TmpIndexKey) "ServiceName" ServiceNameValue
      ifstr(i) $(ServiceNameValue) == ""
        set ServiceNameList = >( $(ServiceNameList), "<null>" )
      else
        set ServiceNameList = >( $(ServiceNameList), *($(ServiceNameValue),4) )
      endif
      GetRegValue $(TmpIndexKey) "Title" ServiceTitleValue
      ifstr(i) $(ServiceTitleValue) == ""
        set ServiceTitleList = >( $(ServiceTitleList), "<null>" )
      else
        set ServiceTitleList = >( $(ServiceTitleList),*($(ServiceTitleValue),4))
      endif
      GetRegValue $(TmpIndexKey) "Description" ServiceDescValue
      ifstr(i) $(ServiceDescValue) == ""
        set ServiceDescList = >( $(ServiceDescList), "<null>" )
      else
        set ServiceDescList = >( $(ServiceDescList), *($(ServiceDescValue),4) )
      endif
    endif
    CloseRegKey $(TmpIndexKey)
  EndForListDo

  CloseRegKey $(ProductNameKey)
  CloseRegKey $(TopLevelKey)

  QueryListSize TmpListSize $(KeyListOur)

  ifint $(TmpListSize) == 0
    set Status = STATUS_NOSUCHPRODUCT
  else
    set Status = STATUS_SUCCESSFUL
  endif

EndFindSNAProductServices =+
  return $(Status) $(ServiceIndexList), +
                   $(ServiceNameList), +
                   $(ServiceTitleList), +
                   $(ServiceDescList)


;------------------------------------------------------------------------
; ROUTINE:      FindSNARegEntry
;
; DESCRIPTION:  Finds the top-level registry entry for the given
;               product name, and returns handles as described below.
;
; ARGUMENTS:    $0   Name of top-level registry node to use
;               $1   Product Name ("<name>_<version>_<instance>")
;
; RETURNS:      $R0  Status
;               $R1  Handle to top-level node
;               $R2  Handle to Product Name sub-key
;               $R3  Handle to "CurrentVersion" sub-sub-key
;               $R4  Handle to NetRules sub-sub-sub-key
;
;------------------------------------------------------------------------
[FindSNARegEntry]
  read-syms "Registry Constants"
  set Status = STATUS_FAILED

  set TopLevelKey       = $(KeyNull)
  set ProductNameKey    = $(KeyNull)
  set ServiceIndexKey   = $(KeyNull)
  set NetRulesKey       = $(KeyNull)

  ifstr(i) $($0) == ""
    goto EndFindSNARegEntry
  else-ifstr(i) $($1) == ""
    goto EndFindSNARegEntry
  endif

;
; Open top-level key.
;
  OpenRegKey $(!REG_H_LOCAL) "" $($0) $(MaskAllAccess) TopLevelKey
  ifstr(i) $(TopLevelKey) == $(KeyNull)
    goto EndFindSNARegEntry
  endif

;
; Get the "Product Name" key if it exists.
;
  OpenRegKey $(TopLevelKey) "" $($1) $(MaskAllAccess) ProductNameKey
  ifstr(i) $(ProductNameKey) == $(KeyNull)
    CloseRegKey $(TopLevelKey)
    set TopLevelKey = $(KeyNull)
    goto EndFindSNARegEntry
  endif

;
; Get the "CurrentVersion" key if it exists.
;
  OpenRegKey $(ProductNameKey) "" "CurrentVersion" $(MaskAllAccess) ServiceIndexKey
  ifstr(i) $(ServiceIndexKey) == $(KeyNull)
    CloseRegKey $(ProductNameKey)
    CloseRegKey $(TopLevelKey)
    set ProductNameKey = $(KeyNull)
    set TopLevelKey    = $(KeyNull)
    goto EndFindSNARegEntry
  endif

;
; Get the NetRules key if it exists.
;
  OpenRegKey $(ServiceIndexKey) "" "NetRules" $(MaskAllAccess) NetRulesKey
  ifstr(i) $(NetRulesKey) == $(KeyNull)
    CloseRegKey $(ServiceIndexKey)
    CloseRegKey $(ProductNameKey)
    CloseRegKey $(TopLevelKey)
    set ServiceIndexKey = $(KeyNull)
    set ProductNameKey    = $(KeyNull)
    set TopLevelKey       = $(KeyNull)
    goto EndFindSNARegEntry
  endif

  set Status = STATUS_SUCCESSFUL

EndFindSNARegEntry =+
  return $(Status) $(TopLevelKey) +
                   $(ProductNameKey) +
                   $(ServiceIndexKey) +
                   $(NetRulesKey)


;-----------------------------------------------------------------------
; ROUTINE:      FindSNAService
;
; DESCRIPTION:  Returns open key handles to an SNA Service, its
;               Parameters key, and its ExtraParameters key.
;
; ARGUMENTS:    $0   Service name
;
; RETURNS:      $R0  Status
;               $R1  Handle to <Service name>
;               $R2  Handle to <Service name>\Parameters
;               $R3  Handle to <Service name>\Parameters\ExtraParameters
;
;------------------------------------------------------------------------
[FindSNAService]
  read-syms "Registry Constants"
  set Status = STATUS_FAILED

  set ServiceNameKey           = $(KeyNull)
  set ServiceNameParamKey      = $(KeyNull)
  set ServiceNameExtraParamKey = $(KeyNull)

  shell "" GetServiceBaseKey
  ifstr(i) $($R0) == STATUS_FAILED
    goto EndFindSNAService
  endif

  set ServiceBaseKey = $($R1)

  OpenRegKey $(ServiceBaseKey) "" $($0) $(MaskAllAccess) ServiceNameKey
  ifstr(i) $(ServiceNameKey) == $(KeyNull)
    CloseRegKey $(ServiceBaseKey)
    goto EndFindSNAService
  endif

  CloseRegKey $(ServiceBaseKey)
  set Status = STATUS_SUCCESSFUL

  OpenRegKey $(ServiceNameKey) "" "Parameters" +
             $(MaskAllAccess) ServiceNameParamKey
  ifstr(i) $(ServiceNameParamKey) == $(KeyNull)
    goto EndFindSNAService
  endif

  OpenRegKey $(ServiceNameParamKey) "" "ExtraParameters" +
             $(MaskAllAccess) ServiceNameExtraParamKey

EndFindSNAService =+
  return $(Status) $(ServiceNameKey) +
                   $(ServiceNameParamKey) +
                   $(ServiceNameExtraParamKey)


;-----------------------------------------------------------------------
; ROUTINE:      GetBusType
;
; DESCRIPTION:  Returns a string indicating which type of bus this
;		machine has:  ISA, EISA, or MCA
;
; ARGUMENTS:    None
;
; RETURNS:      $R0  Status
;               $R1  Bus type string
;
;-----------------------------------------------------------------------
[GetBusType]
  set Status = STATUS_SUCCESSFUL
  OpenRegKey $(!REG_H_LOCAL), "", +
             "HARDWARE\DESCRIPTION\System\EisaAdapter\0", +
             $(!REG_KEY_READ), KeyEisa

  ifstr(i) $(KeyEisa) != $(!KeyNull)
    GetRegValue $(KeyEisa) "Identifier" IDValue
    ifstr(i) $(IDValue) != {}
      set ID = *( $(IDValue), 4 )
    endif
    CloseRegKey $(KeyEisa)

  else
    OpenRegKey $(!REG_H_LOCAL), "", +
             "HARDWARE\DESCRIPTION\System\MultifunctionAdapter\0", +
             $(!REG_KEY_READ), KeyMFA
    ifstr(i) $(KeyMFA) != $(!KeyNull)
      GetRegValue $(KeyMFA) "Identifier" IDValue
      ifstr(i) $(IDValue) != {}
        set ID = *( $(IDValue), 4 )
      endif
      CloseRegKey $(KeyMFA)

    else
      set ID = "ISA"

    endif
  endif

  return $(Status) $(ID)


;-----------------------------------------------------------------------
; ROUTINE:      GetServiceBaseKey
;
; DESCRIPTION:  Returns an open key handle to the top of the services tree.
;
; ARGUMENTS:    None
;
; RETURNS:      $R0  Status
;               $R1  Handle to services tree in registry
;
;------------------------------------------------------------------------
[GetServiceBaseKey]
  read-syms "Registry Constants"

  set Status = STATUS_SUCCESSFUL
  set BS_KeyServices = $(KeyNull)

  OpenRegKey $(!REG_H_LOCAL) "" $(ServicesBaseName) +
             $(MAXIMUM_ALLOWED) BS_KeyServices

  ifstr(i) $(BS_KeyServices) == $(KeyNull)
    set Status = STATUS_FAILED
  endif

  return $(Status), $(BS_KeyServices)


;-----------------------------------------------------------------------
; ROUTINE:      CreateKey
;
; DESCRIPTION:  Creates a key and fixes the values indicated.
;               Key is Handle\Key1\Key2\...\Keyn. Value list
;               is for Valuen.
;
; ARGUMENTS:    $0: Handle into registry
;               $1: KeyTreeComponents {Key1Info, Key2Info..}
;               $2: ValueList {Value1Info, Value2Info, Value3Info}
;
; RETURNS:      $R0: Status: STATUS_SUCCESSFUL
;                            STATUS_FAILED
;                            STATUS_ERROR_CREATEKEY
;                            STATUS_ERROR_CREATEVALUE
;
;               $R1: Handle to created key
;
;------------------------------------------------------------------------
[CreateKey]
  read-syms "Registry Constants"
  set Status = STATUS_FAILED

  ;
  ; traverse down the keytreecomponents and open/create components as
  ; you go along
  ;

  set BaseHandle = $($0)
  set KeyHandle  = $(BaseHandle)

  ForListDo $($1)

    set KeyInfo = $($)
    set KeyName = *($(KeyInfo), 1)

    ;
    ; Try opening the key first

    OpenRegKey $(BaseHandle) "" $(KeyName) $(MaskAllAccess) KeyHandle
    ifint $(RegLastError) != $(!REG_ERROR_SUCCESS)
      ;
      ; Key doesn't exist
      ;
      set RegLastError = 0
      CreateRegKey $(BaseHandle) $(KeyInfo) "" $(MaskAllAccess) "" KeyHandle
      ifint $(RegLastError) != $(!REG_ERROR_SUCCESS)
        set Status = STATUS_ERROR_CREATEKEY
        goto endcreate
      endif
    endif

    ifstr(i) $(BaseHandle) != $($0)
      CloseRegKey $(BaseHandle)
      ifint $(RegLastError) != $(!REG_ERROR_SUCCESS)
        set Status = STATUS_ERROR_CREATEKEY
        goto endcreate
      endif
    endif

    set BaseHandle = $(KeyHandle)

  EndForListDo

  ifstr(i) $($2) != {}
    shell "" AddValueList $(KeyHandle) $($2)
    ifstr(i) $($R0) != STATUS_SUCCESSFUL
      set Status = STATUS_ERROR_CREATEVALUE
      goto endcreate
    endif
  endif

  set Status = STATUS_SUCCESSFUL

endcreate =+
  return $(Status) $(KeyHandle)


;------------------------------------------------------------------------
; ROUTINE:      GetServiceKey
;
; DESCRIPTION:  Returns an open handle into the services tree, creating
;                an entry for the service name if caller so desires.
;
; ARGUMENTS:    $0    Service name
;               $1    CREATE: create if not found; NOCREATE = don't
;
; RETURNS:      $R0   Status
;               $R1   Key handle into registry at $($0), or null
;               $R2   CREATE if key was created; NOCREATE if it wasn't
;
;------------------------------------------------------------------------
[GetServiceKey]
  read-syms "Registry Constants"

;
; Get a key into the Services tree in the registry.
;
  shell "" GetServiceBaseKey

  ifstr(i) $($R0) == STATUS_FAILED
    return STATUS_FAILED $(KeyNull)
  endif

  set ServiceBaseKey = $($R1)

;
; Attempt to get a key for the service we want to add; if we get one,
; the service exists and we can pass back the handle.
;
  OpenRegKey $(ServiceBaseKey) "" $($0) +
             $(MaskAllAccess) ServiceNameKey

  ifint $(RegLastError) == $(!REG_ERROR_SUCCESS)
    return STATUS_SUCCESSFUL $(ServiceNameKey) NOCREATE
  endif

;
; We didn't get a key, and caller doesn't want to create the entry.
;
  ifstr(i) $($1) != CREATE
    CloseRegKey $(ServiceBaseKey)
    return STATUS_FAILED $(KeyNull) NOCREATE
  endif


  CreateRegKey $(ServiceBaseKey) { $($0),$(NoTitle),$(MaskAllAccess) } +
               "" $(MaskAllAccess) "" ServiceNameKey

  ifint $(RegLastError) == $(!REG_ERROR_SUCCESS)
    CloseRegKey $(ServiceBaseKey)
    return STATUS_SUCCESSFUL $(ServiceNameKey) CREATE
  endif

  CloseRegKey $(ServicesBaseKey)
  return STATUS_FAILED $(KeyNull) NOCREATE


;------------------------------------------------------------------------
; ROUTINE:      AddValueList
;
; DESCRIPTION:  Given a nested list of value items, add each to the given
;               key.   Key is left open.
;
; ARGUMENTS:    $0    Registry key handle
;               $1    List of value items; for example:
;                        { {ValueName1,0,$(!REG_VT_SZ),$(ValueData1)}, +
;                          {ValueName2,0,$(!REG_VT_SZ),$(ValueData2)} }
;
; RETURNS:      $R0   Status
;
;------------------------------------------------------------------------
[AddValueList]
  read-syms "Registry Constants"

  ForListDo $($1)
    SetRegValue $($0) $($)
    ifint $(RegLastError) != $(!REG_ERROR_SUCCESS)
      return STATUS_FAILED
    endif
  EndForListDo

  return STATUS_SUCCESSFUL


;------------------------------------------------------------------------
; ROUTINE:      FindRootDir
;
; DESCRIPTION:  Looks for the SNA Server root directory in the registry
;               at $(SetupRegKeyName).
;
; ARGUMENTS:    None
;
; RETURNS:      $R0  Status
;               $R1  Directory name if found, or "" if not
;               $R2  "Server" or "Client"
;
;------------------------------------------------------------------------
[FindRootDir]
  read-syms "Registry Constants"
  set KeyName = $(SetupRegKeyName)
  set RootDirName = ""
  set SetupMode   = ""

  OpenRegKey $(!REG_H_LOCAL) "" $(KeyName) $(!REG_KEY_READ) KeyHandle

  ifint $(RegLastError) == $(!REG_ERROR_SUCCESS)

    GetRegValue $(KeyHandle) "RootDir" RootDirRegEntry
    ifint $(RegLastError) == $(!REG_ERROR_SUCCESS)
      set RootDirName = *( $(RootDirRegEntry), 4 )
    endif

    GetRegValue $(KeyHandle) "SetupMode" SetupModeRegEntry
    ifint $(RegLastError) == $(!REG_ERROR_SUCCESS)
      set SetupMode = *( $(SetupModeRegEntry), 4 )
    endif

    CloseRegKey $(KeyHandle)
  endif

  ifstr(i) $(RootDirName) != ""
    ifstr(i) $(SetupMode) != ""
      return STATUS_SUCCESSFUL $(RootDirName) $(SetupMode)
    endif
  endif

  return STATUS_FAILED "" ""


;------------------------------------------------------------------------
; SECTION:      UpdateRootDir
;
; DESCRIPTION:  Sets $(SetupRegKeyName)\RootDir to the name of the SNA
;               Server root directory.
;
; ARGUMENTS:    $0   Directory name
;               $1   Setup mode ("Server" or "Client")
;
; RETURNS:      $R0  Status
;
;------------------------------------------------------------------------
[UpdateRootDir]
  read-syms "Registry Constants"

  set TmpKeyVals = *( $(SetupRegKeyValues), 1 )
  set KeyVals    = { >($(TmpKeyVals), $($0)) }
  set TmpKeyVals = *( $(SetupRegKeyValues), 2 )
  set KeyVals    = >( $(KeyVals), >( $(TmpKeyVals), $($1) ))

  shell "" CreateKey $(!REG_H_LOCAL) $(SetupRegKeyPath) $(KeyVals)
  ifint $($ShellCode) != 0
    return STATUS_FAILED
  endif
  ifint $($R0) != STATUS_SUCCESSFUL
    return $($R0)
  endif

  CloseRegKey $($R1)
  return STATUS_SUCCESSFUL


;------------------------------------------------------------------------
; SECTION:      StartService
;
; DESCRIPTION:  Calls the StartService wrapper function in the NCPA
;               to start the given service.
;
; ARGUMENTS:    $0   Service name
;
; RETURNS:      $R0  Status
;
;
;------------------------------------------------------------------------
[StartService]
  set Status = STATUS_SUCCESSFUL

  ifstr(i) $($0) == ""
    return STATUS_FAILED
  endif

  install LoadNCPALibrary

  LibraryProcedure StartResult, $(!NCPA_HANDLE), CPlSetup, $(!STF_HWND), +
                   STARTSVC, $($0)

  install FreeNCPALibrary
  return $(Status)


;------------------------------------------------------------------------
; SECTION:      SnapTheNAP
;
; DESCRIPTION:  Signals the NAP that a) some service has been added or
;               changed, or b) that it should terminate itself and all
;               other components as well.
;
; ARGUMENTS:    $0   NOTIFY or TERMINATE
;
; RETURNS:      $R0  Status
;
;------------------------------------------------------------------------
[LoadNapLibrary]
  LoadLibrary "Path to SNAUPDAT.DLL" $(!SNARootDir)"\"$(!SNABinDir)"\SNAUPDAT.DLL" !NAPHANDLE
  exit

[FreeNapLibrary]
  FreeLibrary $(!NAPHANDLE)
  exit

[SnapTheNAP]
; read-syms "Registry Constants"
  read-syms "File Constants"
  set Status = STATUS_SUCCESSFUL

  ifstr(i) $($0) == ""
    set Action = "NOTIFY"
  else
    set Action = $($0)
  endif

  set !NAPHANDLE = ""
  install LoadNapLibrary

  ifstr(i) $(!NAPHANDLE) == ""
    set Status = STATUS_FAILED
    goto EndSnapTheNap
  endif

  StartWait

  set FLibraryErrCtl = 1

  ifstr(i) $(Action) == "NOTIFY"
    LibraryProcedure Result $(!NAPHANDLE) UpdateSNAServices
  else-ifstr(i) $(Action) == "TERMINATE"
    LibraryProcedure Result $(!NAPHANDLE) TerminateSNAServices
  else-ifstr(i) $(Action) == "FORCE"
    LibraryProcedure Result $(!NAPHANDLE) TerminateSNAServices Force
  endif

  EndWait

  ifstr(i) $(Result) == "RUNNING"
    set Status = STATUS_RUNNING
  endif

EndSnapTheNap =+
  install FreeNapLibrary
  return $(Status)


;------------------------------------------------------------------------
; SECTION:      ModifyPath
;
; DESCRIPTION:  Appends the directory name passed in $0 to the system's
;               search path for executables, as defined in the registry
;               in system\control\session manager\environment\path.
;
; ARGUMENTS:    $0   Action ( ADD | DELETE )
;               $1   Directory to be acted upon
;
; RETURNS:      $R0  Status
;
;------------------------------------------------------------------------
[ModifyPath]
  read-syms "Registry Constants"
  set Status = STATUS_FAILED

  ifstr(i) $($0) == ""
    goto EndModifyPath
  else-ifstr(i) $($1) == ""
    goto EndModifyPath
  endif

  set Action = $($0)
  set Dir    = $($1)

  OpenRegKey $(!REG_H_LOCAL) "" $(PathRegKeyName) $(MaskAllAccess) EnvKey
  ifstr(i) $(EnvKey) == $(KeyNull)
    goto EndModifyPath
  endif

  GetRegValue $(EnvKey) "Path" PathValue
  ifstr(i) $(PathValue) == $(KeyNull)
    CloseRegKey $(EnvKey)
    goto EndModifyPath
  endif

  set PathString    = *( $(PathValue), 4 )
  set FoundFlag     = $(!False)
  set Modify        = $(!False)
  set NewPathString = ""

  Split-String $(PathString) ";" PathDirList
  QueryListSize LastItem $(PathDirList)

  ForListDo $(PathDirList)
    ifstr(i) $($) != ";"
      ifstr(i) $($) == $(Dir)
        set FoundFlag = $(!True)
      else
        set NewPathString = $(NewPathString)$($)";"
      endif
    endif
  EndForListDo

  ifstr(i) $(FoundFlag) == $(!True)
    ifstr(i) $(Action) == "Delete"
      set Modify = $(!True)
    endif
  else
    ifstr(i) $(Action) == "Add"
      set NewPathString = $(NewPathString)$(Dir)
      set Modify = $(!True)
    endif
  endif

  ifstr(i) $(Modify) == $(!True)
    SetRegValue $(EnvKey) { "Path", $(NoTitle), $(!REG_VT_EXPAND_SZ), $(NewPathString) }

    install LoadSetupLibrary
    ifstr(i) $(!LIBHANDLE) != ""
      LibraryProcedure Result, $(!LIBHANDLE), SetEnvVar, SYSTEM, +
                       "Path", $(NoTitle), $(!REG_VT_EXPAND_SZ), $(NewPathString)

      install FreeSetupLibrary
    endif
  endif

  set Status = STATUS_SUCCESSFUL
  CloseRegKey $(EnvKey)

EndModifyPath =+
  return $(Status)

;-----------------------------------------------------------------------
;
; FindNextAvailableIndex
;
; DESCRIPTION:  Find the next available instance value for a product's service.
;               All indices are between "01" and "32".
;
; INPUT:        $($0) : List of instances currently in use
;
; OUTPUT:       $($R0): STATUS
;               $($R1): Next Available Index
;
;-----------------------------------------------------------------------

[FindNextAvailableIndex]

    set BaseList = { "01", "02", "03", "04", "05", "06", "07", "08", +
                     "09", "10", "11", "12", "13", "14", "15", "16", +
                     "17", "18", "19", "20", "21", "22", "23", "24", +
                     "25", "26", "27", "28", "29", "30", "31", "32" }

    set TRUE  = 1
    set FALSE = 0
    set Done  = $(FALSE)

    set IndexList = $($0)

    ForListDo $(BaseList)
        ifint $(Done) == $(FALSE)
            ifcontains(i) $($) not-in $(IndexList)
                set Done = $(TRUE)
                set NextIndex = $($)
            endif
        endif
    EndForListDo

    ifint $(Done) == $(TRUE)
        set Status = STATUS_SUCCESSFUL
    else
        set Status = STATUS_FAILED
    endif

    return $(Status) $(NextIndex)

;-----------------------------------------------------------------------
;
; GrepUniqueServiceInfo
;
; DESCRIPTION:  Search the list of information for all services for one
;               keyword and return all the information about that service.
;
; INPUT:        $($0) : Key Type ( "Index" | "Name" | "Title" | "Desc" )
;               $($1) : Keyword
;               $($2) : Service Index List
;               $($3) : Service Name List
;               $($4) : Service Title List
;               $($5) : Service Description List
;
; OUTPUT:       $($R0): STATUS
;               $($R1): Service Index
;               $($R2): Service Name
;               $($R3): Service Title
;               $($R4): Service Description
;
;-----------------------------------------------------------------------

[GrepUniqueServiceInfo]

    set KeyType = $($0)
    set KeyWord = $($1)

    set SvcIndexList = $($2)
    set SvcNameList  = $($3)
    set SvcTitleList = $($4)
    set SvcDescList  = $($5)

    ifstr(i)      $(KeyType) == "Index"
        set SearchList = $(SvcIndexList)
    else-ifstr(i) $(KeyType) == "Name"
        set SearchList = $(SvcNameList)
    else-ifstr(i) $(KeyType) == "Title"
        set SearchList = $(SvcTitleList)
    else                     ;; "Desc"
        set SearchList = $(SvcDescList)
    endif

    set Done = 0
    ForListDo $(SearchList)
        ifint $(Done) == 0
            ifstr(i) $($) == $(KeyWord)
                set Val = $(#)
                set Done = 1
            endif
        endif
    EndForListDo

    ifint $(Done) == 0
        set Status = STATUS_FAILED
        set ServiceIndex = ""
        set ServiceName  = ""
        set ServiceTitle = ""
        set ServiceDesc  = ""
    else
        set Status = STATUS_SUCCESSFUL
        set ServiceIndex = *( $(SvcIndexList), $(Val) )
        set ServiceName  = *( $(SvcNameList) , $(Val) )
        set ServiceTitle = *( $(SvcTitleList), $(Val) )
        set ServiceDesc  = *( $(SvcDescList) , $(Val) )
    endif

    return $(Status) $(ServiceIndex),+
                     $(ServiceName),+
                     $(ServiceTitle),+
                     $(ServiceDesc)

;-----------------------------------------------------------------------
;
; EnterServiceName
;
; DESCRIPTION:  Query the user for a unique eight letter service name.
;
; INPUT:        $($1) : Product Title
;		$($2) : Default 7 Letter Service Name
;		$($3) : Service Index
;
; OUTPUT:       $($R0): STATUS
;               $($R1): Service Name
;
; NOTES:        At some future point in time we should ensure uniqueness
;               We should also find a good way of ensuring 8 chars
;
;-----------------------------------------------------------------------

[EnterServiceName]

    set LanguageList = ^(LanguagesSupported, 1)
    ifcontains(i) $(!STF_LANGUAGE) in $(LanguageList)
        set Status = STATUS_SUCCESSFUL
    else
        set Status = STATUS_NOLANGUAGE
        goto finished
    endif

    ;
    ; These three values are currently hardwired and should be double
    ; checked against those in setup.inf.  However, at this point
    ; in time I don't want to something cute like put these values
    ; in the setup key of the SNA Server product key.  (The only
    ; way INFs can access this info if called from the NCPA.)
    ;
    SetHelpFile $(!SNARootDir)"\SETUP.HLP" "100" "124"
	
    set ProductTitle  = $($0)
    set ServicePrefix = $($1)
    set ServiceIndex  = $($2)

    set SuffixList = { +
            "1","2","3","4","5","6","7","8","9","A","B","C","D","E","F",+
            "G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U" +
		     }

    set ServiceSuffix = *( $(SuffixList), $(ServiceIndex) )
    set RetName = $(ServicePrefix)$(ServiceSuffix)

    goto finished

;;  read-syms EnterServiceNameDLG
;;  read-syms EnterServiceName$(!STF_LANGUAGE)
;;
;;  ui start $(DlgTemplate) $(!DLGHANDLE)
;;
;;  ifstr(i) $(DLGEVENT) == "Exit"
;;      set Status = STATUS_USERCANCEL
;;      set RetName = ""
;;  else                      ;; "Continue"
;;      set Status = STATUS_SUCCESSFUL
;;      set RetName = *( $(EditTextOut) , 1 )
;;  endif
;;
;;  ui pop 1

finished = +
    return $(Status) $(RetName)

[EnterServiceNameDLG]
    DlgType         = "Edit"
    DlgTemplate     = "IDD_ENTERSERVICENAME"
    EditTextIn      = $(ServicePrefix)$(ServiceSuffix)
    EditTextLim     = 8
    HelpContext     = "106" ; see setup.inf for list of IDs

[EnterServiceNameENG]
    Caption	= "Enter Service Name"
    DlgText1	= "Please enter a service name for:"$(!LF)$(!LF)+
		   $(ProductTitle)"."
    EditLabel1	= "Service &Name:"
    Continue	= "&Continue"
    Back	= "&Back"
    Help	= "&Help"
    Exit	= "C&ancel"


;------------------------------------------------------------------------
; SECTION:      DeleteSNAService
;
; DESCRIPTION:  Deletes an SNA service.  (Duh!)  If the service to be
;               deleted is a link service, the appropriate IHV .INF
;               is shelled to.
;
;               The caller may pass an open handle to the Services tree,
;               as it's much faster when calling this routine many times
;               in succession.
;
;               If the global !NCPA_HANDLE is set, then this routine
;               will use it and not attempt to load the NCPA every time.
;               Note that [FreeNCPALibrary] must set the handle to NULL
;               after the library is freed.  Thus, the caller should
;               load and free the NCPA outside of the loop in which it
;               calls this routine.
;
; ARGUMENTS:    $0   Service name to delete
;               $1   Optional handle into the Services tree.
;
; RETURNS:      $R0  Status
;
;------------------------------------------------------------------------
[DeleteSNAService]
  read-syms "Registry Constants"
  set Status     = STATUS_FAILED

  set UnloadNCPA = $(!False)
  set FlushKey   = $(!False)

  ifstr(i) $($0) == ""
    return $(Status)
  endif

  ifstr(i) $($1) != $(KeyNull)
    set SvcHandle = $($1)
  else
    shell "" GetServiceBaseKey
    ifstr(i) $($R0) == STATUS_FAILED
      return $($R0)
    else
      set SvcHandle = $($R1)
      set FlushKey  = $(!True)
    endif
  endif

  ifstr(i) $(!NCPA_HANDLE) == ""
    install LoadNCPALibrary
    set UnloadNCPA = $(!True)
  endif

  set FLibraryErrCtl = 1

  LibraryProcedure DelResult, $(!NCPA_HANDLE), CPlSetup, $(!STF_HWND), DELETESVC, $($0)

; 10/2/92:  NT has gone beta, and this code is supposedly no longer needed.
;
; install LoadSvcLibrary
; ifstr(i) $(!SVCLIBHANDLE) != ""
;   LibraryProcedure DelResult $(!SVCLIBHANDLE) SNADeleteService $($0)
;   install FreeSvcLibrary
; endif

  set Status = STATUS_FAILED
  ifstr(i) $(DelResult) != ""
    ifstr(i) $(DelResult) != {}
      ifstr(i) *( $(DelResult), 1 ) == "0"
        set Status = STATUS_SUCCESSFUL
      endif
    endif
  endif

EndDeleteSNAService =+
  ifstr(i) $(UnloadNCPA) == $(!True)
    install FreeNCPALibrary
  endif

  ifstr(i) $(FlushKey) == $(!True)
    CloseRegKey $(SvcHandle)
  endif

  return $(Status)

;-----------------------------------------------------------------------
;
; SECTION:      RemoveFileList
;
; DESCRIPTION:  This procedure removes a list of files.
;               The files should be in full path format.
;
; INPUT:        $($0) : File List To Remove
;
; OUTPUT:       $($R0): Status
;
;-----------------------------------------------------------------------
[RemoveFileList]
    set FileList = $($0)
    set Status   = STATUS_SUCCESSFUL

    install LoadSetupLibrary

    ForListDo $(FileList)
        LibraryProcedure RemStatus, $(!LIBHANDLE), DelFile, $($)
        ifstr(i) $(RemStatus) == "FAILED"
            set Status = STATUS_FAILED
        endif
    EndForListDo

    install FreeSetupLibrary

    return $(Status)

;-----------------------------------------------------------------------
;
; SECTION:      RemoveDirTree
;
; DESCRIPTION:  This procedure removes a directory tree
;
; INPUT:        $($0) : Directory to be removed
;		$($1) : Notify State (Default: YES | NO)
;
; OUTPUT:       $($R0): Status
;
;-----------------------------------------------------------------------
[RemoveDirTree]
    install LoadSetupLibrary

    LibraryProcedure DelStatus, $(!LIBHANDLE), Delnode, $($0)

    install FreeSetupLibrary

    return STATUS_SUCCESSFUL


;*************************************************************************
;
;     SECTION:   CreateService
;                Hacked by Dan Frumin of SNA Service to work with the
;                SNA Services until Windows NT Beta 1.  The main change is to
;                make the "kernelauto" set of values be a:
;                     Type:  SERVICE_KERNEL_DRIVER
;                     Start: SERVICE_AUTO_START
;
;     PURPOSE:   Create the Services are entry for a new product
;
;   ARGUMENTS:   $0     Name of the service (no imbedded blanks, etc.)
;                $1     image path string
;                $2     type of service:
;                               system
;                               adapter
;                               driver
;                               transport
;                               service
;                               serviceshare
;                $3     group, if any or ""
;                $4     dependency **list**, if any or {}
;		 $5	ObjectName, usually ""
;
;
;     RETURNS:   $R0    Registry error code
;                $R1    Service area key handle
;                $R2    Parameters key handle
;                $R3    Linkage key handle
;
;  REFERENCES:   <list of global or parent variables referenced>
;
;    MODIFIES:   <list of global or parent variables modified>
;
;       NOTES:   If $(!NTN_ScUseRegistry) is != "", then direct Registry
;                access is used in lieu of the Service Controller API
;                wrapper.  The Registry is automatically used if the
;                service type is "adapter".
;
;                The image path format varies for drivers and other
;                services.  For drivers of any kind, it's an NT name space
;                name.  For services, it's a REG_EXPAND_SZ format Win32 name.
;
;      BUGBUG:   This code can be deleted once the new UTILITY.INF has been
;                tested.
;
;     CHANGES:   DavidHov:  6/11/92.  "Groups" is REG_SZ, not REG_EXPAND_SZ
;                           Adapters are type=4, start=4.
;                           Only services get "ObjectName" value
;
;*************************************************************************
[CreateService]
    read-syms InitBaseVars

    set CS_NameOfService = $($0)
    set CS_ImagePath     = $($1)
    set CS_TypeOfService = $($2)
    set CS_Group         = $($3)
    set CS_Dependencies  = $($4)
    set CS_ObjectName	 = $($5)
    set CS_KeyServices   = ""
    set CS_KeyTempSvc    = ""
    set CS_KeySvcManager = ""
    set CS_KeyParameters = ""
    set CS_KeyLinkage    = ""
    set CS_ErrorControl  = 1
    set CS_UseRegistry   = $(!NTN_ScUseRegistry)

    Ifstr(i) $(CS_Dependencies) == ""
      CS_Dependencies = {}
    Endif

;
;  Get the base key handle for the services area
;
    Shell "", GetServiceBaseKey
    set RegistryErrorIndex = $($R0)
    Ifstr(i) $(RegistryErrorIndex) != STATUS_SUCCESSFUL
       set RegistryErrorIndex = UNABLE_ACCESS_CONFIGURE_SERVICE
       goto C_S_Return
    endif

    set CS_KeyServices = $($R1)

    ifstr(i) $(CS_TypeOfService) == "kernelautostart"
	  set TypeValue = 1
	  set StartValue = 2
    else-ifstr(i) $(CS_TypeOfService) == "service"
	  set TypeValue = 16
	  set StartValue = 3
    endif
	;
	; Call NCPA to create service key.
	;
        LibraryProcedure CS_CreateResult $(!NCPA_HANDLE), +
        CPlSetup, $(!STF_HWND), CREATESVC,+
            $(CS_NameOfService), $(StartValue), $(TypeValue), $(CS_ErrorControl),+
            $(CS_ImagePath), $(CS_Group),$(CS_Dependencies)

;;;;;;------------------------------------------------------------------
;;;;;;The following uses our own SETUPSVC.DLL to perform the call to
;;;;;;CreateService.  Commented out (and the NCPA CreateService wrapper
;;;;;;code restored) for NT 323, since it should all work right by now.
;;;;;;------------------------------------------------------------------
;;;;;;  install LoadSvcLibrary
;;;;;;
;;;;;;  ifstr(i) $(!SVCLIBHANDLE) != ""
;;;;;;    LibraryProcedure CS_CreateResult $(!SVCLIBHANDLE), SNACreateService, +
;;;;;;      $(CS_NameOfService), $(StartValue), $(TypeValue), $(CS_ErrorControl),+
;;;;;;      $(CS_ImagePath), $(CS_Group),$(CS_Dependencies)
;;;;;;
;;;;;;    install FreeSvcLibrary
;;;;;;  endif
;;;;;;------------------------------------------------------------------

	;
	; Check the return code
	;
	Set CS_CreateError = *($(CS_CreateResult),1)
	Ifint $(CS_CreateError) != 0
	     Set RegistryErrorIndex = UNABLE_CREATE_CONFIGURE_SERVICE
	     Goto C_S_Return
	Endif
	;
	;  Now open the key which should have been created by the service controller
	;
	OpenRegKey $(CS_KeyServices) "" $(CS_NameOfService) $(MAXIMUM_ALLOWED) +
                 CS_KeyTempSvc
	ifstr $(CS_KeyTempSvc) == $(KeyNull)
	     set RegistryErrorIndex = UNABLE_CREATE_CONFIGURE_SERVICE
	     Goto C_S_Return
	endif
;
;  Open or Create the Parameters subkey
;
    OpenRegKey $(CS_KeyTempSvc) "" "Parameters" $(MAXIMUM_ALLOWED) +
	             CS_KeyParameters
    ifstr $(CS_KeyParameters) == $(KeyNull)
	    CreateRegKey $(CS_KeyTempSvc) {"Parameters",$(NoTitle),$(GenericClass)} +
                     "" $(MAXIMUM_ALLOWED) "" CS_KeyParameters
    endif

    Ifstr $(CS_KeyParameters) == $(KeyNull)
       set RegistryErrorIndex = UNABLE_CREATE_SERVICE_SUBKEY
       goto C_S_Return
    endif

    set RegistryErrorIndex = NO_ERROR
;
;  Open or Create the Linkage subkey
;
    OpenRegKey $(CS_KeyTempSvc) "" "Linkage" $(MAXIMUM_ALLOWED) CS_KeyLinkage
    Ifstr $(CS_KeyLinkage) == $(KeyNull)
	CreateRegKey $(CS_KeyTempSvc) {"Linkage",$(NoTitle),$(GenericClass)} +
                 "" $(MAXIMUM_ALLOWED) "" CS_KeyLinkage
    Endif

    Ifstr $(CS_KeyLinkage) == $(KeyNull)
       set RegistryErrorIndex = UNABLE_CREATE_SERVICE_SUBKEY
       goto C_S_Return
    endif
;
; Return the keys and error codes
;
C_S_Return = +
    Ifstr $(CS_KeyServices) != $(KeyNull)
	     CloseRegKey $(CS_KeyServices)
    endif
    return $(RegistryErrorIndex), $(CS_KeyTempSvc), $(CS_KeyParameters), +
                                  $(CS_KeyLinkage)

;*************************************************************************
;  end of section CreateService
;*************************************************************************

[InitBaseVars]
KeyNull            = ""
MAXIMUM_ALLOWED    = 33554432
KeyInfo            = {}
RegistryErrorIndex = NO_ERROR
NoTitle            = 0
CurrentControlSet  = "SYSTEM\CurrentControlSet"
ServicesBaseName   = $(CurrentControlSet)"\Services"
NetworkCardKeyName = $(!NTN_SoftwareBase)"\Microsoft\Windows NT\CurrentVersion\NetworkCards"
!RegLastError      = NO_ERROR
