'  
'   Rebex Sample Code License
' 
'   Copyright 2026, REBEX CR s.r.o.
'   All rights reserved.
'   https://www.rebex.net/
' 
'   Permission to use, copy, modify, and/or distribute this software for any
'   purpose with or without fee is hereby granted.
' 
'   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
'   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
'   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
'   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
'   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
'   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
'   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
'   OTHER DEALINGS IN THE SOFTWARE.
' 

Imports System
Imports System.IO
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Security.Principal
Imports System.Diagnostics
Imports Rebex
Imports Rebex.Net

Public Class MainForm
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

            ' set the trial license key
            Rebex.Licensing.Key = Rebex.Samples.TrialKey.Key


        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call
        CheckForIllegalCrossThreadCalls = True
        Application.EnableVisualStyles()
    End Sub

    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer
    Private WithEvents tabTimeDifference As System.Windows.Forms.TabPage
    Private WithEvents Label11 As System.Windows.Forms.Label
    Private WithEvents chbSet As System.Windows.Forms.CheckBox
    Private WithEvents tbOldTime As System.Windows.Forms.TextBox
    Private WithEvents tbCorrectedTime As System.Windows.Forms.TextBox
    Private WithEvents tbDifference As System.Windows.Forms.TextBox
    Private WithEvents label3 As System.Windows.Forms.Label
    Private WithEvents label4 As System.Windows.Forms.Label
    Private WithEvents label5 As System.Windows.Forms.Label
    Private WithEvents btnDifference As System.Windows.Forms.Button
    Private WithEvents Label6 As System.Windows.Forms.Label
    Private WithEvents tbVersion As System.Windows.Forms.TextBox
    Private WithEvents tbServerTime As System.Windows.Forms.TextBox
    Private WithEvents Label7 As System.Windows.Forms.Label
    Private WithEvents Label10 As System.Windows.Forms.Label
    Private WithEvents Label9 As System.Windows.Forms.Label
    Private WithEvents cbServers As System.Windows.Forms.ComboBox
    Private WithEvents groupBox1 As System.Windows.Forms.GroupBox
    Private WithEvents label12 As System.Windows.Forms.Label
    Private WithEvents tbStratum As System.Windows.Forms.TextBox
    Private WithEvents label2 As System.Windows.Forms.Label
    Private WithEvents Panel1 As System.Windows.Forms.Panel
    Private WithEvents PictureBox1 As System.Windows.Forms.PictureBox
    Private WithEvents Label8 As System.Windows.Forms.Label
    Private WithEvents btnStratum As System.Windows.Forms.Button
    Private WithEvents tabSynchronize As System.Windows.Forms.TabPage
    Private WithEvents btnSynchronize As System.Windows.Forms.Button
    Private WithEvents TabControl1 As System.Windows.Forms.TabControl
    Private WithEvents tabServerInfo As System.Windows.Forms.TabPage
    Private WithEvents Label1 As System.Windows.Forms.Label

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(MainForm))
        Me.tabTimeDifference = New System.Windows.Forms.TabPage()
        Me.Label1 = New System.Windows.Forms.Label()
        Me.Label11 = New System.Windows.Forms.Label()
        Me.chbSet = New System.Windows.Forms.CheckBox()
        Me.tbOldTime = New System.Windows.Forms.TextBox()
        Me.tbCorrectedTime = New System.Windows.Forms.TextBox()
        Me.tbDifference = New System.Windows.Forms.TextBox()
        Me.label3 = New System.Windows.Forms.Label()
        Me.label4 = New System.Windows.Forms.Label()
        Me.label5 = New System.Windows.Forms.Label()
        Me.btnDifference = New System.Windows.Forms.Button()
        Me.Label6 = New System.Windows.Forms.Label()
        Me.tbVersion = New System.Windows.Forms.TextBox()
        Me.tbServerTime = New System.Windows.Forms.TextBox()
        Me.Label7 = New System.Windows.Forms.Label()
        Me.Label10 = New System.Windows.Forms.Label()
        Me.Label9 = New System.Windows.Forms.Label()
        Me.cbServers = New System.Windows.Forms.ComboBox()
        Me.groupBox1 = New System.Windows.Forms.GroupBox()
        Me.label12 = New System.Windows.Forms.Label()
        Me.tbStratum = New System.Windows.Forms.TextBox()
        Me.label2 = New System.Windows.Forms.Label()
        Me.Panel1 = New System.Windows.Forms.Panel()
        Me.PictureBox1 = New System.Windows.Forms.PictureBox()
        Me.Label8 = New System.Windows.Forms.Label()
        Me.btnStratum = New System.Windows.Forms.Button()
        Me.tabSynchronize = New System.Windows.Forms.TabPage()
        Me.btnSynchronize = New System.Windows.Forms.Button()
        Me.TabControl1 = New System.Windows.Forms.TabControl()
        Me.tabServerInfo = New System.Windows.Forms.TabPage()
        Me.tabTimeDifference.SuspendLayout()
        Me.groupBox1.SuspendLayout()
        Me.Panel1.SuspendLayout()
        CType(Me.PictureBox1, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.tabSynchronize.SuspendLayout()
        Me.TabControl1.SuspendLayout()
        Me.tabServerInfo.SuspendLayout()
        Me.SuspendLayout()
        '
        'tabTimeDifference
        '
        Me.tabTimeDifference.Controls.Add(Me.Label1)
        Me.tabTimeDifference.Controls.Add(Me.Label11)
        Me.tabTimeDifference.Controls.Add(Me.chbSet)
        Me.tabTimeDifference.Controls.Add(Me.tbOldTime)
        Me.tabTimeDifference.Controls.Add(Me.tbCorrectedTime)
        Me.tabTimeDifference.Controls.Add(Me.tbDifference)
        Me.tabTimeDifference.Controls.Add(Me.label3)
        Me.tabTimeDifference.Controls.Add(Me.label4)
        Me.tabTimeDifference.Controls.Add(Me.label5)
        Me.tabTimeDifference.Controls.Add(Me.btnDifference)
        Me.tabTimeDifference.Location = New System.Drawing.Point(4, 22)
        Me.tabTimeDifference.Name = "tabTimeDifference"
        Me.tabTimeDifference.Size = New System.Drawing.Size(392, 222)
        Me.tabTimeDifference.TabIndex = 2
        Me.tabTimeDifference.Text = "Time Difference"
        Me.tabTimeDifference.Visible = False
        '
        'Label1
        '
        Me.Label1.AutoSize = True
        Me.Label1.Location = New System.Drawing.Point(321, 115)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(47, 13)
        Me.Label1.TabIndex = 19
        Me.Label1.Text = "seconds"
        '
        'Label11
        '
        Me.Label11.Location = New System.Drawing.Point(16, 8)
        Me.Label11.Name = "Label11"
        Me.Label11.Size = New System.Drawing.Size(312, 48)
        Me.Label11.TabIndex = 18
        Me.Label11.Text = "Determines the time difference between the current local system time and server t" & _
    "ime, calculates the correct local time and optionally sets the local time as wel" & _
    "l."
        '
        'chbSet
        '
        Me.chbSet.Location = New System.Drawing.Point(16, 144)
        Me.chbSet.Name = "chbSet"
        Me.chbSet.Size = New System.Drawing.Size(200, 24)
        Me.chbSet.TabIndex = 17
        Me.chbSet.Text = "Also set local system time"
        '
        'tbOldTime
        '
        Me.tbOldTime.Location = New System.Drawing.Point(176, 64)
        Me.tbOldTime.Name = "tbOldTime"
        Me.tbOldTime.ReadOnly = True
        Me.tbOldTime.Size = New System.Drawing.Size(200, 20)
        Me.tbOldTime.TabIndex = 14
        '
        'tbCorrectedTime
        '
        Me.tbCorrectedTime.Location = New System.Drawing.Point(176, 88)
        Me.tbCorrectedTime.Name = "tbCorrectedTime"
        Me.tbCorrectedTime.ReadOnly = True
        Me.tbCorrectedTime.Size = New System.Drawing.Size(200, 20)
        Me.tbCorrectedTime.TabIndex = 15
        '
        'tbDifference
        '
        Me.tbDifference.Location = New System.Drawing.Point(176, 112)
        Me.tbDifference.Name = "tbDifference"
        Me.tbDifference.ReadOnly = True
        Me.tbDifference.Size = New System.Drawing.Size(139, 20)
        Me.tbDifference.TabIndex = 16
        '
        'label3
        '
        Me.label3.Location = New System.Drawing.Point(16, 64)
        Me.label3.Name = "label3"
        Me.label3.Size = New System.Drawing.Size(136, 23)
        Me.label3.TabIndex = 11
        Me.label3.Text = "Current local system time:"
        '
        'label4
        '
        Me.label4.Location = New System.Drawing.Point(16, 88)
        Me.label4.Name = "label4"
        Me.label4.Size = New System.Drawing.Size(152, 23)
        Me.label4.TabIndex = 12
        Me.label4.Text = "Time corrected using NTP:"
        '
        'label5
        '
        Me.label5.Location = New System.Drawing.Point(16, 112)
        Me.label5.Name = "label5"
        Me.label5.Size = New System.Drawing.Size(136, 23)
        Me.label5.TabIndex = 13
        Me.label5.Text = "Time difference:"
        '
        'btnDifference
        '
        Me.btnDifference.Location = New System.Drawing.Point(216, 192)
        Me.btnDifference.Name = "btnDifference"
        Me.btnDifference.Size = New System.Drawing.Size(168, 23)
        Me.btnDifference.TabIndex = 10
        Me.btnDifference.Text = "Get time difference"
        '
        'Label6
        '
        Me.Label6.Location = New System.Drawing.Point(16, 88)
        Me.Label6.Name = "Label6"
        Me.Label6.Size = New System.Drawing.Size(100, 23)
        Me.Label6.TabIndex = 16
        Me.Label6.Text = "NTP version:"
        '
        'tbVersion
        '
        Me.tbVersion.Location = New System.Drawing.Point(176, 88)
        Me.tbVersion.Name = "tbVersion"
        Me.tbVersion.ReadOnly = True
        Me.tbVersion.Size = New System.Drawing.Size(200, 20)
        Me.tbVersion.TabIndex = 12
        '
        'tbServerTime
        '
        Me.tbServerTime.Location = New System.Drawing.Point(176, 112)
        Me.tbServerTime.Name = "tbServerTime"
        Me.tbServerTime.ReadOnly = True
        Me.tbServerTime.Size = New System.Drawing.Size(200, 20)
        Me.tbServerTime.TabIndex = 13
        '
        'Label7
        '
        Me.Label7.Location = New System.Drawing.Point(16, 112)
        Me.Label7.Name = "Label7"
        Me.Label7.Size = New System.Drawing.Size(100, 23)
        Me.Label7.TabIndex = 14
        Me.Label7.Text = "Server time:"
        '
        'Label10
        '
        Me.Label10.Location = New System.Drawing.Point(16, 16)
        Me.Label10.Name = "Label10"
        Me.Label10.Size = New System.Drawing.Size(312, 40)
        Me.Label10.TabIndex = 10
        Me.Label10.Text = "Retrieves various information from the NTP/SNTP server."
        '
        'Label9
        '
        Me.Label9.Location = New System.Drawing.Point(16, 48)
        Me.Label9.Name = "Label9"
        Me.Label9.Size = New System.Drawing.Size(376, 24)
        Me.Label9.TabIndex = 5
        Me.Label9.Text = "Select a time server hostname from a list or provide your own."
        '
        'cbServers
        '
        Me.cbServers.Items.AddRange(New Object() {"pool.ntp.org", "north-america.pool.ntp.org", "europe.pool.ntp.org", "asia.pool.ntp.org", "oceania.pool.ntp.org", "south-america.pool.ntp.org"})
        Me.cbServers.Location = New System.Drawing.Point(120, 24)
        Me.cbServers.Name = "cbServers"
        Me.cbServers.Size = New System.Drawing.Size(184, 21)
        Me.cbServers.TabIndex = 4
        Me.cbServers.Text = "test.rebex.net"
        '
        'groupBox1
        '
        Me.groupBox1.Controls.Add(Me.Label9)
        Me.groupBox1.Controls.Add(Me.cbServers)
        Me.groupBox1.Controls.Add(Me.label12)
        Me.groupBox1.Location = New System.Drawing.Point(8, 4)
        Me.groupBox1.Name = "groupBox1"
        Me.groupBox1.Size = New System.Drawing.Size(400, 78)
        Me.groupBox1.TabIndex = 15
        Me.groupBox1.TabStop = False
        Me.groupBox1.Text = " Common settings "
        '
        'label12
        '
        Me.label12.Location = New System.Drawing.Point(16, 24)
        Me.label12.Name = "label12"
        Me.label12.Size = New System.Drawing.Size(72, 23)
        Me.label12.TabIndex = 3
        Me.label12.Text = "Time server:"
        '
        'tbStratum
        '
        Me.tbStratum.Location = New System.Drawing.Point(176, 64)
        Me.tbStratum.Name = "tbStratum"
        Me.tbStratum.ReadOnly = True
        Me.tbStratum.Size = New System.Drawing.Size(200, 20)
        Me.tbStratum.TabIndex = 11
        '
        'label2
        '
        Me.label2.Location = New System.Drawing.Point(16, 64)
        Me.label2.Name = "label2"
        Me.label2.Size = New System.Drawing.Size(100, 23)
        Me.label2.TabIndex = 15
        Me.label2.Text = "Server stratum:"
        '
        'Panel1
        '
        Me.Panel1.BackColor = System.Drawing.Color.White
        Me.Panel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D
        Me.Panel1.Controls.Add(Me.PictureBox1)
        Me.Panel1.Controls.Add(Me.Label8)
        Me.Panel1.Location = New System.Drawing.Point(0, 0)
        Me.Panel1.Name = "Panel1"
        Me.Panel1.Size = New System.Drawing.Size(392, 128)
        Me.Panel1.TabIndex = 12
        '
        'PictureBox1
        '
        Me.PictureBox1.Image = CType(resources.GetObject("PictureBox1.Image"), System.Drawing.Image)
        Me.PictureBox1.Location = New System.Drawing.Point(0, 0)
        Me.PictureBox1.Name = "PictureBox1"
        Me.PictureBox1.Size = New System.Drawing.Size(104, 120)
        Me.PictureBox1.TabIndex = 0
        Me.PictureBox1.TabStop = False
        '
        'Label8
        '
        Me.Label8.Location = New System.Drawing.Point(112, 15)
        Me.Label8.Name = "Label8"
        Me.Label8.Size = New System.Drawing.Size(264, 92)
        Me.Label8.TabIndex = 11
        Me.Label8.Text = "Synchronizes local system time with the time server in a single line of code."
        Me.Label8.TextAlign = System.Drawing.ContentAlignment.MiddleLeft
        '
        'btnStratum
        '
        Me.btnStratum.Location = New System.Drawing.Point(216, 192)
        Me.btnStratum.Name = "btnStratum"
        Me.btnStratum.Size = New System.Drawing.Size(168, 23)
        Me.btnStratum.TabIndex = 17
        Me.btnStratum.Text = "Get server info"
        '
        'tabSynchronize
        '
        Me.tabSynchronize.Controls.Add(Me.Panel1)
        Me.tabSynchronize.Controls.Add(Me.btnSynchronize)
        Me.tabSynchronize.Location = New System.Drawing.Point(4, 22)
        Me.tabSynchronize.Name = "tabSynchronize"
        Me.tabSynchronize.Size = New System.Drawing.Size(392, 222)
        Me.tabSynchronize.TabIndex = 0
        Me.tabSynchronize.Text = "Synchronize"
        '
        'btnSynchronize
        '
        Me.btnSynchronize.Location = New System.Drawing.Point(216, 192)
        Me.btnSynchronize.Name = "btnSynchronize"
        Me.btnSynchronize.Size = New System.Drawing.Size(168, 23)
        Me.btnSynchronize.TabIndex = 10
        Me.btnSynchronize.Text = "Synchronize"
        '
        'TabControl1
        '
        Me.TabControl1.Controls.Add(Me.tabSynchronize)
        Me.TabControl1.Controls.Add(Me.tabTimeDifference)
        Me.TabControl1.Controls.Add(Me.tabServerInfo)
        Me.TabControl1.Location = New System.Drawing.Point(8, 100)
        Me.TabControl1.Name = "TabControl1"
        Me.TabControl1.SelectedIndex = 0
        Me.TabControl1.Size = New System.Drawing.Size(400, 248)
        Me.TabControl1.TabIndex = 17
        '
        'tabServerInfo
        '
        Me.tabServerInfo.Controls.Add(Me.btnStratum)
        Me.tabServerInfo.Controls.Add(Me.label2)
        Me.tabServerInfo.Controls.Add(Me.tbStratum)
        Me.tabServerInfo.Controls.Add(Me.Label6)
        Me.tabServerInfo.Controls.Add(Me.tbVersion)
        Me.tabServerInfo.Controls.Add(Me.tbServerTime)
        Me.tabServerInfo.Controls.Add(Me.Label7)
        Me.tabServerInfo.Controls.Add(Me.Label10)
        Me.tabServerInfo.Location = New System.Drawing.Point(4, 22)
        Me.tabServerInfo.Name = "tabServerInfo"
        Me.tabServerInfo.Size = New System.Drawing.Size(392, 222)
        Me.tabServerInfo.TabIndex = 1
        Me.tabServerInfo.Text = "Server Info"
        Me.tabServerInfo.Visible = False
        '
        'MainForm
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(418, 362)
        Me.Controls.Add(Me.groupBox1)
        Me.Controls.Add(Me.TabControl1)
        Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
        Me.MaximizeBox = False
        Me.Name = "MainForm"
        Me.Text = "Rebex Time - NTP/SNTP Sample Client"
        Me.tabTimeDifference.ResumeLayout(False)
        Me.tabTimeDifference.PerformLayout()
        Me.groupBox1.ResumeLayout(False)
        Me.Panel1.ResumeLayout(False)
        CType(Me.PictureBox1, System.ComponentModel.ISupportInitialize).EndInit()
        Me.tabSynchronize.ResumeLayout(False)
        Me.TabControl1.ResumeLayout(False)
        Me.tabServerInfo.ResumeLayout(False)
        Me.tabServerInfo.PerformLayout()
        Me.ResumeLayout(False)

    End Sub

#End Region

    ''' <summary>
    ''' The main entry point for the application.
    ''' </summary>
    <STAThread> _
    Friend Shared Sub Main()
            ' set the trial license key
            Rebex.Licensing.Key = Rebex.Samples.TrialKey.Key


        Application.EnableVisualStyles()
        Application.SetCompatibleTextRenderingDefault(False)
        Application.Run(New MainForm())
    End Sub

    Private Sub Synchronize()
        ' synchronize local time with time server       
        Ntp.SynchronizeSystemClock(cbServers.Text)

        MessageBox.Show(String.Format("Time set. Corrected local time is {0}.", DateTime.Now), _
            "Time set", MessageBoxButtons.OK, MessageBoxIcon.Information)
    End Sub

    Private Sub btnSynchronize_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSynchronize.Click
        ' check whether elevation is needed or whether we already have admin privileges
        Dim isElevated As Boolean = ElevateIfNeeded()

        ' only synchronize if we have admin privileges
        If isElevated Then
            Synchronize()
        End If
    End Sub

    Private Sub btnStratum_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStratum.Click
        ' Initialize the Ntp object
        Dim client As New Ntp(cbServers.Text)

        ' Since we want to know the highest version the server supports, we 
        ' must declare the highest ourselves (otherwise it would use 
        ' compatibility mode).
        client.VersionNumber = 4

        ' Get the time response
        Dim response As NtpResponse = client.GetTime()
        Dim packet As NtpPacket = response.Packet
        Dim offset As TimeSpan = response.TimeOffset.ToTimeSpan()

        ' Show server stratum
        tbStratum.Text = packet.Stratum.ToString()
        ' Show version
        tbVersion.Text = packet.VersionNumber.ToString()
        ' Show server time
        tbServerTime.Text = (DateTime.Now + offset).ToString("yyyy-MM-dd HH:mm:ss.fff")
    End Sub

    Private Sub btnDifference_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDifference.Click
        ' Initialize the Ntp object
        Dim client As New Ntp(cbServers.Text)

        ' Get the time response
        Dim response As NtpResponse = client.GetTime()
        Dim offset As TimeSpan = response.TimeOffset.ToTimeSpan()

        ' Show local time
        tbOldTime.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")
        ' Show server time
        tbCorrectedTime.Text = (DateTime.Now + offset).ToString("yyyy-MM-dd HH:mm:ss.fff")
        ' Show the time difference
        tbDifference.Text = offset.TotalSeconds.ToString()

        ' Adjust the local clock
        If chbSet.Checked AndAlso ElevateIfNeeded() Then
            SystemClock.AdjustClock(response)
        End If
    End Sub

    Private Function ElevateIfNeeded() As Boolean
        ' determine wheher we currenly have admin privileges
        Dim principal As New WindowsPrincipal(WindowsIdentity.GetCurrent())
        Dim isElevated As Boolean = principal.IsInRole(WindowsBuiltInRole.Administrator)

        ' if we do, then nothing needs to be done
        If isElevated Then Return True

        ' inform he user we are going to try elevating the application
        MessageBox.Show("In order to be able to synchronize local time with the server, this application first needs to be elevated to gain administrator permissions.", "Synchronize")

        ' start a new instance of the application in elevated mode
        Dim startInfo As New ProcessStartInfo()
        startInfo.Verb = "runas"
        startInfo.FileName = Process.GetCurrentProcess().MainModule.FileName
        startInfo.Arguments = "-sync"
        startInfo.UseShellExecute = True
        Try

            Process.Start(startInfo)
            Application.Exit()

        Catch x As Win32Exception

            ' elevation not allowed
        End Try

        Return False
    End Function

End Class
