I'm looking for a way of enumerating MS SQL Servers on the local network from a 64-bit Delphi application. The method I've used thus far on 32-bit works fine but contains assembly code which won't compile on 32-bit. I can't seem to find a way of enumerating servers from a 64-bit client.
The code that I cannot compile is this:
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;
The code that is causing you trouble simply stores and restores the floating point control state. You can write that in a cross-platform way (well, supporting x86 and x64) like this:
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;
This abstracts away the fact that the 32 bit code uses the 8087 unit with its 16 bit control state, and the 64 bit code uses the SSE unit with its 32 bit control state.
Now your function becomes:
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;
There are a number of benefits to this approach. Most clearly:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With