Search code examples
delphidelphi-5

how to call WINAPI DsRoleGetPrimaryDomainInformation in delphi?


I am calling Windows API DsRoleGetPrimaryDomainInformation like shown in below code block. I want to get the Domain forest name and Domain DNS name. When I do ShowMessage for domain DNS name, it is just displaying "????" and for domain forest name it is displaying EmptyString.

unit Unit1;

interface

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

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


    DSROLE_PRIMARY_DOMAIN_INFO_LEVEL = (
    DsRolePrimaryDomainInfoBasic,
    DsRoleUpgradeStatus,
    DsRoleOperationState);

  DSROLE_MACHINE_ROLE = (
    DsRole_RoleStandaloneWorkstation,
   DsRole_RoleMemberWorkstation,
  DsRole_RoleStandaloneServer,
  DsRole_RoleMemberServer,
  DsRole_RoleBackupDomainController,
  DsRole_RolePrimaryDomainController);

   PDSROLE_PRIMARY_DOMAIN_INFO_BASIC = ^DSROLE_PRIMARY_DOMAIN_INFO_BASIC;
  DSROLE_PRIMARY_DOMAIN_INFO_BASIC = record
    MachineRole: DSROLE_MACHINE_ROLE;
    Flags: ULONG; 
    DomainNameFlat: LPWSTR;
    DomainNameDns: LPWSTR;
    DomainForestName: LPWSTR;
    DomainGuid: TGUID;
  end;

  function DsRoleGetPrimaryDomainInformation(lpServer: LPCWSTR;
  InfoLevel: DSROLE_PRIMARY_DOMAIN_INFO_LEVEL; var Buffer: DSROLE_PRIMARY_DOMAIN_INFO_BASIC): DWORD; stdcall; external 'netapi32.dll';


var
  Form1: TForm1;

implementation

{$R *.DFM}


procedure TForm1.Button1Click(Sender: TObject);
var
  pBuffer : DSROLE_PRIMARY_DOMAIN_INFO_BASIC;
begin
  if not DsRoleGetPrimaryDomainInformation(nil,DsRolePrimaryDomainInfoBasic,pBuffer) = ERROR_SUCCESS then
  begin
    ShowMessage('Something is wrong!');
    exit;
  end;
  ShowMessage(pBuffer.DomainNameDns );
  ShowMessage(pBuffer.DomainForestName);
end;

end.

Solution

  • According to the documentation the buffer is not an out parameter but a pointer.

    So

      function DsRoleGetPrimaryDomainInformation(lpServer: LPCWSTR;
      InfoLevel: DSROLE_PRIMARY_DOMAIN_INFO_LEVEL; var Buffer: DSROLE_PRIMARY_DOMAIN_INFO_BASIC): DWORD; stdcall; external 'netapi32.dll';
    

    need to be changed to

      function DsRoleGetPrimaryDomainInformation(lpServer: LPCWSTR;
      InfoLevel: DSROLE_PRIMARY_DOMAIN_INFO_LEVEL; Buffer: pDSROLE_PRIMARY_DOMAIN_INFO_BASIC): DWORD; stdcall; external 'netapi32.dll';
    

    Here is a unit with a complete implementation. Just tested in Delphi 6:

    unit DSRole;
    
    {$WEAKPACKAGEUNIT}
    
    {$HPPEMIT ''}
    {$HPPEMIT '#include "dsrole.h"'}
    {$HPPEMIT ''}
    
    interface
    
    uses
       Windows;
    //
    // Domain information
    //
    type
      _DSROLE_MACHINE_ROLE = (
        DsRole_RoleStandaloneWorkstation,
        DsRole_RoleMemberWorkstation,
        DsRole_RoleStandaloneServer,
        DsRole_RoleMemberServer,
        DsRole_RoleBackupDomainController,
        DsRole_RolePrimaryDomainController);
      {$EXTERNALSYM _DSROLE_MACHINE_ROLE}
      DSROLE_MACHINE_ROLE = _DSROLE_MACHINE_ROLE;
      {$EXTERNALSYM DSROLE_MACHINE_ROLE}
      TDsRoleMachineRole = DSROLE_MACHINE_ROLE;
    
    //
    // Previous server state
    //
      _DSROLE_SERVER_STATE = (DsRoleServerUnknown, DsRoleServerPrimary, DsRoleServerBackup);
      {$EXTERNALSYM DSROLE_SERVER_STATE}
      DSROLE_SERVER_STATE = _DSROLE_SERVER_STATE;
      {$EXTERNALSYM DSROLE_SERVER_STATE}
      PDSROLE_SERVER_STATE = ^DSROLE_SERVER_STATE;
      {$EXTERNALSYM PDSROLE_SERVER_STATE}
      TDsRoleServerState = DSROLE_SERVER_STATE;
    
      _DSROLE_PRIMARY_DOMAIN_INFO_LEVEL = (DsRoleFiller0, DsRolePrimaryDomainInfoBasic, DsRoleUpgradeStatus, DsRoleOperationState);
      {$EXTERNALSYM _DSROLE_PRIMARY_DOMAIN_INFO_LEVEL}
      DSROLE_PRIMARY_DOMAIN_INFO_LEVEL = _DSROLE_PRIMARY_DOMAIN_INFO_LEVEL;
      {$EXTERNALSYM DSROLE_PRIMARY_DOMAIN_INFO_LEVEL}
      TDsRolePrimaryDomainInfoLevel = DSROLE_PRIMARY_DOMAIN_INFO_LEVEL;
    
    //
    // Flags to be used with the PRIMARY_DOMAIN_INFO_LEVEL structures below
    //
    
    const
      DSROLE_PRIMARY_DS_RUNNING          = $00000001;
      {$EXTERNALSYM DSROLE_PRIMARY_DS_RUNNING}
      DSROLE_PRIMARY_DS_MIXED_MODE       = $00000002;
      {$EXTERNALSYM DSROLE_PRIMARY_DS_MIXED_MODE}
      DSROLE_UPGRADE_IN_PROGRESS         = $00000004;
      {$EXTERNALSYM DSROLE_UPGRADE_IN_PROGRESS}
      DSROLE_PRIMARY_DOMAIN_GUID_PRESENT = $01000000;
      {$EXTERNALSYM DSROLE_PRIMARY_DOMAIN_GUID_PRESENT}
    
    //
    // Structure that correspond to the DSROLE_PRIMARY_DOMAIN_INFO_LEVEL
    //
    
    type
      PDSROLE_PRIMARY_DOMAIN_INFO_BASIC = ^DSROLE_PRIMARY_DOMAIN_INFO_BASIC;
      {$EXTERNALSYM PDSROLE_PRIMARY_DOMAIN_INFO_BASIC}
      _DSROLE_PRIMARY_DOMAIN_INFO_BASIC = record
        MachineRole: DSROLE_MACHINE_ROLE;
        Flags: ULONG;
        DomainNameFlat: LPWSTR;
        DomainNameDns: LPWSTR;
        DomainForestName: LPWSTR;
        DomainGuid: TGUID;
      end;
    
      {$EXTERNALSYM _DSROLE_PRIMARY_DOMAIN_INFO_BASIC}
      DSROLE_PRIMARY_DOMAIN_INFO_BASIC = _DSROLE_PRIMARY_DOMAIN_INFO_BASIC;
      {$EXTERNALSYM DSROLE_PRIMARY_DOMAIN_INFO_BASIC} 
      TDsRolePrimaryDomainInfoBasic = DSROLE_PRIMARY_DOMAIN_INFO_BASIC; 
      PDsRolePrimaryDomainInfoBasic = PDSROLE_PRIMARY_DOMAIN_INFO_BASIC; 
    
      PDSROLE_UPGRADE_STATUS_INFO = ^DSROLE_UPGRADE_STATUS_INFO; 
      {$EXTERNALSYM PDSROLE_UPGRADE_STATUS_INFO} 
      _DSROLE_UPGRADE_STATUS_INFO = record 
        OperationState: ULONG; 
        PreviousServerState: DSROLE_SERVER_STATE; 
      end;
    
      {$EXTERNALSYM _DSROLE_UPGRADE_STATUS_INFO} 
      DSROLE_UPGRADE_STATUS_INFO = _DSROLE_UPGRADE_STATUS_INFO; 
      {$EXTERNALSYM DSROLE_UPGRADE_STATUS_INFO} 
      TDsRoleUpgradeStatusInfo = DSROLE_UPGRADE_STATUS_INFO; 
      PDsRoleUpgradeStatusInfo = PDSROLE_UPGRADE_STATUS_INFO; 
    
      _DSROLE_OPERATION_STATE = (DsRoleOperationIdle, DsRoleOperationActive, DsRoleOperationNeedReboot); 
      {$EXTERNALSYM _DSROLE_OPERATION_STATE} 
      DSROLE_OPERATION_STATE = _DSROLE_OPERATION_STATE; 
      {$EXTERNALSYM DSROLE_OPERATION_STATE} 
      TDsRoleOperationState = DSROLE_OPERATION_STATE; 
    
      PDSROLE_OPERATION_STATE_INFO = ^DSROLE_OPERATION_STATE_INFO; 
      {$EXTERNALSYM PDSROLE_OPERATION_STATE_INFO} 
      _DSROLE_OPERATION_STATE_INFO = record 
        OperationState: DSROLE_OPERATION_STATE; 
      end; 
      {$EXTERNALSYM _DSROLE_OPERATION_STATE_INFO} 
      DSROLE_OPERATION_STATE_INFO = _DSROLE_OPERATION_STATE_INFO; 
      {$EXTERNALSYM DSROLE_OPERATION_STATE_INFO} 
      TDsRoleOperationStateInfo = DSROLE_OPERATION_STATE_INFO; 
      PDsRoleOperationStateInfo = PDSROLE_OPERATION_STATE_INFO; 
    
    function DsRoleGetPrimaryDomainInformation(lpServer: LPCWSTR; InfoLevel: DSROLE_PRIMARY_DOMAIN_INFO_LEVEL; Buffer: pDSROLE_PRIMARY_DOMAIN_INFO_BASIC): DWORD; stdcall;
    {$EXTERNALSYM DsRoleGetPrimaryDomainInformation}
    
    procedure DsRoleFreeMemory(Buffer: pointer); stdcall;
    {$EXTERNALSYM DsRoleFreeMemory}
    
    implementation
    
    const
      netapi32 = 'netapi32.dll';
    
    function DsRoleGetPrimaryDomainInformation; external netapi32 name 'DsRoleGetPrimaryDomainInformation';
    procedure DsRoleFreeMemory; external netapi32 name 'DsRoleFreeMemory'; 
    
    end. 
    

    With this in hand you only need to call it:

    uses
     DSRole;
    
    procedure TForm1.FormCreate(Sender: TObject);
    var
      pBuffer : pDSROLE_PRIMARY_DOMAIN_INFO_BASIC;
    begin
      pBuffer := new( pDSROLE_PRIMARY_DOMAIN_INFO_BASIC);
      Caption := BoolToStr(DsRoleGetPrimaryDomainInformation(nil,DsRolePrimaryDomainInfoBasic,pBuffer) = ERROR_SUCCESS, True);
      FreeMem(pBuffer);
    end;