4

I have a minimalist project with FireDac FDConnection & FDSqlQuery, DataSetProvider and ClientDataSet, trying to access the example Employee.FDB that came with the Firebird 2.5 package I downloaded from SourceForge today.

Everything is set to the defaults as theycame off the palette apart from the database name in the FDConnection's pop-up Information tab and the FDQuery's Sql, which is set to select * from employee.

The FDQuery opens fine but as soon as I try to open the CDS, in the IDE or running my app, I get an access violation.

This is all my code:

  FDQuery1.Open;
  Caption := IntToStr(FDQuery1.RecordCount);  // this shows 42 on the form's caption
  CDS1.Open;  // AV here

So, the FDQuery opens ok but the CDS doesn't.

At run time, the exception occurs here:

  function TCustomClientDataSet.CreateDSBase: IDSBase;
  begin
    CreateDbClientObject(CLSID_DSBase, IDSBase, Result);
    Check(Result.SetProp(dspropANSICODEPAGE, DefaultSystemCodePage)); <-- Exception here
    Check(Result.SetProp(dspropUTF8METADATA, NativeUInt(True)));
    Check(Result.SetProp(dspropUTF8ERRORMSG, NativeUInt(True)));
  end;

The exception msg is

Project FBTest1 raised exception class $C0000005 with message 'access vioaltion at 0x0075d05b: read of address 0x00000000'.

In the IDE I get a similar exception if I try to set Active = True on the CDS, which the message said occurred in DSnap200.Bpl.

The first time it happened at run-time I had some kind of "Incident Report" pop-up offering to report it to Embarcadero. First time I've seen that.

If I substitute a SqlConnection and SqlQuery for the FDac components, I get the same error.

So, I guess my question is, can a CDS be provoked into this behaviour simply by using default property settings for a project as simple as this one, i.e. did I miss a step, or is it likely an EMBA QC thing?

Sir Rufo
  • 18,395
  • 2
  • 39
  • 73
MartynA
  • 30,454
  • 4
  • 32
  • 73
  • Why do you need CDS1, FDQuery is already a ClientDataSet. – Peter Aug 05 '14 at 22:55
  • Thanks for your interest. a) because I started out trying to access the FB DB via DBX (which I still want to do) and I wanted to check whether the same problem exists with FD, which it does; b) I want to end up with a datasnap server with CDSs in the client; and c), regardless, a CDS didn't ought to AV like that. – MartynA Aug 05 '14 at 23:07
  • It looks like `CreateDbClientObject(CLSID_DSBase, IDSBase, Result)` is returning `nil` in Result. A guess would be that it can't load MIDAS.DLL or something like that. I would have thought that would have generated a runtime error but you never know. You can try adding MidasLib to your uses clause of your project. – Graymatter Aug 05 '14 at 23:20
  • @Graymatter: Yes. I'll try MidasLib in the morning. Thing is, I've been using Midas and CDSs since D5 days, almost daily with hardly ever a problem, and I have literally dozens of CDS projects on the go, but only this one has a problem. – MartynA Aug 05 '14 at 23:27

1 Answers1

6

Solved! Thanks to Graymatter's suggestion to try Using MidasLib, I've got to the bottom of the problem and fixed it so that the app now works using Midas.Dll. I'm posting this as an answer, rather than a comment, firstly because it's a bit too long for that, but, more importantly, the cause was actually rather strange and the solution may assist anyone else who runs into the problem.

First, I tried Using MidasLib, and the app ran fine, w/o the AV that the q is about.

So, reassured that the problem doesn't arise with the current MidasLib code, I went back to trying to get the app to work with Midas.Dll. I checked the Midas.Dll versions in the XE6 bin directory and \Windows\SysWOW64, and they were both as I was expecting, 20.0.16277.1276 dated 16 June 2014.

Tracing into CheckDBlient in DataSnap.DSIntf and observing carefully, the penny dropped and I realised what was happening:

procedure CheckDbClient(const CLSID: TGUID);
[...]
begin
  [...]
      if DbClientHandle = 0 then
      begin
        Size := 256;
        SetLength(FileName, Size);
        if RegQueryValue(HKEY_CLASSES_ROOT, PChar(Format('CLSID\%s\InProcServer32',
          [GUIDToString(CLSID)])), PChar(FileName), Size) = ERROR_SUCCESS then
          SetLength(FileName, Size) else
        begin
        [...]
        end;
        DbClientHandle := LoadLibrary(PChar(FileName));

This gets the path to Midas.Dll from the InProcServer key in its registration, and this wasn't pointing to XE6's bin directory or SysWOW64, but to another location that was not of my creation and which contained a version of Midas.Dll dating from 2007. Oddly, unlike a copy I have of the Dll dating from the D7 era, this Dll does not have version info on its property page but it has a creation date of 9 August 2002 and a file size of 351Kb.

So, once I'd found that, fixing the problem was as simple as renaming that Dll so that the OS won't load it, and re-registering the version in SysWOW64.

Where the rogue Midas.Dll came from isn't clear, but it certainly arrived since last week, because it isn't in the back-up I happen to have from last Thursday evening.

The only things I've installed since then are a handful of 3rd-party GUI utilities for managing/accessing Access, IB and Firebird databases, so the culprit seems to have been one of them.

MartynA
  • 30,454
  • 4
  • 32
  • 73