How to passing variables from c++ to vb.net - vb.net

I have
c++ api function :
`int readMemory(unsigned int address, unsigned char** data, unsigned int size);`
I want to translate it into vb.net function:
Public Function readMemory(
ByVal address As UInteger, ByRef data As IntPtr, ByVal size As UInteger) As Integer
End Function
When I call readMemory function in vb.net:
Dim startAddress As UInteger = &H801FFFA
Dim dataStruct As IntPtr
Dim size As Integer = 1
Dim readMemoryFlag As Integer = 0
readMemoryFlag = readMemory(startAddress, dataStruct, 0)
Then I getting
access violation exception
. When I declare startAddress as Uint64 then I not getting the exception but size is very random. Any help ?

Related

An error while trying to retrieve and decrypt login in Firefox

I'm working on programm on VB.net to retrieve data from Firefox browser. I have an error while trying to use "PK11SDR_Decrypt" method from nss3.lib. "PK11SDR_Decrypt" returns -1. I don't have master password. I think that the problem in Ctypes/marshalling/base64 decoding. This is the code of function.
Public Function DecryptFF(ByVal str As String)
On Error Resume Next
Dim tSecDec As New TSECItem
Dim e As Integer
Dim sb As New System.Text.StringBuilder(str)
Dim hi2 As Integer = NSSBase64_DecodeBuffer(IntPtr.Zero, IntPtr.Zero, sb, sb.Length)
Dim item As TSECItem = DirectCast(Marshal.PtrToStructure(New IntPtr(hi2), GetType(TSECItem)), TSECItem)
e = PK11SDR_Decrypt(item, tSecDec, 0)
If e = 0 Then
If tSecDec.SECItemLen <> 0 Then
Dim mozDecryptedData = New Byte(tSecDec.SECItemLen - 1) {}
Marshal.Copy(New IntPtr(tSecDec.SECItemData), mozDecryptedData, 0, tSecDec.SECItemLen)
Return Encoding.UTF8.GetString(mozDecryptedData)
End If
End If
Return String.Empty
End Function
And other code part.
Public NSS3 As IntPtr
Public hModuleList As New List(Of IntPtr)
<StructLayout(LayoutKind.Sequential)>
Public Structure TSECItem
Public SECItemType As Integer
Public SECItemData As Integer
Public SECItemLen As Integer
End Structure
Public Function NSS_Init(ByVal configdir As String) As Long
Dim PathM = FindFirefoxInstallationPath()
hModuleList.Add(LoadLibrary(PathM & "\msvcp140.dll"))
hModuleList.Add(LoadLibrary(PathM & "\mozglue.dll"))
hModuleList.Add(LoadLibrary(PathM & "\mozavutils.dll"))
NSS3 = LoadLibrary(PathM & "\nss3.dll")
hModuleList.Add(NSS3)
Return CreateAPI(Of DLLFunctionDelegate)(NSS3, "NSS_Init")(configdir)
End Function
Public Function CreateAPI(Of T)(ByVal hModule As IntPtr, ByVal method As String) As T 'Simple overload to avoid loading the same library every time
Return DirectCast(DirectCast(Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, method), GetType(T)), Object), T)
End Function
Public Function NSSBase64_DecodeBuffer(ByVal arenaOpt As IntPtr, ByVal outItemOpt As IntPtr, ByVal inStr As System.Text.StringBuilder, ByVal inLen As Integer) As Integer
Dim pProc As IntPtr = GetProcAddress(NSS3, "NSSBase64_DecodeBuffer")
Dim dll As DLLFunctionDelegate4 = DirectCast(Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(pProc, GetType(DLLFunctionDelegate4)), DLLFunctionDelegate4)
Return dll(arenaOpt, outItemOpt, inStr, inLen)
End Function
Public Function PK11SDR_Decrypt(ByRef data As TSECItem, ByRef result As TSECItem, ByVal cx As Integer) As Integer
Dim pProc As IntPtr = GetProcAddress(NSS3, "PK11SDR_Decrypt")
Dim dll As DLLFunctionDelegate5 = DirectCast(Marshal.GetDelegateForFunctionPointer(pProc, GetType(DLLFunctionDelegate5)), DLLFunctionDelegate5)
Return dll(data, result, cx)
End Function
<UnmanagedFunctionPointer(CallingConvention.Cdecl)>
Public Delegate Function DLLFunctionDelegate5(ByRef data As TSECItem, ByRef result As TSECItem, ByVal cx As Integer) As Integer
<UnmanagedFunctionPointer(CallingConvention.Cdecl)>
Public Delegate Function DLLFunctionDelegate6() As Long
Public Function NSS_Shutdown() As Long
Return CreateAPI(Of DLLFunctionDelegate6)(NSS3, "NSS_Shutdown")()
End Function
<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Public Shared Function LoadLibrary(ByVal dllFilePath As String) As IntPtr
End Function
<DllImport("kernel32.dll", SetLastError:=True, EntryPoint:="FreeLibrary")>
Public Shared Function FreeLibrary(ByVal hModule As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Ansi, ExactSpelling:=True)>
Public Shared Function GetProcAddress(ByVal hModule As IntPtr, ByVal procName As String) As IntPtr
End Function
DecryptFF get as argument the encrypted login fron logins.json file. Here is the part of code
Dim JSONRegex As New Regex("\""(hostname|encryptedPassword|encryptedUsername)"":""(.*?)""")
Dim mozMC = JSONRegex.Matches(Logins)
For I = 0 To mozMC.Count - 1 Step 3
Dim host = mozMC(I).Groups(2).Value
Dim usr = mozMC(I + 1).Groups(2).Value
Dim pas = mozMC(I + 2).Groups(2).Value
Account = (DecryptFF(usr))
Thank you for your help!

FTDI libMPSSE.dll I2C_DeviceRead() always returns 0xFF

I make import of the FTDI Chip libMPSSE.dll and use it in I2C mode. My test device is sensor BMP280. I try read it's ID register, that contains 0x58 value. The problem is method I2C_DeviceRead() always returns 0xFF, although I see with the logic analyzer that sensor answers correctly:
Original declarations of the methods are:
FT_STATUS I2C_DeviceRead(FT_HANDLE handle, uint32 deviceAddress, uint32 sizeToTransfer, uint8 *buffer, uint32 *sizeTransferred, uint32 options)
FT_STATUS I2C_DeviceWrite(FT_HANDLE handle, uint32 deviceAddress, uint32 sizeToTransfer, uint8 *buffer, uint32 *sizeTransferred, uint32 options)
I import this methods like this:
<DllImport(DLL_MPSSE_PATH, SetLastError:=True, CallingConvention:=CallingConvention.Cdecl)>
Private Shared Function I2C_DeviceRead(ByVal handle As Integer, ByVal deviceAddress As Integer, ByVal sizeToTransfer As Integer, ByVal buffer As Byte(), ByRef sizeTransfered As Integer, ByVal options As I2C_TRANSFER_OPTIONS) As Integer
End Function
<DllImport(DLL_MPSSE_PATH, SetLastError:=True, CallingConvention:=CallingConvention.Cdecl)>
Private Shared Function I2C_DeviceWrite(ByVal handle As Integer, ByVal deviceAddress As Integer, ByVal sizeToTransfer As Integer, ByVal buffer As Byte(), ByRef sizeTransfered As Integer, ByVal options As I2C_TRANSFER_OPTIONS) As Integer
End Function
I2C_TRANSFER_OPTIONS is the Enum with control bits mask.
And further call it (pseudo-code) according to sensor datasheet. First, write register address:
Dim sensorAddr as Integer = &H77
Dim idRegister as Byte() = {&HD0}
Dim options as Integer = &H13 'I2C_TRANSFER_OPTIONS_START_BIT | I2C_TRANSFER_OPTIONS_STOP_BIT | I2C_TRANSFER_OPTIONS_FAST_TRANSFER_BYTES
Dim transferred as Integer = 0
I2C_DeviceWrite(myhandle, sensorAddr, 1, idRegister, transferred, options)
Then read content of the sensor's register:
Dim readLen as Integer = 1
Dim readBuf(readLen-1) as Byte
I2C_DeviceRead(myhandle, sensorAddr, readLen, readBuf, transferred, options)
If readLen is, e.g. 4, so readBuf() contains four 0xFF, although sensor writes to data line (SDA on the picture) other values:
What is the problem with my code? Why I can write correctly, but reading is wrong? Thank you!

VBA with WinSock2: send() sends wrong data

I'm trying to use WinSock2 in VBA to send (and later on, receive) data from a localhost TCP Stream.
For now, I've mostly been trying to replicate the client sample from here,https://msdn.microsoft.com/en-us/library/windows/desktop/ms738630(v=vs.85).aspx
My code "almost" works; I can create a socket & establish a connection to my server.
Sending data (e.g. invoking the send() function of ws2_32.dll) is odd, though..
In the example below, the server would indeed receive a byte array of length 10, but its contents are odd. The first 4 bytes of the array are set (but vary with each call), the last 6 bytes are always 0.
I'm not really sure what's going on; given I run this in 32bit Excel = pointers would be 4 bytes long, it almost seems a bit like only the address of some variable is being sent.
When I try to call this function passing an explicit address of the data (the SendWithPtr() call that is commented out), same issue occurs, so that doesn't help either.
Does anyone know what's going on there? Do I need to call the send() function different in any way?!
Thanks
VBA Code:
Option Explicit
' Constants ----------------------------------------------------------
Const INVALID_SOCKET = -1
Const WSADESCRIPTION_LEN = 256
Const SOCKET_ERROR = -1
' Typ definitions ----------------------------------------------------
Private Type WSADATA
wVersion As Integer
wHighVersion As Integer
szDescription(0 To WSADESCRIPTION_LEN) As Byte
szSystemStatus(0 To WSADESCRIPTION_LEN) As Byte
iMaxSockets As Integer
iMaxUdpDg As Integer
lpVendorInfo As Long
End Type
Private Type ADDRINFO
ai_flags As Long
ai_family As Long
ai_socktype As Long
ai_protocol As Long
ai_addrlen As Long
ai_canonName As LongPtr 'strptr
ai_addr As LongPtr 'p sockaddr
ai_next As LongPtr 'p addrinfo
End Type
' Enums ---------------------------------------------------------------
Enum AF
AF_UNSPEC = 0
AF_INET = 2
AF_IPX = 6
AF_APPLETALK = 16
AF_NETBIOS = 17
AF_INET6 = 23
AF_IRDA = 26
AF_BTH = 32
End Enum
Enum sock_type
SOCK_STREAM = 1
SOCK_DGRAM = 2
SOCK_RAW = 3
SOCK_RDM = 4
SOCK_SEQPACKET = 5
End Enum
' External functions --------------------------------------------------
Public Declare Function WSAStartup Lib "ws2_32.dll" (ByVal wVersionRequested As Integer, ByRef data As WSADATA) As Long
Public Declare Function connect Lib "ws2_32.dll" (ByVal socket As Long, ByVal SOCKADDR As Long, ByVal namelen As Long) As Long
Public Declare Sub WSACleanup Lib "ws2_32.dll" ()
Private Declare PtrSafe Function GetAddrInfo Lib "ws2_32.dll" Alias "getaddrinfo" (ByVal NodeName As String, ByVal ServName As String, ByVal lpHints As LongPtr, lpResult As LongPtr) As Long
Public Declare Function ws_socket Lib "ws2_32.dll" Alias "socket" (ByVal AF As Long, ByVal stype As Long, ByVal Protocol As Long) As Long
Public Declare Function closesocket Lib "ws2_32.dll" (ByVal socket As Long) As Long
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal length As Long)
Public Declare Function Send Lib "ws2_32.dll" Alias "send" (ByVal s As Long, ByRef buf() As Byte, ByVal buflen As Long, ByVal flags As Long) As Long
Public Declare Function SendWithPtr Lib "ws2_32.dll" Alias "send" (ByVal s As Long, ByVal bufPtr As Long, ByVal buflen As Long, ByVal flags As Long) As Long
Private Declare PtrSafe Function WSAGetLastError Lib "ws2_32.dll" () As Long
Private Declare Function VarPtrArray Lib "VBE7" Alias "VarPtr" (var() As Any) As Long
Sub TestWinsock()
Dim m_wsaData As WSADATA
Dim m_RetVal As Integer
Dim m_Hints As ADDRINFO
Dim m_ConnSocket As Long: m_ConnSocket = INVALID_SOCKET
Dim Server As String
Dim port As String
Dim pAddrInfo As LongPtr
Dim RetVal As Long
Dim lastError As Long
RetVal = WSAStartup(MAKEWORD(2, 2), m_wsaData)
If (RetVal <> 0) Then
LogError "WSAStartup failed with error " & RetVal, WSAGetLastError()
Call WSACleanup
Exit Sub
End If
m_Hints.ai_family = AF.AF_UNSPEC
m_Hints.ai_socktype = sock_type.SOCK_STREAM
Server = "localhost"
port = "5001"
RetVal = GetAddrInfo(Server, port, VarPtr(m_Hints), pAddrInfo)
If (RetVal <> 0) Then
LogError "Cannot resolve address " & Server & " and port " & port & ", error " & RetVal, WSAGetLastError()
Call WSACleanup
Exit Sub
End If
m_Hints.ai_next = pAddrInfo
Dim connected As Boolean: connected = False
Do While m_Hints.ai_next > 0
CopyMemory m_Hints, ByVal m_Hints.ai_next, LenB(m_Hints)
m_ConnSocket = ws_socket(m_Hints.ai_family, m_Hints.ai_socktype, m_Hints.ai_protocol)
If (m_ConnSocket = INVALID_SOCKET) Then
LogError "Error opening socket, error " & RetVal
Else
Dim connectionResult As Long
connectionResult = connect(m_ConnSocket, m_Hints.ai_addr, m_Hints.ai_addrlen)
If connectionResult <> SOCKET_ERROR Then
connected = True
Exit Do
End If
LogError "connect() to socket failed"
closesocket (m_ConnSocket)
End If
Loop
If Not connected Then
LogError "Fatal error: unable to connect to the server", WSAGetLastError()
Call WSACleanup
Exit Sub
End If
Dim SendBuf() As Byte
SendBuf = StrConv("Message #1", vbFromUnicode)
Dim buflen As Integer
buflen = UBound(SendBuf) - LBound(SendBuf) + 1
' !!!!!!!!!!!
' !! Send() does not seem to send the right bytes !!
' !!!!!!!!!!!
RetVal = Send(m_ConnSocket, SendBuf, buflen, 0)
' The following does not work either:
' RetVal = SendWithPtr(m_ConnSocket, VarPtrArray(SendBuf), buflen, 0)
If RetVal = SOCKET_ERROR Then
LogError "send() failed", WSAGetLastError()
Call WSACleanup
Exit Sub
Else
Debug.Print "sent " & RetVal & " bytes"
End If
RetVal = closesocket(m_ConnSocket)
If RetVal <> 0 Then
LogError "closesocket() failed", WSAGetLastError()
Call WSACleanup
Else
Debug.Print "closed socket"
End If
End Sub
Public Function MAKEWORD(Lo As Byte, Hi As Byte) As Integer
MAKEWORD = Lo + Hi * 256& Or 32768 * (Hi > 127)
End Function
Private Sub LogError(msg As String, Optional ErrorCode As Long = -1)
If ErrorCode > -1 Then
msg = msg & " (error code " & ErrorCode & ")"
End If
Debug.Print msg
End Sub
Server code, just for reference:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace Server
{
class Program
{
static void Main(string[] args)
{
var address = Dns.GetHostEntry("localhost").AddressList[0];
var addressBytes = address.GetAddressBytes();
var port = 5001;
var ipEndpoint = new IPEndPoint(address, port);
var listener = new TcpListener(ipEndpoint);
listener.Start();
bool done = false;
TcpClient tcpClient = null;
try
{
while (!done)
{
Thread.Sleep(10);
Console.WriteLine("Waiting for broadcast");
tcpClient = listener.AcceptTcpClient();
byte[] bytes = new byte[10];
NetworkStream stream = tcpClient.GetStream();
var bytesRead = stream.Read(bytes, 0, bytes.Length);
// when called via the VBA sample, "bytes" will contain odd values.
// when called through Microsoft's C++ sample, everything works fine
}
}
finally {
tcpClient?.Close();
}
}
}
}
You need to pass the address of the data within the array - i.e. the address of the first element (because the address of the variable itself is the address of the enclosing SAFEARRAY)
Change the send argument to ByRef buf As Any
Pass in the address of the first array element:
RetVal = Send(m_ConnSocket, SendBuf(0), buflen, 0)
Const MAX_BUFFER_LENGTH As Long = 8192
Dim arrBuffers(1 To MAX_BUFFER_LENGTH) As Byte
Dim lngBytesReceived As Long
Dim strTempBuffer As String
lngBytesReceived = recv(s1, arrBuffers(1), MAX_BUFFER_LENGTH, 0&)
strTempBuffer = StrConv(arrBuffers, vbUnicode)
strBuffer = Left$(strTempBuffer, lngBytesReceived)
Dim arrBuffers(1 To MAX_BUFFER_LENGTH) As Byte
Dim lngBytesReceived As Long
Dim strTempBuffer As String
lngBytesReceived = recv(s1, arrBuffers(1), MAX_BUFFER_LENGTH, 0&)
If lngBytesReceived > 0 Then
'
' If we have received some data, convert it to the Unicode
' string that is suitable for the Visual Basic String data type
'
strTempBuffer = StrConv(arrBuffers, vbUnicode)
'
' Remove unused bytes
'
strBuffer = Left$(strTempBuffer, lngBytesReceived)

VBA Winsock Not Working with Longer Port Length (sin_port)

I've created the below Excel VBA code which uses the Winsock API to connect to an IP address, send along a text string from an Excel cell and receive a text string in return.
My code was originally pointed to the IP address 127.0.0.1 with port 80 and had no issues. However, I've since had to update the destination port to 60401 which also required changing the port input variable sin_port to Long, as the new port exceeds the max length of a VBA Integer. After these updates the code still compiles, but the Winsock API doesn't process anything??
I think the error may be related to the sin_zero variable which might be buffering too many zeros with the port length increase? I've tried adjusting this variable and diagnosing the code elsewhere, but it still doesn't process after several hours of tinkering with the code.
All help is really appreciated. Thank you.
Original Code - Port 80 - Compiles and processes successfully
Type WSAData
wVersion As Integer
wHighVersion As Integer
szDescription(0 To 255) As Byte
szSystemStatus(0 To 128) As Byte
iMaxSockets As Integer
iMaxUdpDg As Integer
lpVendorInfo As Long
End Type
Type sockaddr_in
sin_family As Integer
sin_port As Integer
sin_addr As Long
sin_zero(0 to 7) As Byte
End Type
Public Declare Function WSAStartup Lib "ws2_32" ( _
ByVal wVersionRequired As Integer, ByRef lpWSAData As WSAData) As Long
Public Declare Function WSAGetLastError Lib "ws2_32" () As Long
Public Declare Function socket Lib "ws2_32" ( _
ByVal af As Long, ByVal socktype As Long, ByVal protocol As Long) As Long
Public Declare Function connect Lib "ws2_32" ( _
ByVal sock As Long, ByRef name As sockaddr_in, ByVal namelen As Integer) As Long
Public Declare Function send Lib "ws2_32" ( _
ByVal sock As Long, ByVal buf As String, ByVal bufLen As Long, ByVal flags As Long) As Long
Public Declare Function recv Lib "ws2_32" ( _
ByVal sock As Long, ByRef buf As Byte, ByVal bufLen As Long, ByVal flags As Long) As Long
Public Declare Function inet_addr Lib "ws2_32" ( _
ByVal s As String) As Long
Public Declare Function htons Lib "ws2_32" ( _
ByVal hostshort As Long) As Long
Function FetchData() As String
Dim iReturn As Long
Dim wsaDat As WSAData
iReturn = WSAStartup(&H202, wsaDat)
If iReturn <> 0 Then
MsgBox "WSAStartup failed", 0, ""
End If
Dim sock As Long
Dim sock1 As Long
Dim lasterr As Long
Dim i As Long
Dim buf(10) As Byte
Dim s As String
Dim j As Integer
sock = socket(2, 1, 6)
Dim addr As sockaddr_in
addr.sin_family = 2
addr.sin_port = htons(80)
addr.sin_addr = inet_addr("127.0.0.1")
i = connect(sock, addr, LenB(addr))
i = send(sock, "*SRTF" & vbCr, 6, 0)
i = recv(sock, buf(0), 10, 0)
For j = 0 To i - 1
s = s & Chr(buf(j))
Next
FetchData = s
End Function
Sub Button2_Click()
Range("C3").Formula = FetchData()
End Sub
New Code - Port 60401 - Compiles, but doesn't process?
Type WSAData
wVersion As Integer
wHighVersion As Integer
szDescription(0 To 255) As Byte
szSystemStatus(0 To 128) As Byte
iMaxSockets As Integer
iMaxUdpDg As Integer
lpVendorInfo As Long
End Type
Type sockaddr_in
sin_family As Integer
sin_port As Long
sin_addr As Long
sin_zero(0 to 7) As Byte
End Type
Public Declare Function WSAStartup Lib "ws2_32" ( _
ByVal wVersionRequired As Integer, ByRef lpWSAData As WSAData) As Long
Public Declare Function WSAGetLastError Lib "ws2_32" () As Long
Public Declare Function socket Lib "ws2_32" ( _
ByVal af As Long, ByVal socktype As Long, ByVal protocol As Long) As Long
Public Declare Function connect Lib "ws2_32" ( _
ByVal sock As Long, ByRef name As sockaddr_in, ByVal namelen As Integer) As Long
Public Declare Function send Lib "ws2_32" ( _
ByVal sock As Long, ByVal buf As String, ByVal bufLen As Long, ByVal flags As Long) As Long
Public Declare Function recv Lib "ws2_32" ( _
ByVal sock As Long, ByRef buf As Byte, ByVal bufLen As Long, ByVal flags As Long) As Long
Public Declare Function inet_addr Lib "ws2_32" ( _
ByVal s As String) As Long
Public Declare Function htons Lib "ws2_32" ( _
ByVal hostshort As Long) As Long
Function FetchData() As String
Dim iReturn As Long
Dim wsaDat As WSAData
iReturn = WSAStartup(&H202, wsaDat)
If iReturn <> 0 Then
MsgBox "WSAStartup failed", 0, ""
End If
Dim sock As Long
Dim sock1 As Long
Dim lasterr As Long
Dim i As Long
Dim buf(10) As Byte
Dim s As String
Dim j As Integer
sock = socket(2, 1, 6)
Dim addr As sockaddr_in
addr.sin_family = 2
addr.sin_port = htons(60401)
addr.sin_addr = inet_addr("127.0.01")
i = connect(sock, addr, LenB(addr))
i = send(sock, "*SRTF" & vbCr, 6, 0)
i = recv(sock, buf(0), 10, 0)
For j = 0 To i - 1
s = s & Chr(buf(j))
Next
FetchData = s
End Function
Sub Button2_Click()
Range("C3").Formula = FetchData()
End Sub
You altered your definition of sockaddr_in to use a larger data type for the sin_port field. You can't do that. You need to restore your original definition to remain compatible with Winsock.
Your definition of htons() is also wrong. The real htons() function in ws2_32 operates on 16-bit numbers, not 32-bit numbers as you have defined (htonl() operates on 32-bit numbers).
The real problem you are running into is that VBA's Integer type is signed, the highest value it can hold is 32767. If you attempt to use a higher value, it will wrap to negative.
Winsock's actual sockaddr_in struct (and htons() function) uses an 16-bit unsigned type for the sin_port field. VBA simply does not have a 16-bit unsigned type. So you have to live with the limitations of the 16-bit signed Integer.
You need to fix your definitions:
Type sockaddr_in
sin_family As Integer
sin_port As Integer
sin_addr As Long
sin_zero(0 to 7) As Byte
End Type
Public Declare Function htons Lib "ws2_32" ( _ ByVal hostshort As Integer) As Integer
Now, that being said, the unsigned number 60401 is hex 0xEBF1. That is the same value as the signed number -5135. Which becomes 0xF1EB (-3605) when byte swapped by htons().
So, try one of these instead:
addr.sin_port = htons(&HEBF1)
addr.sin_port = htons(-5135)
addr.sin_port = -3605
Furthermore, inet_addr("127.0.01") should read inet_addr("127.0.0.1").

VB6 StrPtr Function to VB.NET

Trying to convert VB6 line of code to VB.net. Code will serve as identification if printer is OFF or ON
Thanks
"PRINTERFOUND = OpenPrinterW(StrPtr(PrinterName), hPrinter)" Particular StrPtr function...
Can't get OpenPrinter to work - Tries to print I simply want to to know if printer is OFF or ON
changing line to
PRINTERFOUND = OpenPrinterW(PrinterName.Normalize(), hPrinter, Nothing)
does not work, thanks
Tried to convert VB6 declaration to VB.net per previous suggestions but it still a same error cant convert String to Integer please see below
'Private Declare Function GetPrinterApi Lib "winspool.drv" Alias "GetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, ByRef BUFFER As Long, ByVal pbSize As Long, ByRef pbSizeNeeded As Long) As Long
<DllImport("winspool.Drv", EntryPoint:="GetPrinterA", SetLastError:=True, CharSet:=CharSet.Ansi, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Function GetPrinterApi(<MarshalAs(UnmanagedType.LPStr)> ByVal hPrinter As String, ByVal Level As IntPtr, ByVal BUFFER As IntPtr, ByVal pbSize As IntPtr, ByRef pbSizeNeeded As IntPtr) As Boolean
End Function
'Private Declare Function OpenPrinterW Lib "winspool.drv" (ByVal pPrinterName As Long, ByRef phPrinter As Long, Optional ByVal pDefault As Long = 0) As Long
<DllImport("winspool.Drv", SetLastError:=True, CharSet:=CharSet.Ansi, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Function OpenPrinterW(ByVal pPrinterName As IntPtr, ByVal phPrinter As Int32, <[In](), MarshalAs(UnmanagedType.LPStruct)> ByVal pDefault As IntPtr) As Boolean
End Function
'Private Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
<DllImport("winspool.Drv", EntryPoint:="ClosePrinter", SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Function ClosePrinter(ByVal hPrinter As IntPtr) As Boolean
End Function
'Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Long, ByRef Source As Long, ByVal Length As Long)
<DllImport("kernel32.dll", SetLastError:=True, EntryPoint:="RtlMoveMemory")> _
Public Function CopyMemory(ByRef Destination As Long, ByVal Source As IntPtr, ByVal Length As String) As IntPtr
End Function
Full code Below
'Acknowledgements : This program has been written making extensive use of the
'Merrion article http://www.merrioncomputing.com/Programming/PrintStatus.htm
'It has also benefited from the contributors to VBForums thread # 733849
'http://www.vbforums.com/showthread.php?t=733849&goto=newpost - especially the code
'suggested by "Bonnie West"
'Program written 14 Sept. 2013 by C.A. Moore
Option Explicit
Dim PRINTERFOUND As Long
Dim GETPRINTER As Long
Dim BUFFER() As Long
Dim pbSizeNeeded As Long
Dim PRINTERINFO As PRINTER_INFO_2
Dim N As Integer
Dim M As Integer
Dim CHAR As String
Dim prnPrinter As Printer
Dim BUF13BINARY As String
' Note : PRINTERREADY as an Integer variable is Dim'd
'"Public PRINTERREADY As Integer" at Form1 Option Explicit
Private Type PRINTER_INFO_2
pServerName As String
pPrinterName As String
pShareName As String
pPortName As String
pDriverName As String
pComment As String
pLocation As String
pDevMode As Long
pSepFile As String
pPrintProcessor As String
pDatatype As String
pParameters As String
pSecurityDescriptor As Long
Attributes As Long
Priority As Long
DefaultPriority As Long
StartTime As Long
UntilTime As Long
Status As Long
JobsCount As Long
AveragePPM As Long
End Type
Private Declare Function GetPrinterApi Lib "winspool.drv" Alias "GetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, BUFFER As Long, ByVal pbSize As Long, pbSizeNeeded As Long) As Long
Private Declare Function OpenPrinterW Lib "winspool.drv" (ByVal pPrinterName As Long, ByRef phPrinter As Long, Optional ByVal pDefault As Long) As Long
Private Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Public Function StringFromPointer(lpString As Long, lMaxLength As Long) As String
'this service function extracts a string (sRet) when fed with a pointer (lpstring)
'from a buffer
Dim sRet As String
Dim lret As Long
If lpString = 0 Then
StringFromPointer = ""
Exit Function
End If
'\\ Pre-initialise the return string...
sRet = Space$(lMaxLength)
CopyMemory ByVal sRet, ByVal lpString, ByVal Len(sRet)
If Err.LastDllError = 0 Then
If InStr(sRet, Chr$(0)) > 0 Then
sRet = Left$(sRet, InStr(sRet, Chr$(0)) - 1)
End If
End If
StringFromPointer = sRet
End Function
Public Function IsPrinterReady(ByRef PrinterName As String)
Form1.PRINTERREADY = 0
'first select the named printer and check if it is installed
For Each prnPrinter In Printers
CHAR = prnPrinter.DeviceName
If CHAR = PrinterName Then
Set Printer = prnPrinter 'sets this as printer
Form1.PRINTERREADY = 1
End If
Next
If Form1.PRINTERREADY = 0 Then GoTo Line1000 'exit. printer not installed
Dim hPrinter As Long
Dim PI6 As PRINTER_INFO_2
PRINTERFOUND = 0
Form1.PRINTERREADY = 0
PRINTERFOUND = OpenPrinterW(StrPtr(PrinterName), hPrinter)
'(OpenPrinterW(ByVal pPrinterName As Long, ByRef phPrinter As Long) As Long)
If PRINTERFOUND = 0 Then 'ie. printer not found
Form1.PRINTERREADY = 0
Debug.Assert ClosePrinter(hPrinter)
GoTo Line100
End If
'If we get here named printer was found and accessed and its hPrinter handle is
'known
'Dim BUFFER() As Long
'Dim pbSizeNeeded As Long
ReDim Preserve BUFFER(0 To 1) As Long
GETPRINTER = GetPrinterApi(hPrinter, 2&, BUFFER(0), UBound(BUFFER), pbSizeNeeded)
ReDim Preserve BUFFER(0 To (pbSizeNeeded / 4) + 3) As Long
GETPRINTER = GetPrinterApi(hPrinter, 2&, BUFFER(0), UBound(BUFFER) * 4, pbSizeNeeded)
If GETPRINTER = 0 Then 'ie. some problem with printer access
Form1.PRINTERREADY = 0
GoTo Line100
End If
'If we get here then GETPRINTER = 1, ie. printer found and accessed OK
With PRINTERINFO '\\ This variable is of type PRINTER_INFO_2
'These quantities are defined here because the Merrion article
'so specifies. However they are not used by this program, and most
'have been found to be void
.pServerName = StringFromPointer(BUFFER(0), 1024)
.pPrinterName = StringFromPointer(BUFFER(1), 1024)
.pShareName = StringFromPointer(BUFFER(2), 1024)
.pPortName = StringFromPointer(BUFFER(3), 1024)
.pDriverName = StringFromPointer(BUFFER(4), 1024)
.pComment = StringFromPointer(BUFFER(5), 1024)
.pLocation = StringFromPointer(BUFFER(6), 1024)
.pDevMode = BUFFER(7)
.pSepFile = StringFromPointer(BUFFER(8), 1024)
.pPrintProcessor = StringFromPointer(BUFFER(9), 1024)
.pDatatype = StringFromPointer(BUFFER(10), 1024)
.pParameters = StringFromPointer(BUFFER(11), 1024)
.pSecurityDescriptor = BUFFER(12)
.Attributes = BUFFER(13)
.Priority = BUFFER(14)
.DefaultPriority = BUFFER(15)
.StartTime = BUFFER(16)
.UntilTime = BUFFER(17)
.Status = BUFFER(18)
.JobsCount = BUFFER(19)
.AveragePPM = BUFFER(20)
End With
'This next code is for interest and program development only.
'It writes into List1 the value of each buffer 1 - 20
'To by-pass it, add a "Go To Line15" statement at this point.
Form1.List1.Clear
N = 0
Line5:
On Error GoTo Line15
Form1.List1.AddItem "Buffer No. " & N & " Buffer Value " & BUFFER(N)
N = (N + 1)
If N = 21 Then GoTo Line15
GoTo Line5
'Now to convert the decimal value of Buffer(13) into a binary
'bit pattern and store this in BUF13BINARY
Line15: 'and to show Buffer(13) as a binary bit pattern at Form1.Label1
N = BUFFER(13)
BUF13BINARY = ""
M = 4196
Line16:
If N < M Then
BUF13BINARY = BUF13BINARY & "0"
GoTo Line20
End If
BUF13BINARY = BUF13BINARY & "1"
N = (N - M)
Line20:
If M = 1 Then GoTo Line10
M = M / 2
GoTo Line16
Line10: 'BUF13BINARY is now the 13 bit binary value of Buffer(13)
'eg. 0011000100010
Form1.Label1.Caption = BUF13BINARY 'display this binary value at form 1
'we now examine the value of the third binary bit in BUF13BINARY
If Mid$(BUF13BINARY, 3, 1) = "0" Then Form1.PRINTERREADY = 1
If Mid$(BUF13BINARY, 3, 1) = "1" Then Form1.PRINTERREADY = 0
Line100:
ClosePrinter (hPrinter)
Line1000:
End Function
and
Option Explicit
Public PRINTERREADY As Integer
Private Sub Command1_Click()
IsPrinterReady ("Brother QL-500")
'IsPrinterReady ("EPSON Stylus CX5400")
MsgBox PRINTERREADY '0 = Not Ready 1 = Ready
End Sub
You cannot convert VarPtr, StrPtr, or ObjPtr, because in .NET you do not directly control memory. These functions were used to extract a pointer from an instance, a variable, or a Unicode string. But in .NET, object locations in memory is managed by the garbage collector, and the GC can move objects around in memory at any time.
Consider the following code, but do not use it! I put it here only to explain why these functions do not exist in .NET.
Private Function VarPtr(ByVal obj As Object) As Integer
' Obtain a pinned handle to the object
Dim handle As GCHandle = GCHandle.Alloc(obj, GCHandleType.Pinned)
Dim pointer As Integer = handle.AddrOfPinnedObject.ToInt32
' Free the allocated handle. At this point the GC can move the object in memory, this is
' why this function does not exist in .NET. If you were to use this pointer as a destination
' for memcopy for example, you could overwrite unintended memory, which would crash the
' application or cause unexpected behavior. For this function to work you would need to
' maintain the handle until after you are finished using it.
handle.Free()
Return pointer
End Function
Edit:
The correct way to get the printer status is through the managed interface for it, in this case through WMI:
Imports System.Management
Public Class Form1
Private Enum PrinterStatus As Integer
Other = 1
Unknown = 2
Idle = 3
Printing = 4
Warmup = 5
Stopped = 6
Offline = 7
End Enum
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim mos = New ManagementObjectSearcher("SELECT * FROM Win32_Printer")
For Each p In mos.Get()
Debug.Print(p.Properties("Name").Value.ToString() & " : " & CType(CInt(p.Properties("PrinterStatus").Value), PrinterStatus).ToString())
Next
End Sub
End Class
You can get more information about the Win32_Printer class here: https://msdn.microsoft.com/en-us/library/aa394363(v=vs.85).aspx
In particular take note of this:
Note If you are retrieving PrinterStatus = 3 or PrinterState = 0, the
printer driver may not be feeding accurate information into WMI. WMI
retrieves the printer information from the spoolsv.exe process. It is
possible the printer driver does not report its status to the spooler.
In this case, Win32_Printer reports the printer as Idle.
From there you can get information about and manage just about any peripheral connected. Just figure out the appropriate WMI classes and read up on the docs.
Thanks Everyone, especially Drunken Code Monkey for all the information provided, I was able to finally achieve what I wanted after reading on https://msdn.microsoft.com/en-us/library/aa394363(v=vs.85).aspx figured need to is boolean WorkOffline; Pew... made it more simple then VB6 language even using that feels kinda hmm old. Also lucky me found codes that did the same thing as I wanted here is link to VB.NET "https://bytes.com/topic/visual-basic-net/answers/524957-detecting-if-printer-connected-pc" And my modification of this code below
Imports System.Management
Public Class Form1
Public Class CheckPrinterStatus
Public Function PrinterIsOnline(ByVal sPrinterName As String) As Boolean
'// Set management scope
Dim scope As ManagementScope = New ManagementScope("\root\cimv2")
scope.Connect()
'// Select Printers from WMI Object Collections
Dim searcher As ManagementObjectSearcher = New ManagementObjectSearcher("SELECT * FROM Win32_Printer")
Dim printerName As String = String.Empty
For Each printer As ManagementObject In searcher.Get()
printerName = printer("Name").ToString() '.ToLower()
If (printerName.Equals(sPrinterName)) Then
MsgBox(printerName)
If (printer("WorkOffline").ToString().ToLower().Equals("true")) Then
MsgBox("Offline")
' Printer is offline by user
Return False
Else
' Printer is not offline
MsgBox("Online")
Return True
End If
End If
Next
Return False
End Function ' PrinterIsOnline
End Class
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim PrinterSatus As New CheckPrinterStatus
PrinterSatus.PrinterIsOnline("Brother QL-500") 'Name of The printer HERE
End Sub
End Class