## Using DirectPlay

This section contains the following topics that explain how to use different aspects of DirectPlay:

- Debug versus Retail DLLs
- Working with GUIDs
- DirectPlay Interfaces
- Using Callback Functions
- Building Lobby-Aware Applications
- DirectPlay Messages
- DirectPlay Address (Optional)
- Migrating from Previous Versions of DirectPlay
- DirectPlay Tools and Samples
- Security and Authentication

### Debug versus Retail DLLs

The Software Development Kit (SDK) has the option to install debug or retail builds of the DirectPlay dynamic-link libraries (DLLs). When developing software, it is best to install the debug versions of the DLLs. The debug DLLs have additional code that will validate internal data structures and output debug error messages (using the Win32® OutputDebugString API) while your program is executing. When an error occurs, the debug output will give you a more detailed description of what the problem is. The debug DLLs will execute more slowly than the retail DLLs but are much more useful for debugging an application. Be sure to ship the retail version with your application.

In order to see the debug messages, it is necessary to configure your computer so that debug output will be displayed in a window or on a remote computer. An interactive development environment like Microsoft® Visual C++™ allows you to do this. Consult the environment's documentation for set-up instructions.

### Working with GUIDs

Globally unique identifiers are 16-byte data structures that you can use to identify objects in a globally unique way. Whenever a GUID is required in an API, a symbol representing that GUID should be used. The symbols are either defined in one of the DirectPlay header files or the application developer must generate them. You can generate GUIDs by using the Guidgen.exe utility that comes with Microsoft Visual C++. For example, every application must define an application GUID that identifies the application that is running in a session.

Note If there are different versions of an application that cannot interoperate in the same session, they should have different application GUIDs to distinguish them.

To use DirectPlay-defined GUIDs successfully in your application, you must either define the INITGUID symbol prior to all other include and define statements, or you must link to the Dxguid.lib library. If you define INITGUID, you should define it in only one of your source modules.

### DirectPlay Interfaces

All the functionality in DirectPlay is accessed through member functions on Component Object Model (COM) interfaces. To use them, an application must obtain the appropriate COM interface.

The standard method of obtaining COM interfaces is to use the Win32 CoCreateInstance API. To use it successfully, the application must first call the Win32 CoInitialize API to initialize COM and then call CoCreateInstance, specifying the GUID of the desired interface. For example, use the following code to obtain an IDirectPlay3A interface:

      // C++ example
      hr = CoCreateInstance( CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER,
                             IID_IDirectPlay3A, (LPVOID*)&lpDirectPlay3A);
      // C example
      hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER,
                             &IID_IDirectPlay3A, (LPVOID*)&lpDirectPlay3A);

When the program is finished, all the COM interfaces must be freed by calling the Release method on each interface. Finally, the Win32 CoUninitialize method should be called to uninitialize COM.

If you call CoCreateInstance without first calling CoInitialize you will get a CO_E_NOTINITIALIZED error, with the error text "CoInitialize has not been called."

DirectPlay has several COM interfaces. Each interface represents a revision of an earlier version of DirectPlay in which new methods are added. COM interfaces are numbered sequentially with each revision. The latest COM interface will have all the latest functionality of DirectPlay. To access the new functionality (for example, IDirectPlay3::SendChatMessage), you must use the latest COM interface. Source code written for an earlier COM interface will work.

Once a COM interface is obtained, an alternate interface can be used on the same object by calling the QueryInterface method on the interface. For example, DirectPlayCreate will create a DirectPlay object and return an IDirectPlay interface. If your application requires an IDirectPlay3 interface, it can call QueryInterface on the IDirectPlay interface. Be sure to release the original IDirectPlay interface if it is no longer needed.

### Using Callback Functions

The enumeration methods in DirectPlay are used to return a list of items to the application. The application calls an enumeration method (such as IDirectPlay3::EnumPlayers) and supplies a pointer to a callback function that it has implemented. DirectPlay will call the callback function once for each item in the list. The enumeration method will not return until all the items in the list have been returned to the application through the callback function.

It is extremely important that all callbacks be declared correctly. For example:

    BOOL FAR PASCAL EnumConnectionsCallback(LPCGUID lpguidSP, LPVOID lpConnection, DWORD dwConnectionSize,
    LPCDPNAME lpName, DWORD dwFlags, LPVOID pContext);

The FAR PASCAL symbol will define the function as _stdcall. That means it will clean up the stack before returning to DirectPlay. Do not cast function pointers when passing them to a DirectPlay enumeration method. If there is a compiler warning about the function pointer, fix the function declaration.

### Building Lobby-Aware Applications

A lobby-aware application is one that, at a minimum, supports being launched from a lobby. A matchmaking lobby is a site on the Internet where end users can find other people to play games with. Once a group of people has decided to start an application session, the lobby software can launch the application on each person's computer and have them all connect to a session. The main benefit for end users is the ease with which they can establish a session with other players. Not only does it allow a user to easily find opponents, but there is also no need for the user to:

- Select a service provider. The lobby will specify which service provider to use.
- Decide whether to host or join a session. The lobby will specify whether to create or join a session.
- Enter a network address or configure the network. The lobby will supply this information if it is needed.
- Enter the name of the player. The lobby will pass in the same name that the user connected to the lobby with.

Other benefits of the lobby are:

- It can keep track of sessions in progress and enable users to join them.
- It can receive status messages from the session and display the progress to other users on a scoreboard.
- It can obtain final scores and maintain player rankings for tournament play.

For a DirectPlay application to be lobby-aware, at a minimum it must support being launched from a lobby. You can add other features to make it integrate better with the lobby. For additional information see the following topics within this section.

- Registering Lobby-Aware Applications
- Supporting External Lobby Launching
- LobbyMessaging (Optional)

#### Registering Lobby-Aware Applications

To enable a lobby to launch a DirectPlay application, the application must add the following entries to the system registry. Once an application has been registered, it will be recognized as a lobby-aware application and lobbies can launch it. These registry entries must be deleted when the application is removed.

The following example shows the registry entries for the DPCHAT sample application included in the SDK.

    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectPlay\Applications\DPChat]
    "Guid"="{5BFDB060-06A4-11D0-9C4F-00A0C905425E}"
    "File"="dpchat.exe"
    "CommandLine"=""
    "Path"="C:\DXSDK\sdk\bin"
    "CurrentDirectory"="C:\DXSDK\sdk\bin"

The keys and values are:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectPlay\Applications\
  The key's name will be the name of the application that the IDirectPlayLobby2::EnumLocalApplications method returns. It is DPChat in the preceding example.
Guid
  This is the 16-byte GUID that identifies the application. It is formatted as shown in the example. This should be the same GUID that is put in the guidApplication member of the DPSESSIONDESC2 structure when creating a session. A GUID can be generated using the Guidgen.exe utility.
File
  This is the file name of the application executable.
CommandLine
  This lists any command-line parameters that are to be specified when a lobby launches the application.
Path
  This is the directory that the application executable resides in.
CurrentDirectory
  This is the directory to set as the current directory after launching the application executable.

#### Supporting External Lobby Launching

Once the application has been registered, the DirectPlay application must be able to recognize whether a lobby launched it or not. If a lobby launched it, it must follow a slightly different code path to set up the network connection. Consult the DUEL (Lobby.c) and DPCHAT (Lobby.cpp) samples in the SDK for the code necessary to support external lobby launching. See Tutorial 1: Connecting by Using the Lobby for a demonstration on how to connect an application by using a DirectPlay lobby.

The necessary basic steps are:

1. At startup, create an IDirectPlayLobby2 interface using the CoCreateInstance API.
2. The application can examine the connection information that was passed in by the lobby and modify some of the connection settings if necessary. The IDirectPlayLobby2::GetConnectionSettings method returns a DPLCONNECTION structure with the connection settings. This method returns DPERR_NOTLOBBIED if a lobby did not launch the application. New settings can be set with IDirectPlayLobby2::SetConnectionSettings.
3. IDirectPlayLobby2::Connect creates or joins the specified application session using the specified service provider, and returns an IDirectPlay2 interface. Connect returns an error if the session could not be created/joined, or if a lobby did not launch the application.
4. Use QueryInterface to obtain an IDirectPlay3 interface and then call Release on the IDirectPlay2 interface.
5. Create a player using the name information supplied in the DPLCONNECTION structure obtained in step two.

At this point, the application can continue on the same code path as if the user had manually selected a connection, joined or created a session, and entered the name of the player to create.

The IDirectPlayLobby2 interface can be saved if the game will pass information back to the lobby (see Lobby Messaging), or it can be discarded by using the Release method if no messages will be sent.

Many lobbies will launch the application and then go into a suspend mode, waiting for the application to terminate. DirectPlay will notify the lobby when the application that it launched has terminated. For this reason it is important that the application launched by the lobby not launch another application.

#### Lobby Messaging (Optional)

After registering a lobby-aware application and adding the code to support external lobby launching, the next step in integrating the application with the lobby is to send information back to the lobby or to request information from the lobby. This is done by exchanging messages with the lobby through the IDirectPlayLobby2::SendLobbyMessage and IDirectPlayLobby2::ReceiveLobbyMessage methods on the IDirectPlayLobby2 interface. Standard message structures have been defined by DirectPlay to facilitate this functionality.

Sending information to the lobby is done through setting properties. The application must create and fill in a DPLMSG_SETPROPERTY structure and send it to the lobby by using the SendLobbyMessage method. Each property identifies a distinct type of data. The application developer should generate GUIDs (using Guidgen.exe) for every property that will be set. The lobby operator needs to obtain this list of GUIDs from the application developer along with the description and data structure of each property.

Properties can take the form of:

- Current individual player scores.
- Final individual player scores.
- Player configuration for later retrieval.
- Current game status (level or mission).

The lobby can store this information or display it to other users in the lobby so they can monitor the game's progress. An application can request confirmation that the property was set correctly by supplying a nonzero request ID with the set property message.

Requesting information from the lobby is done through requesting properties. The application must create and fill in a DPLMSG_GETPROPERTY structure and send it to the lobby by using the SendLobbyMessage method. At some later time, the lobby will send a message back to the application—a DPLMSG_GETPROPERTYRESPONSE structure that contains the property data that was requested. The application can retrieve the message from the lobby message queue using the ReceiveLobbyMessage method. As before, the application developer generates the GUIDs for each property and the lobby operator must obtain them from the developer.

The following list shows examples of some properties that can be requested from the lobby:

- Game configuration settings — enables players to configure the game in the lobby before launching the game.
- Player configuration settings — enables players to configure their players in the lobby or to use a stored configuration from a previous session.
- Other information stored from a previous session.

Not all lobbies will be able to support these standard lobby messages. The application can determine whether the lobby that it was launched from supports standard lobby messages by sending a DPLMSG_GETPROPERTY message requesting the DPLPROPERTY_MessagesSupported property.

### DirectPlay Messages

The following sections describe how to use messages in DirectPlay.

- Synchronization
- Using System Messages
- Using Lobby Messages

#### Synchronization

An application can use two methods to process DirectPlay messages. The first is to check the receive queue during the main loop of the application. Typically, this means the application is single threaded.

Alternatively, an application can have a separate thread to wait for messages and process them. In this case the application should supply a non-NULL auto-reset synchronization event handle (see the Win32 CreateEvent API) when it creates players. DirectPlay will set this event whenever a message arrives for that player. All the local players in an application can share the same event or each can have his or her own event.

The message processing thread should then use the Win32 WaitForSingleObject API to wait until the event is set. Continue calling Receive until there are no more messages in the message queue.

#### Using System Messages

Messages returned by the IDirectPlay3::Receive method from player ID DPID_SYSMSG are system messages. All system messages begin with a double-word value specified by the dwType DWORD value. You can cast the buffer returned by the IDirectPlay3::Receive method to a generic message (DPMSG_GENERIC) and switch on the dwType element, which will have a value equal to one of the messages with the DPSYS_ prefix. After the application has determined which system message it is, the buffer should be cast to the appropriate structure (beginning with the DPMSG_ prefix) to read the data.

Your application should be prepared to handle the following system messages:

Value of dwType | Message structure | Cause
DPSYS_ADDGROUPTOGROUP | DPMSG_ADDGROUPTOGROUP | An existing group has been added to an existing group.
DPSYS_ADDPLAYERTOGROUP | DPMSG_ADDPLAYERTOGROUP | An existing player has been added to an existing group.
DPSYS_CHAT | DPMSG_CHAT | A chat message has been received.
DPSYS_CREATEPLAYERORGROUP | DPMSG_CREATEPLAYERORGROUP | A new player or group has been created.
DPSYS_DELETEGROUPFROMGROUP | DPMSG_DELETEGROUPFROMGROUP | A group has been removed from a group.
DPSYS_DELETEPLAYERFROMGROUP | DPMSG_DELETEPLAYERFROMGROUP | A player has been removed from a group.
DPSYS_DESTROYPLAYERORGROUP | DPMSG_DESTROYPLAYERORGROUP | An existing player or group has been destroyed.
DPSYS_HOST | DPMSG_HOST | The current host has left the session and this application is the new host.
DPSYS_SECUREMESSAGE | DPMSG_SECUREMESSAGE | A digitally signed or encrypted message has been received.
DPSYS_SESSIONLOST | DPMSG_SESSIONLOST | The connection with the session has been lost.
DPSYS_SETPLAYERORGROUPDATA | DPMSG_SETPLAYERORGROUPDATA | Player or group data has changed.
DPSYS_SETPLAYERORGROUPNAME | DPMSG_SETPLAYERORGROUPNAME | Player or group name has changed.
DPSYS_SETSESSIONDESC | DPMSG_SETSESSIONDESC | The session description has changed.
DPSYS_STARTSESSION | DPMSG_STARTSESSION | The lobby server is requesting that a session be started.

#### Using Lobby Messages

Messages returned by the IDirectPlayLobby2::ReceiveLobbyMessage method fall into two categories: DirectPlay-defined messages and custom-defined messages. The message category can be identified by the lpdwMessageFlags parameter of ReceiveLobbyMessage. The flags indicate that the message is either a system message (the DPLMSG_SYSTEM flag) or a standard message (the DPLMSG_STANDARD flag). If neither of these flags is set, the message is custom-defined. System messages are generated automatically by DirectPlay and are sent to the lobby only to inform it of changes in the status of the application. Standard messages can be generated by either the lobby or the application and sent to the other.

The advantage of standard messages over custom-defined messages is that the receiver can positively interpret the message. It is not required that all applications or lobbies act on standard messages.

DirectPlay-defined messages all start with a DWORD value that identifies the type of the message. After retrieving a message using ReceiveLobbyMessage, the lpData pointer to the message data should be cast to the DPLMSG_GENERIC structure and the structure's dwType member examined. Based on the value of dwType, the lpData pointer should then be cast to the appropriate message structure for further processing.

Lobbies should be prepared to handle all the following message types. Applications need to handle the DPLMSG_GETPROPERTYRESPONSE message if they generate DPLMSG_GETPROPERTY messages.

Messages returned by the IDirectPlayLobby2::ReceiveLobbyMessage method that have a dwFlags parameter set to DPLMSG_SYSTEM are system messages. All system messages begin with a double-word value specified by dwType. You can cast the buffer returned by the IDirectPlayLobby2::ReceiveLobbyMessage method to a generic message (DPLMSG_GENERIC) and switch on the dwType element, which will have a value equal to one of the messages with the DPLSYS_ prefix.

The following list shows the possible values of the dwType data member, and the message structure and message cause associated with each value.

Value of dwType | Message structure | Cause
DPLSYS_APPTERMINATED | DPLMSG_GENERIC | The application has terminated.
DPLSYS_CONNECTIONSETTINGSREAD | DPLMSG_GENERIC | The application has read the connection settings.
DPLSYS_DPLAYCONNECTFAILED | DPLMSG_GENERIC | The application failed to connect to the DirectPlay session.
DPLSYS_DPLAYCONNECTSUCCEEDED | DPLMSG_GENERIC | The application successfully connected to the DirectPlay session.
DPLSYS_GETPROPERTY | DPLMSG_GETPROPERTY | The application is requesting a property from the lobby.
DPLSYS_GETPROPERTYRESPONSE | DPLMSG_GETPROPERTYRESPONSE | The lobby is responding to a prior DPLMSG_GETPROPERTY message.
DPLSYS_SETPROPERTY | DPLMSG_SETPROPERTY | The application is setting a property on the lobby.
DPLSYS_SETPROPERTYRESPONSE | DPLMSG_SETPROPERTYRESPONSE | The lobby is responding to a prior DPLMSG_SETPROPERTY message.

### DirectPlay Address (Optional)

A DirectPlay Address is a data format that DirectPlay uses to pass addressing information between lobby servers, applications, DirectPlay, and service providers. The format is flexible enough to hold any number of variable-length data fields that make up a network address. It is not necessary to understand DirectPlay Addresses in order to use DirectPlay. In fact, it is possible to successfully write a DirectPlay application without understanding DirectPlay Addresses at all.

This section contains the following topics:

- DirectPlay Address Data Types
- Using DirectPlay Addresses
- Examples of Using DirectPlay Addresses

It is only necessary to learn about DirectPlay Addresses if you want to do the following things:

- Override the standard service provider dialog boxes. You need to create a DirectPlay Address that specifies which service provider to use and contains all the information the service provider needs to establish a connection. You then pass the DirectPlay Address to the IDirectPlay3::InitializeConnection method.
- Write a lobby client that will launch an external DirectPlay application. The lobby client needs to create a DirectPlay Address that specifies which service provider to use and contains all the information the service provider needs to establish a connection and automatically connect the client to a session. You need to create a DirectPlay Address of the session to be joined and put it in the DPLCONNECTION structure before calling the IDirectPlayLobby2::RunApplication method.

A DirectPlay Address is a sequence of variable-length data chunks tagged with a GUID that supplies all the address information needed by DirectPlay. Examples are the network address of a server, the network address of a player, the e-mail name of a player, or the network address of a session.

#### DirectPlay Address Data Types

Microsoft has predefined the following general data types for each data chunk. Based on the data type, the data must be cast to the appropriate type or structure to interpret the data.

GUID | Type of Data
DPAID_ComPort | A DPCOMPORTADDRESS structure that contains all the settings for the COM port. The serial connection service provider will use this information to configure the serial port.
DPAID_INet | A null-terminated ANSI string (LPSTR) containing an IP address ("137.55.100.173") or a domain net ("gameworld.com"). The length in bytes must include the terminator. A blank address is a string that contains only the ANSI terminator (0x00) and has a length of 1 byte. If a blank address is supplied, the Internet TCP/IP connection service provider will use this information to enumerate sessions on the specified network address or to broadcast on the subnet.
DPAID_INetW | A null-terminated Unicode string (LPWSTR) containing an IP address ("137.55.100.173") or a domain net ("gameworld.com"). The length in bytes must include the terminator. A blank address is a string that contains only the Unicode terminator (0x0000) and has a length of 2 bytes. If a blank address is supplied, the Internet TCP/IP connection service provider will use this information to enumerate sessions on the specified network address or broadcast on the subnet.
DPAID_Modem | A variable-length null-terminated ANSI string (LPSTR) specifying which installed modem to use. The length in bytes must include the terminator. The modem service provider will use this modem without displaying a dialog box asking the user which modem to use. Use the IDirectPlay3::GetPlayerAddress method to determine which modems are available.
DPAID_ModemW | A variable-length null-terminated Unicode string (LPWSTR) specifying which installed modem to use. The length in bytes must include the terminator. The modem service provider will use this modem without displaying a dialog box asking the user which modem to use. Use the IDirectPlay3::GetPlayerAddress method to determine which modems are available.
DPAID_Phone | A variable-length null-terminated ANSI string (LPSTR) containing a phone number. The length in bytes must include the terminator. The modem service provider will call this phone number on the IDirectPlay3::EnumSessions method. If no modem is specified, the first modem will be used.
DPAID_PhoneW | A variable-length null-terminated Unicode string (LPWSTR) containing a phone number. The length in bytes must include the terminator. The modem service provider will call this phone number on the IDirectPlay3::EnumSessions method. If no modem is specified, the first modem will be used.
DPAID_ServiceProvider | The 16-byte GUID that specifies the service provider this DirectPlay Address applies to.

#### Using DirectPlay Addresses

You can use a DirectPlay Address to encapsulate all the information necessary to initialize a DirectPlay object. At a minimum, this is the GUID of a DirectPlay provider, but can also include the network address of an application or lobby server and even a specific session instance GUID.

A DirectPlay Address can be used to supply enough information to DirectPlay (and the DirectPlay provider) when it is initialized so that no dialog boxes appear later during the process of establishing a session or connecting to a session.

The DirectPlay Addresses returned by EnumConnections are simply registered DirectPlay providers that the user can choose from. When one of these is initialized, dialog boxes can appear, which ask the user for more information.

The application can create a DirectPlay Address directly using the IDirectPlayLobby2::CreateAddress and IDirectPlayLobby2::CreateCompoundAddress methods on the IDirectPlayLobby2 interface and pass the connection to the IDirectPlay3::InitializeConnection method to initialize the DirectPlay object. If enough valid information is supplied, then no DirectPlay dialog boxes will appear.

#### Examples of Using DirectPlay Addresses

This topic contains examples of DirectPlay Addresses and the data they contain for different connection types.

A DirectPlay Address describing an IPX connection

Initializing this connection will bind the DirectPlay object to the IPX service provider.

guidDataType | dwDataSize | Data
DPAID_ServiceProvider | 16 | {685BC400-9D2C-11cf-A9CD-00AA006886E3}

A DirectPlay Address describing a modem connection

Initializing this connection binds DirectPlay to the modem service provider and stores the phone number. A subsequent call the IDirectPlay3::EnumSessions will dial the number without asking the user for a phone number.

guidDataType | dwDataSize | Data
DPAID_ServiceProvider | 16 | {44EAA760-CB68-11cf-9C4E-00A0C905425E}
DPAID_Phone | 9 (including NULL terminator) | "555-8237"

A DirectPlay Address describing a TCP/IP connection

Initializing this connection binds DirectPlay to the TCP/IP service provider and stores the IP address. A subsequent call IDirectPlay3::EnumSessions will enumerate sessions on this server without asking the user for an IP address.

guidDataType | dwDataSize | Data
DPAID_ServiceProvider | 16 | {36E95EE0-8577-11cf-960C-0080C7534E82}
DPAID_INet | 10 (including NULL terminator) | "127.0.0.1"

### Migrating from Previous Versions of DirectPlay

The DirectPlay version 5 API is fully compatible with applications written for any previous version of DirectPlay. That is, you can recompile your application by using DirectPlay on the DirectX 5 SDK without making any changes to the code. DirectPlay supplied with the DirectX 5 SDK supports all the APIs and behavior of earlier DirectPlay versions.

For specific information, see:

- Migrating from DirectPlay 3
- Migrating from DirectPlay 2 or Earlier

#### Migrating from DirectPlay 3

If you are migrating to DirectPlay version 5 from DirectPlay version 3, you do not have to make any changes. However, you should upgrade your application to use the new IDirectPlay3 Interface or IDirectPlay3A interfaces.

For a list of new features in version 5 of DirectPlay, see What's New in DirectPlay 5.

Some system messages have changed for DirectPlay 5, with new data members added to the end. Applications that need to be backward-compatible with older run times should either:

- Compile with the DirectX 3 header files and libraries.
- Not reference new data members.
- Test with both the DirectX 3 and the DirectX 5 runtime.

The system message structures that have new members for DirectPlay 5 are:

Structure | New Members
DPMSG_CREATEPLAYERORGROUP | DPID dpIdParent
| DWORD dwFlags
DPMSG_DESTROYPLAYERORGROUP | DPNAME dpnName
| DPID dpIdParent
| DWORD dwFlags

#### Migrating from DirectPlay 2 or Earlier

The names of the DirectPlay DLLs in version 3 and later are different from those in previous DirectPlay versions. Applications compiled with DirectX 2 or earlier do not use the new DirectPlay DLLs. To use the new DLLs, the application must be recompiled and linked to the Dplayx.lib import library.

It is also recommended that you add the code necessary to make the application lobby-aware. This means that an external lobby or matchmaking program can start the application and supply it with all the information necessary to connect to a session. The application need not ask the user to decide on a service provider, select a session, or supply any other information (such as a telephone number or network address).

In addition, several other new features were added in the DirectPlay version 5 API, including:

- Internet support.
- Direct serial connection.
- More stability and robustness.
- Support for Unicode to better support localization.
- Host migration. If the host of a session drops out of the session, host responsibilities are passed on to another player. In DirectPlay version 2, if the host (name server) left a session, no new players could be created.
- Ability of the application to communicate with the lobby program to update games status for spectators, as well as receive information about initial conditions.
- Ability to host more than one application session on a computer.
- Ability to determine when a remote computer loses its connection and to generate appropriate messages.

There are other features in DirectPlay 5 that you can use to reduce the amount of communication-management code in your application, including the following:

- Ability to associate application-specific data with a DirectPlay group ID or player ID. This allows the application to leverage the player and group list-management code that is already part of DirectPlay. Local data is data that the local application uses directly, such as a bitmap that represents a player. Local data is not propagated over the network. Remote data is associated with the player or group. DirectPlay propagates any changes to remote data to all other applications in the session. Remote data must be shared among all the applications in a session, such as a player's position, orientation, and velocity. By using DirectPlay functions to propagate this data, the application need not manage it by using a series of methods that send and receive information.
- Ability for the application to associate a name with a group. This is useful for team play.

Some of the new features added to DirectPlay 5 are not directly related to applications, including the following:

- APIs that the lobby client software uses to start and connect a lobby-able DirectPlay application. Also included are APIs that allow an application and the lobby to exchange information during a session.
- Service provider development kit that includes documentation and sample code for creating your own service provider.

Migrating to the IDirectPlay3 Interface

To migrate an application created with DirectPlay version 2 or earlier, carry out the following steps:

1. Find out if your application was launched from a lobby client. For more information, see Step 2: Retrieving the Connection Settings.
2. If your application is enumerating service providers, use the EnumConnections method to determine if a service provider is available. If so, call the InitializeConnection method on the service provider. If InitializeConnection returns an error, the service provider cannot run on the system, and you should not add that service provider to the list to show to the user. If the call succeeds, use the Release method to release the DirectPlay object and add the service provider to the list.
3. Call the QueryInterface method on the IDirectPlay interface to obtain an IDirectPlay3 (Unicode) or IDirectPlay3A (ANSI) interface. The only difference between the two interfaces is how strings in the structures are read and written. For the Unicode interface, Unicode strings are read and written to the member of the structure that is of the LPWSTR type. For the ANSI interface, ANSI strings are read and written to the member of the structure that is of the LPSTR type.
4. Make all the changes necessary to use the new structures in existing APIs. For example, instead of the following:

       lpDP->SetPlayerName(pidPlayer, lpszFriendlyName, lpszFormalName)

   where lpDP is an IDirectPlay interface, use the following:

       DPNAME PlayerName, *lpPlayerName;
       PlayerName.dwSize = sizeof(DPNAME);
       lpPlayerName = &PlayerName;

       lpPayerName->lpszShortNameA = lpszFriendlyName;
       lpPlayerName->lpszLongNameA = lpszFormalName;
       lpDP3A->SetPlayerName(pidPlayer, lpPlayerName, 0)

   where lpDP3A is an IDirectPlay3A interface. If the application is using Unicode strings (and therefore instantiates an IDirectPlay3 interface), use the following:

       lpPayerName->lpszShortName = lpwszFriendlyName;
       lpPlayerName->lpszLongName = lpwszFormalName;
       lpDP3->SetPlayerName(pidPlayer, lpPlayerName, 0)

   where lpDP3 is an IDirectPlay3 interface.

5. Update the following system messages:
   - DPSYS_ADDPLAYER has been replaced by DPSYS_CREATEPLAYERORGROUP.
   - DPSYS_DELETEPLAYER and DPSYS_DELETEGROUP have been combined in a single DPSYS_DESTROYPLAYERORGROUP message.
   - DPSYS_DELETEPLAYERFROMGRP has been changed to DPSYS_DELETEPLAYERFROMGROUP.
6. Update your application to generate a DPSYS_SETPLAYERORGROUPNAME message when a player or group name changes, and a DPSYS_SETPLAYERORGROUPDATA message when the player or group data changes.
7. Update the DPSESSIONDESC structure to DPSESSIONDESC2, and add the new members to the DPCAPS structure.
8. Update the callback functions for IDirectPlay3::EnumSessions, IDirectPlay3::EnumGroups, IDirectPlay3::EnumGroupPlayers, and IDirectPlay3::EnumPlayers.
9. Update the manner in which the hEvent parameter is supplied to the IDirectPlay3::CreatePlayer method. In previous versions of DirectPlay, this parameter was lpEvent. DirectPlay does not return an event; instead, the application must create it. This allows the application the flexibility of creating one event for all the players.
10. Set the DPSESSION_KEEPALIVE flag in the DPSESSIONDESC2 structure if the application needs DirectPlay to detect when players drop out of the game abnormally.
11. Update your application to create sessions with the DPSESSION_MIGRATEHOST flag. This enables another computer to become the host if the current host drops out of the session. If your application has any special code that only the host runs, then your application should set this flag when it creates a session. It should also add support for the DPSYS_HOST system message. For a list of system messages, see Using System Messages.
12. Become familiar with the new methods of the IDirectPlay3 interface and use them in your application. Pay particular attention to the IDirectPlay3::SetPlayerData and IDirectPlay3::GetPlayerData methods. You might be able to substitute the code where you broadcast player state information to all the other players by using the IDirectPlay3::Send and IDirectPlay3::Receive methods.

### DirectPlay Tools and Samples

The following samples show how to use DirectPlay. These DirectPlay samples are included on the DirectX 5 CD-ROM. The Control Panel tool can be used to find out about DirectPlay applications.

DirectX Control Panel Tool

- Found in Control Panel. Double-click to open the DirectX Properties dialog box.
- The DirectPlay tab displays all the registered DirectPlay service providers and applications.
- Open the DirectX Properties dialog box before starting a DirectPlay application to see on-the-fly statistics about DirectPlay communications such as bytes/second and messages/second.

SDK/SAMPLES/BELLHOP

- A lobby client program that uses the IDirectPlay3 interface to communicate with a lobby server.
- Uses the LSERVER test lobby server so that a real lobby client/server environment can be set up.
- BELLHOP can be used to test external lobby support in your application.
- LSERVER can be used as a test server to write your own lobby client or integrate a lobby client into your application.

SDK/SAMPLES/DPCHAT

- A simple Windows-based chat program that uses IDirectPlay3.
- Uses IDirectPlayLobby to make it lobby-able.

SDK/SAMPLES/DPLAUNCH

- A stand-alone application that demonstrates how a DirectPlay 5 application can be launched from an external source using the IDirectPlayLobby2 interface.
- Can also be used to test the lobby support in your application.

SDK/SAMPLES/DPSLOTS

- A DirectPlay client/server application that uses security.
- The server controls all the slot machines and tracks how much money each player has.
- The client securely logs in to the server.

SDK/SAMPLES/DUEL

- A multiplayer game that uses the IDirectPlay interface.
- Uses IDirectPlayLobby to make it lobby-able.

SDK/SAMPLES/DXVIEW

- An application that shows all the available service providers and their capabilities.
- Shows all the registered lobby-aware applications installed on the system.
- Uses asynchronous EnumSessions to monitor the active sessions on the service provider.

SDK/SAMPLES/OVERRIDE

- A simple demonstration of how to override the DirectPlay service provider dialogs.

### Security and Authentication

DirectPlay security allows an application running on a server to authenticate users against a database of known users before allowing them to join a session. Once a user has been authenticated, all communications between the client and server can be done securely either by digitally signing messages (to verify the identity of the sender) or by encrypting the messages.

The following diagram shows DirectPlay security architecture. (SSPI = Security Support Provider Interface, CAPI = CryptoAPI, MS RSA Base CP = Microsoft RSA Base Cryptographic Provider, NTLM = NT LAN Manager.)

User and Message Authentication

DirectPlay provides user and message authentication (digital signing) support through the Windows® Security Support Provider Interface (SSPI). This is a standard interface that gives software access to various security packages under the Windows operating system. A security package is an implementation of a protocol between a client and server that establishes the identity of the client and provides other security services, such as digital signing. The default security package that DirectPlay uses is called NTLM (Windows® NT® LAN Manager) Security Support Provider.

This security package is based on the NTLM authentication protocol. NTLM is a shared-secret, user challenge-response authentication protocol that supports pass-through authentication to a domain controller in the server's domain or in a domain trusted by the current domain's domain controller. This protocol provides a high level of security because passwords are never sent out on the network. NTLMSSP ships with the Windows 95 and Windows NT operating systems.

A DirectPlay application can choose to use a different SSPI security package when it creates a session by calling the SecureOpen method. For example, DPA (Distributed Password Authentication) Security Support Provider is another security package that organizations can use to provide membership services to a large customer base (hundreds of thousands). This security package is available through the Microsoft Commercial Internet Services (MCIS) Membership Server.

Message Privacy (encryption/decryption)

DirectPlay provides message encryption support through the Windows Cryptography Application Programming Interface (CAPI). This is a standard interface similar to SSPI that gives software access to various cryptographic packages under the Windows operating system. This architecture allows DirectPlay applications to plug in cryptographic packages that provide the desired level of encryption (40 bit, 128 bit, and so on) legally allowed in the locale of use.

The default CryptoAPI (CAPI) provider for DirectPlay cryptography services is the Microsoft RSA Base Cryptographic Provider version 1.0. The default CAPI provider type is PROV_RSA_FULL. The default encryption algorithm is the CALG_RC4 stream cipher. This provider is supplied by Microsoft and is included with Microsoft Internet Explorer for Windows 95, Windows 95 OSR-2 Update, and Windows NT 4.0 operating system.

A DirectPlay application can choose to use a different cryptographic provider when it creates a session by using the SecureOpen method. Please note that DirectPlay only supports stream ciphers.

For more information about SSPI, NTLM, DPA, MCIS, CAPI, and the RSA Base Cryptographic Provider, see http://www.microsoft.com.

Secure Sessions

User authentication should not be confused with password protection of a session. Authentication is used to verify that the user is allowed access to the server by virtue of having been added to the membership database by the administrator of the server. Only users that are part of the membership database are permitted to join the session. A password can be added to a session, so that only those members who know the password can join a particular session. Additionally, authentication requires a server that supports authentication, while any computer can put a password on a session.

For example, a server on the Internet might have a membership of a thousand users. Anybody can enumerate the sessions that are available on the server, but only members will be able to join sessions on the server. Users who want only their friends (who are members) to be able to join can put a password on their session.

Once a secure server has been set up and an initial membership list has been established, a secure DirectPlay session can be started. Creating a secure DirectPlay session simply requires the server to create a session using IDirectPlay3::Open or IDirectPlay3::SecureOpen and to specify the DPSESSION_SECURESERVER flag in the DPSESSIONDESC2 structure.

A DirectPlay application can choose to use alternate providers when it creates a session by calling the SecureOpen method and specifying the providers to use in the DPSECURITYDESC structure. For a different SSPI provider (for user and message authentication), an application needs to specify the provider name in the lpszSSPIProvider member of the DPSECURITYDESC structure. For a different CryptoAPI provider (for message privacy), an application needs to specify the provider name, provider type, and encryption algorithm in the lpszCAPIProvider, dwCAPIProviderType, and dwEncryptionAlgorithm members, respectively.

When a client enumerates this session, the DPSESSIONDESC2 structure returned by IDirectPlay3::EnumSessions will have the DPSESSION_SECURESERVER flag set. This tells the client that authentication credentials will be required to join the session. If the client attempts to join the session using IDirectPlay3::Open, the security package may allow the user in if the user's credentials were already established through a system log on (for example, through NT LAN Manager). Otherwise, a DPERR_LOGONDENIED error is returned. The application must then collect credentials from the user, put them in a DPCREDENTIALS structure, and try to join the session again by calling SecureOpen, passing in the DPCREDENTIALS structure. SecureOpen is recommended for security.

Within a secure session, all DirectPlay system messages are digitally signed to verify the identity of the sender. Certain system messages that carry sensitive information are encrypted. System messages that originate from one player and need to be broadcast to all the other players in the session are first sent to the server. The server then puts its signature on the message and forwards the message to all the other computers in the session. Player to player messages are not signed by default and are not routed through the server.

An application can choose to sign or encrypt specific player-to-player messages using the DPSEND_SIGNED and DPSEND_ENCRYPTED flags in the IDirectPlay3::Send method. Signed and encrypted player messages are routed through the server and delivered as secure system messages. When a secure message is received by a player, the message will contain flags indicating whether the message came in signed or encrypted. Messages that do not pass the verification are dropped.

© 1997 Microsoft Corporation. All rights reserved. Terms of Use.