Advertisement

Does anyone here know how to use DirectPlay?

Started by May 08, 2005 09:20 AM
18 comments, last by hplus0603 19 years, 9 months ago
Yeah, I've heard about DirectPlay being a dying API, and it was just my luck that I learned that AFTER I began a school project using it. :( I don't have the time to switch to Socket or Winsock now, so I'm just asking if anyone here knows DirectPlay well? It seems like no one really does. >_<;;
You should describe the problem first.

-cb
Advertisement
Yes, of course... I have two problems:

1) When the Connect() function is called by the client, the screen resolution changes, causing the program to crash. This is a fullscreen program with exclusive cooperation at 800x600 resolution, and my computer normally runs at 1024x768, so it reverts back to the normal resolution. This didn't occur before, it used to return an OK value, and I'm not sure what I could have changed that would cause it to crash. Any idea why the Connect() function would do that?

Interestingly enough, my debug output says that the connection was successful anyway. O_o Then the program instantly crashes and causes one of those Microsoft error feedback windows to pop up.

2) When calling the GetClientInfo() function, which is a member of the IDirectPlay8Server interface, it says an invalid parameter has been sent. This could be the network ID of the player, the DPN_PLAYER_INFO structure or the &dwSize variable. It's unlikely to be the size, so it must be one of the others.

The networking part of my program is in a general state of messiness at the moment. :D Which doesn't help, either.

Edit: Solved problem 1. Turned out I was accidentally running and old version of my server program, which caused the connection to crash. Problem 2 has been solved, but now the error returned is DPNERR_BUFFERTOOSMALL, that is, the supplied buffer is too small. How do I solve this problem?

[Edited by - Reinhart on May 8, 2005 11:17:23 AM]
Regarding the crash, I suggest you run the program in a debugger, and debug the crash.

One possibility is that the computer is running Windows XP SP2, and the built-in firewall pops up a dialog asking whether to block the program. You can get around that by using the Windows XP SP2 firewall management API to tell the system you're an OK program and don't need the dialog, if the user is running in administrator mode. You're supposed to do this during installation, but can also do it during regular program start-up time.

The same problem could happen with other firewalls, too.
enum Bool { True, False, FileNotFound };
I use ZoneAlarm and the popup message does appear, but it doesn't cause the application to crash. You can simply click the 'Accept' button without any problems.

Another thing is that I tried enumerating hosts, and it couldn't enumerate successfully... I'll check the return values on that, but for now, any ideas on the connect problem? :S

Thanks for the suggestions so far, people. I really appreciate it. :) Network programming rookie right here.
> DPNERR_BUFFERTOOSMALL

The 'pdwSize' parameter returns the required size if this error code has been returned. This is stated in the docs for this function call.

-cb
Advertisement
@cbenoi1: Thanks for that, problem fixed now.

@hplus0603: I use ZoneAlarm and its messages pop up without causing any errors or screen resolution changes. I believe the res change is due to the server window gaining focus.

I still have that problem with the Connect() function. When testing, I'm running both the client and the server programs at the same time on one machine, and perhaps the server program is getting focus, for some reason. when the Connect() function is called in the client. I'm not sure why this would be happening...
DirectPlay is multithreaded. I would guess you are making display calls (unknowingly) within the callback function and this mixes up badly with the main thread. Otherwise I would suggest you don't use fullscreen and refrain from using exclusive mode until your code is fully debugged.

-cb
I took off exclusive cooperation levels for the client and it still crashes, so it musn't be that. However, it doesn't even say that the connection is successful. Here is my connection code, anything wrong with it? I read my IP address and player name from two files. RENDER_DEBUG is a #define which simply allows message boxes to show debug output.

HRESULT ConnectToSession( HWND hwnd ){	HRESULT					hr;	DPN_APPLICATION_DESC	dpnAppDesc			= {0};	DPN_PLAYER_INFO			dpnPlayerInfo		= {0};	char					szClientName[256]	= {0};	WCHAR					wszClientName[256]	= {0};	WCHAR					wszHostName[256]	= {0};	char					szIPAddress[256]	= {0};	DWORD					dwPort				= {TUT09_CLIENTSERVER_PORT};		// Filestream variables	// Open files for input	ifstream FileIPAddress ( "IPAddress.txt" );	ifstream FilePlayerName ( "PlayerName.txt" );	// Read in player name	FilePlayerName &gt;&gt; szClientName;	// Read in IP address to connect to	FileIPAddress &gt;&gt; szIPAddress;	// Explicitly close the filestreams	FilePlayerName.close();	FileIPAddress.close();	// Convert player name from generic string to wide string	DXUtil_ConvertGenericStringToWideCb( wszClientName, szClientName, sizeof( wszClientName ) );	// Convert IP address from generic string to wide string	DXUtil_ConvertGenericStringToWideCb( wszHostName, szIPAddress, sizeof( wszHostName ) );	// Set player information	ZeroMemory( &dpnPlayerInfo, sizeof( DPN_PLAYER_INFO ) );	dpnPlayerInfo.dwSize = sizeof( DPN_PLAYER_INFO );	dpnPlayerInfo.dwInfoFlags = DPNINFO_NAME;	dpnPlayerInfo.pwszName = wszClientName;	// Set client information	// Make it a synchronous connection	if( FAILED( g_pDPClient-&gt;SetClientInfo( &dpnPlayerInfo, NULL, NULL, DPNSETCLIENTINFO_SYNC ) ) )	{#ifdef RENDER_DEBUG		MessageBox( hwnd, "Could not SetClientInfo", "Client Message - ConnectToSession()", 0 );#endif	}#ifdef RENDER_DEBUG	MessageBox( hwnd, "SetClientInfo Successful", "Client Message - ConnectToSession()", 0 );#endif	// Prepare the application description	ZeroMemory( &dpnAppDesc, sizeof( DPN_APPLICATION_DESC ) );	dpnAppDesc.dwSize = sizeof( DPN_APPLICATION_DESC );	dpnAppDesc.guidApplication = g_guidApp;	// Add hostname to address	if( FAILED( g_pHostAddress-&gt;AddComponent( DPNA_KEY_HOSTNAME, wszHostName, ( wcslen( wszHostName ) + 1 ) * sizeof( WCHAR ), DPNA_DATATYPE_STRING ) ) )	{#ifdef RENDER_DEBUG		MessageBox( hwnd, "Could not AddComponent HostName", "Client Message - ConnectToSession()", 0 );#endif	}#ifdef RENDER_DEBUG	MessageBox( hwnd, "AddComponent HostName Successful", "Client Message - ConnectToSession()", 0 );#endif	// Add port to address	if( FAILED( g_pHostAddress-&gt;AddComponent( DPNA_KEY_PORT, &dwPort, sizeof(DWORD), DPNA_DATATYPE_DWORD ) ) )	{#ifdef RENDER_DEBUG		MessageBox( hwnd, "Could not AddComponent Port", "Client Message - ConnectToSession()", 0 );#endif	}#ifdef RENDER_DEBUG	MessageBox( hwnd, "AddComponent Port Successful", "Client Message - ConnectToSession()", 0 );#endif		// Connect!		hr = g_pDPClient-&gt;Connect(	&dpnAppDesc,			// pdnAppDesc									g_pHostAddress,			// pHostAddr									g_pDeviceAddress,		// pDeviceInfo									NULL,					// pdnSecurity									NULL,					// pdnCredentials									NULL, 0,				// pvUserConnectData, Size									NULL,					// pvAsyncContext									NULL,		// pvAsyncHandle									DPNCONNECT_SYNC );	// dwFlags		if( hr != E_PENDING && FAILED( hr ) )		{			MessageBox( hwnd, "Connect() Unsuccessful", "Client Message - ConnectToSession()", 0 );			// Determine what kind of error is returned			switch( hr )			{			case DPNERR_HOSTREJECTEDCONNECTION:				MessageBox( hwnd, "Host rejected connection", "Client Message - ConnectToSession()", 0 );				break;			case DPNERR_INVALIDAPPLICATION:				MessageBox( hwnd, "GUID is invalid", "Client Message - ConnectToSession()", 0 );				break;			case DPNERR_INVALIDDEVICEADDRESS:				MessageBox( hwnd, "Invalid device address", "Client Message - ConnectToSession()", 0 );				break;			case DPNERR_INVALIDFLAGS:				MessageBox( hwnd, "Invalid flags", "Client Message - ConnectToSession()", 0 );				break;			case DPNERR_INVALIDHOSTADDRESS:				MessageBox( hwnd, "Invalid host address", "Client Message - ConnectToSession()", 0 );				break;			case DPNERR_INVALIDINSTANCE:				MessageBox( hwnd, "Invalid instance", "Client Message - ConnectToSession()", 0 );				break;			case DPNERR_INVALIDINTERFACE:				MessageBox( hwnd, "Invalid interface", "Client Message - ConnectToSession()", 0 );				break;			case DPNERR_INVALIDPASSWORD:				MessageBox( hwnd, "Invalid password", "Client Message - ConnectToSession()", 0 );				break;			case DPNERR_NOCONNECTION:				MessageBox( hwnd, "No connection could be established", "Client Message - ConnectToSession()", 0 );				break;			case DPNERR_NOTHOST:				MessageBox( hwnd, "Not a host", "Client Message - ConnectToSession()", 0 );				break;			case DPNERR_SESSIONFULL:				MessageBox( hwnd, "Session is full!", "Client Message - ConnectToSession()", 0 );				break;			case DPNERR_ALREADYCONNECTED:				MessageBox( hwnd, "Already connected!", "Client Message - ConnectToSession()", 0 );				break;			case S_OK:				MessageBox( hwnd, "Okay", "Client Message - ConnectToSession()", 0 );				break;			default:				MessageBox( hwnd, "Unknown", "Client Message - ConnectToSession()", 0 );				break;			}			return -1;		}		else if( hr == S_OK )		{#ifdef RENDER_DEBUG			MessageBox( hwnd, "Connect() Successful", "Client Message - ConnectToSession()", 0 );#endif		}	//}	return hr;}


My server program also doesn't respond to any DPN_MSGID messages. Does it need to? In the Microsoft DirectPlay tutorials, they connect without any errors, and they have virtually empty message handlers.

If you need to see any other code, I'd be glad to show it. I'm running out of time for this, too... Thanks for your time, people.
The main thread is waiting at the Connect() call; you have specified DPNCONNECT_SYNC. In the mean time, other threads are active and you are receiving messages through your callback handler; those messages are exchanged as part of the connection process. Unless you have used locks (critical sections, semaphores, etc) to lock down common resources used within the callback function, multi-threaded access to those common resources will cause those resources to become unstable and cause a crash later on. This is especially true if you are calling DirectX or OpenGL from the callback threads when there isn't a graphics context attached to those threads.

-cb

This topic is closed to new replies.

Advertisement