A general observation is that failures to connect with a started DDE server process are often caused by the manner in which the WaitForInputIdle function determines that the DDE server process is ready for communication to begin. Basically, the DDE Server process has done something during startup to cause WaitForInputIdle to believe that it has gone input idle before it can process DDE messages.
Raymond Chen's blog contains a number of articles about this issue. For example,
Psychic debugging: Understanding DDE initiation
WaitForInputIdle should really be called WaitForProcessStartupComplete
WaitForInputIdle waits for any thread, which might not be the thread you care about
Once you go input-idle, your application is deemed ready to receive DDE messages
On the importance of making sure WaitForInputIdle doesn’t think you’re idle, episode 1
On the importance of making sure WaitForInputIdle doesn’t think you’re idle, episode 2