Option Strict Off
Imports System.Collections
Imports Microsoft.Win32
Imports System.Text.RegularExpressions
Imports System.IO
Imports System.IO.MemoryMappedFiles
Imports System.Runtime.InteropServices
Imports System.Threading
Imports System.Security
Imports System.ComponentModel
Imports Microsoft.Win32.SafeHandles
Imports System.Runtime.ConstrainedExecution
Imports System.Security.Permissions

Public Class Class1
    Implements GOverlayPlugin.Interfaces.IPlugin
    Public testvar As Integer = 1

    Private objHost As GOverlayPlugin.Interfaces.IHost
    Public PluginName As String = "SpeedFan Plugin"

    Public Cache As String

    Public Const MapPrefix As String = ""
    Public Const MapName As String = "SFSharedMemory_ALM"
    Public Const FullMapName As String = MapPrefix & MapName

    Public PosSlot As Integer
    Public LastCache As New System.Collections.Hashtable

    Dim hMapFile As SafeFileMappingHandle = Nothing
    Public pView As IntPtr = IntPtr.Zero
    Public speedfan As SFStruct

    ' File offset where the view is to begin.
    Public Const ViewOffset As UInt32 = 0

    ' The number of bytes of a file mapping to map to the view. All bytes of the
    ' view must be within the maximum size of the file mapping object (MAP_SIZE). 
    ' If VIEW_SIZE is 0, the mapping extends from the offset (VIEW_OFFSET) to 
    ' the end of the file mapping.
    'Friend Const ViewSize As UInt32 = &H400
    Public Const ViewSize As UInt32 = 259
    Public Sub Initialize(ByVal Host As GOverlayPlugin.Interfaces.IHost) Implements GOverlayPlugin.Interfaces.IPlugin.Initialize
        objHost = Host
        speedfan.data_temps = New Hashtable
    End Sub

    Public ReadOnly Property Description() As String Implements GOverlayPlugin.Interfaces.IPlugin.Description
        'Return your plugin name
        Get
            Return "This plugin allows to read the temperature sensors from SpeedFan." & vbNewLine & vbNewLine & _
                "Make sure the SpeedFan is running." & vbNewLine & _
                "Developed by TheLaGmAn"
        End Get
    End Property

    Public ReadOnly Property Name() As String Implements GOverlayPlugin.Interfaces.IPlugin.Name
        'Return your plugin name
        Get
            Return PluginName
        End Get        
    End Property

    Public ReadOnly Property Display() As String Implements GOverlayPlugin.Interfaces.IPlugin.Display
        'Return the display this plugin belongs to
        Get
            Return "lcdsys"
        End Get
    End Property

    Function CallBack(method As String) As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.CallBacks
        'Send the request to upload all the files
        'objHost.DebugMessage("ETS2 Plugin - Callback Requested")
        'objHost.DebugMessage("ETS2 Plugin - " & method)

        Try
            Dim returnHT As Hashtable = New Hashtable

            Dim value = 0

            If method = "willrequestvalues" Then
                'Comes here once per run (only if sensors are used thru here)
                GrabData(0)
            ElseIf method = "willrequestvdisplay" Then
                'Comes here once per run (only if sensors are used thru here)                
            Else
                If method.IndexOf("SF.Temp") > -1 Then
                    value = speedfan.data_temps(method)
                End If
            End If

            returnHT("value") = value

            Return returnHT
        Catch ex As Exception
            objHost.DebugMessage("Error grabbing action : " & method)
        End Try
    End Function

    Function AvailableSensors(pluginOptions As Hashtable) As System.Collections.Generic.Dictionary(Of String, String) Implements GOverlayPlugin.Interfaces.IPlugin.AvailableSensors
        'Create the list of the sensors/elements this plugin has
        'You can access your pluginOptions here as pluginOptions(your_option)        
        Try
            'objHost.DebugMessage("called as")
            GrabData(pluginOptions("metric"))

            Dim sensors As New System.Collections.Generic.Dictionary(Of String, String)
            Dim x As Integer = 1
            For x = 1 To speedfan.temps
                sensors.Add("SF.Temp" & x, "Temperature # " & x & ": " & pluginOptions("metric"))
            Next

            Return sensors
        Catch ex As Exception
            objHost.DebugMessage("Error loading sensors:" & ex.Message & ": " & ex.StackTrace)
            'MsgBox(ex.Message & ":: " & ex.StackTrace)
        End Try
    End Function

    Function LCDSys2_AvailableSensors(pluginOptions As Hashtable) As System.Collections.Generic.Dictionary(Of String, String) Implements GOverlayPlugin.Interfaces.IPlugin.LCDSys2_AvailableSensors
        Return AvailableSensors(pluginOptions)
    End Function

    Function SensorHasCustomDraw(sensor_name As String) As Boolean Implements GOverlayPlugin.Interfaces.IPlugin.SensorHasCustomDraw
        'All sensors are drawn with GOverlay default drawing
        Return False
    End Function

    Function ComboBoxes() As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.ComboBoxes
        'Create custom ComboBox for your configuration to use
        Dim boxes As New Hashtable
        Dim myboxOptions As New Hashtable
        'Set each one of the Combobox options as value, Display Name
        myboxOptions.Add("C", "C")
        myboxOptions.Add("F", "F")
        'myboxOptions.Add("DriveLetter", "Drive Letter")
        'myboxOptions.Add("Model", "Model")
        'myboxOptions.Add("Temperature", "Temperature")
        'myboxOptions.Add("TemperatureClass", "Temperature Class")

        'Add the combobox options as the combobox "PLUG.optioncustom1"
        boxes.Add("SF.ComboMetric", myboxOptions)
        Return boxes
    End Function

    Public Function SetDefaultOptions(sensorId As String, elementData As Hashtable) As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.SetDefaultOptions
        'Set the default values you want to have on your sensor when its created, if the user doesnt change any option, he will have this settings

        elementData("width") = 50
        elementData("height") = 20
        elementData("font_style") = 0
        elementData("basic_color") = 0
        elementData("font_size") = 1
        elementData("font_color") = 0
        elementData("font_transform") = 0

        Return elementData
    End Function

    Public Function CreateOptions(sensorId As String, elementData As Hashtable) As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.CreateOptions
        'Set the options the user will have when clicking on the element
        'The available option_types are:
        'Text: Input text
        'Combo3: Combo with options (Enabled=0, Disabled=1)
        'Sensors: Combo with available sensors
        'ColorBasic: Combo with basic colors for the regular text font
        'ColorRGB: Combo with common RGB colors = 16bitinteger
        'ComboOnOff: Combo with options (Disabled=0, Enabled=1)
        'ComboYesNo: Combo with options (Yes=Yes, No=No)
        'TextSize: Combo with options (Extra Small=4, Very Small=5, Small=10, Normal=15, Big=20, Very Big=30, Extreme=40)
        'FontStyle2: Combo with options (Regular Font=0, Square Font=1, Numbers Font 1=2
        'Orientation: Combo with options (Horizontal=0, Vertical=1)
        'Here you can also load your custom comboboxes
        Return New Hashtable
    End Function

    Public Function LCDSys2_CreateOptions(sensorId As String, elementData As Hashtable) As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.LCDSys2_CreateOptions
        'Set the options the user will have when clicking on the element
        'The available option_types are:
        'Text: Input text
        'Combo3: Combo with options (Enabled=0, Disabled=1)
        'Sensors: Combo with available sensors
        'ColorRGB: Combo with common RGB colors = 16bitinteger
        'ComboOnOff: Combo with options (Disabled=0, Enabled=1)
        'ComboYesNo: Combo with options (Yes=Yes, No=No)
        'FontStyle: Combo with options of the fonts the user has installed
        'Orientation: Combo with options (Horizontal=0, Vertical=1)
        'Alignment: Left=-1,Center=0,Right=1
        'Here you can also load your custom comboboxes

        'No options because GOverlay draws instead of us
        Return New Hashtable
    End Function

    Public Function PluginOptionsDefault() As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.PluginOptionsDefault
        'Set the default values you want to have on plugin, if the user doesnt change any option, he will have this settings
        Dim options As New Hashtable
        options("metric") = "C"
        Return options
    End Function
    Public Function PluginOptions(pluginCurrentOptions As Hashtable) As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.PluginOptions
        'Set the options the user will have when going to the plugins tab and clicking on your plugin
        'The availalbe option_type are teh same as CreateOptions function
        Dim options As New Hashtable
        'Option: option_index as integer, option_data as ArrayList
        'Option_Data: option_type as string, option_label as string, option_name as string (no spaces, no _)
        'options.Add(0, New ArrayList({"TextMulti", "Temperature in C or F? (write C or F)", "metric"}))
        options.Add(0, New ArrayList({"SF.ComboMetric", "Temperature in C or F?", "metric"}))
        Return options
    End Function

    Structure SFStruct

        Dim fans As Integer
        Dim temps As Integer
        Dim volts As Integer

        Dim data_fans As Hashtable
        Dim data_temps As Hashtable
        Dim data_volts As Hashtable

    End Structure

    Public Function GrabData(metric As String)
        Try
            'objHost.DebugMessage("metric is: " & metric)

            ' Try to open the named file mapping.
            If hMapFile Is Nothing OrElse hMapFile.IsInvalid Then
                hMapFile = NativeMethod.OpenFileMapping(FileMapAccess.FILE_MAP_READ, False, FullMapName)
                objHost.DebugMessage("SpeedFan - Connected to hMapFile")
            End If

            If pView = IntPtr.Zero Then
                pView = NativeMethod.MapViewOfFile(hMapFile, FileMapAccess.FILE_MAP_READ, 0, ViewOffset, ViewSize)
                objHost.DebugMessage("SpeedFan - pView Inited")
            End If

            If hMapFile Is Nothing Then Return False

            If (hMapFile.IsInvalid) Then Return False

            If (pView = IntPtr.Zero) Then Throw New Win32Exception


            Dim value As Integer = 0

            Try
                Dim arrSize As Integer = 259
                Dim data(arrSize - 1) As Byte
                Dim i As Integer
                For i = 0 To arrSize - 1
                    data(i) = Marshal.ReadByte(New IntPtr(pView.ToInt32() + i))
                Next

                speedfan.temps = data(12)
                speedfan.volts = data(13)
                speedfan.fans = data(14)

                'objHost.DebugMessage("SpeedFan - Found " & speedfan.temps & " temperature sensors")
                Dim row = 0
                Dim check = 18
                Dim x = 0

                For x = 0 To speedfan.temps - 1
                    Dim t = BitConverter.ToUInt32(data, check) / 100
                    If metric = "F" Then
                        t = t * 1.8 + 32
                    End If
                    speedfan.data_temps("SF.Temp" & x) = Math.Round(t)
                    'objHost.DebugMessage("grab and metric is: " & metric)
                    row = row + 1
                    check = check + 4
                Next

            Catch ex As Exception

                MsgBox("exception:" & ex.Message & " : " & ex.StackTrace)
            End Try


            Return True
        Catch ex As Exception
            Return False
        End Try
    End Function
    Public Function DisplayOnLCD(sensorId As String, elementData As Hashtable, pluginOptions As Hashtable, cacheRuns As Integer) As ArrayList Implements GOverlayPlugin.Interfaces.IPlugin.DisplayOnLCD
        Return New ArrayList
    End Function

    Public Function LCDSys2_DisplayOnLCD(sensorId As String, elementData As Hashtable, pluginOptions As Hashtable, cacheRuns As Integer) As ArrayList Implements GOverlayPlugin.Interfaces.IPlugin.LCDSys2_DisplayOnLCD
        'GOverlay draws instead of us
        Return New ArrayList
    End Function


    Public Function convertcolorto16bit(cr, cg, cb)

        Dim R As Double
        Dim G As Double
        Dim B As Double

        R = cr / 256 * 32
        G = cg / 256 * 64
        B = cb / 256 * 32

        R = Math.Floor(R)
        G = Math.Floor(G)
        B = Math.Floor(B)

        Dim final As Int32 = (CInt(R) << 11)
        final = final + Int(G << 5)
        final = final + Int(B)

        Return final

    End Function



#Region "Native API Signatures and Types"

    ''' <summary>
    ''' Access rights for file mapping objects
    ''' http://msdn.microsoft.com/en-us/library/aa366559.aspx
    ''' </summary>
    ''' <remarks></remarks>
    Public Enum FileMapAccess
        FILE_MAP_COPY = 1
        FILE_MAP_WRITE = 2
        FILE_MAP_READ = 4
        FILE_MAP_ALL_ACCESS = &HF001F
    End Enum


    ''' <summary>
    ''' Represents a wrapper class for a file mapping handle. 
    ''' </summary>
    ''' <remarks></remarks>
    <SuppressUnmanagedCodeSecurity(), _
    HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort:=True)> _
    Friend NotInheritable Class SafeFileMappingHandle
        Inherits SafeHandleZeroOrMinusOneIsInvalid

        <SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode:=True)> _
        Private Sub New()
            MyBase.New(True)
        End Sub

        <SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode:=True)> _
        Public Sub New(ByVal handle As IntPtr, ByVal ownsHandle As Boolean)
            MyBase.New(ownsHandle)
            MyBase.SetHandle(handle)
        End Sub

        <ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), _
        DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Private Shared Function CloseHandle(ByVal handle As IntPtr) _
        As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function

        Protected Overrides Function ReleaseHandle() As Boolean
            Return SafeFileMappingHandle.CloseHandle(MyBase.handle)
        End Function

    End Class


    Friend ReadOnly INVALID_HANDLE_VALUE As New IntPtr(-1)


    ''' <summary>
    ''' The class exposes Windows APIs used in this code sample.
    ''' </summary>
    ''' <remarks></remarks>
    <SuppressUnmanagedCodeSecurity()> _
    Friend Class NativeMethod

        ''' <summary>
        ''' Opens a named file mapping object.
        ''' </summary>
        ''' <param name="dwDesiredAccess">
        ''' The access to the file mapping object. This access is checked against 
        ''' any security descriptor on the target file mapping object.
        ''' </param>
        ''' <param name="bInheritHandle">
        ''' If this parameter is TRUE, a process created by the CreateProcess 
        ''' function can inherit the handle; otherwise, the handle cannot be 
        ''' inherited.
        ''' </param>
        ''' <param name="lpName">
        ''' The name of the file mapping object to be opened.
        ''' </param>
        ''' <returns>
        ''' If the function succeeds, the return value is an open handle to the 
        ''' specified file mapping object.
        ''' </returns>
        <DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Public Shared Function OpenFileMapping( _
            ByVal dwDesiredAccess As FileMapAccess, _
            ByVal bInheritHandle As Boolean, _
            ByVal lpName As String) _
            As SafeFileMappingHandle
        End Function


        ''' <summary>
        ''' Maps a view of a file mapping into the address space of a calling 
        ''' process.
        ''' </summary>
        ''' <param name="hFileMappingObject">
        ''' A handle to a file mapping object. The CreateFileMapping and 
        ''' OpenFileMapping functions return this handle.
        ''' </param>
        ''' <param name="dwDesiredAccess">
        ''' The type of access to a file mapping object, which determines the 
        ''' protection of the pages.
        ''' </param>
        ''' <param name="dwFileOffsetHigh">
        ''' A high-order DWORD of the file offset where the view begins.
        ''' </param>
        ''' <param name="dwFileOffsetLow">
        ''' A low-order DWORD of the file offset where the view is to begin.
        ''' </param>
        ''' <param name="dwNumberOfBytesToMap">
        ''' The number of bytes of a file mapping to map to the view. All bytes 
        ''' must be within the maximum size specified by CreateFileMapping.
        ''' </param>
        ''' <returns>
        ''' If the function succeeds, the return value is the starting address of
        ''' the mapped view.
        ''' </returns>
        <DllImport("Kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Public Shared Function MapViewOfFile( _
            ByVal hFileMappingObject As SafeFileMappingHandle, _
            ByVal dwDesiredAccess As FileMapAccess, _
            ByVal dwFileOffsetHigh As UInt32, _
            ByVal dwFileOffsetLow As UInt32, _
            ByVal dwNumberOfBytesToMap As UInt32) _
            As IntPtr
        End Function


        ''' <summary>
        ''' Unmaps a mapped view of a file from the calling process's address 
        ''' space.
        ''' </summary>
        ''' <param name="lpBaseAddress">
        ''' A pointer to the base address of the mapped view of a file that is to 
        ''' be unmapped.
        ''' </param>
        ''' <returns></returns>
        <DllImport("Kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Public Shared Function UnmapViewOfFile( _
            ByVal lpBaseAddress As IntPtr) _
            As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function

    End Class

#End Region
End Class