!include MUI2.nsh
!include WinVer.nsh

; The locked file to test on.
!define THE_FILE $TEMP\Locked.tmp
; Please lock the file for me (i.e. it isn't currently locked).
!define LOCK_THE_FILE

Name LockedListTest
OutFile LockedListTest.exe
ShowInstDetails show

!insertmacro MUI_PAGE_WELCOME
Page Custom LockedListPageShow
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH

!insertmacro MUI_UNPAGE_WELCOME
UninstPage Custom un.LockedListPageShow
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH

!insertmacro MUI_LANGUAGE English

ReserveFile `${NSISDIR}\Plugins\LockedList.dll`

Function .onInit

  ${Unless} ${AtLeastWinNt4}
    MessageBox MB_OK|MB_ICONSTOP `You cannot run this installer on < Win NT`
    Abort
  ${EndUnless}

  InitPluginsDir

!ifdef LOCK_THE_FILE

  !tempfile TEMP
  !appendfile `${TEMP}` `Name LockFile$\r$\n`
  !appendfile `${TEMP}` `Caption "File locked for testing"$\r$\n`
  !appendfile `${TEMP}` `OutFile ${TEMP}.exe$\r$\n`
  !appendfile `${TEMP}` `XPStyle on$\r$\n`
  !appendfile `${TEMP}` `SilentInstall silent$\r$\n`
  !appendfile `${TEMP}` `Function .onInit$\r$\n`
  !appendfile `${TEMP}` `FileOpen $R0 "${THE_FILE}" w$\r$\n`
  !appendfile `${TEMP}` `MessageBox MB_OK "Click OK to unlock the file ${THE_FILE}."$\r$\n`
  !appendfile `${TEMP}` `FileClose $R0$\r$\n`
  !appendfile `${TEMP}` `Delete "${THE_FILE}"$\r$\n`
  !appendfile `${TEMP}` `FunctionEnd$\r$\n`
  !appendfile `${TEMP}` `Section$\r$\n`
  !appendfile `${TEMP}` `SectionEnd$\r$\n`
  !execute `"${NSISDIR}\makensis.exe" "${TEMP}"`
  File /oname=$PLUGINSDIR\LockFile.exe `${TEMP}.exe`
  !delfile `${TEMP}`

  Exec `"$PLUGINSDIR\LockFile.exe"`

  Sleep 1000
  BringToFront

!endif

FunctionEnd

Function LockedListPageShow

  !insertmacro MUI_HEADER_TEXT `LockedList install dialog` `This is a list of programs that have our files held hostage...`

  LockedList::AddFile `${THE_FILE}`
  LockedList::Dialog /ignore ``
  Pop $R0

FunctionEnd

Function un.LockedListPageShow

  !insertmacro MUI_HEADER_TEXT `LockedList uninstall dialog` `This is a list of programs that have our files held hostage...`

  LockedList::AddFile `${THE_FILE}`
  LockedList::Dialog /ignore ``
  Pop $R0

FunctionEnd

Section `Uninstall test` Section_UninstallTest

  DetailPrint `Launching uninstaller...`
  WriteUninstaller $EXEDIR\LockedListUninstallTest.exe
  ExecWait `"$EXEDIR\LockedListUninstallTest.exe" _?=$EXEDIR`
  Delete $EXEDIR\LockedListUninstallTest.exe

SectionEnd

Section `SilentSearch test` Section_SilentSearchTest

  DetailPrint `Testing LockedList without threading, please wait...`

  LockedList::AddFile `${THE_FILE}`
  LockedList::AddModule $PLUGINSDIR\LockedList.dll

  # Begin the search now.
  LockedList::SilentSearch

  DetailPrint `Searching... 100%`

  # Retrieve stack items.
  # First item on stack is /start (or /end if no files found).
  Pop $R0
  ${DoWhile} $R0 != `/end`

    Pop $R0 # Process identity?
    DetailPrint `Process id: $R0`

    Pop $R0 # Process full path
    DetailPrint `Process path: $R0`

    Pop $R0 # Process window caption
    DetailPrint `Process caption: $R0`

    # Next item on stack is /next (or /end if no more files).
    Pop $R0

  ${Loop}

  DetailPrint ``

SectionEnd

Section `SilentSearch asynchronous test` Section_SilentSearchThreadTest

  DetailPrint `Testing LockedList with threading, please wait...`

  LockedList::AddFile `${THE_FILE}`
  LockedList::AddModule $PLUGINSDIR\LockedList.dll

  # Begin the search in a separate thread.
  LockedList::SilentSearch /thread

  SetDetailsPrint textonly
  ${Do}

    # What is the current status?
    LockedList::SilentPercentComplete
    Pop $R0
    DetailPrint `Searching... $R0%`

    # Wait a maximum of 500ms.
    LockedList::SilentWait /time 500
    Pop $R0

  ${LoopWhile} $R0 == `/wait`
  SetDetailsPrint both

  DetailPrint `Searching... 100%`

  # Retrieve stack items.
  # First item on stack is /start (or /end if no files found).
  Pop $R0
  ${DoWhile} $R0 != `/end`

    Pop $R0 # Process identity
    DetailPrint `Process id: $R0`

    Pop $R0 # Process full path
    DetailPrint `Process path: $R0`

    Pop $R0 # Process window caption
    DetailPrint `Process caption: $R0`

    # Next item on stack is /next (or /end if no more files).
    Pop $R0

  ${Loop}

  DetailPrint ``

SectionEnd

Section Uninstall
SectionEnd

!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
  !insertmacro MUI_DESCRIPTION_TEXT ${Section_UninstallTest} `Tests the LockedList plug-in in the dummy uninstaller executable.`
  !insertmacro MUI_DESCRIPTION_TEXT ${Section_SilentSearchTest} `Calls SilentSearch and waits for it to finish.`
  !insertmacro MUI_DESCRIPTION_TEXT ${Section_SilentSearchThreadTest} `Calls SilentSearch using threading to showing progress indication.`
!insertmacro MUI_FUNCTION_DESCRIPTION_END