Attribute VB_Name = "modCheckRevision"
'------------------------------------------------
' MirageBot Account Module
' Written by Eric Naeseth
' Edited by Christopher Nevin (lancergli@gmail.com)
'------------------------------------------------

Option Explicit

'----------------------------------------------------------
'CheckRevision.dll
'----------------------------------------------------------
Public Declare Function CheckRevisionEx Lib "CheckRevision.dll" (ByVal FileEXE As String, ByVal FileStormDLL As String, ByVal FileBnetDLL As String, ByVal HashText As String, ByRef version As Long, ByRef checksum As Long, ByVal exeinfo As String, ByVal PathToDLL As String, ByVal PathToLockdown01 As String, ByVal PathToVideoBin As String) As Long
Public Declare Function CheckRevisionLD Lib "CheckRevision.dll" (ByVal FileEXE As String, ByVal FileStormDLL As String, ByVal FileBnetDLL As String, ByVal HashText As String, ByRef version As Long, ByRef checksum As Long, ByVal exeinfo As String, ByVal PathToDLL As String, ByVal PathToLockdown01 As String, ByVal PathToVideoBin As String) As Long


'----------------------------------------------------------
'WardenHandler.dll
'----------------------------------------------------------
Public Declare Sub WardenInit Lib "WardenHandler.dll" (ByVal Cookie As Long, ByVal clientid As Long, ByVal seed As Long)
Public Declare Sub WardenCleanup Lib "WardenHandler.dll" (ByVal Cookie As Long)
Public Declare Function WardenOnData Lib "WardenHandler.dll" _
    (ByVal Cookie As Long, ByRef Data() As Byte) As Byte()
'clientid
'0 - STAR.ini, 1 - SEXP.ini, 2 - W2BN.ini, 3 - D2DV.ini, 4 - D2XP.ini, 5 - WAR3.ini, 6 - W3XP.ini


'----------------------------------------------------------
'BncsUtil.dll
'----------------------------------------------------------
Public Declare Function bncsutil_getVersion Lib "bncsutil.dll" () As Long
Public Declare Function bncsutil_getVersionString_Raw Lib "bncsutil.dll" _
    Alias "bncsutil_getVersionString" (ByVal outBuf As String) As Long

' CheckRevision
Public Declare Function extractMPQNumber Lib "bncsutil.dll" _
    (ByVal mpqName As String) As Long
' [!] You should use checkRevision and getExeInfo (see below) instead of their
'     _Raw counterparts.
Public Declare Function checkRevision_Raw Lib "bncsutil.dll" Alias "checkRevisionFlat" _
    (ByVal valueString As String, ByVal File1 As String, ByVal File2 As String, _
     ByVal File3 As String, ByVal mpqNumber As Long, ByRef checksum As Long) As Long
Public Declare Function getExeInfo_Raw Lib "bncsutil.dll" Alias "getExeInfo" _
    (ByVal FileName As String, ByVal exeInfoString As String, _
    ByVal infoBufferSize As Long, version As Long, ByVal Platform As Long) As Long

' Old Logon System
' [!] You should use doubleHashPassword and hashPassword instead of their
'     _Raw counterparts.  (See below for those functions.)
Public Declare Sub doubleHashPassword_Raw Lib "bncsutil.dll" Alias "doubleHashPassword" _
    (ByVal Password As String, ByVal clientToken As Long, ByVal serverToken As Long, _
    ByVal outBuffer As String)
Public Declare Sub hashPassword_Raw Lib "bncsutil.dll" Alias "hashPassword" _
    (ByVal Password As String, ByVal outBuffer As String)

' Broken SHA-1
Public Declare Sub calcHashBuf Lib "bncsutil.dll" _
    (ByVal Data As String, ByVal Length As Long, ByVal Hash As String)

' CD-Key Decoding

' Call kd_init() first to set up the decoding system, unless you are only using kd_quick().
' Then call kd_create() to create a key decoder "handle" each time you want to
' decode a CD-key.  It will return the handle or -1 on failure.  The handle
' should then be passed as the "decoder" argument to all the other kd_ functions.
' Call kd_free() on the handle when finished with the decoder to free the
' memory it is using.

'Public Declare Function kd_quick Lib "bncsutil.dll" _
    (ByVal Cdkey As String, ByVal clientToken As Long, ByVal serverToken As Long, _
    PublicValue As Long, product As Long, ByVal HashBuffer As String, ByVal BufferLen As Long) As Long
    
    'kd_quick(Cdkey, ClientToken, ServerToken, lngProduct, strBuffer,
    
Public Declare Function kd_init Lib "bncsutil.dll" () As Long
Public Declare Function kd_create Lib "bncsutil.dll" _
    (ByVal Cdkey As String, ByVal KeyLength As Long) As Long
Public Declare Function kd_free Lib "bncsutil.dll" _
    (ByVal decoder As Long) As Long
'Public Declare Function kd_val2Length Lib "bncsutil.dll" _
    (ByVal decoder As Long) As Long
Public Declare Function kd_product Lib "bncsutil.dll" _
    (ByVal decoder As Long) As Long
Public Declare Function kd_val1 Lib "bncsutil.dll" _
    (ByVal decoder As Long) As Long
'Public Declare Function kd_val2 Lib "bncsutil.dll" _
    (ByVal decoder As Long) As Long
'Public Declare Function kd_longVal2 Lib "bncsutil.dll" _
    (ByVal decoder As Long, ByVal Out As String) As Long
Public Declare Function kd_calculateHash Lib "bncsutil.dll" _
    (ByVal decoder As Long, ByVal clientToken As Long, ByVal serverToken As Long) As Long
Public Declare Function kd_getHash Lib "bncsutil.dll" _
    (ByVal decoder As Long, ByVal Out As String) As Long
Public Declare Function kd_isValid Lib "bncsutil.dll" _
    (ByVal decoder As Long) As Long
    
'New Logon System

' Call nls_init() to get a "handle" to an NLS object (nls_init will return 0
' if it encounters an error).  This "handle" should be passed as the "NLS"
' argument to all the other nls_* functions.  You do not need to change the
' username and password to upper-case as nls_init() will do this for you.
' Call nls_free() on the handle to free the memory it's using.
' nls_Account_create() and nls_Account_logon() generate the bodies of
' SID_AUTH_ACCOUNTCREATE and SID_AUTH_ACCOUNTLOGIN packets, respectively.

Public Declare Function nls_init Lib "bncsutil.dll" _
    (ByVal Username As String, ByVal Password As String) As Long 'really returns a POINTER!
'Public Declare Function nls_init_l Lib "bncsutil.dll" _
    (ByVal Username As String, ByVal Username_Length As Long, _
    ByVal Password As String, ByVal Password_Length As Long) As Long
'Public Declare Function nls_reinit Lib "bncsutil.dll" _
    (ByVal nls As Long, ByVal Username As String, ByVal Password As String) As Long
'Public Declare Function nls_reinit_l Lib "bncsutil.dll" _
    (ByVal nls As Long, ByVal Username As String, ByVal Username_Length As Long, _
    ByVal Password As String, ByVal Password_Length As Long) As Long
Public Declare Sub nls_free Lib "bncsutil.dll" _
    (ByVal nls As Long)
Public Declare Function nls_account_create Lib "bncsutil.dll" _
    (ByVal nls As Long, ByVal Buffer As String, ByVal buflen As Long) As Long
'Public Declare Function nls_account_logon Lib "bncsutil.dll" _
    (ByVal nls As Long, ByVal Buffer As String, ByVal buflen As Long) As Long
Public Declare Sub nls_get_A Lib "bncsutil.dll" _
    (ByVal nls As Long, ByVal Out As String)
Public Declare Sub nls_get_M1 Lib "bncsutil.dll" _
    (ByVal nls As Long, ByVal Out As String, ByVal B As String, ByVal Salt As String)
Public Declare Function nls_check_M2 Lib "bncsutil.dll" _
    (ByVal nls As Long, ByVal M2 As String, ByVal B As String, ByVal Salt As String) As Long
Public Declare Function nls_check_signature Lib "bncsutil.dll" _
    (ByVal Address As Long, ByVal Signature As String) As Long
Public Declare Function nls_account_change_proof Lib "bncsutil.dll" _
    (ByVal nls As Long, ByVal Buffer As String, ByVal NewPassword As String, _
    ByVal B As String, ByVal Salt As String) As Long 'returns a new NLS pointer for the new password
'Public Declare Sub nls_get_S Lib "bncsutil.dll" _
    (ByVal nls As Long, ByVal Out As String, ByVal B As String, ByVal Salt As String)
'Public Declare Sub nls_get_K Lib "bncsutil.dll" _
    (ByVal nls As Long, ByVal Out As String, ByVal S As String)
    
Private Declare Function bncsutil_debug_status Lib "bncsutil.dll" () As Long
Private Declare Function bncsutil_set_debug_status Lib "bncsutil.dll" (ByVal NewStatus As Long) As Long
Private Declare Sub bncsutil_debug_message Lib "bncsutil.dll" (ByVal Message As String)
Private Declare Sub bncsutil_debug_dump Lib "bncsutil.dll" (ByVal Message As String, ByVal Length As Long)
Private Declare Function bncsutil_internal_debug_messages Lib "bncsutil.dll" () As Long
    
'  Constants
'---------------------------
Public Const BNCSUTIL_PLATFORM_X86& = &H1
Public Const BNCSUTIL_PLATFORM_WINDOWS& = &H1
Public Const BNCSUTIL_PLATFORM_WIN& = &H1

Public Const BNCSUTIL_PLATFORM_PPC& = &H2
Public Const BNCSUTIL_PLATFORM_MAC& = &H2

Public Const BNCSUTIL_PLATFORM_OSX& = &H3

'  Winsock
'---------------------------
Private Type sockaddr_in
    Family As Integer
    Port As Integer
    Address As Long
    Filler As String * 8
End Type

Private Const prSTAR1 As Long = &H1
Private Const prSTAR2 As Long = &H2
Private Const prSTAR3 As Long = &H17
Private Const prD2DV1 As Long = &H6
Private Const prD2DV2 As Long = &H18
Private Const prD2XP1 As Long = &HA
Private Const prD2XP2 As Long = &H19
Private Const prW2BN As Long = &H4
Private Const prWAR3 As Long = &HE
Private Const prW3XP As Long = &H12
    
Private Declare Function getsockname Lib "ws2_32" (ByVal S As Long, Name As sockaddr_in, NameLen As Long) As Long


'---------------------------------------'
'  VB-Specifc Functions and Properties  '
'---------------------------------------'

Public Property Get version() As String
    version = bncsutil_getVersionString()
End Property

Public Property Get DebugMode() As Boolean
    DebugMode = (bncsutil_debug_status() <> 0)
End Property

Public Property Let DebugMode(ByVal NewValue As Boolean)
    If (NewValue) Then
        bncsutil_set_debug_status 1
    Else
        bncsutil_set_debug_status 0
    End If
End Property

Public Property Get InternalDebugMessages() As Boolean
    InternalDebugMessages = (bncsutil_internal_debug_messages() <> 0)
End Property

Public Sub DebugMessage(Message As String)
    bncsutil_debug_message Message
End Sub

Public Sub DebugHexDump(Data As String, Optional ByVal Length As Long = -1)
    If (Length = -1) Then
        Length = Len(Data)
    End If
    
    bncsutil_debug_dump Data, Length
End Sub


' RequiredVersion must be a version as a.b.c
' Returns True if the current BNCSutil version is sufficent, False if not.
Public Function bncsutil_checkVersion(ByRef RequiredVersion As String) As Boolean
    Dim I&, J&
    Dim Frag() As String
    Dim Req As Long, Check As Long
    bncsutil_checkVersion = False
    Frag = Split(RequiredVersion, ".")
    J = 0
    For I = UBound(Frag) To 0 Step -1
        Check = Check + (CLng(Val(Frag(I))) * (100 ^ J))
        J = J + 1
    Next I
    Check = bncsutil_getVersion()
    If (Check >= Req) Then
        bncsutil_checkVersion = True
    End If
End Function

Public Function bncsutil_getVersionString() As String
    Dim S As String * 12
    Dim Length As Long
    Length = bncsutil_getVersionString_Raw(S)
    bncsutil_getVersionString = Left$(S, Length)
End Function

'CheckRevision
Public Function checkRevision(valueString As String, File1$, File2$, File3$, mpqNumber As Long, checksum As Long) As Boolean
    checkRevision = (checkRevision_Raw(valueString, File1, File2, File3, mpqNumber, checksum) > 0)
End Function

Public Function CheckRevisionA(valueString As String, Files() As String, mpqNumber As Long, checksum As Long) As Boolean
    CheckRevisionA = (checkRevision_Raw(valueString, Files(0), Files(1), Files(2), mpqNumber, checksum) > 0)
End Function

'EXE Information
'Information string (file name, date, time, and size) will be placed in InfoString.
'InfoString does NOT need to be initialized (e.g. InfoString = String$(255, vbNullChar))
'Returns the file version or 0 on failure.
Public Function getExeInfo(EXEFile As String, InfoString As String, Optional ByVal Platform As Long = BNCSUTIL_PLATFORM_WINDOWS) As Long
    Dim version As Long, InfoSize As Long, Result As Long
    Dim I&
    InfoSize = 256
    InfoString = String$(256, vbNullChar)
    Result = getExeInfo_Raw(EXEFile, InfoString, InfoSize, version, Platform)
    If Result = 0 Then
        getExeInfo = 0
        Exit Function
    End If
    While Result > InfoSize
        If InfoSize > 1024 Then
            getExeInfo = 0
            Exit Function
        End If
        InfoSize = InfoSize + 256
        InfoString = String$(InfoSize, vbNullChar)
        Result = getExeInfo_Raw(EXEFile, InfoString, InfoSize, version, Platform)
    Wend
    getExeInfo = version
    I = InStr(InfoString, vbNullChar)
    If I = 0 Then Exit Function
    InfoString = Left$(InfoString, I - 1)
End Function

'OLS Password Hashing
Public Function doubleHashPassword(Password As String, ByVal clientToken&, ByVal serverToken&) As String
    Dim Hash As String * 20
    doubleHashPassword_Raw Password, clientToken, serverToken, Hash
    doubleHashPassword = Hash
End Function

Public Function hashPassword(Password As String) As String
    Dim Hash As String * 20
    hashPassword_Raw Password, Hash
    hashPassword = Hash
End Function

Public Function nls_check_socket_signature(ByVal SocketHandle As Long, Signature As String) As Boolean
    Dim NameLen As Long, Name As sockaddr_in
    
    NameLen = 16
    getsockname SocketHandle, Name, NameLen
    
    nls_check_socket_signature = (nls_check_signature(Name.Address, Signature) <> 0)
End Function

Public Function GetBinaries(ProductID As String) As String()
    Dim Hashes(2) As String, bIn As String
    bIn = App.Path & "\Binaries\"
    Select Case ProductID
        Case "STAR", "SEXP"
            Hashes(0) = bIn & "STAR\StarCraft.exe"
            Hashes(1) = bIn & "STAR\Storm.dll"
            Hashes(2) = bIn & "STAR\Battle.snp"
        Case "W2BN"
            Hashes(0) = bIn & "W2BN\WarCraft II BNE.exe"
            Hashes(1) = bIn & "W2BN\Storm.dll"
            Hashes(2) = bIn & "W2BN\Battle.snp"
        Case "D2DV"
            Hashes(0) = bIn & "D2DV\Game.exe"
            Hashes(1) = bIn & "D2DV\Bnclient.dll"
            Hashes(2) = bIn & "D2DV\D2client.dll"
        Case "D2XP"
            Hashes(0) = bIn & "D2XP\Game.exe"
            Hashes(1) = bIn & "D2XP\Bnclient.dll"
            Hashes(2) = bIn & "D2XP\D2client.dll"
        Case "WAR3", "W3XP"
            Hashes(0) = bIn & "WAR3\War3.exe"
            Hashes(1) = bIn & "WAR3\Storm.dll"
            Hashes(2) = bIn & "WAR3\Game.dll"
    End Select
    GetBinaries = Hashes
End Function

Public Function CdkeyProduct(Cdkey As String) As String
    Dim K As Long, p As Long
    K = kd_create(Cdkey, Len(Cdkey))
    If K = -1 Then Exit Function
    p = kd_product(K)
    kd_free K
    Select Case p
    Case &H1, &H2, &H17: CdkeyProduct = "STAR"
    Case &H6, &H18: CdkeyProduct = "D2DV"
    Case &HA, &H19: CdkeyProduct = "D2XP"
    Case &H4: CdkeyProduct = "W2BN"
    Case &HE: CdkeyProduct = "WAR3"
    Case &H12: CdkeyProduct = "W3XP"
    End Select
End Function

Public Function ValidateCdkey(ProductID As String, Cdkey As String) As Boolean
    'CDKEY PRODUCT VALUES:
    '0x01, 0x02, and 0x17 are Starcraft
    '0x06 and 0x18 are Diablo II
    '0x0A and 0x19 are Lord of Destruction
    '0x04 is Warcraft II
    '0x0E is Warcraft III
    '0x12 is The Frozen Throne
    Dim K As Long, p As Long
    K = kd_create(Cdkey, Len(Cdkey))
    If K = -1 Then Exit Function
    p = kd_product(K)
    kd_free K
    Select Case UCase$(ProductID)
    Case "STAR", "SEXP"
        If p = prSTAR1 Or p = prSTAR2 Or p = prSTAR3 Then ValidateCdkey = True
    Case "D2DV"
        If p = prD2DV1 Or p = prD2DV2 Then ValidateCdkey = True
    Case "D2XP"
        If p = prD2XP1 Or p = prD2XP2 Then ValidateCdkey = True
    Case "W2BN"
        If p = prW2BN Then ValidateCdkey = True
    Case "WAR3"
        If p = prWAR3 Then ValidateCdkey = True
    Case "W3XP"
        If p = prW3XP Then ValidateCdkey = True
    End Select
End Function

