The Delphi Bug List

Entry No.
686
VCL - General - Controls
FindControl may return an invalid result, causing a "Read of address 00098053" access violation.
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 4.03 5.0 5.01 6.0 6.01 6.02 Kylix 1.0
ExistsExistsExistsExistsExistsExistsExistsExistsExistsExistsExistsExistsExistsExistsN/A
Description
Reported by many on newsgroups; checked by Jordan Russell, others
FindControl may return an invalid result, causing a "Read of address 00098053" access violation. This is most commonly seen when a user drops down a combo box (e.g. TComboBox), and moves the mouse over the dropped-down list.

It is a conflict with the Microsoft Identity Manager (msident.dll), used by MS Outlook Express and possibly other MS apps. The Identity Manager calls SetProp to set a window property on the desktop window (GetDesktopWindow) with a value of $00098053. Unfortunately, this property sometimes has the same atom ID as the atom used internally by the VCL when accessing its own properties. When that happens and the VCL calls FindControl with the desktop window handle, it will get back the value set by the Identity Manager - $00098053. Since that is not a valid pointer, an access violation occurs.

For more details, see the thread on Google Groups.

Solution / workaround
I believe this can only be fixed by modifying Controls.pas. Below is one solution - it makes FindControl and IsDelphiHandle check the process ID of Handle to ensure it is not the desktop window or a window of another process.

Delphi 6

function FindControl(Handle: HWnd): TWinControl;
var
  PID: DWORD;
begin
  Result := nil;
  if (Handle <> 0) then
  begin
    if (GetWindowThreadProcessId(Handle, @PID) <> 0) and
       (PID = GetCurrentProcessId) then
    begin
      if GlobalFindAtom(PChar(ControlAtomString)) = ControlAtom then
        Result := Pointer(GetProp(Handle, MakeIntAtom(ControlAtom)))
      else
        Result := ObjectFromHWnd(Handle);
    end;
  end;
end;

...

function IsDelphiHandle(Handle: HWND): Boolean;
var
  PID: DWORD;
begin
  Result := False;
  if Handle <> 0 then
  begin
    if (GetWindowThreadProcessId(Handle, @PID) <> 0) and
       (PID = GetCurrentProcessId) then
    begin
      if GlobalFindAtom(PChar(WindowAtomString)) = WindowAtom then
        Result := GetProp(Handle, MakeIntAtom(WindowAtom)) <> 0
      else
        Result := ObjectFromHWnd(Handle) <> nil;
    end;
  end;
end;
Delphi 2 through 5
function FindControl(Handle: HWnd): TWinControl;
var
  PID: DWORD;
begin
  Result := nil;
  if Handle <> 0 then
  begin
    if (GetWindowThreadProcessId(Handle, @PID) <> 0) and
       (PID = GetCurrentProcessId) then
      Result := Pointer(GetProp(Handle, MakeIntAtom(ControlAtom)));
  end;
end;

...
 
function IsDelphiHandle(Handle: HWND): Boolean;
var
  PID: DWORD;
begin
  Result := (Handle <> 0) and
    (GetWindowThreadProcessId(Handle, @PID) <> 0) and
    (PID = GetCurrentProcessId) and
    (GetProp(Handle, MakeIntAtom(WindowAtom)) <> 0);
end;
Latest update of this entry: 2002-03-19

Post a comment on this bug


Index page
Delphi Bug List home page
The Delphi Bug Lists are presently maintained by Jordan Russell, who has taken over this task from Reinier Sterkenburg since August 2000.
All feedback is appreciated. See also the feedback section of the Delphi Bug List home page.