PrintToVeraeTimeStamp/platform/windows/installer-windows.nsi
Cursor Agent 17bb067010
Keep one IPP advertisement and accept link-local IPv6.
DnsServiceRegister stays the only owner of the _ipp._tcp instance. The shared UDP responder answers subtype PTRs only, so mDNS no longer renames a second copy to Name(1). The IPP port listens on IPv4 and on [::] with IPV6_V6ONLY, and the firewall rules allow fe80::/10, so a Mac connect to the host's link-local address completes.

Co-authored-by: George Lambert <marchon@gmail.com>
2026-10-05 00:34:34 +00:00

916 lines
32 KiB
NSIS

; Verae Print Stamp — Windows installer (release).
; One interactive, elevated install: files, Verae key (detect / sign in / create
; account / paste / skip), IPP printer + Local Port fallback printer, helper as the
; logged-in user (scheduled task), autostart, diagnostics on failure, per-step
; results on the finish page. All scripts run hidden (nsExec); secrets are passed
; only through files in $PLUGINSDIR that are deleted immediately and are never logged.
; Logging: one concise %ProgramData%\Verae\logs\installer-<time>.log with errors and
; the per-step result summary. (Start > Verae > Collect diagnostics for troubleshooting.)
!ifndef VERSION
!define VERSION "0.3.2"
!endif
!ifndef ARCH
!define ARCH "amd64"
!endif
!ifndef SRCDIR
!define SRCDIR "."
!endif
!ifndef OUTDIR
!define OUTDIR "."
!endif
!define PRODUCT_NAME "Verae Print Stamp"
!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\VeraePrintStamp"
!define OLD_DEBUG_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\VeraePrintStampDebug"
!define PORTAL_URL "https://customer.verae.ai/portal/"
Name "${PRODUCT_NAME} ${VERSION}"
OutFile "${OUTDIR}\VeraePrintStamp-windows-${ARCH}-${VERSION}-setup.exe"
InstallDir "$PROGRAMFILES64\Verae\PrintStamp"
RequestExecutionLevel admin
Unicode true
SetCompressor /SOLID lzma
ShowInstDetails hide
ShowUninstDetails hide
BrandingText "Verae TimeStamp PDF ${VERSION}"
!include "MUI2.nsh"
!include "nsDialogs.nsh"
!include "x64.nsh"
!include "LogicLib.nsh"
!include "FileFunc.nsh"
!include "WinMessages.nsh"
!include "netprint-upgrade.nsh"
!include "StrFunc.nsh"
${Using:StrFunc} StrStr
!insertmacro GetParameters
!insertmacro GetOptions
Var LogDir
Var LogFile
Var PS
Var Exe
; key page state
Var TargetUser
Var KeyPresent
Var KeyMasked
Var KeyCheck
Var KeyChoice ; keep|login|create|paste|skip
Var TokenReady ; 1 when $PLUGINSDIR\newtoken.txt holds a key to save
Var TokenMasked
Var PendingId
Var PolicyText
Var InstallApi
Var Checked
; controls
Var Dlg
Var hR1
Var hR2
Var hR3
Var hR4
Var hR5
Var hName
Var hEmail
Var hPass
Var hConfirm
Var hTotp
Var hCode
Var hKey
Var hOpenChk
Var hOpenFolder
Var hOpenPdf
Var OpenMode ; folder|pdf|none
Var hPromptChk
Var PromptMode ; true|false (promptForFilename)
Var hNetChk
Var NetPrint ; 1 when the optional LAN printer is selected
Var hNetPublic
Var hNetQueue
Var NetPublic ; 1 to also allow Public networks (off by default)
Var NetQueue ; 1 to add the local "Verae Timestamp" queue (off by default)
Var NetStopped ; 1 when this upgrade stopped VeraeNetPrint to unlock verae-print.exe
Var FwProfile
Var TargetProfile
; results
Var FinishTitle
Var FinishText
!define MUI_ABORTWARNING
!define MUI_FINISHPAGE_TITLE "$FinishTitle"
!define MUI_FINISHPAGE_TEXT "$FinishText"
!define MUI_FINISHPAGE_TEXT_LARGE
!define MUI_FINISHPAGE_LINK "Open the logs folder"
!define MUI_FINISHPAGE_LINK_LOCATION "$LogDir"
!define MUI_FINISHPAGE_NOREBOOTSUPPORT
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "${SRCDIR}\LICENSE.txt"
Page custom KeyPageCreate KeyPageLeave
Page custom LoginPageCreate LoginPageLeave
Page custom CreatePageCreate CreatePageLeave
Page custom VerifyPageCreate VerifyPageLeave
Page custom PastePageCreate PastePageLeave
Page custom OptionsPageCreate OptionsPageLeave
Page custom NetExtraCreate NetExtraLeave
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_LANGUAGE "English"
; ---------- logging (never pass secrets to these) ----------
!macro LOG text
Push `${text}`
Call WriteLog
!macroend
!define LOG "!insertmacro LOG"
Function WriteLog
Exch $0
Push $1
Push $2
${GetTime} "" "L" $R1 $R2 $R3 $R4 $R5 $R6 $R7
FileOpen $1 $LogFile a
${If} $1 != ""
FileSeek $1 0 END
FileWriteUTF16LE $1 "$R3-$R2-$R1 $R5:$R6:$R7 $0$\r$\n"
FileClose $1
${EndIf}
Pop $2
Pop $1
Pop $0
FunctionEnd
; write "Key=Value" request lines (UTF-16LE + BOM) — values may contain any chars
!macro REQ_OPEN path
FileOpen $9 `${path}` w
FileWriteWord $9 0xFEFF
!macroend
!macro REQ_KV key val
FileWriteUTF16LE $9 `${key}=${val}$\r$\n`
!macroend
!macro REQ_CLOSE
FileClose $9
!macroend
Function .onInit
${IfNot} ${RunningX64}
MessageBox MB_ICONSTOP "This build targets 64-bit Windows." /SD IDOK
Abort
${EndIf}
SetRegView 64
SetShellVarContext all
AllowSkipFiles off
ReadEnvStr $LogDir "ProgramData"
StrCpy $LogDir "$LogDir\Verae\logs"
CreateDirectory $LogDir
${GetTime} "" "L" $R1 $R2 $R3 $R4 $R5 $R6 $R7
StrCpy $LogFile "$LogDir\installer-$R3$R2$R1-$R5$R6$R7.log"
StrCpy $PS '"$WINDIR\Sysnative\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden'
InitPluginsDir
SetOutPath $PLUGINSDIR
File "${SRCDIR}\verae-print.exe"
File "${SRCDIR}\scripts\common.ps1"
File "${SRCDIR}\scripts\user-token.ps1"
StrCpy $Exe "$PLUGINSDIR\verae-print.exe"
StrCpy $NetPrint "0"
StrCpy $NetPublic "0"
StrCpy $NetQueue "0"
StrCpy $NetStopped "0"
${GetParameters} $R0
ClearErrors
${GetOptions} $R0 "/PUBLIC=" $R1
${IfNot} ${Errors}
${If} $R1 == "1"
StrCpy $NetPublic "1"
${EndIf}
${EndIf}
ClearErrors
${GetOptions} $R0 "/QUEUE=" $R1
${IfNot} ${Errors}
${If} $R1 == "1"
StrCpy $NetQueue "1"
${EndIf}
${EndIf}
StrCpy $Checked 0
StrCpy $TokenReady 0
StrCpy $KeyChoice "skip"
StrCpy $OpenMode "folder"
StrCpy $PromptMode "true"
FunctionEnd
Function un.onInit
SetRegView 64
SetShellVarContext all
AllowSkipFiles off
ReadEnvStr $LogDir "ProgramData"
${If} $LogDir == ""
StrCpy $LogDir "C:\ProgramData"
${EndIf}
StrCpy $LogDir "$LogDir\Verae\logs"
StrCpy $LogFile "$LogDir\netprint-installer.log"
FunctionEnd
; ======================= Page: Verae key status / choice =======================
Function KeyPageCreate
!insertmacro MUI_HEADER_TEXT "Verae signing key" "Timestamps are registered with your Verae account."
${If} $Checked == 0
Banner::show /NOUNLOAD "Checking for an existing Verae key..."
nsExec::Exec '$PS -File "$PLUGINSDIR\user-token.ps1" -Mode status -IniOut "$PLUGINSDIR\tok.ini"'
Pop $0
nsExec::Exec '"$Exe" installer-account --op capabilities --out "$PLUGINSDIR\caps.ini"'
Pop $1
Banner::destroy
ReadINIStr $TargetUser "$PLUGINSDIR\tok.ini" token account
ReadINIStr $KeyPresent "$PLUGINSDIR\tok.ini" token present
ReadINIStr $KeyMasked "$PLUGINSDIR\tok.ini" token masked
ReadINIStr $KeyCheck "$PLUGINSDIR\tok.ini" token check
ReadINIStr $PolicyText "$PLUGINSDIR\caps.ini" account policyText
ReadINIStr $InstallApi "$PLUGINSDIR\caps.ini" account installApi
ReadINIStr $TargetProfile "$PLUGINSDIR\tok.ini" token profile
${If} $TargetUser == ""
${LOG} "ERROR could not determine the logged-in user (user-token.ps1 exit $0)"
${EndIf}
StrCpy $Checked 1
${EndIf}
nsDialogs::Create 1018
Pop $Dlg
${NSD_CreateLabel} 0 0 100% 12u "Windows user: $TargetUser"
Pop $0
${If} $KeyPresent == "1"
${If} $KeyCheck == "valid"
StrCpy $1 "An existing Verae key was found: $KeyMasked (verified with Verae)."
${ElseIf} $KeyCheck == "invalid"
StrCpy $1 "A saved key was found ($KeyMasked) but Verae REJECTED it. Please sign in or paste a new key."
${Else}
StrCpy $1 "An existing Verae key was found: $KeyMasked (could not verify right now: $KeyCheck)."
${EndIf}
${Else}
StrCpy $1 "No Verae key was found for this user. You need one to timestamp documents."
${EndIf}
${NSD_CreateLabel} 0 14u 100% 20u "$1"
Pop $0
${NSD_CreateRadioButton} 10u 38u 95% 12u "Keep the existing key ($KeyMasked)"
Pop $hR1
${NSD_CreateRadioButton} 10u 52u 95% 12u "Sign in to my Verae account (email + password) and create a key"
Pop $hR2
${NSD_CreateRadioButton} 10u 66u 95% 12u "Create a new Verae account"
Pop $hR3
${NSD_CreateRadioButton} 10u 80u 95% 12u "I already have an xVerae- key - paste it"
Pop $hR4
${NSD_CreateRadioButton} 10u 94u 95% 12u "Skip for now (the printer will ask for a key on first print)"
Pop $hR5
${NSD_CreateLabel} 0 112u 100% 24u "Your password is sent only to customer.verae.ai over HTTPS and is never stored; only the issued key is saved in $TargetUser's profile (.verae\xverae-token)."
Pop $0
${If} $KeyPresent == "1"
${AndIf} $KeyCheck != "invalid"
${NSD_Check} $hR1
${Else}
EnableWindow $hR1 0
${NSD_Check} $hR2
${EndIf}
nsDialogs::Show
FunctionEnd
Function KeyPageLeave
${NSD_GetState} $hR1 $0
${NSD_GetState} $hR2 $1
${NSD_GetState} $hR3 $2
${NSD_GetState} $hR4 $3
${If} $0 == ${BST_CHECKED}
StrCpy $KeyChoice "keep"
${ElseIf} $1 == ${BST_CHECKED}
StrCpy $KeyChoice "login"
${ElseIf} $2 == ${BST_CHECKED}
StrCpy $KeyChoice "create"
${ElseIf} $3 == ${BST_CHECKED}
StrCpy $KeyChoice "paste"
${Else}
StrCpy $KeyChoice "skip"
MessageBox MB_YESNO|MB_ICONEXCLAMATION "Continue without a Verae key?$\r$\n$\r$\nThe printer will be installed, but documents cannot be timestamped until you add a key. On your first print you will be asked for one (or use Start > Verae > Setup signing key)." /SD IDYES IDYES +2
Abort
${EndIf}
StrCpy $TokenReady 0
StrCpy $PendingId ""
FunctionEnd
; ======================= Page: sign in =======================
Function LoginPageCreate
${If} $KeyChoice != "login"
Abort
${EndIf}
!insertmacro MUI_HEADER_TEXT "Sign in to Verae" "A new signing key will be created for this PC."
nsDialogs::Create 1018
Pop $Dlg
${NSD_CreateLabel} 0 0 30% 12u "Email"
Pop $0
${NSD_CreateText} 30% 0 70% 12u ""
Pop $hEmail
${NSD_CreateLabel} 0 18u 30% 12u "Password"
Pop $0
${NSD_CreatePassword} 30% 18u 70% 12u ""
Pop $hPass
${NSD_CreateLabel} 0 36u 30% 12u "Authenticator code"
Pop $0
${NSD_CreateText} 30% 36u 30% 12u ""
Pop $hTotp
${NSD_CreateLabel} 62% 37u 38% 12u "(only if you use 2FA)"
Pop $0
${NSD_CreateLabel} 0 60u 100% 24u "Forgot your password or prefer the website? Open the customer portal, create an xVerae- key under Security, then go Back and choose 'paste it'."
Pop $0
${NSD_CreateLink} 0 86u 100% 12u "Open customer.verae.ai in your browser"
Pop $0
${NSD_OnClick} $0 OpenPortal
${NSD_SetFocus} $hEmail
nsDialogs::Show
FunctionEnd
Function OpenPortal
Pop $0
ExecShell "open" "${PORTAL_URL}"
FunctionEnd
Function LoginPageLeave
${NSD_GetText} $hEmail $1
${NSD_GetText} $hPass $2
${NSD_GetText} $hTotp $3
${If} $1 == ""
${OrIf} $2 == ""
MessageBox MB_ICONEXCLAMATION "Please enter your email and password." /SD IDOK
Abort
${EndIf}
!insertmacro REQ_OPEN "$PLUGINSDIR\req.txt"
!insertmacro REQ_KV "Email" "$1"
!insertmacro REQ_KV "Password" "$2"
!insertmacro REQ_KV "Totp" "$3"
!insertmacro REQ_CLOSE
StrCpy $2 ""
Banner::show /NOUNLOAD "Signing in to Verae..."
nsExec::Exec '"$Exe" installer-account --op login --in "$PLUGINSDIR\req.txt" --out "$PLUGINSDIR\acct.ini" --token-out "$PLUGINSDIR\newtoken.txt"'
Pop $0
Banner::destroy
Delete "$PLUGINSDIR\req.txt"
Call HandleAccountResult
FunctionEnd
; reads acct.ini; on success sets TokenReady, else Abort (stay on page)
Function HandleAccountResult
ReadINIStr $4 "$PLUGINSDIR\acct.ini" account result
ReadINIStr $5 "$PLUGINSDIR\acct.ini" account detail
ReadINIStr $TokenMasked "$PLUGINSDIR\acct.ini" account masked
Delete "$PLUGINSDIR\acct.ini"
${If} $4 != "ok"
${AndIf} $4 != "code_sent"
${AndIf} $4 != "totp_required"
${LOG} "ERROR account: $4 ($5)"
${EndIf}
${If} $4 == "ok"
StrCpy $TokenReady 1
MessageBox MB_ICONINFORMATION "A new Verae key was created for this PC.$\r$\nIt will be saved for $TargetUser." /SD IDOK
${ElseIf} $4 == "code_sent"
; handled by caller
${ElseIf} $4 == "totp_required"
MessageBox MB_ICONINFORMATION "$5" /SD IDOK
${NSD_SetFocus} $hTotp
Abort
${Else}
${If} $4 == ""
StrCpy $5 "No response from the helper (exit $0)."
${EndIf}
MessageBox MB_ICONEXCLAMATION "Verae said: $5" /SD IDOK
Abort
${EndIf}
FunctionEnd
; ======================= Page: create account =======================
Function CreatePageCreate
${If} $KeyChoice != "create"
Abort
${EndIf}
!insertmacro MUI_HEADER_TEXT "Create a Verae account" "Your account holds your timestamps and signing keys."
nsDialogs::Create 1018
Pop $Dlg
${NSD_CreateLabel} 0 0 30% 12u "Name"
Pop $0
${NSD_CreateText} 30% 0 70% 12u ""
Pop $hName
${NSD_CreateLabel} 0 16u 30% 12u "Email"
Pop $0
${NSD_CreateText} 30% 16u 70% 12u ""
Pop $hEmail
${NSD_CreateLabel} 0 32u 30% 12u "Password"
Pop $0
${NSD_CreatePassword} 30% 32u 70% 12u ""
Pop $hPass
${NSD_CreateLabel} 0 48u 30% 12u "Confirm password"
Pop $0
${NSD_CreatePassword} 30% 48u 70% 12u ""
Pop $hConfirm
${If} $PolicyText == ""
StrCpy $PolicyText "Password: at least 10 characters, a letter and a number"
${EndIf}
${NSD_CreateLabel} 30% 64u 70% 20u "$PolicyText"
Pop $0
${If} $InstallApi == "1"
StrCpy $1 "We will email you a 6-digit code to verify your address."
${Else}
StrCpy $1 "Your account is created immediately (this Verae server does not send verification codes yet)."
${EndIf}
${NSD_CreateLabel} 0 88u 100% 20u "$1"
Pop $0
${NSD_SetFocus} $hName
nsDialogs::Show
FunctionEnd
Function CreatePageLeave
${NSD_GetText} $hName $1
${NSD_GetText} $hEmail $2
${NSD_GetText} $hPass $3
${NSD_GetText} $hConfirm $6
${If} $3 != $6
MessageBox MB_ICONEXCLAMATION "The passwords do not match." /SD IDOK
Abort
${EndIf}
!insertmacro REQ_OPEN "$PLUGINSDIR\req.txt"
!insertmacro REQ_KV "Name" "$1"
!insertmacro REQ_KV "Email" "$2"
!insertmacro REQ_KV "Password" "$3"
!insertmacro REQ_KV "Confirm" "$6"
!insertmacro REQ_CLOSE
StrCpy $3 ""
StrCpy $6 ""
Banner::show /NOUNLOAD "Creating your Verae account..."
nsExec::Exec '"$Exe" installer-account --op register --in "$PLUGINSDIR\req.txt" --out "$PLUGINSDIR\acct.ini" --token-out "$PLUGINSDIR\newtoken.txt"'
Pop $0
Banner::destroy
Delete "$PLUGINSDIR\req.txt"
ReadINIStr $4 "$PLUGINSDIR\acct.ini" account result
${If} $4 == "code_sent"
ReadINIStr $PendingId "$PLUGINSDIR\acct.ini" account pendingId
ReadINIStr $5 "$PLUGINSDIR\acct.ini" account detail
Delete "$PLUGINSDIR\acct.ini"
${Else}
Call HandleAccountResult
${EndIf}
FunctionEnd
; ======================= Page: email verification code =======================
Function VerifyPageCreate
${If} $PendingId == ""
Abort
${EndIf}
!insertmacro MUI_HEADER_TEXT "Verify your email" "Enter the code we sent you."
nsDialogs::Create 1018
Pop $Dlg
${NSD_CreateLabel} 0 0 100% 24u "We emailed a 6-digit verification code to the address you entered. It may take a minute; check your spam folder."
Pop $0
${NSD_CreateLabel} 0 30u 30% 12u "Code"
Pop $0
${NSD_CreateText} 30% 30u 30% 12u ""
Pop $hCode
${NSD_CreateButton} 30% 50u 30% 14u "Send a new code"
Pop $0
${NSD_OnClick} $0 ResendCode
${NSD_SetFocus} $hCode
nsDialogs::Show
FunctionEnd
Function ResendCode
Pop $0
!insertmacro REQ_OPEN "$PLUGINSDIR\req.txt"
!insertmacro REQ_KV "PendingId" "$PendingId"
!insertmacro REQ_CLOSE
nsExec::Exec '"$Exe" installer-account --op resend --in "$PLUGINSDIR\req.txt" --out "$PLUGINSDIR\acct.ini"'
Pop $0
ReadINIStr $5 "$PLUGINSDIR\acct.ini" account detail
Delete "$PLUGINSDIR\acct.ini"
MessageBox MB_ICONINFORMATION "$5" /SD IDOK
FunctionEnd
Function VerifyPageLeave
${NSD_GetText} $hCode $1
!insertmacro REQ_OPEN "$PLUGINSDIR\req.txt"
!insertmacro REQ_KV "PendingId" "$PendingId"
!insertmacro REQ_KV "Code" "$1"
!insertmacro REQ_CLOSE
Banner::show /NOUNLOAD "Verifying..."
nsExec::Exec '"$Exe" installer-account --op verify --in "$PLUGINSDIR\req.txt" --out "$PLUGINSDIR\acct.ini" --token-out "$PLUGINSDIR\newtoken.txt"'
Pop $0
Banner::destroy
Delete "$PLUGINSDIR\req.txt"
Call HandleAccountResult
FunctionEnd
; ======================= Page: paste key =======================
Function PastePageCreate
${If} $KeyChoice != "paste"
Abort
${EndIf}
!insertmacro MUI_HEADER_TEXT "Paste your Verae key" "Keys start with xVerae- and are shown once when created."
nsDialogs::Create 1018
Pop $Dlg
${NSD_CreateLabel} 0 0 100% 30u "1. Click the button to open the Verae customer portal and sign in.$\r$\n2. Open Security and create an xVerae- token (it is shown only once).$\r$\n3. Copy it and paste it below, then click Next."
Pop $0
${NSD_CreateButton} 0 34u 60% 14u "Open customer.verae.ai"
Pop $0
${NSD_OnClick} $0 OpenPortal
${NSD_CreateLabel} 0 56u 100% 12u "xVerae- key"
Pop $0
${NSD_CreatePassword} 0 70u 100% 12u ""
Pop $hKey
${NSD_SetFocus} $hKey
nsDialogs::Show
FunctionEnd
Function PastePageLeave
${NSD_GetText} $hKey $1
${If} $1 == ""
MessageBox MB_ICONEXCLAMATION "Please paste your key (or go Back and choose Skip)." /SD IDOK
Abort
${EndIf}
FileOpen $9 "$PLUGINSDIR\newtoken.txt" w
FileWriteWord $9 0xFEFF
FileWriteUTF16LE $9 "$1"
FileClose $9
StrCpy $1 ""
Banner::show /NOUNLOAD "Checking the key with Verae..."
nsExec::Exec '"$Exe" validate-key --token-file "$PLUGINSDIR\newtoken.txt" --out "$PLUGINSDIR\val.ini"'
Pop $0
Banner::destroy
ReadINIStr $4 "$PLUGINSDIR\val.ini" validate result
ReadINIStr $5 "$PLUGINSDIR\val.ini" validate detail
ReadINIStr $TokenMasked "$PLUGINSDIR\val.ini" validate masked
Delete "$PLUGINSDIR\val.ini"
${If} $4 != "valid"
${LOG} "ERROR pasted key $TokenMasked: $4 ($5)"
${EndIf}
${If} $4 == "valid"
StrCpy $TokenReady 1
${ElseIf} $4 == "invalid"
Delete "$PLUGINSDIR\newtoken.txt"
MessageBox MB_ICONEXCLAMATION "Verae rejected this key ($5). Please check it and paste again." /SD IDOK
Abort
${ElseIf} $4 == "badformat"
Delete "$PLUGINSDIR\newtoken.txt"
MessageBox MB_ICONEXCLAMATION "That does not look like a Verae key: $5" /SD IDOK
Abort
${Else}
MessageBox MB_YESNO|MB_ICONQUESTION "Could not reach Verae to check the key ($5).$\r$\nSave it anyway?" /SD IDYES IDYES +3
Delete "$PLUGINSDIR\newtoken.txt"
Abort
StrCpy $TokenReady 1
${EndIf}
FunctionEnd
; ======================= Page: after each print =======================
Function OptionsPageCreate
!insertmacro MUI_HEADER_TEXT "After each print" "What should happen when a document has been timestamped?"
nsDialogs::Create 1018
Pop $Dlg
${NSD_CreateCheckbox} 0 0 100% 12u "&Ask for a file name for each print (Save As dialog)"
Pop $hPromptChk
${NSD_CreateLabel} 14u 13u 90% 18u "Choose where to save each printed PDF; the Verae certificate and receipt are saved next to it. Cancel discards the print (nothing is stamped)."
Pop $0
${NSD_CreateCheckbox} 0 36u 100% 12u "&Open the result automatically after each print"
Pop $hOpenChk
${NSD_OnClick} $hOpenChk OptionsToggle
${NSD_CreateRadioButton} 14u 52u 90% 12u "Show the new certificate PDF in File Explorer"
Pop $hOpenFolder
${NSD_CreateRadioButton} 14u 66u 90% 12u "Open the certificate PDF in my PDF viewer"
Pop $hOpenPdf
${NSD_CreateLabel} 0 88u 100% 24u "Without the Save As dialog, files are saved in Documents\Verae Timestamps. You can change these later in %USERPROFILE%\.verae\config.json (promptForFilename: true/false; openOnComplete: folder, pdf or none)."
Pop $0
${NSD_CreateCheckbox} 0 116u 100% 28u "Also install the &network timestamp printer (off unless checked)$\r$\nSame service and tray icon as the standalone Verae Network Printer setup. Other computers on your LAN can print to it."
Pop $hNetChk
${If} $PromptMode != "false"
${NSD_Check} $hPromptChk
${EndIf}
${If} $OpenMode == "none"
${NSD_Check} $hOpenFolder
EnableWindow $hOpenFolder 0
EnableWindow $hOpenPdf 0
${Else}
${NSD_Check} $hOpenChk
${If} $OpenMode == "pdf"
${NSD_Check} $hOpenPdf
${Else}
${NSD_Check} $hOpenFolder
${EndIf}
${EndIf}
nsDialogs::Show
FunctionEnd
Function OptionsToggle
Pop $0
${NSD_GetState} $hOpenChk $0
${If} $0 == ${BST_CHECKED}
EnableWindow $hOpenFolder 1
EnableWindow $hOpenPdf 1
${Else}
EnableWindow $hOpenFolder 0
EnableWindow $hOpenPdf 0
${EndIf}
FunctionEnd
Function OptionsPageLeave
${NSD_GetState} $hPromptChk $0
${If} $0 == ${BST_CHECKED}
StrCpy $PromptMode "true"
${Else}
StrCpy $PromptMode "false"
${EndIf}
${NSD_GetState} $hOpenChk $0
${NSD_GetState} $hOpenPdf $1
${If} $0 != ${BST_CHECKED}
StrCpy $OpenMode "none"
${ElseIf} $1 == ${BST_CHECKED}
StrCpy $OpenMode "pdf"
${Else}
StrCpy $OpenMode "folder"
${EndIf}
${NSD_GetState} $hNetChk $0
${If} $0 == ${BST_CHECKED}
StrCpy $NetPrint "1"
${Else}
StrCpy $NetPrint "0"
${EndIf}
FunctionEnd
; Shown only when the network printer option is checked. Both boxes stay off by default.
Function NetExtraCreate
${If} $NetPrint != "1"
Abort
${EndIf}
!insertmacro MUI_HEADER_TEXT "Network printer" "Optional. Both stay off unless you turn them on."
nsDialogs::Create 1018
Pop $Dlg
${NSD_CreateCheckbox} 0 0 100% 28u "Allow connections from &Public networks (off by default).$\r$\nPrivate and Domain networks are always allowed."
Pop $hNetPublic
${NSD_CreateCheckbox} 0 36u 100% 28u "Add a local Windows printer named &Verae Timestamp (off by default)."
Pop $hNetQueue
${If} $NetPublic == "1"
${NSD_Check} $hNetPublic
${EndIf}
${If} $NetQueue == "1"
${NSD_Check} $hNetQueue
${EndIf}
nsDialogs::Show
FunctionEnd
Function NetExtraLeave
${NSD_GetState} $hNetPublic $0
${If} $0 == ${BST_CHECKED}
StrCpy $NetPublic "1"
${Else}
StrCpy $NetPublic "0"
${EndIf}
${NSD_GetState} $hNetQueue $0
${If} $0 == ${BST_CHECKED}
StrCpy $NetQueue "1"
${Else}
StrCpy $NetQueue "0"
${EndIf}
FunctionEnd
; ======================= Install =======================
!macro STEP_RESULT label value
StrCpy $FinishText "$FinishText${label}: ${value}$\r$\n"
!macroend
Section "Verae Print Stamp + printer" SecMain
SectionIn RO
SetDetailsPrint both
DetailPrint "Stopping running helper (if any)"
nsExec::Exec 'schtasks /End /TN "Verae Print Helper"'
Pop $0
nsExec::Exec 'taskkill /F /IM verae-printhelper.exe'
Pop $0
; VeraeNetPrint may be running this folder's verae-print.exe. Stop it
; before the File copy, or a locked exe is skipped and the old binary stays.
!insertmacro NETPRINT_STOP_IF_OURS
; replace a previous DEBUG test build (0.3.0-debug) cleanly
DeleteRegKey HKLM "${OLD_DEBUG_KEY}"
Delete "$SMPROGRAMS\Verae\Uninstall Verae Print Stamp (debug).lnk"
Delete "$INSTDIR\README-TEST.txt"
StrCpy $R9 "OK"
ClearErrors
SetOverwrite on
AllowSkipFiles off
SetOutPath "$INSTDIR\bin"
!insertmacro NETPRINT_COPY_CHECKED "${SRCDIR}\verae-print.exe" "verae-print.exe"
!insertmacro NETPRINT_COPY_CHECKED "${SRCDIR}\verae-printhelper.exe" "verae-printhelper.exe"
SetOutPath "$INSTDIR\scripts"
File "${SRCDIR}\scripts\common.ps1"
File "${SRCDIR}\scripts\user-token.ps1"
File "${SRCDIR}\scripts\install-printer.ps1"
File "${SRCDIR}\scripts\uninstall-printer.ps1"
File "${SRCDIR}\scripts\verae-diag.ps1"
SetOutPath "$INSTDIR"
File "${SRCDIR}\README-WINDOWS.txt"
File "${SRCDIR}\LICENSE.txt"
WriteUninstaller "$INSTDIR\Uninstall.exe"
${If} ${Errors}
StrCpy $R9 "FAIL"
${EndIf}
${If} $R9 != "OK"
${LOG} "ERROR could not write all program files to $INSTDIR"
nsExec::Exec 'sc start VeraeNetPrint'
Pop $0
MessageBox MB_ICONSTOP "Could not write all program files to $INSTDIR.$\r$\nDetails: $LogFile" /SD IDOK
Abort
${EndIf}
${If} $NetStopped == "1"
${AndIf} $NetPrint != "1"
nsExec::Exec 'sc start VeraeNetPrint'
Pop $0
!insertmacro NETPRINT_LOG "restarted VeraeNetPrint after replacing verae-print.exe (exit $0)"
${EndIf}
WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${PRODUCT_NAME} ${VERSION}"
WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" '"$INSTDIR\Uninstall.exe"'
WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${VERSION}"
WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "Verae"
CreateDirectory "$SMPROGRAMS\Verae"
CreateShortCut "$SMPROGRAMS\Verae\Verae - Setup signing key.lnk" "$INSTDIR\bin\verae-printhelper.exe" "key-dialog"
CreateShortCut "$SMPROGRAMS\Verae\Verae - Start print helper.lnk" "$INSTDIR\bin\verae-printhelper.exe"
CreateShortCut "$SMPROGRAMS\Verae\Verae - Logs folder.lnk" "$WINDIR\explorer.exe" '"$LogDir"'
CreateShortCut "$SMPROGRAMS\Verae\Verae - Collect diagnostics.lnk" "$WINDIR\System32\WindowsPowerShell\v1.0\powershell.exe" '-NoProfile -ExecutionPolicy Bypass -File "$INSTDIR\scripts\verae-diag.ps1"'
CreateShortCut "$SMPROGRAMS\Verae\Uninstall Verae Print Stamp.lnk" "$INSTDIR\Uninstall.exe"
StrCpy $FinishText ""
!insertmacro STEP_RESULT "Program files" "$R9"
; ---- key ----
${If} $TokenReady == "1"
DetailPrint "Saving Verae key ($TokenMasked) for $TargetUser"
nsExec::Exec '$PS -File "$INSTDIR\scripts\user-token.ps1" -Mode save -TokenFile "$PLUGINSDIR\newtoken.txt" -IniOut "$PLUGINSDIR\save.ini"'
Pop $0
Delete "$PLUGINSDIR\newtoken.txt"
ReadINIStr $1 "$PLUGINSDIR\save.ini" save result
ReadINIStr $2 "$PLUGINSDIR\save.ini" save path
ReadINIStr $3 "$PLUGINSDIR\save.ini" save detail
${If} $1 != "OK"
${LOG} "ERROR saving key for $TargetUser: $3"
${EndIf}
!insertmacro STEP_RESULT "Verae key" "$1 - $TokenMasked saved to $2 $3"
${ElseIf} $KeyChoice == "keep"
!insertmacro STEP_RESULT "Verae key" "OK - kept existing $KeyMasked"
${Else}
!insertmacro STEP_RESULT "Verae key" "SKIPPED - you will be asked on first print"
${EndIf}
; ---- after-each-print preference (user's ~/.verae/config.json) ----
${If} $TargetProfile != ""
nsExec::Exec '"$INSTDIR\bin\verae-print.exe" config --open-on-complete $OpenMode --prompt-for-filename $PromptMode --file "$TargetProfile\.verae\config.json"'
Pop $0
${If} $0 == 0
!insertmacro STEP_RESULT "After each print" "OK - open: $OpenMode, ask for file name: $PromptMode"
${Else}
${LOG} "ERROR writing $TargetProfile\.verae\config.json (exit $0)"
!insertmacro STEP_RESULT "After each print" "FAIL (default: show in folder)"
${EndIf}
${EndIf}
; ---- printers + helper ----
DetailPrint "Installing printers and starting the helper"
nsExec::Exec '$PS -File "$INSTDIR\scripts\install-printer.ps1" -InstallDir "$INSTDIR" -ResultIni "$PLUGINSDIR\printer.ini"'
Pop $0
ReadINIStr $1 "$PLUGINSDIR\printer.ini" printer task
ReadINIStr $2 "$PLUGINSDIR\printer.ini" printer helper
ReadINIStr $3 "$PLUGINSDIR\printer.ini" printer ipp
ReadINIStr $4 "$PLUGINSDIR\printer.ini" printer fallback
ReadINIStr $5 "$PLUGINSDIR\printer.ini" printer overall
ReadINIStr $6 "$PLUGINSDIR\printer.ini" printer spooler
ReadINIStr $7 "$PLUGINSDIR\printer.ini" printer oplog
${If} $5 == ""
StrCpy $5 "FAIL"
StrCpy $3 "FAIL - script did not report (exit $0)"
${EndIf}
!insertmacro STEP_RESULT "Print Spooler" "$6"
!insertmacro STEP_RESULT "PrintService log" "$7"
!insertmacro STEP_RESULT "Helper autostart task" "$1"
!insertmacro STEP_RESULT "Helper running as you" "$2"
!insertmacro STEP_RESULT "Printer 'Verae TimeStamp PDF'" "$3"
!insertmacro STEP_RESULT "Printer '(Local Port)'" "$4"
ReadINIStr $8 "$PLUGINSDIR\printer.ini" printer errors
${If} $8 != ""
${LOG} "ERROR printer setup step(s) failed - details in $8"
${EndIf}
${If} $NetPrint == "1"
!insertmacro NETPRINT_KILL_TRAY
${If} $NetStopped != "1"
!insertmacro NETPRINT_STOP_IF_OURS
${EndIf}
SetOverwrite on
AllowSkipFiles off
SetOutPath "$INSTDIR\bin"
!insertmacro NETPRINT_COPY_CHECKED "${SRCDIR}\verae-netprint-tray.exe" "verae-netprint-tray.exe"
DetailPrint "Installing the Verae network printer (service + tray)"
; TCP 631, TCP 8632 (not the helper's 8631), UDP 5353.
; Private and domain unless the Public checkbox was turned on.
; remoteip=any includes IPv4, global IPv6, and link-local fe80::/10.
StrCpy $FwProfile "private,domain"
StrCpy $R8 "false"
${If} $NetPublic == "1"
StrCpy $FwProfile "private,domain,public"
StrCpy $R8 "true"
${EndIf}
nsExec::Exec 'netsh advfirewall firewall delete rule name="Verae NetPrint IPP"'
Pop $0
nsExec::Exec 'netsh advfirewall firewall add rule name="Verae NetPrint IPP" dir=in action=allow protocol=TCP localport=631 remoteip=any profile=$FwProfile'
Pop $0
nsExec::Exec 'netsh advfirewall firewall delete rule name="Verae NetPrint IPP Fallback"'
Pop $0
nsExec::Exec 'netsh advfirewall firewall add rule name="Verae NetPrint IPP Fallback" dir=in action=allow protocol=TCP localport=8632 remoteip=any profile=$FwProfile'
Pop $0
nsExec::Exec 'netsh advfirewall firewall delete rule name="Verae NetPrint mDNS"'
Pop $0
nsExec::Exec 'netsh advfirewall firewall add rule name="Verae NetPrint mDNS" dir=in action=allow protocol=UDP localport=5353 remoteip=any profile=$FwProfile'
Pop $0
CreateDirectory "$LogDir"
StrCpy $R9 '"$INSTDIR\bin\verae-print.exe" netprint install --owner driver --allow-public=$R8'
${If} $NetQueue == "1"
StrCpy $R9 '$R9 --local-queue'
${EndIf}
nsExec::ExecToStack $R9
Pop $0
Pop $1
ClearErrors
FileOpen $2 "$LogDir\netprint-installer.log" a
${IfNot} ${Errors}
FileSeek $2 0 END
FileWrite $2 "driver netprint install allow-public=$R8 local-queue=$NetQueue exit $0$\r$\n$1$\r$\n"
FileClose $2
${EndIf}
${If} $0 == 0
!insertmacro STEP_RESULT "Network printer" "OK - Verae Timestamp on the LAN, tray at login"
${Else}
${LOG} "ERROR network printer install exit $0. See $LogDir\netprint-installer.log"
!insertmacro STEP_RESULT "Network printer" "FAIL (exit $0) - see netprint-installer.log"
${EndIf}
${Else}
!insertmacro STEP_RESULT "Network printer" "SKIPPED"
${EndIf}
${If} $5 == "OK"
StrCpy $FinishTitle "Verae TimeStamp PDF is installed"
StrCpy $FinishText "$FinishText$\r$\nPrint from any app and choose 'Verae TimeStamp PDF'. Results go to Documents\Verae Timestamps."
${Else}
StrCpy $FinishTitle "Installed with problems"
StrCpy $FinishText "$FinishText$\r$\nSee the logs folder (link below). For support, run Start > Verae > Collect diagnostics and send the zip."
${EndIf}
; concise log: per-step summary (errors were appended above as they happened)
${LOG} "SUMMARY ${VERSION} user=$TargetUser:$\r$\n$FinishText"
SectionEnd
Section "Uninstall"
!insertmacro NETPRINT_STOP_SERVICE
!insertmacro NETPRINT_KILL_TRAY
nsExec::Exec '"$WINDIR\Sysnative\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden -File "$INSTDIR\scripts\uninstall-printer.ps1"'
Pop $0
nsExec::Exec '"$INSTDIR\bin\verae-print.exe" netprint uninstall --owner driver'
Pop $0
nsExec::Exec 'taskkill /F /IM verae-printhelper.exe'
Pop $0
; Standalone NetPrint lives in its own folder. Always remove this driver's files.
; Drop the shared firewall rules only when the standalone product is gone.
ClearErrors
ReadRegDWORD $R1 HKLM "Software\Verae\NetPrint" "Standalone"
${If} ${Errors}
StrCpy $R1 0
${EndIf}
ClearErrors
${If} $R1 != 1
nsExec::Exec 'netsh advfirewall firewall delete rule name="Verae NetPrint IPP"'
Pop $0
nsExec::Exec 'netsh advfirewall firewall delete rule name="Verae NetPrint IPP Fallback"'
Pop $0
nsExec::Exec 'netsh advfirewall firewall delete rule name="Verae NetPrint mDNS"'
Pop $0
${EndIf}
!insertmacro NETPRINT_DELETE_CHECKED "$INSTDIR\bin\verae-print.exe"
!insertmacro NETPRINT_DELETE_CHECKED "$INSTDIR\bin\verae-printhelper.exe"
!insertmacro NETPRINT_DELETE_CHECKED "$INSTDIR\bin\verae-netprint-tray.exe"
RMDir "$INSTDIR\bin"
Delete "$INSTDIR\scripts\*.ps1"
RMDir "$INSTDIR\scripts"
Delete "$INSTDIR\README-WINDOWS.txt"
Delete "$INSTDIR\LICENSE.txt"
Delete "$INSTDIR\Uninstall.exe"
RMDir "$INSTDIR"
Delete "$SMPROGRAMS\Verae\Verae - Setup signing key.lnk"
Delete "$SMPROGRAMS\Verae\Verae - Start print helper.lnk"
Delete "$SMPROGRAMS\Verae\Verae - Logs folder.lnk"
Delete "$SMPROGRAMS\Verae\Verae - Collect diagnostics.lnk"
Delete "$SMPROGRAMS\Verae\Uninstall Verae Print Stamp.lnk"
Delete "$SMPROGRAMS\Verae\Uninstall Verae Print Stamp (debug).lnk"
RMDir "$SMPROGRAMS\Verae"
DeleteRegKey HKLM "Software\Verae\PrintStamp"
DeleteRegKey HKLM "${UNINST_KEY}"
; logs and the user's .verae\xverae-token are kept on purpose
SectionEnd