Microsoft DirectX 8.1 (C++)

Tutorial 1: Creating a DirectPlay Object and Enumerating Service Providers

This series of tutorials demonstrate how to implement a simple peer-to-peer multiplayer game using Microsoft® DirectPlay® 8.1. This tutorial outlines the initial steps: creating a DirectPlay object and enumerating the available network service providers. Subsequent tutorials build on this foundation to take you through the key steps needed to construct a simple peer-to-peer console application. Much of the information in these tutorials can also be applied to client/server applications. The complete sample code for this tutorial is included with the Microsoft® DirectX® Software Development Kit (SDK) and can be found at (SDK root)\Samples\Multimedia\DirectPlay\Tutorials\Tut01_EnumSP.

For a general discussion of peer-to-peer applications, seePeer-to-Peer Sessions.

Note  The error handling code for the examples in this document has been deleted for clarity. See the tutorial sample for a complete version of the code.

User's Guide

When you run this tutorial sample, a Microsoft® MS-DOS® command window opens and the application prints the service providers found on your computer. To end the tutorial, press any key.

Creating a DirectPlay Peer Object

One of the first things a peer-to-peer application must do is create and initialize a DirectPlay peer object (CLSID_DirectPlay8Peer). To create a DirectPlay peer object, call CoCreateInstance, and request a pointer to an IDirectPlay8Peer interface. All of your subsequent interaction with DirectPlay and your fellow players will be through this interface.

Once you have created the peer object, you must initialize it by calling the IDirectPlay8Peer::Initialize method. This method takes three parameters:

The message handler is a key part of a DirectPlay application. You communicate with DirectPlay by calling methods on a DirectPlay interface. DirectPlay in turn communicates with your application by sending messages to your message handler, much like Microsoft® Windows® sends messages to a window procedure. See DirectPlay Callback Functions and Multithreading Issues for details on how to implement a message handler.

The player context value is an application defined value that is returned each time a message is sent to your message handler. See Using Player Context Values for a discussion of how to handle player context values.

There is only one flag value that can be set, DPNINITIALIZE_DISABLEPARAMVAL. Setting this flag disables parameter validation for all DirectPlay methods. While setting this flag improves your application's performance, you should only do so with an application that has been thoroughly tested.

The following excerpt from the tutorial sample illustrates how to create and initialize a DirectPlay peer object.

#include <dplay8.h>
.
.
.
// Create the IDirectPlay8Peer Object
   hr = CoCreateInstance( CLSID_DirectPlay8Peer, NULL, 
                                       CLSCTX_INPROC_SERVER,
                                       IID_IDirectPlay8Peer, 
                                       (LPVOID*) &g_pDP);
    
// Initialize DirectPlay
   hr = g_pDP->Initialize(NULL, DirectPlayMessageHandler, 0);

Enumerating Service Providers

DirectPlay is an application programming interface (API) that allows game players to easily connect with each other and exchange messages, regardless of the underlying transport protocol. It enables you to use one or more service providers when hosting, connecting to, or enumerating sessions. To determine which service providers are available on your system, DirectPlay allows your application to enumerate your system's valid installed service providers as well as their adapters.

To enumerate your service providers, call IDirectPlay8Peer::EnumServiceProviders. This method fills an application-supplied buffer with information about the valid service providers on your system. As you do not know the minimum size of the buffer prior to calling this method, you should call it twice. The first time, specify a zero-length buffer and the method returns the required size. Use this size value in your second method call and DirectPlay fills the buffer with valid data. See Using DirectPlay Enumerations for further information on DirectPlay enumeration.

The following excerpt from the tutorial sample illustrates how to enumerate available service providers.

    DPN_SERVICE_PROVIDER_INFO*  pdnSPInfo       = NULL;
    DPN_SERVICE_PROVIDER_INFO*  pdnSPInfoEnum   = NULL;
    DWORD                       dwItems         = 0;
    DWORD                       dwSize          = 0;
    DWORD                       i;

    // Determine the required buffer size
    hr = g_pDP->EnumServiceProviders(NULL, NULL, NULL, &dwSize, &dwItems, 0);

     pdnSPInfo = (DPN_SERVICE_PROVIDER_INFO*) new BYTE[dwSize];
    
    //Fill the buffer with service provider information
    hr = g_pDP->EnumServiceProviders(NULL, NULL, pdnSPInfo, &dwSize, &dwItems, 0)

    // Print the provider descriptions
    pdnSPInfoEnum = pdnSPInfo;
    for (i = 0; i < dwItems; i++)
    {
        printf("Found Service Provider:  %S\n", pdnSPInfoEnum->pwszName);
        pdnSPInfoEnum++;
    }

Terminating a DirectPlay Application

If a DirectPlay peer object was successfully initialized by calling IDirectPlay8Peer::Initialize, it should be closed by calling IDirectPlay8Peer::Close. You should then release all active objects before terminating the application. A DirectPlay object can be reused once it has been closed, provided that it is re-initialized by calling IDirectPlay8Peer::Initialize.

The following excerpt from the tutorial sample illustrates how to close and release DirectPlay objects.


hr = g_pDP->Close(0); 

g_pDP->Release();
g_pDP = NULL;