mfc >> Understanding DDE and OnDDEExecute

by Sam Carleton » Thu, 04 Dec 2003 01:41:41 GMT

I believe I understand enough about DDE to understand how to do what
I am trying to do, I just cannot figure out how to do it in MFC 7.

The SDI app current allow multiple instances of itself to run. It
should only allow one instance to run. Also, when double clicking
one of this applications data files, the file needs to be loaded
into the application, if it is already running.

Now I found an old Win16 sample called FileAsso.EXE. I have been
able to compile it and I understand how and why it does works.

There are two things I need to know:

1: Does CFrameWnd call DdeInitialize(), DdeCreateStringHandle(),
etc? If so, where?

2: It does not appear that the FileAsso.EXE is executed a second
time when one of it's data files are clicked. I believe that is
because of how the values in the registry. Where will I find
documentation about registry configuration for DDE?

Sam


Similar Threads

1. DDE Command lost in CFrameWnd::OnDDEExecute ()?

2. DDE Client on another computer cannot ddemlclienttransaction to DDE Server

3. BUG: CFrameWnd::OnDDEExecute MFC 7.1

4. Bug in CFrameWnd::OnDDEExecute

I noticed that my app did not respond to a DDE msg 
(double-click on doc in Win Explorer), when the app was 
already running. I traced this problem to an error in the 
code in CFrameWnd::OnDDEExecute. This MFC routine stores 
a pointer to the DDE command string into "LPCTSTR lpsz" 
but passes a pointer to an empty string "TCHAR szCommand" 
to the app, forgetting to copy the string from lpsz into 
szCommand:
	TCHAR szCommand[_MAX_PATH * 2];
	LPCTSTR lpsz = (LPCTSTR)GlobalLock(hData);
        ... 
        ... //there should be a copy in here someplace???
        ...	
        // execute the command
	if (!AfxGetApp()->OnDDECommand(szCommand))
           ...
Surely, somebody else has noticed this or am I in the 
Twilight Zone?

5. CFrameWnd::OnDDEExecute is broken

6. BUG: CFrameWnd::OnDDEExecute MFC 7.1

This function is executed when a application file is 
double-clicked to open in a VC++ application. 
Specifically, this function is enabled by 
RegisterShellFileTypes () in the application's 
InitInstance. 
However, under MFC 7.1 for VC++ .NET 2003, 
CFrameWnd::OnDDEExecute has a bug that repeatedly 
generates this error message in the debugger 

Error: failed to execute DDE command ''. 

Therefore, the problem is that the command is not being 
propagated properly to this function, since the string 
should be something like 
'[open("C:\YourFileNameHere")]' 
rather than the empty string 
'' 

Examining the code for this function in more detail, we 
can see the bug here: 

LPCTSTR lpsz = (LPCTSTR)GlobalLock(hData); 
int commandLength = lstrlen(lpsz); 
if (commandLength >= _countof(szCommand)) 
{ 
// The command would be truncated. This 
could be a security problem 
TRACE0("Warning: Command was ignored 
because it was too long.\n"); 
return 0; 
} 
GlobalUnlock(hData); 

The data string '[open("C:\YourFileNameHere")]' is stored 
in the LPCTSTR lpsz. Then a check is done to make sure 
that the length of this string is not longer than the new 
buffer szCommand. However, the string is never copied in 
szCommand, and the data is effectively released by 
GlobalUnlock! Then when this command is executed 

if (!AfxGetApp()->OnDDECommand(szCommand)) 

szCommand is empty, and the error is generated. 

Hopefully, Microsoft will address this bug and issue a 
patch. Please respond to this posting to indicate if this 
problem is being addressed. Any workarounds in the mean 
time?

7. Severe bug in CFrameWnd::OnDDEExecute

8. Code of the original CFrameWnd::OnDDEExecute is buggy & doesn't wo

I had encountered a problem with DDE support and processing while using MFC7.1 
Open this routine's source located in a file "winfrm.cpp", and see for your 
very self. 

CFrameWnd::OnDDEExecute, (files: afxwin.h and winfrm.cpp)

The following code is provided by Microsoft
////////////////////////////////////////////////////////////////////////////////////////////////////
// get the command string
	TCHAR szCommand[_MAX_PATH * 2];
	LPCTSTR lpsz = (LPCTSTR)GlobalLock(hData);
	int commandLength = lstrlen(lpsz);
	if (commandLength >= _countof(szCommand))
	{
		// The command would be truncated. This could be a security problem
		TRACE0("Warning: Command was ignored because it was too long.\n");
		return 0;
	}
	GlobalUnlock(hData)
////////////////////////////////////////////////////////////////////////////////////////////////////

There are two hints here:
1. Hint (most important)
The thing is that  in a furhter call to AfxGetApp()->OnDDECommand(szCommand) 
szCommand goes uninitialized!!!  That code is not safe, however DDE would not 
work anyway (the better thing would be if 0 == szCommand[0]) !!!

2. Hint (less significant)
LPCTSTR lpsz .... and this guys use lstrlen(lpsz)! What if I compile my 
program with _UNICODE, UNICODE defined?

I had made some modifications to the code above and got the things working!
Suggestions
////////////////////////////////////////////////////////////////////////////////////////////////////
	TCHAR	szCommand[_MAX_PATH * 2];
	LPCTSTR lpsz = (LPCTSTR)GlobalLock(hData);

	if ( _tcslen(lpsz) >= _countof(szCommand) )
	{
		// The command would be truncated. This could be a security problem
		//
		TRACE0("Warning: Command was ignored because it was too long.\n");
		return	0;
	}

	// copy command data to our buffer and perform unlock operation
	//
	_tcscpy(szCommand, lpsz), GlobalUnlock(hData)
////////////////////////////////////////////////////////////////////////////////////////////////////

This code I give possesses no bugs mentioned above. What do you people think 
about the matter? I'd spent some time to locate a problem of non-functional 
DDE in the project and finally got the solution. This might save your time 
around...

I hope Microsoft would fix their code.