Microsoft KB Archive/236614

= DirectPlay 6.1a Supports Ripple Launch Technology =

Article ID: 236614

Article Last Modified on 6/29/2007

-

APPLIES TO


 * Microsoft Windows 2000 Server
 * Microsoft Windows 2000 Advanced Server
 * Microsoft Windows 2000 Professional Edition
 * Microsoft Windows NT Server 4.0 Standard Edition
 * Microsoft Windows NT 4.0 Service Pack 4
 * Microsoft Windows NT Workstation 4.0 Developer Edition
 * Microsoft Windows NT Workstation 4.0 Developer Edition
 * Microsoft Windows NT Server 4.0 Enterprise Edition
 * Microsoft Windows NT 4.0 Service Pack 4

-



This article was previously published under Q236614





SUMMARY
The primary enhancement of DirectPlay (DPlay) 6.1a over earlier versions of DPlay is that it supports Ripple Launch technology. By definition, ripple launch uses one program to start another program. For example, the ripple launcher program masks itself as a program to start another requested program, thus becoming a third-party negotiator.

More specifically, a ripple launcher program is a security program used to start games and prevent their piracy. A game that requires a ripple launcher program to install and run cannot be pirated because the ripple launcher program is encrypted into each program and cannot be duplicated. For this reason, Ripple Launch technology is gaining popularity among software developers and vendors.



MORE INFORMATION
If you use a versions of DPlay earlier than 6.1a (released 4/99) to run a game created with Ripple Raunch capability, you may be unable to connect to the game online or lose connections that you did make because the ripple launcher program's encryption scheme breaks DPlay's handshaking protocol. DPlay 6.1a (or later) is updated to allow your game (or the program you are developing) to use this encryption technology with DPlay. The original functionality of DPlay remains the same and is backwards compatible with earlier versions.

The most significant change to DPlay 6.1a for Ripple Launch support involves the processing of Interprocess Communication (IPC) facilities with connections in the DirectPlayLobby. Before DPlay 6.1a, an IPC connection was established by including the process ID of the program being started in the shared IPC object name. Each program has a static Globally Unique Identifier (GUID) embedded and installed with the program and a dynamic process ID automatically issued with each running instance of the program. With DPlay 6.1a, the IPC connection is established when the ripple launcher program uses its own process identifier to send a command-line switch to the program to inform it of the identify of the IPC objects. In a ripple launch scenario, each program can also be issued a dynamic GUID along with the dynamic process identifier.

To implement a ripple launch scenario for those games relying on Setup to create the Lobby registry entries, changes must be made to the DirectPlayLobby registry keys "Launcher" and "File." The Launcher registry key must be the name of the path of the executable file being started and File is the name of the original executable file for the game with an .icd extension instead of an .exe extension (for example, ).

These registry changes put numerous requirements on the ripple launching program and the registration of the game for lobbying. These details are as follows:

Changes to DirectPlayLobby in RegisterApplication
RegisterApplication now accepts both LPDPAPPLICATIONDESC and LPDPAPPLICATIONDESC2 in the lpAppDesc field.

HRESULT RegisterApplication(    DWORD dwFlags,     LPVOID lpAppDesc ); You may notice that the DPAPPLICATIONDESC2 structure has an additional field for specifying lpszAppLauncherName. This is the name of the binary file to be started, instead of the program. The ripple launcher program should reside in the same directory as the actual binary file. The program name still needs to be provided and is used in the case of WaitForConnectionSettings in order to find the running program on the system. typedef struct { DWORD  dwSize; DWORD  dwFlags; union { LPSTR   lpszApplicationNameA; LPWSTR  lpszApplicationName; }   GUID    guidApplication; union { LPSTR    lpszFilenameA; LPWSTR   lpszFilename; }   union { LPSTR  lpszCommandLineA; LPWSTR lpszCommandLine; }   union { LPSTR  lpszPathA; LPWSTR lpszPath; }   union { LPSTR   lpszCurrentDirectoryA; LPWSTR  lpszCurrentDirectory; }   LPSTR   lpszDescriptionA; LPWSTR lpszDescriptionW; } DPAPPLICATIONDESC, FAR *LPDPAPPLICATIONDESC; type def struct DPAPPLICATIONDESC2

{   DWORD       dwSize; DWORD      dwFlags; union {       LPSTR       lpszApplicationNameA; LPWSTR     lpszApplicationName; };   GUID        guidApplication; union {       LPSTR       lpszFilenameA; LPWSTR     lpszFilename; };   union {       LPSTR       lpszCommandLineA; LPWSTR     lpszCommandLine; };   union {       LPSTR       lpszPathA; LPWSTR     lpszPath; };   union {       LPSTR       lpszCurrentDirectoryA; LPWSTR     lpszCurrentDirectory; };   LPSTR       lpszDescriptionA; LPWSTR     lpszDescriptionW; union {       LPSTR       lpszAppLauncherNameA; LPWSTR     lpszAppLauncherName; }; } DPAPPLICATIONDESC2, *LPDPAPPLICATIONDESC2;

Sample Code Showing Class Registration Change
- Before DPAPPLICATIONDESC  dpad;

... dpad.dwSize = sizeof (DPAPPLICATIONDESC); dpad.dwFlags = 0; dpad.lpszApplicationNameA= "MyApp"; dpad.guidApplication = {12345678-...}; dpad.lpszFilenameA= "myapp.exe"; dpad.lpszCommandLineA= "/lobbied"; dpad.lpszPathA= "C:\\games"; dpad.lpszCurrentDirectoryA= "C:\\games"; dpad.lpszDescriptionA= "My Application"; dpad.lpszDescriptionW= L"My Application";

hr = lpDPLobby3A->RegisterApplication(0, &dpad); ... "C:\games\myapp.exe /lobbied" is executed when RunApplication is called with the {12345678-...} GUID.

After DPAPPLICATIONDESC2 dpad2;

... dpad2.dwSize = sizeof (DPAPPLICATIONDESC2); dpad2.dwFlags = 0; dpad2.lpszApplicationNameA= "MyApp"; dpad2.guidApplication = {12345678-...}; dpad2.lpszFilenameA= "myapp.exe"; dpad2.lpszCommandLineA= "/lobbied"; dpad2.lpszPathA= "C:\\games"; dpad2.lpszCurrentDirectoryA= "C:\\games"; dpad2.lpszDescriptionA= "My Application"; dpad2.lpszDescriptionW= L"My Application"; dpad2.lpszAppLauncherNameA= "launcher.exe";

hr = lpDPLobby3A->RegisterApplication(0, &dpad2); ... "C:\games\launcher.exe /dplay_ipc_guid:{12345678-...} /lobbied" is run when RunApplication is called with the {12345678-...} GUID. The ripple launch program must pass all command-line parameters to.

Requirements for a Program Started with Launcher.exe
The ripple launch program must pass any command-line parameters to the program being started. The launcher.exe program must reside in the same folder as the program being started.

Requirements for Programs Started with Launcher.exe
A program started with the ripple launch program should silently ignore any command-line parameters it does not understand. Such a program should always call GetConnectionSettings at least once before using WaitForConnectionSettings.

Sample Ripple Launch Program
// // ripple.c : example ripple launcher. Win32 Console Application //


 * 1) include 
 * 2) include "stdio.h"

int main(int argc, char* argv[]) {   PROCESS_INFORMATION ProcInfo; STARTUPINFO StartupInfo; BOOL bCreated;

LPTSTR lpCommandLine;

printf("Launcher application\n");

lpCommandLine = GetCommandLineA;

// Strip EXE name from command line, pass rest to ripple launched app. while(*lpCommandLine && *lpCommandLine!= ' ') lpCommandLine++; printf("passing command line: %s\n",lpCommandLine);

memset(&StartupInfo,0,sizeof(StartupInfo)); StartupInfo.cb = sizeof(StartupInfo); bCreated=CreateProcessA(       "duel.exe",     // the program we are ripple launching.        lpCommandLine,        NULL,        NULL,        TRUE,        0,        NULL,        NULL,        &StartupInfo,        &ProcInfo);

if(bCreated){ printf("Waiting for application to exit\n"); WaitForSingleObject(ProcInfo.hThread, INFINITE); } else { printf("Failed to create process\n"); }

printf("launcher application has left the building...\n");

return 0; }

