Конференция "Сети" » функция NetBIOS и Windows Vista [D7]
 
  • _netbios_ (03.03.10 16:27) [0]
    Столько лет нормально работала функция NetBIOS. Получал с помощью нее MAC-адреса хостов. Очень незаменимая вещь — может вернуть MAC хоста за маршрутизатором (если протокол разрешен NETBIOS). И тут на-те! MS оказывается прекратила ее поддержку начиная с Висты!
    http://msdn.microsoft.com/en-us/library/bb870903%28VS.85%29.aspx
    ..."[Netbios is not supported on Windows Vista, Windows Server 2008, and subsequent versions of the operating system]"...

    Я потратил несколько месяцев на понимание, отчего моя прога вдруг начала непредсказуемо глючить в ходе выполнения этой функции именно в Висте и 7ке. Память сильно портилась, ломались указатели в разных местах... Как следствие — исключения, приводящие к завершению. Перепробовал кучу примеров из инета по использованию ее. Полез в оффлан-мсдн — там даже описания нет ее. И наконец полез в онлайн-мсдн, и сделал печальное открытие. Какие комментарии, товарищи разработчики? Как дальше жить без нее? Может замена какая есть, а я не знаю просто? Самое интересное, что если хост существует, то функция нормально отрабатывает и возвращает MAC. Иначе — глюки с памятью после вызова: то цикл от i=0 to 0 вдруг становится бесконечным, то объекты созданные до вызова NetBIOS перестают нормально существовать.
  • DVM © (03.03.10 17:44) [1]

    > Иначе — глюки с памятью после вызова: то цикл от i=0 to
    > 0 вдруг становится бесконечным, то объекты созданные до
    > вызова NetBIOS перестают нормально существовать.

    По моему у тебя в программе ошибка.
  • _netbios_ (03.03.10 21:04) [2]

    > По моему у тебя в программе ошибка.


    В 5й строке? :)
  • _netbios_ (04.03.10 16:35) [3]
    Вот, ребята с другого форума подсказали, как реализовать замену функции NetBIOS. Просто отправить нужный NBQuery по UDP хосту, MAC которого нужно узнать. Замечательно работает в случае, если хост включен и работает netbios на нем. Иначе обычный выход по таймауту при select. Никаких заморочек, как в случае с функцией NetBIOS.


    const
    NB_QUERY : array[0..37] of Byte = ($20,$43,$4b,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41 ,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$00,$00,$21,$00,$01);

    type
    PMacAddress = ^TMacAddress;
    TMacAddress = array[0..5] of byte;

    type
    PNB_HEADER = ^NB_HEADER;
    NB_HEADER = packed record
     wTransId : Word;
     wFlags : Word;
     wQuestions : Word;
     wAnswerRRs : Word;
     wAuthRRs : Word;
     wAdditionalRRs : Word;
    end;

    type
    PNB_NAME = ^NB_NAME;
    NB_NAME = packed record
     Name : array[0..15] of char;
     Flags : Word;
    end;

    type
    PNB_ANSWER = ^NB_ANSWER;
    NB_ANSWER = packed record
     RRName : array[0..33] of char;
     Nbtype : Word;
     Nbclass : Word;
     dwTTL : DWord;
     wDataLen : Word;
     NumNames : Byte;
    end;
       .................

    function GetMACAddrUDP(hostaddr: string; var mac: string): boolean;
    var
     S: TSocket;
     AddrSize, Return: Integer;
     Header: NB_HEADER;
     Target: TSockAddrIn;
     P: Pointer;
     OrigTransId: Word;
     TimeOut: TTimeVal;
     FDSet: TFDSet;
     Buffer: array[0..$800] of Byte;
     NumNames, Offset: Integer;
     MA: TMacAddress;
    begin
     mac := '';
     Result := False;
     s := socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
     try
     {Keep trans ID}
       OrigTransId := LoWord(GetTickCount);
     {Prepare request}
       ZeroMemory(@Header, SizeOf(Header));
       Header.wTransId := OrigTransId;
       Header.wFlags := $1000;
       Header.wQuestions := htons(1);
     {Prepare address}
       ZeroMemory(@Target, SizeOf(Target));
       Target.sin_family := AF_INET;
       Target.sin_addr.S_addr :=  inet_addr(Pchar(hostaddr));
       Target.sin_port := htons(137);
     {Glue reuqest}
       GetMem(P, SizeOf(Header) + SizeOf(NB_QUERY));
       try
         ZeroMemory(P, SizeOf(Header) + SizeOf(NB_QUERY));
         MoveMemory(P, @Header, SizeOf(Header));
         MoveMemory(Ptr(DWORD(P) + SizeOf(Header)), @NB_QUERY, SizeOf(NB_QUERY));
         if sendto(s, P^, SizeOf(Header) + SizeOf(NB_QUERY), 0, Target, SizeOf(Target)) <> SOCKET_ERROR then
         begin
           ZeroMemory(@FDSet, SizeOf(FDSet));
           FDSet.fd_array[0] := S;
           FDSet.fd_count := 1;
           ZeroMemory(@TimeOut, SizeOf(TimeOut));
           TimeOut.tv_sec := 1;
           if select(0, @FDSet, nil, nil, @TimeOut) > 0 then
           begin
             ZeroMemory(@Buffer, SizeOf(Buffer));
             AddrSize := SizeOf(Target);
             Return := recvfrom(s, Buffer, SizeOf(Buffer), 0, Target, AddrSize);
             if Return > SizeOf(Header) then
             begin
               with PNB_HEADER(@Buffer)^ do
                 if (OrigTransId = wTransId) and ((wFlags shr 12) = 0) and (htons(wAnswerRRs) = 1) then
                 begin
                   NumNames := PNB_ANSWER(Ptr(DWord(@Buffer) + SizeOf(NB_HEADER)))^.NumNames;
                   if NumNames * SizeOf(NB_NAME) + SizeOf(TMacAddress) < (Return - SizeOf(NB_HEADER)) then
                   begin
                     Offset := SizeOf(NB_HEADER) + SizeOf(NB_ANSWER) + NumNames * SizeOf(NB_NAME);
                     MA := PMacAddress(Ptr(Integer(@Buffer) + Offset))^;
                     mac := IntToHex(MA[0], 2);
                     mac := mac + '-' + IntToHex(MA[1], 2);
                     mac := mac + '-' + IntToHex(MA[2], 2);
                     mac := mac + '-' + IntToHex(MA[3], 2);
                     mac := mac + '-' + IntToHex(MA[4], 2);
                     mac := mac + '-' + IntToHex(MA[5], 2);
                     Result := True;
                   end;
                 end;
             end;
           end;
         end;
       finally
         FreeMem(P);
       end;
     finally
       closesocket(S);
     end;
    end;

 
Конференция "Сети" » функция NetBIOS и Windows Vista [D7]
Есть новые Нет новых   [134437   +29][b:0][p:0.003]