vb6 implementation for icmpsendecho2 - vb6

I'm trying to implement a Ping program in vb6 which works for both IPv4 & IPv6 addresses. The IPv4 implementation uses IcmpSendEcho which is working fine, but the IPv6 implementation uses Icmp6SendEcho2 and I'm having a lot of difficulty getting it to work.
The function call works fine and it does not error out but the return value is always 0, and GetLastError returns 0 indicating that no errors occurred
https://msdn.microsoft.com/en-us/library/windows/desktop/aa366041(v=vs.85).aspx
The process I follow is as follows:
Load the windows sockets dll by calling WSAStartup
Open a port handle via a call to Icmp6CreateHandle
Send a ICMP ECHO message via a call to Icmp6SendEcho2 and analyze the response
close the port handle by calling IcmpCloseHandle
Unload dll by calling WSACleanup
The definition of Icmp6SendEcho2 is as follows
Private Declare Function Icmp6SendEcho2 Lib "Iphlpapi.dll" _
(ByVal IcmpHandle As Long, _
ByVal EventtoRaise As Long, _
ByVal ApcRoutine As Long, _
ByVal ApcContext As Long, _
ByVal SourceAddressPointer As Long, _
ByVal DestinationAddressPointer As Long, _
ByVal RequestData As String, _
ByVal RequestSize As Long, _
ByVal RequestOptions As Long, _
ReplyBuffer As ICMPV6_ECHO_REPLY, _
ByVal ReplySize As Long, _
ByVal timeOut As Long) As Long
Where ICMPV6_ECHO_REPLY is defined as follows
Private Type ICMPV6_ECHO_REPLY
Address As IPV6_ADDRESS
Status As Long
RoundTripTime As Long
End Type
Private Type IPV6_ADDRESS
sin6_port As Integer
sin6_flowinfo As Long
sin6_addr(1 To 8) As Integer
sin6_scope_id As Long
End Type
The call to Icmp6SendEcho2 is made as follows
lPingResponse = Icmp6SendEcho2(lPortHandle, 0, 0, 0, VarPtr(SourceAddress), VarPtr(DestinationAddress), sMessage, Len(sMessage), 0, Reply, Len(Reply), timeOut)
I used the following link for implementing Ping for IPv4
https://support.microsoft.com/en-us/kb/300197
Any help would be awesome
Nish

The issue was associated with there not being a sufficient buffer to get the response. Changing the response structure to something like this did the trick
Private Type ICMPV6_ECHO_REPLY
Address As IPV6_ADDRESS
Status As Long
RoundTripTime As Long
data(0 To 1023) As Byte
End Type

Related

Numeric values of WinHTTP constants (eg. WINHTTP_NO_CLIENT_CERT_CONTEXT)

I need to set this property for a WinHttp request...
BOOL fRet = WinHttpSetOption(hRequest,
WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
WINHTTP_NO_CLIENT_CERT_CONTEXT,
0);
But from within an old VB application. I can access the method but can't use the constants.
I can use this to access the method from VB...
Declare Function WinHttpSetOption Lib "winhttp.dll" _
(ByVal hInternet As Variant, ByVal dwOption As Integer, ByVal lpBuffer As Byte, ByVal dwBufferLength As Integer) _
As Boolean
And then call it like so...
Call WinHttpSetOption(hRequest, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
But have to replace the constants WINHTTP_OPTION_CLIENT_CERT_CONTEXT and WINHTTP_NO_CLIENT_CERT_CONTEXT with the correct numbers, or figure out how to import them.
After I long google search, I think WINHTTP_OPTION_CLIENT_CERT_CONTEXT is 47 but can't find WINHTTP_NO_CLIENT_CERT_CONTEXT anywhere.
Many thanks

VB.net SendMessage with CB_ADDSTRING '0' not valid for 'index'

I'm trying to fasten up the loading of one form, which populates several combobox with a big amount of data. I did my best stopping the UI while loading ecc shredding the loading time from 20s to 13s, but still the only bottleneck remaining is loading data into ComboBox which takes about 3-4s each. I did research on the internet and found that using Windows API you can fasten it up a lot more. So I did the code:
Private Const CB_ERR As Integer = -1
Private Const CB_ADDSTRING As Integer = &H143
Private Const CB_SETITEMDATA As Integer = &H151
<DllImport("user32.dll", CharSet:=CharSet.Auto)>
Private Function SendMessage(ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, lParam As String) As Integer
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto)>
Private Function SendMessage(ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, lParam As Object) As Integer
End Function
Public Sub AddItem(cmb As ComboBox, Item As Object)
Dim l As Integer
l = SendMessage(cmb.Handle, CB_ADDSTRING, 0&, Item.ToString())
SendMessage(cmb.Handle, CB_SETITEMDATA, l, Item)
End Sub
But on CB_ADDSTRING the program crashes with this error (that can be catched):
InvalidArgument=Value of '0' not valid for 'index'. Parameter Name: index
Since I'm using Krypton Controls, I had to shuffle trough Parents until I found KryptonComboBox, and then pass it's Handle value.

VB6 sidebar app

All.
I'm attempting to develop a 'sidebar' application with vb6, which I want to behave like windows Vista's gadget sidebar or Google Desktop sidebar, in the respect that other windows could not maximize over it.
I'm aware that chances of this happening are probably very little, but I'm asking just in case.
Currently, I've got a form that has multiple controls, and runs a function on load which makes itself the exact height of the screen, minus the taskbar, and it's 'left' location is set by a timer to be 'screen.width - me.width', so it will start at full height on the far right of the screen, and cannot be moved. Code for the height is as follows, if it is necessary.
Declare Function GetUserNameA Lib "advapi32.dll" (ByVal lpBuffer As String, nSize As Long) As Long
Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" ( _
ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" ( _
ByVal hwnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Public Declare Function SetLayeredWindowAttributes Lib "user32" ( _
ByVal hwnd As Long, _
ByVal crKey As Long, _
ByVal bAlpha As Byte, _
ByVal dwFlags As Long) As Long
Public Const GWL_STYLE = (-16)
Public Const GWL_EXSTYLE = (-20)
Public Const WS_EX_LAYERED = &H80000
Public Const LWA_COLORKEY = &H1
Public Const LWA_ALPHA = &H2
Private Const ABM_GETTASKBARPOS = &H5
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type APPBARDATA
cbSize As Long
hwnd As Long
uCallbackMessage As Long
uEdge As Long
rc As RECT
lParam As Long
End Type
Private Declare Function SHAppBarMessage Lib "shell32.dll" (ByVal dwMessage As Long, pData As APPBARDATA) As Long
Function Fixheight()
Dim ABD As APPBARDATA
SHAppBarMessage ABM_GETTASKBARPOS, ABD
Form1.Height = Screen.Height - ((ABD.rc.Bottom - ABD.rc.Top) * 12)
If Form1.Height <= 600 Then
Form1.Height = Screen.Height
End If
End Function
To be clear, I do not want an 'always on top' function. I already have that, and it's driving me insane, as the form has to me closed or minimized in order to maximize, minimize of close another program (i.e. chrome, word, etc) behind it. This form must instead not allow other programs to maximize over it, so that if for example, the user maximized Chrome, chrome would maximize minus form1.width.
I doubt that this is possible because as far as I'm concerned, that would mean taking control of chrome, and essentially making it's maximize function as
me.height = screen.height - ((ABD.rc.Bottom - ABD.rc.Top) * 12)
me.width = screen.width - form1.width
which isn't possible.
Anyway, hopefully someone out there can help. As I said, I seriously doubt the possibility of having this work, but if so, all the better.
Thanks in advance!
Thanks to Ken White, I googled SHAppBarMessage and found the following website, offering a downloadable source with the very feature I needed. I just have to implement it now!!
Very glad I asked! Thank you!
Edit: Found this spanish website, which while needed some help from Google Translate, is more suited to my needs. Just need to figure out how to make it work on the Right Hand Side! Thanks again!

Set global hotkey with Windows modifier

I want to set up a global hotkey* in VB6 that listens to the keyboard shortcut Win + O.
I have found heaps of messy examples, but nothing which involves the Windows key.
What's the ideal way to setup hotkeys and how does one include the Windows key as a modifier?
* I'm after a global shortcut. That means I don't have to have the application in focus for it to work.
RegisterHotKey in the Windows API will allow you to register a global hot key. You will also need to use GlobalAddAtom to obtain a unique hot key identifier. See this link for details.
Private Declare Function RegisterHotKey Lib "user32" (ByVal hwnd As Long, ByVal id As Long, ByVal fsModifiers As Long, ByVal vk As Long) As Long
Private Declare Function GlobalAddAtom Lib "kernel32" Alias "GlobalAddAtomA" (ByVal lpString As String) As Integer
Private Const WM_HOTKEY As Long = &H312
Private Const MOD_WIN As Long = &H8
m_lHotkey = GlobalAddAtom("MyHotkey")
Call RegisterHotKey(Me.hwnd, m_lHotkey, MOD_WIN, vbKeyO)
Then you just need to listen for the WM_HOTKEY message on your window.

CheckTokenMembership in VB6

I'm having a hard time converting this C++ code to VB6 code. I've search the net and haven't found anything. PInvoke.net only has reference to VB.NET code. Here's the code from MSDN:
BOOL IsUserAdmin(VOID)
/*++
Routine Description: This routine returns TRUE if the caller's
process is a member of the Administrators local group. Caller is NOT
expected to be impersonating anyone and is expected to be able to
open its own process and process token.
Arguments: None.
Return Value:
TRUE - Caller has Administrators local group.
FALSE - Caller does not have Administrators local group. --
*/
{
BOOL b;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
PSID AdministratorsGroup;
b = AllocateAndInitializeSid(
&NtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&AdministratorsGroup);
if(b)
{
if (!CheckTokenMembership( NULL, AdministratorsGroup, &b))
{
b = FALSE;
}
FreeSid(AdministratorsGroup);
}
return(b);
}
It would be great if somebody can help out in converting this to VB6 code.
Thanks!
EDIT:
I was originally going to use that function but MSDN says:
This function is a wrapper for CheckTokenMembership. It is recommended to call that function directly to determine Administrator group status rather than calling IsUserAnAdmin.
Try this
Option Explicit
Private Const SECURITY_BUILTIN_DOMAIN_RID As Long = &H20
Private Const DOMAIN_ALIAS_RID_ADMINS As Long = &H220
Private Declare Function AllocateAndInitializeSid Lib "advapi32.dll" (pIdentifierAuthority As Any, ByVal nSubAuthorityCount As Byte, ByVal nSubAuthority0 As Long, ByVal nSubAuthority1 As Long, ByVal nSubAuthority2 As Long, ByVal nSubAuthority3 As Long, ByVal nSubAuthority4 As Long, ByVal nSubAuthority5 As Long, ByVal nSubAuthority6 As Long, ByVal nSubAuthority7 As Long, lpPSid As Long) As Long
Private Declare Sub FreeSid Lib "advapi32.dll" (ByVal pSid As Long)
Private Declare Function CheckTokenMembership Lib "advapi32.dll" (ByVal hToken As Long, ByVal pSidToCheck As Long, pbIsMember As Long) As Long
Private Type SID_IDENTIFIER_AUTHORITY
Value(0 To 5) As Byte
End Type
Private Function pvIsAdmin() As Boolean
Dim uAuthNt As SID_IDENTIFIER_AUTHORITY
Dim pSidAdmins As Long
Dim lResult As Long
uAuthNt.Value(5) = 5
If AllocateAndInitializeSid(uAuthNt, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, pSidAdmins) <> 0 Then
If CheckTokenMembership(0, pSidAdmins, lResult) <> 0 Then
pvIsAdmin = (lResult <> 0)
End If
Call FreeSid(pSidAdmins)
End If
End Function
You've posted the MSDN sample code for CheckTokenMembership - it uses CheckTokenMembership to determine whether the user is an administrator.
In VB6 it's easier to use IsUserAnAdmin, which is a wrapper for CheckTokenMembership. The MSDN docs do say IsUserAnAdmin is deprecated, but it's so much easier to call than CheckTokenMembership.
Private Declare Function IsUserAnAdmin Lib "Shell32" Alias "#680" () As Integer
If IsUserAnAdmin() = 0 Then
MsgBox "Not admin"
Else
MsgBox "Admin"
End If
Unless there is a reason to convert the code, use the API
Private Declare Function IsUserAdmin Lib "Shell32" Alias "#680" () As Boolean
Private Sub Form_Load()
If IsUserAdmin Then MsgBox "User is Admin"
End Sub

Resources