[QUESTION] Network connections: retrieving details

Discuss other useful utilities, general computing tips & tricks, Internet resources, etc.
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

[QUESTION] Network connections: retrieving details

20 Jun 2016, 10:16

This topic reaches out to people that still know straight windows API and a few - possibly undocumented - tricks. Please do not offer "solutions" such as "use the X tool" (such as netsh or similar) nor anything that involves COM, classes, .NET and other high-level language - only API that can be directly invoked by DllCall().

While working on a network monitoring script in AHK I've stumbled into a few problems. Some have been overcome, some are still to be fixed. I'm here for the latter.

1. How to programmatically retrieve the Default Internet connection and Shared connection attributes in all existing connections on a system?

Consider a (probably classic already) setup with one Ethernet adapter and one 3G modem.
The Ethernet is connected to a switch where other local computers are connected too.
The 3G modem is shared for all local network computers by means of ICS (Internet Connection Sharing).
The machine is doing NAT through DHCP acting as gateway for all other machines on the LAN.

Between Ethernet (LAN connection) and 3G modem (DIGI connection), the modem has been manually selected as Default Internet connection.
The modem has also been manually shared.
The two may not always be set up this way. And other machines in the world may have completely different setups, with different adapters.

What I need to know is:
a. How to enumerate all possible network/Internet connections (not adapters/interfaces!) on a given machine
b. How to retrieve the 'default' attribute of a certain connection
c. How to retrieve the 'shared' attribute of a certain connection

The screenshot below shows a 3G modem connection called 'DIGI' which is both Default and Shared:
20160620171545a.png
3G modem Status panel: General
2. How to programmatically retrieve the 3G (and/or Wi-Fi or other similar) connection details as shown by the Status panel?

Some of the information in the screenshot below can be retrieved by reading and parsing the phonebook file (rasphone.pbk), however certain values either are missing or must be interpreted according to an internal list.
What I need to know is the right way to retrieve all the information originally presented by the OS in the Status > Details panel.

The screenshot below shows the Details tab where the required information is presented on an XP system:
20160620174627a.png
3G modem Status panel: Details
3. How to programmatically Disable/Enable a non-DHCP (!) Ethernet connection?
Same thing as using the 'Disable' button in the LAN Status panel. The iphlpapi API apparently only does that for DHCP connections, however I need it for manually configured connections.

4. How to programmatically Disconnect/Connect a 3G/Wi-Fi/similar connection?
Same thing as using the 'Disconnect' button in the modem [DIGI] Status panel.

I've spent days on search engines and MSDN trying to figure out how to do the above, to no avail. When solutions appeared to exist it was all COM/.NET-related. I'm trying to avoid this, mainly because the script is primarily intended for Win9x systems and AHK Basic doesn't have COM facilities built-in plus I don't have the necessary background to work with COM objects and all that stuff.
So if anyone knows some low-level straight API that can accomplish the desired tasks please speak up. Even hints would be welcome.
Thank you in advance!
Part of my AHK work can be found here.
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: [QUESTION] Network connections: retrieving details

05 Jul 2016, 09:26

I'm still looking for answers to the above…
Part of my AHK work can be found here.
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: [QUESTION] Network connections: retrieving details

06 Jul 2016, 01:56

evtl. 1a => Netstat
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: [QUESTION] Network connections: retrieving details

06 Jul 2016, 06:41

Thank you but that code doesn't help with my issues. I've already built a wrapper for the most used APIs in iphlpapi.dll and a few in wininet.dll and ws2_32.dll but still can't find the right approach. In 1a I'm referring to the icons one sees in Network Neighborhood (see screenshot):
Network Connections list.png
Network Connections list in XP's Start Menu
[EDIT]
OK, maybe I should elaborate further.
What I want is to find all possible Internet and network connections that are altready set up on a given machine, be that Ethernet, 3G/ADSL/whatever modem, Wi-Fi and so on. Then retrieve their properties (how to connect/disconnect, how to read traffic etc.), build a list of connections and let the user choose which one to monitor. The trick is to be able to set the script to monitor a connection without it being actually connected (to the Internet or local network). Currently the script I have can't "see" an interface until it's connected so can't monitor an idle connection, can't start the script at system boot and wait for certain connection to become live. That's my main problem.

[EDIT 2]
For example, in the screenshot above DIGI is a connection set up for a 3G modem. This modem does not show up in the interfaces table retrieved by GetIfTable() until the connection is being dialed and established. Therefore a call to GetIfTable() at Windows start would not allow the script to select the respective interface/connection for monitoring. Sadly that is exactly what I need the script to do.
So I need a different approach, by enumerating the existing connections in the Network Connections folder and monitoring the status of the chosen one. Once the connection is established and active the script can then call GetIfTable(), select the corresponding interface and from then on everything is already in place and working. Well, except for the modem details and other points mentioned in first post.

I hope it's clearer this time. :)
Part of my AHK work can be found here.
qwerty12
Posts: 468
Joined: 04 Mar 2016, 04:33
Contact:

Re: [QUESTION] Network connections: retrieving details

06 Jul 2016, 15:29

(I'm certainly not the sort of person as described in the first sentence of your post, and I'm sure as hell not going to try to connect Windows 98 to the Internet in 2016, virtual machine or no virtual machine, so these non-answers pertain to XP)
3. How to programmatically Disable/Enable a non-DHCP (!) Ethernet connection?
I was going to say "use setupapi.dll", since disabling an Ethernet connection from Network Connections shows it as being disabled in the Device Manager, but according to this, it's apparently not without its problems (although take that with a grain of salt; those could be problems related to the NIC driver in use on the system. If you can use devcon.exe repeatedly without any problem, then you'll probably be fine). https://groups.google.com/forum/#!topic ... pZ1f5kl3nk and the devcon source would be a good place to start looking, as well as StackOverflow, of course.
4. How to programmatically Disconnect/Connect a 3G/Wi-Fi/similar connection?
RasHangUp, presumably

WlanDisconnect for a Wi-Fi connection, but be aware of what's mentioned in the remarks.

If you know of a way I can have a dial-up connection emulated (I don't need actual Internet access, just for Windows to think it's connected somewhere using dial-up) I might (like I said, I'm not a WinAPI expert in the slightest) be able to have a look at 2.

Oh, this appears to be a good resource outlining all the options you have: https://web.archive.org/web/20140831104 ... manage.asp
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: [QUESTION] Network connections: retrieving details

06 Jul 2016, 16:02

Thank you for replying and for some useful links. :)

There is a great deal of confusion between devices, interfaces and connections. I'm not even sure I understand all of them properly myself.
Anyway, what I'm trying to achieve has two parts, for now:
1. duplicate as best as possible XP's status panel for network/Internet connections
2. monitor (and log, if necessary) chosen connection(s)

First part is necessary for 9x machines that do not have any visual feedback for network/Internet connections. My programming machine runs 98SE and is connected to home LAN, which has Internet connection available through another machine (the DIGI connection pertaining to the 3G modem on XP). Obviously I can only monitor the Ethernet interface there and I can enable/disable it easily since it is using DHCP (provided by the XP machine). The status panel duplication is almost complete, only misses a way to launch the adapter properties panel (Properties button in first screenshot of top post) and maybe a few details related to 'repairing' a connection (Repair button in the Details tab of the status panel).

Second part is necessary on the XP machine where the 3G modem resides (only because the chinese did not build/offer 9x drivers for it!) and this is because it's a metered connection with a fixed monthly download quota and sometimes it feels I'm being scammed, having the DL speed capped way before reaching the monthly limit. Other people may find some other use for such script though.

Well, on to checking out those links, hopefully something good will come out of this. Thanks again! :)
Part of my AHK work can be found here.
qwerty12
Posts: 468
Joined: 04 Mar 2016, 04:33
Contact:

Re: [QUESTION] Network connections: retrieving details

07 Jul 2016, 04:00

Drugwash wrote:b. How to retrieve the 'default' attribute of a certain connection
The default connection is something specific to phone connections - Ethernet etc. connections have their priority determined from the Advanced Settings inside the Network Connections folder and probably the metric assigned to the IPv4 + v6 protocols for a specific interface. With that in mind, you can get what the default dial-up connection is by doing something like (AHK_L, sorry. The only thing I know how to do with the basic version is disable Shift+Delete)

Code: Select all

#SingleInstance, Force
DllCall( "LoadLibrary", "Str","Rasapi32.dll" )
global SUCCESS := 0, ERROR_BUFFER_TOO_SMALL := 603

MsgBox % RasGetAutodialAddress()
Return

RasGetAutodialAddress() {
	nRet := ERROR_BUFFER_TOO_SMALL
	cbAutoDialEntries := szAutoDialEntries := 528
	Loop { ; there should only be one default connection, but...
		if (nRet == ERROR_BUFFER_TOO_SMALL) {
			VarSetCapacity(AutoDialEntries, cbAutoDialEntries, 0)
			NumPut(szAutoDialEntries, AutoDialEntries, 0, "UInt")
		} else
			return 0
	} until ((nRet := DllCall("Rasapi32\RasGetAutodialAddressW", "Ptr", 0, "Ptr", 0, "Ptr", &AutoDialEntries, "UInt*", cbAutoDialEntries, "UInt*", cAutoDialEntries, "UInt")) == SUCCESS)
	
	return StrGet(&AutoDialEntries + 12, "UTF-16")
}
SKAN has already wrapped the RAS function to list the available connections here: https://autohotkey.com/boards/viewtopic ... 736#p30736
BUT the actual function is insanely unreliable. On my VM, as soon as I add another dial-up connection, RasEnumEntries stops showing the names of available connections. The Network Connections folder never even touches this function to show the available dial-up networks and for good reason, it seems.


To determine whether a RAS connection is shared, rasapi exports the RasIsSharedConnection function. This function is undocumented and unlikely to be figured out by me because:
  • I need a debugger to reliably determine the offsets of the fields RISC looks at in the struct (size 420 bytes) passed as its first argument to be able to how to get the shared status of a connection. The problem: I don't know how to use WinDbg
  • You need to know the name of the connection in the first place to determine whether it's shared. If RasEnumEntries is broken...
  • It goes through COM itself ;-)
I'm going to say to bite the bullet and use the netshell COM interface. It already does the work of aggregating all the available connections, no matter their type, and for dial-up connections, it seems to be far more reliable than the rasapi WinAPI function at doing so... I've not used it so I can't say for sure, but from a quick glance at netcon.h, it seems far easier to determine whether a connection is shared and/or the default. That's only available on XP, though, according to Gershnik. Of course, it's your choice, but to determine if whether, say, an Ethernet connection is shared, you'll have no choice but to use COM anyway (that's the only publicly documented way - even if a function has a nice, neat entry in some DLL's export table, it'll still go through COM). My guess is that the only other alternative would be to find the setting in the Registry somewhere.
Drugwash wrote:The status panel duplication is almost complete, only misses a way to launch the adapter properties panel (Properties button in first screenshot of top post) and maybe a few details related to 'repairing' a connection (Repair button in the Details tab of the status panel).
Don't quote me on this, but I suspect they could be launched through a COM interface somewhere...

EDIT: Disregard what I said about RasEnumEntries. I fixed SKAN's code slightly and this produces a proper result:

Code: Select all

#Warn
#SingleInstance, Force
DllCall( "LoadLibrary", "Str","Rasapi32.dll" )

MsgBox % RAS_EnumAll() 

Return                                                              ; // end of auto-execute section //


RAS_EnumAll() {
Static ERROR_BUFFER_TOO_SMALL :=  603
     , ERROR_INVALID_SIZE     :=  632
     , SizeOf_RASENTRYNAME    :=  520  

Local TSz, RASENTRYNAME, pRASENTRYNAME, EC := 0, CC := 0, PBEntry, PBEntries := "`n", RASCONN, pRASCONN  
  
  TSz := SizeOf_RASENTRYNAME  
  VarSetCapacity( RASENTRYNAME, TSz, 0 )         
  NumPut( SizeOf_RASENTRYNAME, RASENTRYNAME )
  
  Error := DllCall( "Rasapi32\RasEnumEntriesW", "Int",0, "Int",0, "Ptr",&RASENTRYNAME, "PtrP",TSz, "PtrP",EC )

  If ( Error = ERROR_BUFFER_TOO_SMALL ) 
      VarSetCapacity( RASENTRYNAME, TSz, 0 ) 
    , NumPut( SizeOf_RASENTRYNAME, RASENTRYNAME )
    , DllCall( "Rasapi32\RasEnumEntriesW", "Int",0, "Int",0, "Ptr",&RASENTRYNAME, "PtrP",TSz, "PtrP",EC )

  Loop %EC% 
  { 
     PBEntry := StrGet(&RASENTRYNAME + (SizeOf_RASENTRYNAME * (A_Index - 1)) + 4, "UTF-16" )
     PBEntries .=  A_Index . 	"|" PBEntry "`n"
  }
  StringTrimRight, PBEntries, PBEntries, 1

Return Trim( PBEntries , "`n" )
}	
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: [QUESTION] Network connections: retrieving details

07 Jul 2016, 05:33

Dang, I hate this COM! :(
I know some of the things I need can be done through WMI, which again is out of my expertise. And I've read that Gershnik page, which unfortunately links to other pages that seem to have not been captured by WebArchive and that would have provided very useful information.

Since the scope of this script encompasses both 9x and NT-based OS versions I definitely need to find a common denominator, something as low-level as possible that would work on all of them with no significant differences. And this is extremely hard. But thinking logically, everything should go at some point through some simple APIs, unless all this COM/WMI/NetAPI/etc are built to directly interface with drivers, CPU and all the rest at assembly language level, which is quite unlikely in my opinion.

Of course, there would be a few things unavailable in 9x (I already stumbled into NotifyAddrChange() in iphlpapi which only works in 2000+ and is one of the critical pieces of the puzzle) but these apart all the rest should be common code.

Going back to the beginning: a common (9x - NT) way to enumerate items in Network Connections. That's the starting point which I miss. Right now I'm relying on GetIfTable() which as I said somewhere before cannot list 3G modems, Wi-Fi adapters and so on until they're connected.

In the mean time I'll take a look at the RAS API, see what use it could be, thanks for pointing out SKAN's code. Unfortunately RasIsSharedConnection() is not present in 98SE's rasapi32.dll so I'll have to put it aside for NT-only usage and see if there's anything similar for 9x.

For now I have to go cook before I starve. :) Thanks again! ;)
Part of my AHK work can be found here.
qwerty12
Posts: 468
Joined: 04 Mar 2016, 04:33
Contact:

Re: [QUESTION] Network connections: retrieving details

07 Jul 2016, 06:17

Drugwash wrote:Dang, I hate this COM! :(
If it helps any, simple COM usage (which is all I know and for that, I can't recommend https://maul-esel.github.io/tutorials/C ... faces.html enough) is pretty much straight DllCall (and under AHK_L IDispatch interfaces don't necessarily need that).
I know some of the things I need can be done through WMI, which again is out of my expertise. And I've read that Gershnik page, which unfortunately links to other pages that seem to have not been captured by WebArchive and that would have provided very useful information.
Yes, I'm not hot on WMI, either. (I also suspect I may have broken parts of it on my system :problem:). It's a shame a redirector script was used on that page.

Yeah, sorry, I keep forgetting about your 9x requirement. The code I've posted is AHK_L centred and I'm using the Unicode APIs. I don't know anything about 9x programming (my first computer came with Windows ME and a year of that soured me permanently re. 9x. Conversely, I still have a place in my heart for Windows 2000 to this very day). Lexikos provided a standalone version of StrGet for AHK Classic somewhere, FWIW. I think the rest would be fixing the offsets, sizes and forcing the use of the "A" variants of the APIs.

What I think netshell.dll under 2000+ does is look at the interfaces that are stored in the Registry and it handles the abstraction itself: when it needs to get information on a specific interface, it delegates the work to the specific APIs itself (rasapi for a dialup connection, wlanapi [and of course, XP was the first OS to provide a standard interface for the specifics of Wi-Fi connections] for Wi-Fi connections and iphlpapi for Ethernet connections?) and then under 2000+, applications can just query that. But, yeah, that's not going to work either for a script that needs to run on 98 :\ And I was wrong anyway about RasEnumEntries - I fixed SKAN's code slightly in an edit, you may want to use that instead - under XP, the names of available RAS interfaces are successfully returned, so you may be able to skip COM (although I'm pretty sure it's needed under XP to determine a connection's shared status - officially, anyway). Under 98, ICS may not use COM, but I wouldn't know :)

Oh, regarding getting the full details of a RAS connection, RasGetConnectionStatus and RasGetProjectionInfo should be enough (but I can't test, since I don't have a way of a creating a successful dial-up connection - 3G or otherwise).

Good luck with everything!
drawback
Posts: 34
Joined: 11 Aug 2016, 11:31

Re: [QUESTION] Network connections: retrieving details

11 Aug 2016, 11:47

Hello!

@qwerty12

Code: Select all

  VarSetCapacity( RASENTRYNAME, TSz, 0 )         
  NumPut( SizeOf_RASENTRYNAME, RASENTRYNAME )
 
  Error := DllCall( "Rasapi32\RasEnumEntriesW", "Int",0, "Int",0, "Ptr",&RASENTRYNAME, "PtrP",TSz, "PtrP",EC )
 
  If ( Error = ERROR_BUFFER_TOO_SMALL ) 
      VarSetCapacity( RASENTRYNAME, TSz, 0 ) 
    , NumPut( SizeOf_RASENTRYNAME, RASENTRYNAME )
    , DllCall( "Rasapi32\RasEnumEntriesW", "Int",0, "Int",0, "Ptr",&RASENTRYNAME, "PtrP",TSz, "PtrP",EC )
What exactly is done here? The If statement uses the exact same parameters as the code before which produced the ERROR_BUFFER_TOO_SMALL, or am I missing something here? If the first ones fails, won't the second fail here too?
qwerty12
Posts: 468
Joined: 04 Mar 2016, 04:33
Contact:

Re: [QUESTION] Network connections: retrieving details

11 Aug 2016, 12:13

Hey,

I didn't write the original code, but I think I get how it works: enough memory is initially allocated with enough space to hold one RASENTRYNAME structure. If the first call to RasEnumEntriesW fails with ERROR_BUFFER_TOO_SMALL, RasEnumEntriesW will write the expected size into the TSz variable, and from there, VarSetCapacity is called again to resize the allocated space for RASENTRYNAME and RasEnumEntriesW is tried again.

As to why it starts off with allocating space for just one RASENTRYNAME, my guesses:
  • If there's only one dial up connection, it saves time maybe...
  • It might be one of those quirky WinAPI functions that require you to pass it the initial size first (as opposed to 0) before it will return the right size
drawback
Posts: 34
Joined: 11 Aug 2016, 11:31

Re: [QUESTION] Network connections: retrieving details

12 Aug 2016, 06:44

That actually makes sense (even for me) :)

Thanks a lot for the explanation!
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: [QUESTION] Network connections: retrieving details

29 Aug 2016, 07:44

Guys, I've had a tough time lately. Might sound silly for some but my cat died a month ago and I've been devastated ever since - he was like a son to me. Worst of all is I was working precisely on this script the morning he got killed in the street so I kinda hate this script for that. Call me weird.

Anyway, I've made little progress in the right direction since the last time I posted and today I just added something that makes it a little more usable although still on the wrong approach. Dunno if/when I'll be able to continue working on it (or anything else, for that matter) and I thought somebody in this world might need it so I uploaded it to my cloud repository (see my signature, the NetMeterEx folder). Feel free to use/modify it at will and discuss it here (or anywhere else). Thank you very much everyone for your help!
Part of my AHK work can be found here.
qwerty12
Posts: 468
Joined: 04 Mar 2016, 04:33
Contact:

Re: [QUESTION] Network connections: retrieving details

29 Aug 2016, 09:49

Drugwash wrote:Guys, I've had a tough time lately. Might sound silly for some but my cat died a month ago and I've been devastated ever since - he was like a son to me. Worst of all is I was working precisely on this script the morning he got killed in the street so I kinda hate this script for that. Call me weird.
I'm really sorry to hear that. My first cat had to be put down a couple of years ago (his health suddenly deteriorated severely - no warning at all) and I still think about him a lot, so I get where you're coming from. :(
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: [QUESTION] Network connections: retrieving details

29 Aug 2016, 10:46

Thank you so much for understanding and I'm sorry you had to go through this too, it's really hard to bear the loss of such a lovely (and loving) creature. :(
Part of my AHK work can be found here.
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: [QUESTION] Network connections: retrieving details

05 Sep 2016, 06:21

A new version is up (1.4.1.1). A few changes, possibly definitely new bugs. Added credits where due. Maybe I should dedicate this script to my late cat.

EDIT:

Sorry for the mess, I've changed some things in v1.4.0.0 and didn't check all the code so it'll behave badly. Please use older v1.3.4.5 until I fix the mess (if I'll ever do that).
Part of my AHK work can be found here.
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: [QUESTION] Network connections: retrieving details

15 Nov 2016, 14:30

Version 1.5.0.1 is up.
Part of my AHK work can be found here.

Return to “Other Utilities & Resources”

Who is online

Users browsing this forum: No registered users and 19 guests