The Delphi Bug List

Visual Component Library (VCL)

System


The color codes indicate in which version(s) of Delphi the bug occurs and what its status is.
Latest update: 20 December 1998
Bug # Delphi versions Description
373 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 DDE
You can't make a static link to a 16 bit DLL that contains the DDEMAN unit under Windows 3.x. If you load the DLL dynamically from another application, the static links works OK.
374 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 DDE
There are problems with multiple clients on the same form. Probably caused by subscript bug in TDdeClientConv.ClearItems
375 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 DDE
On Windows95, a DDE hot-link will die on the client side, if you enter a menu or "live" drag the form containing the DDE client.
376 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 DDE
Don't ever use Application.ProcessMessages in a DDE event handler (not really a bug, but should be documented). The DDE links will die.
377 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 DDE
If you use Form.Release on a form containing a server with open links, the form will never be destroyed.
378 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 DDE
Closing a link while there are DDE messages in the message queue will cause a GPF (both client and server). With netDDE you can sometimes cause a GPF on two different machines simultaneously by closing one end.
379 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 DDE
In some situations you must explicitely remove the link between the conversation component and the item component (both client and server) before the form is destroyed - or else... GPF.
380 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 DDE
You get an access violation if you try to remove a TDdeClientConv with a linked TDdeClientItem.
381 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 DDE
A DDE hot-link dies on the client side if the client performs a database action using BDE/Paradox and sometimes using BDE/Microsoft ODBC Paradox.
382 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 DDE
When a form has both DdeClientConv and DdeServerConv components, problems arise.
22 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TDdeClientConv
If TDdeClientConv.ExecuteMacro or TDdeClientConv.ExecuteMacroLines is called with the WaitFlg parameter set to True, the TDdeClientConv.WaitStat property remains True for ever (it should become False when the server completes the processing of the macro)
23 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TDdeClientConv
Potential memory overrun in TDdeClientConv
24 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TDdeServerConv
DDE ExecuteMacro may fail if debugging VCL *with* range checking turned on.
514 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TMediaPlayer
Problem when AutoOpen = True

Bug #378; last modified: before April 1998
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Unknown Unknown Unknown Unknown Unknown Unknown Unknown Unknown
System - DDE

Closing a link while there are DDE messages in the message queue will cause a GPF (both client and server). With netDDE you can sometimes cause a GPF on two different machines simultaneously by closing one end.

Description
Reported by Anders Bo Melander
Solution / workaround
The method I use at the moment to circumvent this one, is to send out a message from the server telling the clients to shut up and disconnect, wait a few seconds to make sure that the server have received the last message and then kill the server.
Really stupid - Takes me 5 seconds to destroy the form.

Bug #381; last modified: before April 1998
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Unknown Unknown Unknown Unknown Unknown Unknown Unknown Unknown
System - DDE

A DDE hot-link dies on the client side if the client performs a database action using BDE/Paradox and sometimes using BDE/Microsoft ODBC Paradox.

Description
Reported by Menno Avegaart
Solution / workaround
Fixes by Luca Ridarelli (checked by Arjen Broeze):
I solved the following DDE bugs:
  • TDDeclientConvs where losing links with a dde server under Win 95 when using menus or scrollbars or BDE.
  • A Delphi application with "live" DDE links would cause a GPF if closed (a quit).
  • After one week of debugging (I used Turbo Debugger for Win32!) I discovered a fault in the implementation of the DDEManagerCallback function in DDEMAN.PAS. Borland uses the following function to associate the incoming data from the DDE server to the clientconv object in the application:
    if  DdeQueryConvInfo(Conv, QID_SYNC, @ci)=0 then Exit;
    This turns out to be wrong, since it's not warranteed that the DdeQueryConvInfo will return a good address in the ci structure under Win95.

    Microsoft in the Win 32 documentation recommends to use the hsz1 and hsz2 parameters passed to the callback function as the Item and Topic of the conversation to find the target of the incoming data. I changed the way the DDEManagerCallback function works by keeping a list of the DDEClientConvs with open links in the DDEMgr variable and by searching for the target DDEClientConvs in the list during arrival of new data from the server.
    Here is the old code:
     Result := 0;
         case CallType of
        XTYP_CONNECT:
          Result := HDdeData(ddeMgr.AllowConnect(hsz2, hsz1));
        XTYP_WILDCONNECT:
          Result := ddeMgr.AllowWildConnect(hsz2, hsz1);
        XTYP_CONNECT_CONFIRM:
          ddeMgr.Connect(Conv, hsz1, Boolean(Data2));
      if Conv <> 0 then
      begin
        ci.cb := sizeof(TConvInfo);
        if DdeQueryConvInfo(Conv, QID_SYNC, @ci)=0 then Exit;
    and here is the new one:
     Result := 0;
      case CallType of
        XTYP_CONNECT:
          Result := HDdeData(ddeMgr.AllowConnect(hsz2, hsz1));
        XTYP_WILDCONNECT:
          Result := ddeMgr.AllowWildConnect(hsz2, hsz1);
        XTYP_CONNECT_CONFIRM:
          ddeMgr.Connect(Conv, hsz1, Boolean(Data2));
        XTYP_ADVDATA:     {added for Win 95 broken link bug}
         begin
          RLTopic := DDeQueryString(Ddemgr.FddeInstId,
                                    hsz1, @STopic, 256, CP_WINANSI);
          RLItem  := DDeQueryString(Ddemgr.FddeInstId,
                                    hsz2, @SItem, 256, CP_WINANSI);
          if integer(RLTopic)>0 
          then SSTopic:=StrPas(STopic)
          else SSTopic:='';
          if integer(RLItem)>0 
          then SSItem:=StrPas(SItem)
          else SSItem:='';
          Result:=HDdeData(DDE_FNOTPROCESSED);
          for I:=0 to DdeMgr.FClientConvs.Count-1
           do
            begin
             DummyClientConv:=TDDEClientConv(DdeMgr.FClientConvs.Items[I]);
             if (DummyClientConv.FConv=Conv) and 
                (DummyClientConv.FDdeTopic=SSTopic)
              then
               begin
                Result:=HDdeData(DummyClientConv.DataChange(Data, hsz2));
                break;
               end;
            end;
         end;
      end;
      if Conv <> 0 then
      begin
        ci.cb := sizeof(TConvInfo);
        if  DdeQueryConvInfo(Conv, QID_SYNC, @ci)=0 then Exit;
    This solution addresses also the problem of having GPFs when trying to close an application with live links and incoming data , since the open DDEClientConvs are removed from the lookup list (and thus not receiving data anymore!) BEFORE physically removing the connection in the OS. In this way no incoming data can reach a freed DDEClientConv during an application quit!

    Since the modification is extensive I include the whole surce of the modified DDEMan.pas. I also added some other patches apparently left over by Borland. I have also to say that I had no help at all from Borland despite several help requests.
    Bug #382; last modified: before April 1998
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    Exists Exists Unknown Unknown Unknown Unknown Unknown Unknown
    System - DDE

    When a form has both DdeClientConv and DdeServerConv components, problems arise.

    Description
    By Sean Keeley

    If a form has both a DdeClientConv and a DdeServerConv component, an access violation occurs when the form is closed. Sample PAS and DFM code to illustrate is available. On my system using the test program attached below, the error message says (more or less):
    EAccessViolation in TestDDE.EXE at 000075DE.
        Access violation at address 004087DE. Read address FFFFFFFF.
    Solution / workaround
    Solution 1 (partial by-pass):
    Inserting an explicit Free of the DdeServerConv into the FormClose method by-passes the problem as is documented in the sample code.
    Solution 2 (full (?) by-pass):
    Browsing the Ddeman.pas source, I found a line in the TDdeClientConv.OpenLink method which is commented as a by-pass for a DdeUninitialize bug (win3.1). The line is
      ddeMgr.ComponentIndex := Application.ComponentCount -1;
    and it's line 822 in my copy of the source. Commenting out this line appears to resolve the particular problem as the demonstration program no longer needs the DdeServConv1.Free in FormClose to avoid a crash on form close.

    This by-pass may fix one problem but there still at least one problem with the DDE support in Delphi 2.0. With more complex applications which are "cross-linked" via DDE, i.e. the applications are both clients and servers, failures still occur when the form is closed. These failures are slightly intermittent but they happen roughly 80-90% of the time. A typical failure is:

    EAccessViolation in DDESamp.EXE at 000018xx. Access violation at address
    00402Axx. Read address 007949C6C [or sometimes FFFFFFFF or FFFFFFFC].
    where "xx" indicates a value that changes from compile to compile. Sometimes a Windows "illegal operation" error occurs. The following is typical:
    PROGRAM caused a general protection fault
    in module DDEML.DLL at 0002:00004c38.
    Registers:
    EAX=00003c26 CS=16e7 EIP=00004c38 EFLGS=00000246
    EBX=172f0550 SS=3b7f ESP=00008d64 EBP=00008d78
    ECX=0000b01a DS=16df ESI=00000550 FS=3b87
    EDX=00000000 ES=3ade EDI=00000510 GS=0000
    Bytes at CS:EIP:
    c4 7f 16 26 8b 35 26 8b 55 02 89 56 f6 66 83 7f
    Stack dump:
    05100550 00000510 00000000 022e0000 00008da6 06358da6 055016e7 3b870157
    08b40157 0000b01a 00000000 001fbc01 011b0253 01870028 0000c2bc bff70510
    Further Information

    I've tested in the "Gold" (950) version of Windows 95, the Gold version plus Service Pack 1, and both the preceding plus the latest OLE Update (UPD960125a). The errors are more or less identical in all cases.

    Bug #22; last modified: before April 1998
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    Unknown Unknown Unknown Unknown Unknown Unknown Unknown Unknown
    System - TDdeClientConv

    If TDdeClientConv.ExecuteMacro or TDdeClientConv.ExecuteMacroLines is called with the WaitFlg parameter set to True, the TDdeClientConv.WaitStat property remains True for ever (it should become False when the server completes the processing of the macro)

    Description
    Reported by Chris Jobson; not independently confirmed
    If TDdeClientConv.ExecuteMacro or TDdeClientConv.ExecuteMacroLines is called with the WaitFlg parameter set to True, the TDdeClientConv.WaitStat property remains True for ever more (it should become False when the server completes the processing of the macro).
    I have experienced and investigated this with Delphi 3, but the Delphi 2 source looks identical and so I asume the problem will occur in Delphi 2 too.

    Cause:

    Delphi sets FWaitStat to True before issuing the Execute transaction to the DDEML. It uses the TIMEOUT_ASYNC flag in the Execute, so it expects to get a DDE callback of type XTYP_XACT_COMPLETE when the server finishes the transaction. The DDE callback routine should then call TDdeClientConv.XactComplete which sets FWaitStat to false.
    The problem is that Delphi is using the DDEML DDESetUserHandle and DDEQueryConvInfo functions to store the TDdeClientConv pointer in the hUser member of the CONVINFO structure maintained by the DDEML. In the DDE callback handler it uses DDEQueryConvInfo to get the TDdeClientConv associated with the callback, passing it the transaction id for XTYP_XACT_COMPLETE callbacks and QID_SYNC for all other callbacks. Unfortunately it only calls DDESetUserHandle with QID_SYNC (when the conversation is opened), and never calls it with the transaction id for async transactions, so it never finds the TDdeClientConv for XTYP_XACT_COMPLETE callbacks.

    Solution / workaround
    Modify the code in ddeman.pas as follows.
    function DdeMgrCallBack(CallType, Fmt: UINT; Conv: HConv; hsz1, hsz2: HSZ;
      Data: HDDEData; Data1, Data2: DWORD): HDDEData; stdcall;
    var
      ci: TConvInfo;
      ddeCli: TComponent;
      ddeSrv: TDdeSrvrConv;
      ddeObj: TComponent;
      xID: Integer;
    begin
      Result := 0;
      case CallType of
        XTYP_CONNECT:         Result := HDdeData(ddeMgr.AllowConnect(hsz2, hsz1));
        XTYP_WILDCONNECT:     Result := ddeMgr.AllowWildConnect(hsz2, hsz1);
        XTYP_CONNECT_CONFIRM: ddeMgr.Connect(Conv, hsz1, Boolean(Data2));
      end;
      if Conv <> then
      begin
        ci.cb := sizeof(TConvInfo);
    // FIX TO BUG - COMMENT OUT NEXT 3 LINES
    //    if CallType = XTYP_XACT_COMPLETE then 
    //      xID := Data1
    //    else xID := QID_SYNC;

    Bug #23; last modified: before April 1998
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    Exists Unknown Unknown Unknown Unknown Unknown Unknown Unknown
    System - TDdeClientConv

    Potential memory overrun in TDdeClientConv

    Description
    Reported by Gary Cramblitt
    The DDE API does not require a returned error code to be a null terminated "string", but the VCL does rely on this. A StrCopy thus may cause a memory overrun.
    Solution / workaround
    In the VCL source code of DDEMAN.PAS modify the implementation of
    function TDdeClientConv.RequestData(const Item: string): PChar;
    ....
    begin
      ...
      if pData <> nil then
      begin
        try
    {$IFDEF FixPotentialOverflowBug}
          Result := StrAlloc (len + 1);
          FillChar(Result^,len+1,0);
          StrLCopy(Result, pData, len);
    {$ELSE}
          Result := StrAlloc (StrLen (PData) + 1);
          StrCopy (Result, pData);
    {$ENDIF}
        finally
          DdeUnaccessData(hdata);
        end;
      end;

    Bug #24; last modified: before April 1998
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    Exists Unknown Unknown Unknown Unknown Unknown Unknown Unknown
    System - TDdeServerConv

    DDE ExecuteMacro may fail if debugging VCL *with* range checking turned on.

    Description
    Reported by Frank Marvin Weigel; improved by Stefan Hoffmeister
    Delphi uses a shadow class TDdeSrvrConv where the ExecuteMacro function is defined to return an integer and not a Longint as it is with TDdeServerConv. TDdeSrvrConv.ExecuteMacro calls DdeServerConv.ExecuteMacro and the return code is passed through. But if a macro is executed successfully, the TDdeServerConv returns dde_FAck ($8000). That is out of range for an integer, so an exception is raised.
    Note that this will only happen if the VCL source code is recompiled with range checking turned on. When using the Borland supplied DCUs this should not be an issue.
    Solution / workaround
    In the VCL sources for DDEMAN.PAS change the declaration
        {$IFDEF FixDDESrvrConv}
          function ExecuteMacro(Conv: HConv;  hszTopic: HSZ; Data:
                                HDdeData): LongInt;
        {$ELSE}
          function ExecuteMacro(Conv: HConv;  hszTopic: HSZ; Data:
                                HDdeData): Integer;
        {$ENDIF}
    both in the object interface for TDdeSrvrConv as well as in the implementation.

    Bug #514; last modified: 20-Dec-98
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    Absent Absent Absent Absent Absent Exists Exists Exists
    System - TMediaPlayer

    Problem when AutoOpen = True

    Description
    Reported by Vito Nicola Palmisano
    To reproduce:
    Drop a TMediaPlayer component, set the properties AutoOpen:= true and DeviceType:= dtCDAudio, run the application: a EMCIDeviceError exception will be raised (this works fine in Delphi 3).
    Solution / workaround
    The problem should be in TMediaPlayer.Open; as matter of fact in Delphi 3 there was a check for the property FElementName being empty that has been dropped in Delphi 4;
    So the two lines in TMediaPlayer.Open of Delphi 4 that now are:
      OpenParm.lpstrElementName := PChar(FElementName);
    and
      FFlags := FFlags or mci_Open_Element;
    should be rewritten as:
      if FElementName <> '' then
        OpenParm.lpstrElementName := PChar(FElementName);
    and
      if FElementName <> '' then FFlags := FFlags or mci_Open_Element;
    To test this I copied MPlayer.Pas from \Delphi4\SourceVCL in a separate directory and applied the patch described; then I wrote a small application with a TMediaPlayer created at runtime i.e.:
    procedure TForm1.FormShow(Sender: TObject);
    begin
      Mp:= TMediaPlayer.Create(Self);
      Mp.Parent:= Self;
      Mp.DeviceType:= dtCDAudio;
      Mp.Open;
    end;

    Index page
    The Delphi Bug Lists are maintained by Reinier Sterkenburg, with help from the DeBug Team.
    All feedback is appreciated. See also the feedback section of the Delphi Bug List home page.