I want to get some unique machine information using a firefox add-on.
With this code I can get the name:
var dns = Cu.components.classes["@mozilla.org/network/dns-service;1"]
.getService(Cu.components.interfaces.nsIDNSService);
var myName = dns.myHostName;
Now I need NIC information (Like mac address, adapter name). I trying to use getAdaptersInfo
function, but this will work only for Windows, and I need some solution cross platform.
Anyone has an idea?
This is my code for getAdaptersInfo:
function getMacAddress(){
const MAX_ADAPTER_NAME_LENGTH = 256;
const MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
const ERROR_BUFFER_OVERFLOW = 111;
const NO_ERROR = 0;
var IP_ADDRESS_STRING = ctypes.StructType('IP_ADDRESS_STRING',[
{'String': ctypes.char}
]);
var IP_ADDR_STRING = ctypes.StructType('IP_ADDR_STRING');
IP_ADDR_STRING.define([
{'Next': IP_ADDR_STRING.ptr},
{'IpAddress': IP_ADDRESS_STRING},
{'IpMask': IP_ADDRESS_STRING},
{'Context': ctypes.long}
]);
var IP_ADAPTER_INFO = ctypes.StructType('IP_ADAPTER_INFO');
const DWORD = ctypes.uint32_t;
IP_ADAPTER_INFO.define([
{'Next': IP_ADAPTER_INFO.ptr},
{'ComboIndex': DWORD},
{'AdapterName': ctypes.char},
{'Description': ctypes.char},
{'AddressLength': ctypes.int32_t},
{'Address': ctypes.uint8_t.array(10).ptr},
{'Index': DWORD},
{'Type': ctypes.uintptr_t},
{'DhcpEnabled': ctypes.uintptr_t},
{'CurrentIpAddress': IP_ADDR_STRING.ptr},
{'IpAddressList': IP_ADDR_STRING},
{'GatewayList' : IP_ADDR_STRING},
{'DhcpServer': IP_ADDR_STRING},
{'HaveWins': ctypes.int32_t},
{'PrimaryWinsServer': IP_ADDR_STRING},
{'SecondaryWinsServer':IP_ADDR_STRING},
{'LeaseObtained': ctypes.uintptr_t},
{'LeaseExpires': ctypes.uintptr_t}
]);
const nomes = [ctypes.libraryName('IPHLPAPI')];
const lib = loadLibrary(nomes);
try{
if(!lib)
return null
console.log("Biblioteca aberta!");
/*DWORD GetAdaptersInfo(
_Out_ PIP_ADAPTER_INFO pAdapterInfo,
_Inout_ PULONG pOutBufLen
);*/
var getAdaptersInfo = lib.declare(
"GetAdaptersInfo",
ctypes.default_abi,
DWORD,
IP_ADAPTER_INFO.ptr,
ctypes.long.ptr);
let buf = (IP_ADAPTER_INFO)();
let pbuf = buf.address();
let ret = ctypes.long(2000);
let pret = ret.address();
let sts = getAdaptersInfo(pbuf,pret);
if(sts == ERROR_BUFFER_OVERFLOW){ //o tamanho do buffer enviado não foi o suficiente.
buf = null;
//agora mando novamente usando o que a lib me retornou.
sts = getAdaptersInfo(pbuf,pret);
}
if(sts != NO_ERROR){ //aqui ocorreu um erro que não conseguiremos resolver ainda.
throw Error("Erro buscando configuracoes do adaptador.");
}
}catch(ex){
console.log("Erro na biblioteca", ex, ex.message);
}finally{
lib.close();
}
}
But firefox crash when I run cfx run.
Ok now THIS works :) The issue was I was telling the function to accept list of structures by defining it as this IP_ADAPTER_INFO.ptr.array()
then I was creating an array of structures like this let pbuf = IP_ADAPTER_INFO.ptr.array(1)()
however this would crash, and when we increased to sizes of 2 or more it crashed faster. So I changed up to declare it like this in the function IP_ADAPTER_INFO.ptr
and then I create an array of structs like this let pbuv = IP_ADAPTER_INFO.array(?)
where ?
can be any number and it works fine :)
Cu.import('resource://gre/modules/ctypes.jsm');
function getMacAddress(){
var MAX_ADAPTER_NAME_LENGTH = 256;
var MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
var ERROR_BUFFER_OVERFLOW = 111;
var NO_ERROR = 0;
var MAX_ADAPTER_ADDRESS_LENGTH = 8;
var IP_ADDRESS_STRING = ctypes.StructType('IP_ADDRESS_STRING',[
{'String': ctypes.char.array(4 * 4)}
]);
var IP_MASK_STRING = ctypes.StructType('IP_MASK_STRING',[
{'String': ctypes.char.array(4 * 4)}
]);
var DWORD = ctypes.unsigned_long;
var IP_ADDR_STRING = ctypes.StructType('IP_ADDR_STRING');
IP_ADDR_STRING.define([
{'Next': IP_ADDR_STRING.ptr},
{'IpAddress': IP_ADDRESS_STRING},
{'IpMask': IP_MASK_STRING},
{'Context': DWORD}
]);
var PIP_ADDR_STRING = IP_ADDR_STRING.ptr;
var time_t = ctypes.long; // based on this github search https://github.com/search?utf8=%E2%9C%93&q=time_t+ctypes&type=Code&ref=searchresults AND based on this answer here: http://stackoverflow.com/a/471287/1828637
var IP_ADAPTER_INFO = ctypes.StructType('IP_ADAPTER_INFO');
IP_ADAPTER_INFO.define([ // have to use .define because one of the fields "Next" is a ptr to itself
{'Next': IP_ADAPTER_INFO.ptr},
{'ComboIndex': DWORD},
{'AdapterName': ctypes.char.array(MAX_ADAPTER_NAME_LENGTH + 4)},
{'Description': ctypes.char.array(MAX_ADAPTER_DESCRIPTION_LENGTH + 4)},
{'AddressLength': ctypes.unsigned_int},
{'Address': ctypes.unsigned_char.array(MAX_ADAPTER_ADDRESS_LENGTH)}, // BYTE is ctypes.unsigned_char
{'Index': DWORD},
{'Type': ctypes.unsigned_int},
{'DhcpEnabled': ctypes.unsigned_int},
{'CurrentIpAddress': PIP_ADDR_STRING},
{'IpAddressList': IP_ADDR_STRING},
{'GatewayList' : IP_ADDR_STRING},
{'DhcpServer': IP_ADDR_STRING},
{'HaveWins': ctypes.bool},
{'PrimaryWinsServer': IP_ADDR_STRING},
{'SecondaryWinsServer':IP_ADDR_STRING},
{'LeaseObtained': time_t},
{'LeaseExpires': time_t}
]);
var lib = ctypes.open(ctypes.libraryName('IPHLPAPI'));
try{
if(!lib)
return null
console.log("Biblioteca aberta!");
/*DWORD GetAdaptersInfo(
_Out_ PIP_ADAPTER_INFO pAdapterInfo,
_Inout_ PULONG pOutBufLen
);*/
var getAdaptersInfo = lib.declare("GetAdaptersInfo", ctypes.winapi_abi,
DWORD,
IP_ADAPTER_INFO.array(),
ctypes.unsigned_long.ptr
);
let pbuf = IP_ADAPTER_INFO.array(0)();
console.info('pbuf.length:', pbuf, pbuf.length, 'IP_ADAPTER_INFO.size:', IP_ADAPTER_INFO.size, 'pbuf size:', pbuf.length * IP_ADAPTER_INFO.size);
let ret = ctypes.unsigned_long(pbuf.length * IP_ADAPTER_INFO.size);
let sts = getAdaptersInfo(pbuf, ret.address()); // initial fetch to get size needed
console.info('sts:', ctypes.UInt64.lo(sts));
console.info('sts:', sts, sts.toString(), uneval(sts));
console.info('ret:', ret, ret.toString(), uneval(ret));
if(sts == ERROR_BUFFER_OVERFLOW){ //o tamanho do buffer enviado não foi o suficiente.
// ret is defined as unsigned_long which is always a UInt64 in jsctypes `CData { value: UInt64 } `
var ret_jsInt = parseInt(ret.value.toString());
console.info('ret_jsInt:', ret_jsInt);
var neededLength = Math.round(ret_jsInt / IP_ADAPTER_INFO.size);
pbuf = IP_ADAPTER_INFO.array(neededLength)();
console.info('pbuf RE-size:', pbuf.length * IP_ADAPTER_INFO.size);
if (pbuf.length * IP_ADAPTER_INFO.size != ret_jsInt) {
throw new Error('winapi says the size needed is ' + ret_jsInt + ' and i calculated the length by dividing the ID_ADAPTER_INFO.size which is ' + ID_ADAPTER_INFO.size + ' so the needed length was ' + neededLength + ' but the size of this list of neededLength DOES NOT match what winapi says it needs, the size of the neededLength resized list is ' + (pbuf.length * IP_ADAPTER_INFO.size));
}
//agora mando novamente usando o que a lib me retornou.
console.error('going for 2nd time');
sts = getAdaptersInfo(pbuf, ret.address()); // we just pass same ret, as it was updated to the right size // crashing here!!!
if (sts != NO_ERROR) {
throw new Error('after 2nd fetch it still failed, now i need to add more error handling here, error was: ' + sts.toString());
} else {
console.info('succesfully obtained after 2nd time:', pbuf.toString());
for (var i=0; i<pbuf.length; i++) {
console.log(i, pbuf[i].addressOfField('AdapterName').contents.readString(), pbuf[i].addressOfField('IpAddressList').contents.IpAddress.String.readString(), pbuf[i].addressOfField('Description').contents.readString());
}
}
} else {
console.error('this should never happen! i passed 0 size into it it should always overflow!! unless there is no adapater info but there has to be!!');
}
/*
if(sts != NO_ERROR){ //aqui ocorreu um erro que não conseguiremos resolver ainda.
throw Error("Erro buscando configuracoes do adaptador.");
}
*/
}catch(ex){
console.log("Erro na biblioteca", ex, ex.message);
}finally{
lib.close();
}
}
getMacAddress();
Whoa dude I'm looking at this more and it looks like it takes an array of IP_ADAPTER_INFO
s doing this makes it not crash on Win7
I have an issue though, as never mind this i fixed the issue i had tetsed doing ret
comes back as saying the needed size is 2560. But the size of our IP_ADAPTER_INFO
struct is 132. So 2560/132 = 19.333 so something is wrong with our structure we have to figure that out.ctypes.char.array(4*4).ptr
instead of just ctypes.char.array(4*4)
So this is where I figured out we need to pass an array of IP_ADAPTER_INFO: https://github.com/manimaul/Matrix-Mariner-GPS/blob/8989621dfda0e291820a37096d582cc1f355e346/src/getIPwin.py#L45
This is my work, so the issue right now is its crashing after 2nd fetch. we need to fix that.
edit:
Ok dude this is definitely on the right track, its now crashing on the 2nd fetch on all systems, win7 and win81 (i didnt try xp but im sure it will), we have to figure out why on earth its crashing. if you comment out the second sts = getAdapters...
it will not crash, we have to figure this out its bothering me haha
Cu.import('resource://gre/modules/ctypes.jsm');
function getMacAddress(){
const MAX_ADAPTER_NAME_LENGTH = 256;
const MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
const ERROR_BUFFER_OVERFLOW = 111;
const NO_ERROR = 0;
const MAX_ADAPTER_ADDRESS_LENGTH = 8;
var IP_ADDRESS_STRING = ctypes.StructType('IP_ADDRESS_STRING',[
{'String': ctypes.char.array(4 * 4)}
]);
const DWORD = ctypes.uint32_t;
var IP_ADDR_STRING = ctypes.StructType('IP_ADDR_STRING');
IP_ADDR_STRING.define([
{'Next': IP_ADDR_STRING.ptr},
{'IpAddress': IP_ADDRESS_STRING},
{'IpMask': IP_ADDRESS_STRING},
{'Context': DWORD}
]);
var PIP_ADDR_STRING = IP_ADDR_STRING.ptr;
var time_t = ctypes.long; // based on this github search https://github.com/search?utf8=%E2%9C%93&q=time_t+ctypes&type=Code&ref=searchresults AND based on this answer here: http://stackoverflow.com/a/471287/1828637
var IP_ADAPTER_INFO = ctypes.StructType('IP_ADAPTER_INFO');
IP_ADAPTER_INFO.define([ // have to use .define because one of the fields "Next" is a ptr to itself
{'Next': IP_ADAPTER_INFO.ptr},
{'ComboIndex': DWORD},
{'AdapterName': ctypes.char.array(MAX_ADAPTER_NAME_LENGTH + 4)},
{'Description': ctypes.char.array(MAX_ADAPTER_DESCRIPTION_LENGTH + 4)},
{'AddressLength': ctypes.unsigned_int},
{'Address': ctypes.unsigned_char.array(MAX_ADAPTER_ADDRESS_LENGTH)}, // BYTE is ctypes.unsigned_char
{'Index': DWORD},
{'Type': ctypes.unsigned_int},
{'DhcpEnabled': ctypes.unsigned_int},
{'CurrentIpAddress': PIP_ADDR_STRING},
{'IpAddressList': IP_ADDR_STRING},
{'GatewayList' : IP_ADDR_STRING},
{'DhcpServer': IP_ADDR_STRING},
{'HaveWins': ctypes.bool},
{'PrimaryWinsServer': IP_ADDR_STRING},
{'SecondaryWinsServer':IP_ADDR_STRING},
{'LeaseObtained': time_t},
{'LeaseExpires': time_t}
])
const lib = ctypes.open(ctypes.libraryName('IPHLPAPI'));
try{
if(!lib)
return null
console.log("Biblioteca aberta!");
/*DWORD GetAdaptersInfo(
_Out_ PIP_ADAPTER_INFO pAdapterInfo,
_Inout_ PULONG pOutBufLen
);*/
var getAdaptersInfo = lib.declare(
"GetAdaptersInfo",
ctypes.default_abi,
DWORD,
IP_ADAPTER_INFO.ptr.array(),
ctypes.unsigned_long.ptr);
let pbuf = IP_ADAPTER_INFO.ptr.array(1)();
console.info('pbuf.length:', pbuf.length, 'IP_ADAPTER_INFO.size:', IP_ADAPTER_INFO.size, 'pbuf size:', pbuf.length * IP_ADAPTER_INFO.size);
let ret = ctypes.unsigned_long(pbuf.length * IP_ADAPTER_INFO.size);
let sts = getAdaptersInfo(pbuf, ret.address()); // initial fetch to get size needed
console.info('sts:', sts.toString(), 'ret:', ret.toString());
if(sts == ERROR_BUFFER_OVERFLOW){ //o tamanho do buffer enviado não foi o suficiente.
// ret is defined as unsigned_long which is always a UInt64 in jsctypes `CData { value: UInt64 } `
var ret_jsInt = parseInt(ret.value.toString());
console.info('ret_jsInt:', ret_jsInt);
var neededLength = ret_jsInt / IP_ADAPTER_INFO.size;
pbuf = IP_ADAPTER_INFO.ptr.array(neededLength)();
console.info('pbuf RE-size:', pbuf.length * IP_ADAPTER_INFO.size);
if (pbuf.length * IP_ADAPTER_INFO.size != ret_jsInt) {
throw new Error('winapi says the size needed is ' + ret_jsInt + ' and i calculated the length by dividing the ID_ADAPTER_INFO.size which is ' + ID_ADAPTER_INFO.size + ' so the needed length was ' + neededLength + ' but the size of this list of neededLength DOES NOT match what winapi says it needs, the size of the neededLength resized list is ' + (pbuf.length * IP_ADAPTER_INFO.size));
}
//agora mando novamente usando o que a lib me retornou.
console.error('going for 2nd time');
//sts = getAdaptersInfo(pbuf, ret.address()); // we just pass same ret, as it was updated to the right size // crashing here!!!
if (sts != NO_ERROR) {
throw new Error('after 2nd fetch it still failed, now i need to add more error handling here, error was: ' + sts.toString());
} else {
console.info('succesfully obtained after 2nd time:');
}
} else {
console.error('this should never happen! i passed 0 size into it it should always overflow!! unless there is no adapater info but there has to be!!');
}
/*
if(sts != NO_ERROR){ //aqui ocorreu um erro que não conseguiremos resolver ainda.
throw Error("Erro buscando configuracoes do adaptador.");
}
*/
}catch(ex){
console.log("Erro na biblioteca", ex, ex.message);
}finally{
lib.close();
}
}
getMacAddress();