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.