!include "LogicLib.nsh"

OutFile EnumNet.exe
ShowInstDetails show

Section
  SetDetailsPrint both
  DetailPrint "Searching local network for computers..."
  SetDetailsPrint listonly
  Push 0
  Call EnumerateNetwork
  SetDetailsPrint both
  SetPluginUnload manual
  System::Free 0
  SetPluginUnload alwaysoff
SectionEnd

Function EnumerateNetwork
  Exch $R0                              ; LPNETRESOURCE/HANDLE
  Push $0                               ; Returns statuses

  ; Begin the enumeration
  System::Call `mpr::WNetOpenEnumA(i2, i0, i0, iR0, *i.R0) i.r0`    ; RESOURCE_GLOBALNET, RESOURCETYPE_ANY
  ${If} $0 = 0                          ; Success
    System::Alloc 16384                 ; Allocate a 16K buffer
    Exch $R1
    Push $R2                            ; Number of items
    System::Alloc 4                     ; Memory to store this
    Exch $R3
    Push $1                             ; Item pointer
    Push $2                             ; Temp value
    Push $3                             ; Temp value
    Push $4                             ; Temp value
    ${Do}
      ; Continue the enumeration
      System::Call `*$R3(i-1)`
      System::Call `mpr::WNetEnumResourceA(iR0, iR3, iR1, *i16384) i.r0`
      System::Call `*$R3(i.R2)`
      ${If} $0 <> 0                     ; Failed
        ${Break}
      ${EndIf}
      ; Process the returned entries
      StrCpy $1 $R1
      ${DoUntil} $R2 = 0
        ; Fetch the details
        System::Call `*$1(i, i, i.r0, i.r2, t, t.r3, t.r4)` ; dwDisplayType, dwUsage, lpRemoteName, lpComment
        ${If} $0 = 2                    ; RESOURCEDISPLAYTYPE_SERVER (i.e. a machine)
          ; Found a computer
          DetailPrint `Found "$3"`
        ${Else}
          ; Call recursively if appropriate
          IntOp $2 $2 & 2               ; RESOURCEUSAGE_CONTAINER
          ${Unless} $2 = 0
            DetailPrint `Searching "$3"...`
            Push $1
            Call EnumerateNetwork
          ${EndIf}
        ${EndIf}
        IntOp $1 $1 + 32                ; sizeof(NETRESOURCEA)
        IntOp $R2 $R2 - 1
      ${Loop}
    ${Loop}
    ${If} $0 <> 259                     ; ERROR_NO_MORE_ITEMS
      DetailPrint "WNetEnumResource failed with $0"
    ${EndIf}
    Pop $4
    Pop $3
    Pop $2
    Pop $1
    System::Free $R3
    Pop $R3
    Pop $R2
    ; Free the allocated buffer
    System::Free $R1
    Pop $R1
    ; Close the handle
    System::Call `mpr::WNetCloseEnum(iR0)`
  ${Else}
    DetailPrint "WNetOpenEnum failed with $0"
  ${EndIf}

  Pop $0
  Pop $R0
FunctionEnd
