• Welcome to Jose's Read Only Forum 2023.
 

Assorted Window API Examples

Started by José Roca, August 29, 2011, 03:33:10 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

José Roca

 
This article demonstrates how to get the Media Access Control (MAC) address for an ethernet adapter programmatically by using NetBIOS, if your card is bound to NetBIOS.

http://support.microsoft.com/kb/118623

To get the Media Access Control (MAC) address for an ethernet adapter programmatically, use the Netbios() NCBASTAT command and provide a "*" as the name in the NCB.ncb_CallName field. This is demonstrated in the sample code below.

For computers with multiple network adapters you need to enumerate the LANA numbers and perform the NCBASTAT command on each. Even when you have a single network adapter, it is a good idea to enumerate valid LANA numbers first and perform the NCBASTAT on one of the valid LANA numbers. It is considered bad programming to hardcode the LANA number to 0.

In addition, other hardware and software may be assigned their own MAC addresses. For example, a modem can have a MAC address. Also, a RAS client or server can install "dummy" network adapters that correspond to a dialup or serial connection. Normally, these MAC addresses are randomly generated. If an adapter status is called on a LANA that corresponds to one of these adapters when no connection is present, Netbios returns error 0x34 (NRC_ENVNOTDEF) even if a reset was previously performed.

With the NetBEUI and IPX transports, the same information can be obtained at a command prompt by using:


   net config workstation

            
The ID given is the MAC address.

The following code enumerates all LANA numbers, performs a reset (NCBREST), and an adapter status (NCBASTAT).

C++ Example:


#include <windows.h>
#include <wincon.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

typedef struct _ASTAT_
{

   ADAPTER_STATUS adapt;
   NAME_BUFFER    NameBuff [30];

}ASTAT, * PASTAT;

ASTAT Adapter;

void main (void)
{
   NCB Ncb;
   UCHAR uRetCode;
   char NetName[50];
   LANA_ENUM   lenum;
   int      i;

   memset( &Ncb, 0, sizeof(Ncb) );
   Ncb.ncb_command = NCBENUM;
   Ncb.ncb_buffer = (UCHAR *)&lenum;
   Ncb.ncb_length = sizeof(lenum);
   uRetCode = Netbios( &Ncb );
   printf( "The NCBENUM return code is: 0x%x \n", uRetCode );

   for(i=0; i < lenum.length ;i++)
   {
       memset( &Ncb, 0, sizeof(Ncb) );
       Ncb.ncb_command = NCBRESET;
       Ncb.ncb_lana_num = lenum.lana[i];

       uRetCode = Netbios( &Ncb );
       printf( "The NCBRESET on LANA %d return code is: 0x%x \n",
               lenum.lana[i], uRetCode );

       memset( &Ncb, 0, sizeof (Ncb) );
       Ncb.ncb_command = NCBASTAT;
       Ncb.ncb_lana_num = lenum.lana[i];

       strcpy( Ncb.ncb_callname,  "*               " );
       Ncb.ncb_buffer = (char *) &Adapter;
       Ncb.ncb_length = sizeof(Adapter);

       uRetCode = Netbios( &Ncb );
       printf( "The NCBASTAT on LANA %d return code is: 0x%x \n",
               lenum.lana[i], uRetCode );
       if ( uRetCode == 0 )
       {
          printf( "The Ethernet Number on LANA %d is:
                  %02x%02x%02x%02x%02x%02x\n",
         lenum.lana[i],
               Adapter.adapt.adapter_address[0],
               Adapter.adapt.adapter_address[1],
               Adapter.adapt.adapter_address[2],
               Adapter.adapt.adapter_address[3],
               Adapter.adapt.adapter_address[4],
               Adapter.adapt.adapter_address[5] );
       }
    }

}


PowerBASIC Example:


' SED_PBCC - Use the console compiler
#INCLUDE ONCE "windows.inc"

TYPE ASTAT
   adapt        AS ADAPTER_STATUS
   NameBuff(29) AS NAME_BUFFER
END TYPE

FUNCTION PBMAIN

   LOCAL Adapter AS ASTAT
   LOCAL tNcb AS NCB
   LOCAL bRetCode AS BYTE
   LOCAL NetName AS ASCIIZ * 50
   LOCAL lenum AS LANA_ENUM
   LOCAL i AS LONG

   tNcb.ncb_command = %NCBENUM
   tNcb.ncb_buffer = VARPTR(lenum)
   tNcb.ncb_length = SIZEOF(lenum)
   bRetCode = Netbios(tNcb)
   ? "The NCBENUM return code is: " & HEX$(bRetCode)

   FOR i = 0 TO lenum.length - 1
      RESET tNcb
      tNcb.ncb_command = %NCBRESET
      tNcb.ncb_lana_num = lenum.lana(i)
      bRetCode = Netbios(tNcb)
      ? "The NCBRESET on LANA " & FORMAT$(lenum.lana(i)) & _
        " return code is: " & HEX$(bRetCode)
      RESET tNcb
      tNcb.ncb_command = %NCBASTAT
      tNcb.ncb_lana_num = lenum.lana(i)
      tNcb.ncb_callname = "*               "
      tNcb.ncb_buffer = VARPTR(Adapter)
      tNcb.ncb_length = SIZEOF(Adapter)
      bRetCode = Netbios(tNcb)
      ? "The NCBASTAT on LANA " & FORMAT$(lenum.lana(i)) & _
        " return code is: " & HEX$(bRetCode)
      IF bRetCode = 0 THEN
         ? "The Ethernet Number on LANA " & FORMAT$(lenum.lana(i)) & " is: " & _
            HEX$(Adapter.adapt.adapter_address(0), 2) & "-" & _
            HEX$(Adapter.adapt.adapter_address(1), 2) & "-" & _
            HEX$(Adapter.adapt.adapter_address(2), 2) & "-" & _
            HEX$(Adapter.adapt.adapter_address(3), 2) & "-" & _
            HEX$(Adapter.adapt.adapter_address(4), 2) & "-" & _
            HEX$(Adapter.adapt.adapter_address(5), 2)
      END IF
   NEXT

   #IF %DEF(%PB_CC32)
      PRINT "Press a key..."
      WAITKEY$
      LOCATE ,1
   #ENDIF

END FUNCTION


Note The Netbios function is not available for use on Windows Vista, Windows Server 2008, and subsequent versions of the operating system.

José Roca

 
You can use the Windows API SendMessage function to close any active window that has a system menu by sending an WM_SYSCOMMAND message.


#COMPILE EXE
#DIM ALL
#INCLUDE "windows.inc"

FUNCTION PBMAIN () AS LONG

   LOCAL dwHandle AS DWORD

   ' Retrieve the handle to the Calculator window
   dwHandle = FindWindow("SciCalc", "Calculator")
   IF dwHandle <> %NULL THEN
      ' Send a message to end its existence.
      SendMessage dwHandle, %WM_SYSCOMMAND, %SC_CLOSE, %NULL
   END IF

END FUNCTION


Remarks

The FindWindow function retrieves a handle to the top-level window whose class name and window name match the specified strings. This function does not search child windows. This function does not perform a case-sensitive search.

If you aren't using an English language version of Windows, you will have to change the second parameter. For example, for the Spanish version of Windows you will have to use "Calculadora" instead of "Calculator".