Solved

Delphi Programming question

Posted on 1997-08-30
17
186 Views
Last Modified: 2010-04-04
I am looking for a way to find a network card's hardware address.  This is the address that uniquely identifies it on a network.  The network card will be in a computer running Windows 95 or possibly NT.  Can you tell me a way of getting this address from either or both of these operating systems? I know this is a tough question but I only have 55 points to spare.  Sorry.
0
Comment
Question by:tdiamond
  • 8
  • 7
  • 2
17 Comments
 
LVL 1

Expert Comment

by:sassas081597
ID: 1343121
I think this is your case. Sorry not in Pascal, however you can convert it from C to Pascal yourself.
NCB is a record. You need its fourth parameter.

UCHAR Netbios( PNCB:  pncb) {address of network control block};

typedef struct _NCB { // ncb
    UCHAR  ncb_command;
    UCHAR  ncb_retcode;
    UCHAR  ncb_lsn;
    UCHAR  ncb_num;
    PUCHAR ncb_buffer;
    WORD   ncb_length;
    UCHAR  ncb_callname[NCBNAMSZ];
    UCHAR  ncb_name[NCBNAMSZ];
    UCHAR  ncb_rto;
    UCHAR  ncb_sto;
    void (*ncb_post) (struct _NCB *);
    UCHAR  ncb_lana_num;
    UCHAR  ncb_cmd_cplt;
    UCHAR  ncb_reserve[10];
    HANDLE ncb_event;
} NCB;

ncb_lana_num

Specifies the LAN adapter number. This zero-based number corresponds to a particular transport provider using a particular LAN adapter board.

0
 

Author Comment

by:tdiamond
ID: 1343122
How can you find out the address of the network control block and will it be different depending on the computer?
0
 
LVL 1

Expert Comment

by:sassas081597
ID: 1343123
The Netbios function gives you all the information you need about the network controlblock as shown in the answer above.
0
 

Author Comment

by:tdiamond
ID: 1343124
I don't mean to keep bugging you, but do you think that you could give me more info on where to put the struct and where to execute the Netbios function that you mentioned (in a header file or in your main.cpp file?)  I would like to try what you suggested in C or C++ before I convert it to Delphi/Pascal, but I'm having trouble getting it to compile.  I am using Microsoft C++ 4.0.  Could you possibly give me the minimal amount of C code to get it to work and tell me where to put it (.h,.cpp) just so that I don't have to keep bugging you.  I'd really appreciate it.

Thanks...
0
 

Author Comment

by:tdiamond
ID: 1343125
I don't mean to keep bugging you, but do you think that you could give me more info on where to put the struct and where to execute the Netbios function that you mentioned (in a header file or in your main.cpp file?)  I would like to try what you suggested in C or C++ before I convert it to Delphi/Pascal, but I'm having trouble getting it to compile.  I am using Microsoft C++ 4.0.  Could you possibly give me the minimal amount of C code to get it to work and tell me where to put it (.h,.cpp) just so that I don't have to keep bugging you.  I'd really appreciate it.

Thanks...
0
 

Author Comment

by:tdiamond
ID: 1343126
I don't mean to keep bugging you, but do you think that you could give me more info on where to put the struct and where to execute the Netbios function that you mentioned (in a header file or in your main.cpp file?)  I would like to try what you suggested in C or C++ before I convert it to Delphi/Pascal, but I'm having trouble getting it to compile.  I am using Microsoft C++ 4.0.  Could you possibly give me the minimal amount of C code to get it to work and tell me where to put it (.h,.cpp) just so that I don't have to keep bugging you.  I'd really appreciate it.

Thanks...
0
 
LVL 3

Expert Comment

by:mirek071497
ID: 1343127
Hi
Do you still have any problems and waiting for help ?
0
 

Author Comment

by:tdiamond
ID: 1343128
Yes, I still need help.  I still haven't received a reply to my last comment (which I mistakenly posted 3 times).  I am new to C/C++ and would like more information on how to implement the 'struct' that was given to me by sassas.  I put it all in one file (along with the netbios function call) and it bombed with 50 or more compiler errors.  A snippet of code that is known to work in MS C++ 4.0 (if possible), would be great.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 3

Expert Comment

by:mirek071497
ID: 1343129
Ok here is the code to list all network card's number in you'r system. I don't know which Version of Delphi so if You have Delphi2 please enable dirrective for this "$Define ForD2"

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private {}
  public  {}
  end;

{ $Define ForD2}   { Define This if You have Delphi2 }
{$IFDEF ForD2}
  function Netbios(P: Pointer): Char; stdcall;
{$ENDIF}

var
  Form1: TForm1;

implementation

{$R *.DFM}

{$IFNDEF ForD2}
uses
  NB30;

{$ELSE}
function Netbios; external 'netapi32.dll' name 'Netbios';


const
  NCBNAMSZ   = 16;             // absolute length of a net name
  MAX_LANA   = 254;            // lana's in range 0 to MAX_LANA inclusive
  NCBRESET   = $32;            // NCB RESET
  NCBASTAT   = $33;            // NCB ADAPTER STATUS
  NCBENUM    = $37;            // NCB ENUMERATE LANA NUMBERS

type
  // Network Control Block
  PNCB = ^TNCB;
  TNCBPostProc = procedure(P: PNCB);
  TNCB = packed record
    ncb_command: Char;         // command code
    ncb_retcode: Char;         // return code
    ncb_lsn: Char;             // local session number
    ncb_num: Char;             // number of our network name
    ncb_buffer: PChar;         // address of message buffer
    ncb_length: Word;          // size of message buffer
    ncb_callname: array[0..NCBNAMSZ - 1] of char;  // blank-padded name of remote
    ncb_name: array[0..NCBNAMSZ - 1] of char;      // our blank-padded netname
    ncb_rto: Char;             // rcv timeout/retry count
    ncb_sto: Char;             // send timeout/sys timeout
    ncb_post: TNCBPostProc;    // POST routine address
    ncb_lana_num: Char;        // lana (adapter) number
    ncb_cmd_cplt: Char;        // 0xff => commmand pending
    ncb_reserve: array[0..9] of Char;              // reserved, used by BIOS
    ncb_event: THandle;        // HANDLE to Win32 event which
                               // will be set to the signalled
                               // state when an ASYNCH command
                               // completes
  end;

  // Structure returned to the NCB command NCBASTAT is ADAPTER_STATUS followed
  // by an array of NAME_BUFFER structures.
  PAdapterStatus = ^TAdapterStatus;
  TAdapterStatus = packed record
    adapter_address: array[0..5] of Char;
    rev_major: Char;
    reserved0: Char;
    adapter_type: Char;
    rev_minor: Char;
    duration: Word;
    frmr_recv: Word;
    frmr_xmit: Word;
    iframe_recv_err: Word;
    xmit_aborts: Word;
    xmit_success: DWORD;
    recv_success: DWORD;
    iframe_xmit_err: Word;
    recv_buff_unavail: Word;
    t1_timeouts: Word;
    ti_timeouts: Word;
    reserved1: DWORD;
    free_ncbs: Word;
    max_cfg_ncbs: Word;
    max_ncbs: Word;
    xmit_buf_unavail: Word;
    max_dgram_size: Word;
    pending_sess: Word;
    max_cfg_sess: Word;
    max_sess: Word;
    max_sess_pkt_size: Word;
    name_count: Word;
  end;

  // Structure returned to the NCB command NCBENUM.
  // On a system containing lana's 0, 2 and 3, a structure with
  // length =3, lana[0]=0, lana[1]=2 and lana[2]=3 will be returned.
  PLanaEnum = ^TLanaEnum;
  TLanaEnum = packed record
    length: Char;         //  Number of valid entries in lana[]
    lana: array[0..MAX_LANA] of Char;
  end;
{$ENDIF}

procedure TForm1.Button1Click(Sender: TObject);
var
  MyNCB     : PNCB;
  AdaptStat : PAdapterStatus;
  LanaEnum  : PLanaEnum;
  i         : integer;
begin
  Memo1.Clear;
  New(MyNCB);
  New(AdaptStat);
  New(LanaEnum);
  MyNCB^.ncb_command := chr(NCBRESET);
  MyNCB^.ncb_lana_num := '0';
  if NetBios( MyNCB )<>#0 then
    ShowMessage( 'Error on RESET' )
  else
    begin
      MyNCB^.ncb_command := chr(NCBENUM);
      MyNCB^.ncb_callname := '*               ';
      MyNCB^.ncb_buffer := PChar( LanaEnum );
      MyNCB^.ncb_length := SizeOf(TLanaEnum);
      if NetBios( MyNCB )<>#0 then
        ShowMessage( 'Error on LANAENUM' )
      else
        begin
          MyNCB^.ncb_command := chr(NCBASTAT);
          MyNCB^.ncb_buffer := PChar( AdaptStat );
          MyNCB^.ncb_length := SizeOf(TAdapterStatus);
          for i:=0 to integer(LanaEnum^.length)-1 do
          begin
            MyNCB^.ncb_lana_num := LanaEnum^.lana[i];
            if NetBios( MyNCB )=#0 then
              Memo1.Lines.Add(
                'Adapter nr '+IntToStr(i)+' addr='+
                IntToStr(integer(PAdapterStatus(MyNCB^.ncb_Buffer).adapter_address[0]))+':'+
                IntToStr(integer(PAdapterStatus(MyNCB^.ncb_Buffer)^.adapter_address[1]))+':'+
                IntToStr(integer(PAdapterStatus(MyNCB^.ncb_Buffer)^.adapter_address[2]))+':'+
                IntToStr(integer(PAdapterStatus(MyNCB^.ncb_Buffer)^.adapter_address[3]))+':'+
                IntToStr(integer(PAdapterStatus(MyNCB^.ncb_Buffer)^.adapter_address[4]))+':'+
                IntToStr(integer(PAdapterStatus(MyNCB^.ncb_Buffer)^.adapter_address[5]))
                );
          end;
        end;
    end;
  Dispose(LanaEnum);
  Dispose(AdaptStat);
  Dispose(MyNCB);
end;

end.

Regards
Mirek
0
 

Author Comment

by:tdiamond
ID: 1343130
I tried the code you gave me and it didn't list any card addresses in the memo component.  I'm using using Delphi 3.0.  I have an SMC PCI 10Mbps Etherpower Network card and it didn't find it.  What am I doing wrong?  
0
 
LVL 3

Expert Comment

by:mirek071497
ID: 1343131
I don't know. Have You any error messages ? Try debug - this code was tested on My Win95 and created with Delphi3, however i tested this in Delphi2 too. Describe  more what is going on.

BTW  The card must be properlly installed in You'r Windows, but i think so you have this.
0
 

Author Comment

by:tdiamond
ID: 1343132
I tried it in Delphi 2.0 and 3.0 and it doesn't work in either.  It reports no error messages.  The problem is that it never enters into the "For" loop below because the expression "integer(LanaEnum^.length)-1" equals zero or NULL so the loop never executes even once.  Do you think the fact that my card is PNP is causing trouble?  What kind of card did you test this code on?

  ShowMessage( 'Error on LANAENUM' )
else
  begin
    MyNCB^.ncb_command := chr(NCBASTAT);
    MyNCB^.ncb_buffer := PChar( AdaptStat );
    MyNCB^.ncb_length := SizeOf(TAdapterStatus);
**   for i:=0 to integer(LanaEnum^.length)-1 do  **
      begin
        MyNCB^.ncb_lana_num := LanaEnum^.lana[i];
        if NetBios( MyNCB )=#0 then
          Memo1.Lines.Add(
          'Adapter nr '+IntToStr(i)+' addr='+ .....
0
 
LVL 3

Expert Comment

by:mirek071497
ID: 1343133
This enumerates all cards in Network so Dialup too. I just start try when this can happened, but now i don't know.

p.s. LanaEnum^.length=0 means so you have not Network adapters available for netbios calls.
0
 
LVL 3

Expert Comment

by:mirek071497
ID: 1343134
Hi
My code don't work when you are conected to internet (mayby in some other situation). I will try to resolve this.
0
 

Author Comment

by:tdiamond
ID: 1343135
I do have a PPP dialup adapter set up which permits me to dial
into my ISP.  Do you think I should remove it from my device
list and run the program again to try to find my NIC card?
0
 
LVL 3

Accepted Solution

by:
mirek071497 earned 10 total points
ID: 1343136
NO !!!!

I only found where is the mistake.

I corrected this now.

When you have more than one network then you must set correct caller_name.

add in this proc varialble

var
  name_len  : DWORD;

and change code :

       MyNCB^.ncb_callname := '*               ';

to this :

      { getting UserName }
      name_len := SizeOf(MyNCB^.ncb_callname) ;
      GetUserName( @MyNCB^.ncb_callname, name_len );
      for i := 0 to name_len-1 do MyNCB^.ncb_callname[i] := UpCase(MyNCB^.ncb_callname[i]);
      for i := name_len-1 to SizeOf(MyNCB^.ncb_callname) do MyNCB^.ncb_callname[i]:=#32;
      { end of setting UserName }


all ned works fine.
0
 
LVL 3

Expert Comment

by:mirek071497
ID: 1343137
BTW when you copy from Ex-Ex then probably spaces in ncb_callname was truncated.

ncb_callname must be filled to length=16 with spaces. This is problem with Ex-Ex.
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Suggested Solutions

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now