title: How to implement return codes in DdeCallback function
body: <p>What is the correct way to write <code>DdeCallback</code> function? To be more precise, I'm talking about return codes.</p>
  
  <p>From the official <a href="https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms648742(v=vs.85).aspx" rel="nofollow">docs</a>:</p>
  
  <blockquote>
    <p>The return value depends on the transaction class. For more
    information about the return values, see descriptions of the
    individual transaction types</p>
  </blockquote>
  
  <p>For example, my application need to handle <code>XTYP_ADVDATA</code> messages by itself and ignore the others.</p>
  
  <p>So, according to the <a href="https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms648714(v=vs.85).aspx" rel="nofollow">docs</a> for <code>XTYP_ADVDATA</code>, I need to return <code>DDE_FACK</code> if I processed this message:</p>
  
  <blockquote>
    <p>A DDE callback function should return DDE_FACK if it processes this
    transaction, DDE_FBUSY if it is too busy to process this transaction,
    or DDE_FNOTPROCESSED if it rejects this transaction</p>
  </blockquote>
  
  <p>But what about the other messages? What should I return in the other cases?</p>
  
  <p>// Initialization</p>
  
  <pre><code>DWORD id_inst = 0;
  UINT res = DdeInitializeA(
    &amp;id_inst,
    (PFNCALLBACK)DdeCallback,
    APPCLASS_STANDARD | APPCMD_CLIENTONLY,
    0 // Reserved; must be set to zero
  );
  
  // XTYP_ADVSTART
  
  HDDEDATA data = DdeClientTransaction(
    NULL,   // The beginning of the data the client must pass to the server. This parameter is required only if the wType parameter is XTYP_EXECUTE or XTYP_POKE. Otherwise, this parameter should be NULL
    0,      // The length, in bytes, of the data pointed to by the pData parameter
    conv,
    item,
    CF_TEXT,
    XTYP_ADVSTART,
    30000,  // The maximum amount of time, in milliseconds, that the client will wait for a response from the server application in a synchronous transaction
    NULL    // A pointer to a variable that receives the result of the transaction. An application that does not check the result can use NULL for this value
  );
  </code></pre>
  
  <p></p>
  
  <pre><code>HDDEDATA CALLBACK DdeCallback(
    UINT uType,     // The transaction type
    UINT uFmt,      // The format atom of the data sent from the server
    HCONV hconv,    // A handle to the conversation
    HSZ hsz1,       // A handle to the topic name
    HSZ hsz2,       // A handle to the item name
    HDDEDATA hdata, // A handle to the data associated with the topic name and item name pair
    DWORD dwData1,  // Not used
    DWORD dwData2)  // Not used
  {
    switch (uType)
    {
    case XTYP_ADVDATA:
      DWORD data_size = DdeGetData(hdata, NULL, 0, 0);
      std::unique_ptr&lt;char[]&gt; buf(new char[data_size]);
      DdeGetData(
        hdata,
        (BYTE *)buf.get(),
        data_size,
        0 // An offset within the DDE object. Data is copied from the object beginning at this offset
      );
      std::cout &lt;&lt; "Data received: " &lt;&lt; buf.get() &lt;&lt; std::endl;
      return (HDDEDATA)DDE_FACK;
    }
  
    return /* ??? */;
  }
  </code></pre>