Add Original SDK
This commit is contained in:
321
Dinkey Pro 7.6.1/Samples/Visual Basic .NET/DinkeyRemote/drpf.vb
Normal file
321
Dinkey Pro 7.6.1/Samples/Visual Basic .NET/DinkeyRemote/drpf.vb
Normal file
@@ -0,0 +1,321 @@
|
||||
' !! this file should not be modified
|
||||
|
||||
' DRPF file is in the following format:
|
||||
' REMOTEINFO
|
||||
' LICENCEINFO (however many are needed)
|
||||
' ALGCHANGE (however many are needed)
|
||||
' DATACHANGE blocks (however many are needed) - may refer to external files.
|
||||
|
||||
' Remember: you only need to specify a value if you want to change it. Otherwise you
|
||||
' specify the default "no change" setting. For most entries this is indicated by 0.
|
||||
' However, for MaxNetUsers and LicenceNetUsers it is "-2" because 0 is a valid value to change to.
|
||||
|
||||
Imports System
|
||||
Imports System.Runtime.InteropServices ' so we can marshal our structures as a block of memory
|
||||
Imports System.Text ' for StringBuilder
|
||||
|
||||
' *********** define structures that make up the DRPF file *******************
|
||||
|
||||
Module drpf_code
|
||||
|
||||
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _
|
||||
Structure REMOTEINFO
|
||||
Dim Header1 As Byte ' Should be set to "DRPF" = DinkeyRemote Parameter File
|
||||
Dim Header2 As Byte
|
||||
Dim Header3 As Byte
|
||||
Dim Header4 As Byte
|
||||
Dim Version As Integer ' version of this structure - currently 2
|
||||
<VBFixedString(12), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=12)> _
|
||||
Dim ProdCode As String ' Product Code
|
||||
Dim DongleNumber As UInt32
|
||||
Dim UpdateNumber As Integer
|
||||
<VBFixedString(256), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _
|
||||
Dim Notes As String ' user-defined notes
|
||||
Dim NumLicences As Integer
|
||||
Dim NumAlgs As Integer ' number of algs to set (incl r/w alg)
|
||||
Dim NumDataChanges As Integer ' number of data change blocks specified
|
||||
Dim DataAreaSize As Integer ' -1 = increase as necessary. specifies the new size of the data area
|
||||
Dim PerLicence As Integer ' 0 = no change, 1 = per licence net users, 2 = per product net users
|
||||
Dim MaxNetUsers As Integer ' product net users, unlimited = -1, no change = -2
|
||||
Dim LastUsedDay As Integer ' Day = 0 (only) -> no change
|
||||
Dim LastUsedMonth As Integer
|
||||
Dim LastUsedYear As Integer
|
||||
<VBFixedString(12), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=12)> _
|
||||
Dim DataEncKeyProdCode As String
|
||||
Dim ChangeCodeType As Integer ' 0 = no change, bit0 = only accept secure codes, bit1 = accept secure & short codes
|
||||
Dim CodeType As Integer ' type of code to generate. 0 = secure code, 1 = short code
|
||||
<VBFixedString(256), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _
|
||||
Dim OutputFileName As String ' name of file to output code to. Null (default) -> UpdateCode.ducf
|
||||
Dim LockDongle As Integer ' 1 = lock dongle to user's computer
|
||||
Dim ResetDongleLock As Integer ' 1 = reset the dongle lock so that the dongle can be locked to a new machine
|
||||
End Structure
|
||||
|
||||
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _
|
||||
Structure LICENCEINFO
|
||||
<VBFixedString(256), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _
|
||||
Dim LicenceName As String ' licence name
|
||||
Dim Action As Integer ' 0 = change, 1 = delete, 2 = add
|
||||
Dim AddSetExecs As Integer ' 0 = no change to execs, 1 = add, 2 = set
|
||||
Dim Execs As Integer ' -1 = no limit
|
||||
Dim ExecsWarn As Integer ' 0 = remove warning, -1 = no change
|
||||
Dim ExpiryDay As Integer ' -1 = no limit, 0 = no change
|
||||
Dim ExpiryMonth As Integer
|
||||
Dim ExpiryYear As Integer
|
||||
Dim AddSetMaxDays As Integer ' 0 = no change, 1 = add, 2 = set
|
||||
Dim MaxDays As Integer ' -1 = no limit
|
||||
Dim DaysWarn As Integer ' 0 = remove warning, -1 = no change
|
||||
Dim FeaturesFlag As Integer ' 0 = don't change features, 1 = change features
|
||||
Dim Features As UInt32 ' all values OK
|
||||
Dim LicenceNetUsers As Integer ' unlimited = -1, no change = -2
|
||||
End Structure
|
||||
|
||||
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _
|
||||
Structure ALGCHANGE
|
||||
Dim alg_number As Integer ' number of algorithm to set (0 = r/w algorithm)
|
||||
<VBFixedArray(12), MarshalAs(UnmanagedType.ByValArray, SizeConst:=12)> _
|
||||
Dim alg As Byte() ' coded form of algorithm
|
||||
End Structure
|
||||
|
||||
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _
|
||||
Structure DATACHANGE
|
||||
Dim type As Integer ' 1 = file, 2 = hex data, 3 = ascii, 4 = ascii null-term string
|
||||
Dim offset As Integer ' offset in dongle data memory to write data
|
||||
Dim length As Integer ' length of data to change
|
||||
<VBFixedArray(256), MarshalAs(UnmanagedType.ByValArray, SizeConst:=256)> _
|
||||
Dim data As Byte() ' data to write OR name of data file depending on which method set
|
||||
End Structure
|
||||
|
||||
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _
|
||||
Structure UPDATE_CODE_OUTPUTS
|
||||
<VBFixedString(128*3), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=128*3)> _
|
||||
Dim ShortCode As String ' the update code (for short update codes only)
|
||||
<VBFixedString(256), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _
|
||||
Dim UpdateCodeFile As String ' the output ducf that contains the update code
|
||||
<VBFixedString(8), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=8)> _
|
||||
Dim ConfirmationCode As String ' the confirmation code
|
||||
End Structure
|
||||
|
||||
' ********************** DinkeyRemote Module Imports ************************
|
||||
|
||||
' Loads DRPF from disk and returns handle
|
||||
Declare Ansi Function LoadDRPFFromFile32 Lib "DinkeyRemote32.dll" Alias "LoadDRPFFromFile" (ByVal drpf_file As String, ByRef err_code As Integer) As IntPtr
|
||||
Declare Ansi Function LoadDRPFFromFile64 Lib "DinkeyRemote64.dll" Alias "LoadDRPFFromFile" (ByVal drpf_file As String, ByRef err_code As Integer) As IntPtr
|
||||
|
||||
' Loads DRPF from disk into structures supplied (so we can modify DRPF in memory)
|
||||
Declare Ansi Function ReadDRPFEx32 Lib "DinkeyRemote32.dll" Alias "ReadDRPFEx" (ByVal drpf_file As String, ByRef MyRemoteInfo As REMOTEINFO, ByVal licence_bytes() As Byte, _
|
||||
ByVal algchange_bytes() As Byte, ByVal datachange_bytes() As Byte, ByRef drpf_version As Integer, ByRef drpf_format As Integer) As Integer
|
||||
Declare Ansi Function ReadDRPFEx64 Lib "DinkeyRemote64.dll" Alias "ReadDRPFEx" (ByVal drpf_file As String, ByRef MyRemoteInfo As REMOTEINFO, ByVal licence_bytes() As Byte, _
|
||||
ByVal algchange_bytes() As Byte, ByVal datachange_bytes() As Byte, ByRef drpf_version As Integer, ByRef drpf_format As Integer) As Integer
|
||||
|
||||
' Loads DRPF from structures and returns a handle
|
||||
Declare Ansi Function LoadDRPF32 Lib "DinkeyRemote32.dll" Alias "LoadDRPF" (ByRef MyRemoteInfo As REMOTEINFO, ByVal licence_bytes() As Byte, ByVal algchange_bytes() As Byte, _
|
||||
ByVal datachange_bytes() As Byte, ByRef ret_code As Integer) As IntPtr
|
||||
Declare Ansi Function LoadDRPF64 Lib "DinkeyRemote64.dll" Alias "LoadDRPF" (ByRef MyRemoteInfo As REMOTEINFO, ByVal licence_bytes() As Byte, ByVal algchange_bytes() As Byte, _
|
||||
ByVal datachange_bytes() As Byte, ByRef ret_code As Integer) As IntPtr
|
||||
|
||||
' saves the DRPF file to disk
|
||||
Declare Ansi Function WriteDRPFEx32 Lib "DinkeyRemote32.dll" Alias "WriteDRPFEx" (ByVal drpf_handle As IntPtr, ByVal drpf_file As String, ByVal drpf_format As Integer, _
|
||||
ByVal drpf_version As Integer, ByVal flags As Integer) As Integer
|
||||
Declare Ansi Function WriteDRPFEx64 Lib "DinkeyRemote64.dll" Alias "WriteDRPFEx" (ByVal drpf_handle As IntPtr, ByVal drpf_file As String, ByVal drpf_format As Integer, _
|
||||
ByVal drpf_version As Integer, ByVal flags As Integer) As Integer
|
||||
|
||||
' unloads the DRPF file
|
||||
Declare Ansi Sub UnloadDRPF32 Lib "DinkeyRemote32.dll" Alias "UnloadDRPF" (ByRef drpf_handle As IntPtr)
|
||||
Declare Ansi Sub UnloadDRPF64 Lib "DinkeyRemote64.dll" Alias "UnloadDRPF" (ByRef drpf_handle As IntPtr)
|
||||
|
||||
'main functions
|
||||
Declare Ansi Function GenerateUpdateCode32 Lib "DinkeyRemote32.dll" Alias "GenerateUpdateCode" (ByVal drpf_handle As IntPtr, ByVal dongle_number As UInt32, _
|
||||
ByVal update_number As Integer, ByVal ducf_file As String, ByVal logfile As String, ByRef Outputs As UPDATE_CODE_OUTPUTS) As Integer
|
||||
Declare Ansi Function GenerateUpdateCode64 Lib "DinkeyRemote64.dll" Alias "GenerateUpdateCode" (ByVal drpf_handle As IntPtr, ByVal dongle_number As UInt32, _
|
||||
ByVal update_number As Integer, ByVal ducf_file As String, ByVal logfile As String, ByRef Outputs As UPDATE_CODE_OUTPUTS) As Integer
|
||||
|
||||
' get the message output by DinkeyRemote
|
||||
Declare Ansi Sub GetLastMessage32 Lib "DinkeyRemote32.dll" Alias "GetLastMessage" (ByVal message As StringBuilder, ByVal buffer_size As Integer, ByRef message_length As Integer)
|
||||
Declare Ansi Sub GetLastMessage64 Lib "DinkeyRemote64.dll" Alias "GetLastMessage" (ByVal message As StringBuilder, ByVal buffer_size As Integer, ByRef message_length As Integer)
|
||||
|
||||
' get the extended error (set if an error occurs)
|
||||
Declare Ansi Function GetLastExtendedError32 Lib "DinkeyRemote32.dll" Alias "GetLastExtendedError" () As Integer
|
||||
Declare Ansi Function GetLastExtendedError64 Lib "DinkeyRemote64.dll" Alias "GetLastExtendedError" () As Integer
|
||||
|
||||
' ********************** Constants ************************
|
||||
Public Const DRPF_VERSION As Integer = 2 ' current DRPF version
|
||||
|
||||
' WriteDRPFEx API flags
|
||||
Public Const FLAGS_LOSE_FEATURES As Integer = 1 ' means that you can save the DRPF file to an earlier version even if it means losing some new features that have been currently set
|
||||
|
||||
' constants for drpf_format in ReadDRPFEx and WriteDRPFEx functions
|
||||
Public Const DRPF_FORMAT_BINARY As Integer = 1
|
||||
Public Const DRPF_FORMAT_JSON As Integer = 2
|
||||
Public Const DRPF_FORMAT_JSON_MIN As Integer = 3 ' this value is only used with WriteDRPEx. ReadDRPFEx cannot return this value.
|
||||
|
||||
' private constants
|
||||
Private const MAX_LICENCES As Integer = 255 ' max number of licence changes in a DRPF file (theoretically unlimited but easier if we limit it)
|
||||
Private Const MAX_ALG_CHANGES As Integer = 21 ' max number of alg changes in DRPF file
|
||||
Private Const MAX_DATA_CHANGES As Integer = 127 ' max number of data area changes in DRPF file
|
||||
|
||||
' ********************** API Functions ************************
|
||||
' We only want to load the correct DLL for the bit-ness of the computer. The other DLL may not exist.
|
||||
' if the appropriate DLL does not exist in the same directory as this test program you will receive a DllNotFoundException
|
||||
|
||||
' call the correct dll depending on whether we are running 32-bit or 64-bit code
|
||||
Function LoadDRPFFromFile(ByVal drpf_file As String, ByRef err_code As Integer) As IntPtr
|
||||
If (IntPtr.Size = 4) Then
|
||||
LoadDRPFFromFile = LoadDRPFFromFile32(drpf_file, err_code)
|
||||
Else
|
||||
LoadDRPFFromFile = LoadDRPFFromFile64(drpf_file, err_code)
|
||||
End If
|
||||
End Function
|
||||
|
||||
' we have to do some marshalling of arrays of bytes into arrays of structures
|
||||
Function ReadDRPFEx(ByVal drpf_file As String, ByRef MyRemoteInfo As REMOTEINFO, ByRef LicenceInfoArray() As LICENCEINFO, ByRef AlgChangesArray() As ALGCHANGE, _
|
||||
ByRef DataChangesArray() As DATACHANGE, ByRef drpf_version As Integer, ByRef drpf_format As Integer) As Integer
|
||||
Dim i As Integer
|
||||
Dim MyLicenceInfo As New LICENCEINFO
|
||||
Dim licence_bytes(MAX_LICENCES * Marshal.SizeOf(MyLicenceInfo)) As Byte
|
||||
Dim licence_bytes_one_struct(Marshal.SizeOf(MyLicenceInfo)) As Byte
|
||||
Dim MyAlgChanges As New ALGCHANGE
|
||||
Dim algchange_bytes(MAX_ALG_CHANGES * Marshal.SizeOf(MyAlgChanges)) As Byte
|
||||
Dim algchange_bytes_one_struct(Marshal.SizeOf(MyAlgChanges)) As Byte
|
||||
Dim MyDataChanges As New DATACHANGE
|
||||
Dim datachange_bytes(MAX_DATA_CHANGES * Marshal.SizeOf(MyDataChanges)) As Byte
|
||||
Dim datachange_bytes_one_struct(Marshal.SizeOf(MyDataChanges)) As Byte
|
||||
Dim MyGC As GCHandle
|
||||
MyRemoteInfo = New REMOTEINFO
|
||||
|
||||
If (IntPtr.Size = 4) Then
|
||||
ReadDRPFEx = ReadDRPFEx32(drpf_file, MyRemoteInfo, licence_bytes, algchange_bytes, datachange_bytes, drpf_version, drpf_format)
|
||||
Else
|
||||
ReadDRPFEx = ReadDRPFEx64(drpf_file, MyRemoteInfo, licence_bytes, algchange_bytes, datachange_bytes, drpf_version, drpf_format)
|
||||
End If
|
||||
|
||||
If ReadDRPFEx <> 0 Then
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' convert byte array to an array of structs
|
||||
ReDim LicenceInfoArray(MyRemoteInfo.NumLicences)
|
||||
For i = 0 To MyRemoteInfo.NumLicences - 1
|
||||
LicenceInfoArray(i) = New LICENCEINFO
|
||||
Array.Copy(licence_bytes, i * Marshal.SizeOf(MyLicenceInfo.GetType), licence_bytes_one_struct, 0, Marshal.SizeOf(MyLicenceInfo.GetType))
|
||||
MyGC = GCHandle.Alloc(licence_bytes_one_struct, GCHandleType.Pinned)
|
||||
LicenceInfoArray(i) = Marshal.PtrToStructure(MyGC.AddrOfPinnedObject, MyLicenceInfo.GetType)
|
||||
MyGC.Free()
|
||||
Next
|
||||
|
||||
ReDim AlgChangesArray(MyRemoteInfo.NumAlgs)
|
||||
For i = 0 To MyRemoteInfo.NumAlgs - 1
|
||||
AlgChangesArray(i) = New ALGCHANGE
|
||||
Array.Copy(algchange_bytes, i * Marshal.SizeOf(MyAlgChanges.GetType), algchange_bytes_one_struct, 0, Marshal.SizeOf(MyAlgChanges.GetType))
|
||||
MyGC = GCHandle.Alloc(algchange_bytes_one_struct, GCHandleType.Pinned)
|
||||
AlgChangesArray(i) = Marshal.PtrToStructure(MyGC.AddrOfPinnedObject, MyAlgChanges.GetType)
|
||||
MyGC.Free()
|
||||
Next
|
||||
|
||||
ReDim DataChangesArray(MyRemoteInfo.NumDataChanges)
|
||||
For i = 0 To MyRemoteInfo.NumDataChanges - 1
|
||||
DataChangesArray(i) = New DATACHANGE
|
||||
Array.Copy(datachange_bytes, i * Marshal.SizeOf(MyDataChanges.GetType), datachange_bytes_one_struct, 0, Marshal.SizeOf(MyDataChanges.GetType))
|
||||
MyGC = GCHandle.Alloc(datachange_bytes_one_struct, GCHandleType.Pinned)
|
||||
DataChangesArray(i) = Marshal.PtrToStructure(MyGC.AddrOfPinnedObject, MyDataChanges.GetType)
|
||||
MyGC.Free()
|
||||
Next
|
||||
|
||||
End Function
|
||||
|
||||
Function LoadDRPF(ByRef MyRemoteInfo As REMOTEINFO, ByRef LicenceInfoArray() As LICENCEINFO, ByRef AlgChangesArray() As ALGCHANGE, ByRef DataChangesArray() As DATACHANGE, _
|
||||
ByRef ret_code As Integer) As IntPtr
|
||||
Dim i As Integer
|
||||
Dim MyLicenceInfo As New LICENCEINFO
|
||||
Dim licence_bytes(MAX_LICENCES * Marshal.SizeOf(MyLicenceInfo)) As Byte
|
||||
Dim licence_bytes_one_struct(Marshal.SizeOf(MyLicenceInfo)) As Byte
|
||||
Dim MyAlgChanges As New ALGCHANGE
|
||||
Dim algchange_bytes(MAX_ALG_CHANGES * Marshal.SizeOf(MyAlgChanges)) As Byte
|
||||
Dim algchange_bytes_one_struct(Marshal.SizeOf(MyAlgChanges)) As Byte
|
||||
Dim MyDataChanges As New DATACHANGE
|
||||
Dim datachange_bytes(MAX_DATA_CHANGES * Marshal.SizeOf(MyDataChanges)) As Byte
|
||||
Dim datachange_bytes_one_struct(Marshal.SizeOf(MyDataChanges)) As Byte
|
||||
Dim MyGC As GCHandle
|
||||
|
||||
' convert array of structs to byte arrays
|
||||
For i = 0 To MyRemoteInfo.NumLicences - 1
|
||||
MyGC = GCHandle.Alloc(licence_bytes_one_struct, GCHandleType.Pinned)
|
||||
Marshal.StructureToPtr(LicenceInfoArray(i), MyGC.AddrOfPinnedObject, False)
|
||||
MyGC.Free()
|
||||
Array.Copy(licence_bytes_one_struct, 0, licence_bytes, i * Marshal.SizeOf(MyLicenceInfo.GetType), Marshal.SizeOf(MyLicenceInfo.GetType))
|
||||
Next
|
||||
|
||||
For i = 0 To MyRemoteInfo.NumAlgs - 1
|
||||
MyGC = GCHandle.Alloc(algchange_bytes_one_struct, GCHandleType.Pinned)
|
||||
Marshal.StructureToPtr(AlgChangesArray(i), MyGC.AddrOfPinnedObject, False)
|
||||
MyGC.Free()
|
||||
Array.Copy(algchange_bytes_one_struct, 0, algchange_bytes, i * Marshal.SizeOf(MyAlgChanges.GetType), Marshal.SizeOf(MyAlgChanges.GetType))
|
||||
Next
|
||||
|
||||
For i = 0 To MyRemoteInfo.NumDataChanges - 1
|
||||
MyGC = GCHandle.Alloc(datachange_bytes_one_struct, GCHandleType.Pinned)
|
||||
Marshal.StructureToPtr(DataChangesArray(i), MyGC.AddrOfPinnedObject, False)
|
||||
MyGC.Free()
|
||||
Array.Copy(datachange_bytes_one_struct, 0, datachange_bytes, i * Marshal.SizeOf(MyDataChanges.GetType), Marshal.SizeOf(MyDataChanges.GetType))
|
||||
Next
|
||||
|
||||
If (IntPtr.Size = 4) Then
|
||||
LoadDRPF = LoadDRPF32(MyRemoteInfo, licence_bytes, algchange_bytes, datachange_bytes, ret_code)
|
||||
Else
|
||||
LoadDRPF = LoadDRPF64(MyRemoteInfo, licence_bytes, algchange_bytes, datachange_bytes, ret_code)
|
||||
End If
|
||||
|
||||
End Function
|
||||
|
||||
Function WriteDRPFEx(ByVal drpf_handle As IntPtr, ByVal drpf_file As String, ByVal drpf_format As Integer, ByVal drpf_version As Integer, ByVal flags As Integer) As Integer
|
||||
If (IntPtr.Size = 4) Then
|
||||
WriteDRPFEx = WriteDRPFEx32(drpf_handle, drpf_file, drpf_format, drpf_version, flags)
|
||||
Else
|
||||
WriteDRPFEx = WriteDRPFEx64(drpf_handle, drpf_file, drpf_format, drpf_version, flags)
|
||||
End If
|
||||
End Function
|
||||
|
||||
Sub UnloadDRPF(ByRef drpf_handle As IntPtr)
|
||||
If (IntPtr.Size = 4) Then
|
||||
UnloadDRPF32(drpf_handle)
|
||||
Else
|
||||
UnloadDRPF64(drpf_handle)
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Function GenerateUpdateCode(ByVal drpf_handle As IntPtr, ByVal dongle_number As UInt32, ByVal update_number As Integer, ByVal ducf_file As String, _
|
||||
ByVal logfile As String, ByRef Outputs As UPDATE_CODE_OUTPUTS) As Integer
|
||||
If (IntPtr.Size = 4) Then
|
||||
GenerateUpdateCode = GenerateUpdateCode32(drpf_handle, dongle_number, update_number, ducf_file, logfile, Outputs)
|
||||
Else
|
||||
GenerateUpdateCode = GenerateUpdateCode64(drpf_handle, dongle_number, update_number, ducf_file, logfile, Outputs)
|
||||
End If
|
||||
End Function
|
||||
|
||||
' do a bit of work here to make the function easier to use for VB.NET
|
||||
Function GetLastMessage() As String
|
||||
Dim length, dummy As Integer
|
||||
Dim message As StringBuilder
|
||||
|
||||
If (IntPtr.Size = 4) Then
|
||||
GetLastMessage32(Nothing, 0, length)
|
||||
message = New StringBuilder(length)
|
||||
GetLastMessage32(message, length, dummy)
|
||||
Else
|
||||
GetLastMessage64(Nothing, 0, length)
|
||||
message = New StringBuilder(length)
|
||||
GetLastMessage64(message, length, dummy)
|
||||
End If
|
||||
|
||||
Return message.ToString()
|
||||
End Function
|
||||
|
||||
Function GetLastExtendedError() As Integer
|
||||
If (IntPtr.Size = 4) Then
|
||||
GetLastExtendedError = GetLastExtendedError32()
|
||||
Else
|
||||
GetLastExtendedError = GetLastExtendedError64()
|
||||
End If
|
||||
End Function
|
||||
|
||||
|
||||
End Module
|
||||
Reference in New Issue
Block a user