Thursday, February 3, 2011

Get list of domains on the network

Using the Windows API, how can I get a list of domains on my network?

  • Answered my own question:

    Use the NetServerEnum function, passing in the SVTYPEDOMAIN_ENUM constant for the "servertype" argument.

    In Delphi, the code looks like this:

    <snip>
    type
      NET_API_STATUS = DWORD;
      PSERVER_INFO_100 = ^SERVER_INFO_100;
      SERVER_INFO_100 = packed record
        sv100_platform_id : DWORD;
        sv100_name        : PWideChar;
    end;
    
    function NetServerEnum(  //get a list of pcs on the network (same as DOS cmd "net view")
      const servername    : PWideChar;
      const level         : DWORD;
      const bufptr        : Pointer;
      const prefmaxlen    : DWORD;
      const entriesread   : PDWORD;
      const totalentries  : PDWORD;
      const servertype    : DWORD;
      const domain        : PWideChar;
      const resume_handle : PDWORD
    ) : NET_API_STATUS; stdcall; external 'netapi32.dll';
    
    function NetApiBufferFree(  //memory mgmt routine
      const Buffer : Pointer
    ) : NET_API_STATUS; stdcall; external 'netapi32.dll';
    
    const
      MAX_PREFERRED_LENGTH = DWORD(-1);
      NERR_Success = 0;
      SV_TYPE_ALL  = $FFFFFFFF;
      SV_TYPE_DOMAIN_ENUM = $80000000;
    
    
    function TNetwork.ComputersInDomain: TStringList;
    var
      pBuffer        : PSERVER_INFO_100;
      pWork          : PSERVER_INFO_100;
      dwEntriesRead  : DWORD;
      dwTotalEntries : DWORD;
      i              : integer;
      dwResult       : NET_API_STATUS;
    begin
      Result := TStringList.Create;
      Result.Clear;
    
      dwResult := NetServerEnum(nil,100,@pBuffer,MAX_PREFERRED_LENGTH,
                                @dwEntriesRead,@dwTotalEntries,SV_TYPE_DOMAIN_ENUM,
                                PWideChar(FDomainName),nil);
    
      if dwResult = NERR_SUCCESS then begin
        try
          pWork := pBuffer;
          for i := 1 to dwEntriesRead do begin
            Result.Add(pWork.sv100_name);
            inc(pWork);
          end;  //for i
        finally
          NetApiBufferFree(pBuffer);
        end;  //try-finally
      end  //if no error
      else begin
        raise Exception.Create('Error while retrieving computer list from domain ' +
                               FDomainName + #13#10 +
                               SysErrorMessage(dwResult));
      end;
    end;
    <snip>
    
  • You will need to use some LDAP queries

    Here is some code I have used in a previous script (it was taken off the net somewhere, and I've left in the copyright notices)

    ' This VBScript code gets the list of the domains contained in the 
    ' forest that the user running the script is logged into
    
    ' ---------------------------------------------------------------
    ' From the book "Active Directory Cookbook" by Robbie Allen
    ' Publisher: O'Reilly and Associates
    ' ISBN: 0-596-00466-4
    ' Book web site: http://rallenhome.com/books/adcookbook/code.html
    ' ---------------------------------------------------------------
    
    set objRootDSE = GetObject("LDAP://RootDSE")
    strADsPath =  "<GC://" & objRootDSE.Get("rootDomainNamingContext") & ">;"
    strFilter  = "(objectcategory=domainDNS);"
    strAttrs   = "name;"
    strScope   = "SubTree"
    
    set objConn = CreateObject("ADODB.Connection")
    objConn.Provider = "ADsDSOObject"
    objConn.Open "Active Directory Provider"
    set objRS = objConn.Execute(strADsPath & strFilter & strAttrs & strScope)
    objRS.MoveFirst
    while Not objRS.EOF
        Wscript.Echo objRS.Fields(0).Value
        objRS.MoveNext
    wend
    


    Also a C# version

0 comments:

Post a Comment