3
votes

I have a piece of code written in Delphi 2005 that searches for a particular attribute on a user in LDAP. I get an access violation when this is run on either Windows 7 or Server 2008, but not on XP or 2003.

Function IsSSOUser(UserId: String): Boolean;
var
  S : string;
  ADOQuery : TADOQuery;
  ADOConnectionSSO: TADOConnection;
begin
  result := false;
  Setdomainname;
  ADOQuery := TADOQuery.Create(nil);
  ADOConnectionSSO := TADOConnection.Create(nil);
  try
    ADOConnectionSSO.LoginPrompt := false;
    ADOConnectionSSO.Mode := cmRead;
    ADOConnectionSSO.Provider := 'ADsDSOObject';
    ADOQuery.Connection := ADOConnectionSSO;
    ADOQuery.ConnectionString := 'Provider=ADsDSOObject;Encrypt Password=False;Mode=Read;Bind Flags=0;ADSI Flag=-2147483648';
    ADOQuery.SQL.Clear;
    try
      S := 'SELECT AdsPath, CN, SN, SSOguid FROM '''
           + LDAPString + ''' WHERE objectClass=''user'' and CN = ''' + UserId + ''' ';
      ADOQuery.SQL.Add(S);
      ADOQuery.Open;
      ADOQuery.ExecSQL;
      if trim(ADOQuery.FieldByName('SSOguid').AsString) = '' then
        result := false
      else
        result := true;
    except
      on e:Exception do
        if e.ClassType <> EOleException then
          Showmessage(format('[%s] Exception in IsSSOUser: [%s]',[e.ClassType.ClassName, e.Message]));
    end;
  finally
    ADOQuery.Close;
    ADOConnectionSSO.Close;
    ADOQuery.free;
    ADOConnectionSSO.free;
  end;
end;

This code works fine on Windows XP and Windows Server 2003, but I get an access violation on both Windows 7 and Server 2008. I see a number of threads online about how changes to ADODB interface can break things on downstream OSes, but I am seemingly having the opposite problem. I'm building on a Windows 7 machine and the code only works on previous versions of Windows.

1
Which line raises the exception? - jachguate
ADOQuery.SQL.Add(S); is the line that causes the exception. When I run the tester app in the Delphi IDE debugger, it shows the error happening in ADODB.pas on OLEDBParameters.SetParameterInfo(0,nil,nil); - mcmar
Your code is a mess! You don't have to Clear a freshly created ADOQuery.SQL. and I'm confused about why you create an ADOConnection but at the same time assign a value to the ConnectionString property of the ADOQuery, not to talk about the ExecSQL call after the call to Open on the same ADOQuery, or the if to assign a true/false value where you just can assign the (negated) condition itself. - jachguate
@jachguate, This particular code is an inherited mess, which has worked until recently. But if changes are needed, mcmar may be able to clean it up using your recommendations. - Chris Thornton
This question is important and you guys are not helping, the lines that are not important you are talking about are not the reason of the exception, if any body knows the answer please let him answer... - ZORRO_BLANCO

1 Answers

5
votes

You will have to add

AdoQuery.ParamCheck := false;

before your

ADOQuery.SQL.Add(S);

since your LDAPString may contains a colon (:) eg. "LDAP://...." which causes the query to try create a parameter object for it. In addition there is no need for ADOQuery.ExecSQL after ADOQuery.Open.