How to list MSSQL servers from a 64-bit client application?

I am looking for a way to list MS SQL Servers on a local network from a 64-bit Delphi application. The method that I have used so far on 32-bit works fine, but contains assembly code that will not compile on 32-bit. I cannot find a way to list the servers from a 64-bit client.

The code I cannot compile is as follows:

function PtCreateADOObject(const ClassID: TGUID): IUnknown;
var
  Status: HResult;
  FPUControlWord: Word;
begin
  asm
    FNSTCW FPUControlWord
  end;
  Status := CoCreateInstance(
              CLASS_Recordset,
              nil,
              CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER,
              IUnknown,
              Result);
  asm
    FNCLEX
    FLDCW FPUControlWord
  end;
  OleCheck(Status);
end;
+4
source share
2 answers

The example from here , adopted for x64, is now compatible with both x32 / x64 systems.

uses
  ActiveX, ComObj, OleDB, DB, ADOInt, ADODB;

function CreateADOObject(const ClassID: TGUID): IUnknown;
var
  Status: HResult;
{$IFDEF CPUX86}
  FPUControlWord: Word;
{$ENDIF CPUX86}
begin

{$IFDEF CPUX86}
  asm
    FNSTCW  FPUControlWord
  end;
{$ENDIF CPUX86}
  Status := CoCreateInstance(ClassID, nil, CLSCTX_INPROC_SERVER or
    CLSCTX_LOCAL_SERVER, IUnknown, Result);
{$IFDEF CPUX86}
  asm
    FNCLEX
    FLDCW FPUControlWord
  end;
{$ENDIF CPUX86}
  if (Status = REGDB_E_CLASSNOTREG) then
    raise Exception.Create('error')
  else
    OleCheck(Status);
end;

procedure ListAvailableSQLServers(Names: TStringList);
var
  RSCon: ADORecordsetConstruction;
  Rowset: IRowset;
  SourcesRowset: ISourcesRowset;
  SourcesRecordset: _Recordset;
  SourcesName, SourcesType: TField;
begin
  SourcesRecordset := CreateADOObject(CLASS_Recordset) as _Recordset;
  RSCon := SourcesRecordset as ADORecordsetConstruction;
   SourcesRowset := CreateComObject(ProgIDToClassID('SQLOLEDB Enumerator')) as ISourcesRowset;
   OleCheck(SourcesRowset.GetSourcesRowset(nil, IRowset, 0, nil, IUnknown(Rowset)));
   RSCon.Rowset := RowSet;
   with TADODataSet.Create(nil) do
   try
     Recordset := SourcesRecordset;
     SourcesName := FieldByName('SOURCES_NAME');
     SourcesType := FieldByName('SOURCES_TYPE');
     Names.BeginUpdate;
     Names.Clear;
     try
        while not EOF do
        begin
          if (SourcesType.AsInteger = DBSOURCETYPE_DATASOURCE) and
             (SourcesName.AsString <> '')
           then
            Names.Add(SourcesName.AsString);
          Next;
        end;
     finally
        Names.EndUpdate;
     end;
  finally
     Free;
  end;
end;

procedure GetServer;
var
  oItems: TStringList;
begin
  oItems:= TStringList.Create;
  try
    ListAvailableSQLServers(oItems);
    // To something with oItems
    ShowMessage(oItems.Text);
  finally
    oItems.Free;
  end;
end;
0
source

, , . - (, x86 x64) :

type
  TFPControlState = {$IFDEF CPUX86}Word{$ENDIF}{$IFDEF CPUX64}UInt32{$ENDIF};

function GetFPControlState: TFPControlState;
begin
  {$IFDEF CPUX86}
  Result := Get8087CW;
  {$ENDIF}
  {$IFDEF CPUX64}
  Result := GetMXCSR;
  {$ENDIF}
end;

procedure SetFPControlState(const Value: TFPControlState);
begin
  {$IFDEF CPUX86}
  Set8087CW(Value);
  {$ENDIF}
  {$IFDEF CPUX64}
  SetMXCSR(Value);
  {$ENDIF}
end;

, 32- 8087 16- , 64- SSE- 32- .

:

function PtCreateADOObject(const ClassID: TGUID): IUnknown;
var
  Status: HResult;
  FPControlState: TFPControlState;
begin
  FPControlState := GetFPControlState;
  Status := CoCreateInstance(
    CLASS_Recordset,
    nil,
    CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER,
    IUnknown,
    Result
  );
  SetFPControlState(FPControlState);
  OleCheck(Status);
end;

. :

  • .
  • RTL .
  • . , , .
+8

Source: https://habr.com/ru/post/1546279/


All Articles