带有firefox附加组件的getAdaptersInfo

时间:2015-03-27 13:05:14

标签: firefox-addon firefox-addon-sdk jsctypes

我想使用firefox附件获取一些独特的机器信息。

使用此代码我可以得到名称:

var dns = Cu.components.classes["@mozilla.org/network/dns-service;1"]
                    .getService(Cu.components.interfaces.nsIDNSService);
var myName = dns.myHostName;

现在我需要NIC信息(如mac地址,适配器名称)。我尝试使用getAdaptersInfo函数,但这只适用于Windows,我需要一些解决方案跨平台。

有人有想法吗?

这是我的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();
    }

}

但是当我运行cfx run时,firefox会崩溃。

2 个答案:

答案 0 :(得分:2)

忽略此解决方案是非常错误的 - 请立即查看我的第二个解决方案正在进行的工作

您的代码有效,只需访问.contents pbuf,将下面的代码粘贴到暂存器并将环境设置为浏览器并点击运行。请参阅此处了解如何从暂存器启用浏览器环境:Youtube :: How to Enable Scratchpad Environment - Browser

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,
            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);
        } else {
            console.log('got it', pbuf.contents.toString());
        }

        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();

<击>

答案 1 :(得分:1)

好的,现在这可行:)问题是我告诉函数接受结构列表,将其定义为IP_ADAPTER_INFO.ptr.array()然后我创建了一个像let pbuf = IP_ADAPTER_INFO.ptr.array(1)()这样的结构数组但是这样做崩溃,当我们增加到2或更多的大小时,它崩溃得更快。所以我更改为在函数IP_ADAPTER_INFO.ptr中声明它,然后我创建了一个像let pbuv = IP_ADAPTER_INFO.array(?)这样的结构数组,其中?可以是任何数字,它可以正常工作:)

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();

下面的OLD STUFF - 离开这里,所以我可以从中学习,因为我第一次尝试通过将其定义为IP_ADAPTER_LIST.ptr.array()来告诉函数接受数组,但我必须将其更改为IP_ADAPTER_LIST.ptr,如上所示


哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇

我有一个问题,因为IP_ADAPTER_INFO回来说需要的大小是2560.但我们的ret结构的大小是132.所以2560/132 = 19.333所以我们的结构是错误的,我们必须弄明白。 从不介意我修复了我所做的问题IP_ADAPTER_INFO而非ctypes.char.array(4*4).ptr

所以我知道我们需要传递一个IP_ADAPTER_INFO数组:https://github.com/manimaul/Matrix-Mariner-GPS/blob/8989621dfda0e291820a37096d582cc1f355e346/src/getIPwin.py#L45

这是我的工作,所以现在的问题是它在第二次获取后崩溃。我们需要解决这个问题。

编辑: 好吧,老兄,这肯定是在正确的轨道上,它现在崩溃在所有系统上的第二次获取,win7和win81(我没有尝试xp,但我确定它会),我们必须弄清楚为什么它在地球上崩溃。如果你注释掉第二个ctypes.char.array(4*4)它不会崩溃,我们必须弄明白它困扰我哈哈

sts = getAdapters...