Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

Re: Getting MAC Address(s) on Windows PCs

by almut (Canon)
on Sep 14, 2007 at 22:38 UTC ( #639099=note: print w/replies, xml ) Need Help??

in reply to Getting MAC Address(s) on Windows PCs

Win32API::File seems to provide the required low-level calls. So, I played around a bit, essentially reverse engineering some C code I found here, and something like this does work for me (tested on Win XP):

use Win32API::File qw(CreateFile DeviceIoControl :FILE_SHARE_ :Misc); use Win32::TieRegistry; sub IOCTL_NDIS_QUERY_GLOBAL_STATS () { 0x17 << 16 | 2 }; sub OID_802_3_PERMANENT_ADDRESS () { 0x01010101 }; sub OID_802_3_CURRENT_ADDRESS () { 0x01010102 }; sub NDIS_Query { my ($handle, $oid) = @_; my $nBytes = 0; my $buf = "\0"x10; DeviceIoControl($handle, IOCTL_NDIS_QUERY_GLOBAL_STATS(), pack("L", $oid), 0, $buf, length($buf), $nBytes, [] ); return join "-", unpack("(a2)*", unpack("H*", $buf) ); } my $key= $Registry->Open("LMachine/SOFTWARE/Microsoft/Windows NT/Curre +ntVersion/NetworkCards/2", { Access => "KEY_READ", Delimiter => "/" } ); my $adapterName = $key->{ServiceName}; print "Adapter name = $adapterName\n"; my $hMAC = CreateFile("//./$adapterName", 0, FILE_SHARE_READ(), [], OPEN_EXISTING(), 0, []) +; for ( [ "permanent" => OID_802_3_PERMANENT_ADDRESS() ], [ "current " => OID_802_3_CURRENT_ADDRESS() ], ) { my ($type, $oid) = @$_; my $mac = NDIS_Query($hMAC, $oid); print "MAC $type = $mac\n"; }

On my machine this prints (which is the same info that the mentioned C program reports):

Adapter name = {0AA29800-521D-4B20-888F-9D3CB9E64E96} MAC permanent = 00-0c-29-ee-47-65 MAC current = 00-0c-29-ee-47-65

The cryptic network card name is being looked up in the registry. You might have to experiment a little with the lookup path (in particular the final "2", which is the card number). Good luck.

Replies are listed 'Best First'.
Re^2: Getting MAC Address(s) on Windows PCs
by cmv (Chaplain) on Sep 17, 2007 at 14:57 UTC
    Fantastic response almut! This is one of the key pieces you have cracked. Once you have an ethernet device to query, this is how get the information using these OID's.

    I believe using these OIDs to get the information is better than the other methods of getting the MAC address for a couple of reasons:
    1.) It will show you both the currently-being-used MAC address of the device, and the permanent MAC address of the device that is burned into the hardware.
    2.) This information is coming directly from the running device driver (Is that true? That is my current understanding).

    If that is true, then is it also true that manipulating it is a bit more difficult?

    Now, the remaining pieces of the puzzle are, discovering all ethernet devices (even those that are not being used), and discovering which of those are on the motherboard (by that I mean not easily removable).

    I'm compiling all the bits of information as they come in, and will post the results, once I have things working the best way for my situation.

    Many thanks for all the help


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://639099]
[Corion]: Yaerox: That's a somewhat hard problem. Encode solves the conversion part, but for guessing what encoding a file is in, that's the hard part
[Corion]: Yaerox: There is Encode::Guess, but that needs a limited set of inputs, and it also cannot handle multiple single-byte encodings
[Corion]: If you have a BOM, that's a really easy way to recognize UTF-8. Otherwise, you can try to decode a file from UTF-8, and if that works OK and doesn't crash, most likely the file was valid UTF-8
[Corion]: But as "ansi" (Latin-1?) is a single-byte encoding, any file is a valid ANSI file

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (6)
As of 2017-03-28 13:19 GMT
Find Nodes?
    Voting Booth?
    Should Pluto Get Its Planethood Back?

    Results (332 votes). Check out past polls.