INFO: Calling DdePostAdvise() from XTYP_ADVREQ (102571)



The information in this article applies to:

  • Microsoft Windows Software Development Kit (SDK) 3.1
  • Microsoft Win32 Application Programming Interface (API), when used with:
    • Microsoft Windows NT Server 3.5
    • Microsoft Windows NT Server 3.51
    • Microsoft Windows NT Workstation 3.5
    • Microsoft Windows NT Workstation 3.51
    • Microsoft Windows 95

This article was previously published under Q102571

SUMMARY

The documentation for DdePostAdvise() in the Windows 3.1 Software Development Kit "Programmer's Reference, Volume 2: Functions" states the following in the Comments section:

   If a server calls DdePostAdvise() with a topic/item/format name set
   that includes the set currently being handled in an XTYP_ADVREQ
   callback, a stack overflow may result.
				

MORE INFORMATION

This is merely a warning against calling DdePostAdvise() from within a DDE callback function's XTYP_ADVREQ transaction, because it may result in a stack overflow.

Like window procedures, DDE callbacks must be coded with care to avoid infinite recursion (eventually resulting in a stack overflow). Because DdePostAdvise() causes DDEML to send an XTYP_ADVREQ transaction to the calling application's DDE callback function, calling DdePostAdvise() on the same topic/item/format name set as the one currently being handled results in an infinite loop.

An analogous piece of code that has become a classic problem in Windows programming involves calling UpdateWindow() in a WM_PAINT case:

   case WM_PAINT:
				

InvalidateRect (hWnd, NULL, TRUE); UpdateWindow (hWnd);



Calling UpdateWindow() as in the code above causes a WM_PAINT message to be sent to a window procedure, and thus results in the same type of infinite recursion that occurs when calling DdePostAdvise() from an XTYP_ADVREQ transaction.

An example of a situation that would lend itself to this scenario would be one where data needs to be updated as a result of a previous data change. There are two ways to work around the stack overflow problem in this case:

  • Post a user-defined message and handle the data change asynchronously. For example,
          // in DdeCallback:
          case XTYP_ADVREQ:
                    if ((!DdeCmpStringHandles (hsz1, ghszTopic)) &&
                        (!DdeCmpStringHandles (hsz2, ghszItem)) &&
                        (fmt == CF_SOMEFORMAT))
                      {
                            HDDEDATA  hData;
    
                            hData = DdeCreateDataHandle ();
                            PostMessage (hWnd, WM_DATACHANGED,hData,);
                            return (hData);
                      }
                      break;
    
           // in MainWndProc():
           case WM_DATACHANGED:
                   DdePostAdvise (idInst, ghszTopic, ghszItem);
                     :
    						
  • Return CBR_BLOCK from the XTYP_ADVREQ and let DDEML suspend further transactions on that conversation, while the server prepares data asynchronously.
More information on how returning CBR_BLOCK allows an application to process data "asynchronously" may be derived from Section 5.8.6 of the Windows 3.1 Software Development Kit (SDK) "Programmer's Reference, Volume 1: Overview," or by querying on the following words in the Microsoft Knowledge Base:

   DDEML and CBR_BLOCK
				

Modification Type:MinorLast Reviewed:3/7/2005
Keywords:kbinfo KB102571