DPSLOTS.CPP
/*========================================================================== 
 * 
 *  Copyright (C) 1997 Microsoft Corporation.  All Rights Reserved. 
 * 
 *  File:       dpslots.cpp 
 *  Content:common dpslots code 
 * 
 ***************************************************************************/ 
 
#include <windows.h> 
#include <windowsx.h> 
#include <stdio.h> 
 
#include "dpslots.h" 
#include "resource.h" 
 
// globals 
HANDLEghReceiveThread = NULL;// handle of receive thread 
DWORDgidReceiveThread = 0;// id of receive thread 
HANDLEghKillReceiveEvent = NULL;// event used to kill receive thread 
HINSTANCEghInstance = NULL;// application instance 
CHARgszDatabaseName[MAXSTRLEN];// database name 
 
// prototypes 
HRESULTSetupConnection(HINSTANCE hInstance, LPDPLAYINFO lpDPInfo); 
HRESULTShutdownConnection(LPDPLAYINFO lpDPInfo); 
DWORD WINAPIReceiveThread(LPVOID lpThreadParameter); 
HRESULTReceiveMessage(LPDPLAYINFO lpDPInfo); 
voidHandleSystemMessage(LPDPLAYINFO lpDPInfo, LPDPMSG_GENERIC lpMsg, DWORD dwMsgSize, 
DPID idFrom, DPID idTo); 
voidHandleApplicationMessage(LPDPLAYINFO lpDPInfo, LPDPMSG_GENERIC lpMsg, DWORD dwMsgSize, 
 DPID idFrom, DPID idTo); 
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
   LPSTR lpCmdLine, int nCmdShow ) 
{ 
DPLAYINFODPInfo; 
intiResult = 0; 
HRESULThr; 
 
ghInstance = hInstance; 
srand(GetTickCount()); 
lstrcpy(gszDatabaseName, DEFAULTDATABASE); 
 
// Initialize COM library 
hr = CoInitialize(NULL); 
if (FAILED(hr)) 
goto FAILURE; 
 
// setup the connection 
hr = SetupConnection(hInstance, &DPInfo); 
if FAILED(hr) 
goto FAILURE; 
 
// show the server window 
if (DPInfo.bIsHost) 
{ 
iResult = DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_SERVERDIALOG), NULL, (DLGPROC) ServerWndProc, (LPARAM) &DPInfo); 
} 
 
// show the client window 
else 
{ 
iResult = DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_CLIENTDIALOG), NULL, (DLGPROC) ClientWndProc, (LPARAM) &DPInfo); 
} 
 
FAILURE: 
// shut down the connection 
hr = ShutdownConnection(&DPInfo); 
 
// Uninitialize the COM library 
CoUninitialize(); 
 
return (iResult); 
} 
 
HRESULT SetupConnection(HINSTANCE hInstance, LPDPLAYINFO lpDPInfo) 
{ 
HRESULThr; 
 
ZeroMemory(lpDPInfo, sizeof(DPLAYINFO)); 
 
// create event used by DirectPlay to signal a message has arrived 
lpDPInfo->hPlayerEvent = CreateEvent(NULL,// no security 
 FALSE,// auto reset 
 FALSE,// initial event reset 
 NULL);// no name 
if (lpDPInfo->hPlayerEvent == NULL) 
{ 
hr = DPERR_NOMEMORY; 
goto FAILURE; 
} 
 
// create event used to signal that the receive thread should exit 
ghKillReceiveEvent = CreateEvent(NULL,// no security 
 FALSE,// auto reset 
 FALSE,// initial event reset 
 NULL);// no name 
if (ghKillReceiveEvent == NULL) 
{ 
hr = DPERR_NOMEMORY; 
goto FAILURE; 
} 
 
// create thread to receive player messages 
ghReceiveThread = CreateThread(NULL,// default security 
   0,// default stack size 
   ReceiveThread,// pointer to thread routine 
   lpDPInfo,// argument for thread 
   0,// start it right away 
   &gidReceiveThread); 
if (ghReceiveThread == NULL) 
{ 
hr = DPERR_NOMEMORY; 
goto FAILURE; 
} 
 
// try to connect using the lobby 
hr = ConnectUsingLobby(lpDPInfo); 
if FAILED(hr) 
{ 
// if the error returned is DPERR_NOTLOBBIED, that means we 
// were not launched by a lobby and we should ask the user for 
// connection settings. If any other error is returned it means 
// we were launched by a lobby but there was an error making the 
// connection. 
 
if (hr != DPERR_NOTLOBBIED) 
ErrorBox("Could not connect using lobby because of error 0x%08X", hr); 
 
// if there is no lobby connection, ask the user for settings 
hr = ConnectUsingDialog(hInstance, lpDPInfo); 
if FAILED(hr) 
goto FAILURE; 
} 
 
return (DP_OK); 
 
FAILURE: 
ShutdownConnection(lpDPInfo); 
 
return (hr); 
} 
 
HRESULT ShutdownConnection(LPDPLAYINFO lpDPInfo) 
{ 
if (ghReceiveThread) 
{ 
// wake up receive thread and wait for it to quit 
SetEvent(ghKillReceiveEvent); 
WaitForSingleObject(ghReceiveThread, INFINITE); 
 
CloseHandle(ghReceiveThread); 
ghReceiveThread = NULL; 
} 
 
if (ghKillReceiveEvent) 
{ 
CloseHandle(ghKillReceiveEvent); 
ghKillReceiveEvent = NULL; 
} 
 
if (lpDPInfo->lpDirectPlay3A) 
{ 
if (lpDPInfo->dpidPlayer) 
{ 
lpDPInfo->lpDirectPlay3A->DestroyPlayer(lpDPInfo->dpidPlayer); 
lpDPInfo->dpidPlayer = 0; 
} 
lpDPInfo->lpDirectPlay3A->Close(); 
lpDPInfo->lpDirectPlay3A->Release(); 
lpDPInfo->lpDirectPlay3A = NULL; 
} 
 
if (lpDPInfo->hPlayerEvent) 
{ 
CloseHandle(lpDPInfo->hPlayerEvent); 
lpDPInfo->hPlayerEvent = NULL; 
} 
 
return (DP_OK); 
} 
 
DWORD WINAPI ReceiveThread(LPVOID lpThreadParameter) 
{ 
    LPDPLAYINFOlpDPInfo = (LPDPLAYINFO) lpThreadParameter; 
HANDLEeventHandles[2]; 
 
eventHandles[0] = lpDPInfo->hPlayerEvent; 
eventHandles[1] = ghKillReceiveEvent; 
 
// loop waiting for player events. If the kill event is signaled 
// the thread will exit 
while (WaitForMultipleObjects(2, eventHandles, FALSE, INFINITE) == WAIT_OBJECT_0) 
{ 
// receive any messages in the queue 
ReceiveMessage(lpDPInfo); 
} 
 
ExitThread(0); 
 
return (0); 
} 
 
HRESULT ReceiveMessage(LPDPLAYINFO lpDPInfo) 
{ 
DPIDidFrom, idTo; 
LPVOIDlpvMsgBuffer; 
DWORDdwMsgBufferSize; 
HRESULThr; 
 
lpvMsgBuffer = NULL; 
dwMsgBufferSize = 0; 
 
// loop to read all messages in queue 
do 
{ 
// loop until a single message is successfully read 
do 
{ 
// read messages from any player, including system player 
idFrom = 0; 
idTo = 0; 
 
hr = lpDPInfo->lpDirectPlay3A->Receive(&idFrom, &idTo, DPRECEIVE_ALL, 
   lpvMsgBuffer, &dwMsgBufferSize); 
 
// not enough room, so resize buffer 
if (hr == DPERR_BUFFERTOOSMALL) 
{ 
if (lpvMsgBuffer) 
GlobalFreePtr(lpvMsgBuffer); 
lpvMsgBuffer = GlobalAllocPtr(GHND, dwMsgBufferSize); 
if (lpvMsgBuffer == NULL) 
hr = DPERR_OUTOFMEMORY; 
} 
} while (hr == DPERR_BUFFERTOOSMALL); 
 
if ((SUCCEEDED(hr)) &&// successfully read a message 
(dwMsgBufferSize >= sizeof(DPMSG_GENERIC)))// and it is big enough 
{ 
// check for system message 
if (idFrom == DPID_SYSMSG) 
{ 
HandleSystemMessage(lpDPInfo, (LPDPMSG_GENERIC) lpvMsgBuffer, 
dwMsgBufferSize, idFrom, idTo); 
} 
else 
{ 
HandleApplicationMessage(lpDPInfo, (LPDPMSG_GENERIC) lpvMsgBuffer, 
 dwMsgBufferSize, idFrom, idTo); 
} 
} 
} while (SUCCEEDED(hr)); 
 
// free any memory we created 
if (lpvMsgBuffer) 
GlobalFreePtr(lpvMsgBuffer); 
 
return (DP_OK); 
} 
 
void HandleSystemMessage(LPDPLAYINFO lpDPInfo, LPDPMSG_GENERIC lpMsg, DWORD dwMsgSize, 
 DPID idFrom, DPID idTo) 
{ 
if (lpDPInfo->bIsHost) 
{ 
ServerSystemMessage(lpDPInfo, lpMsg, dwMsgSize, idFrom, idTo); 
} 
else 
{ 
ClientSystemMessage(lpDPInfo, lpMsg, dwMsgSize, idFrom, idTo); 
} 
} 
 
void HandleApplicationMessage(LPDPLAYINFO lpDPInfo, LPDPMSG_GENERIC lpMsg, DWORD dwMsgSize, 
  DPID idFrom, DPID idTo) 
{ 
// When using a secure session we should not get any messages here 
// because encrypted messages come through as system messages. Therefore, 
// it is a security hole to process messages here. 
 
if (lpDPInfo->bIsSecure) 
return; 
 
if (lpDPInfo->bIsHost) 
{ 
ServerApplicationMessage(lpDPInfo, lpMsg, dwMsgSize, idFrom, idTo); 
} 
else 
{ 
ClientApplicationMessage(lpDPInfo, lpMsg, dwMsgSize, idFrom, idTo); 
} 
} 
 
void ErrorBox(LPSTR lpszErrorStr, HRESULT hr) 
{ 
CHARszStr[200]; 
 
wsprintf(szStr, lpszErrorStr, hr); 
 
MessageBox(NULL, szStr, "Error", MB_OK); 
} 
 
void CheckDlgItem(HWND hDlg, int nIDDlgItem, BOOL bCheck) 
{ 
SendDlgItemMessage(hDlg, nIDDlgItem, BM_SETCHECK, 
   (WPARAM) ((bCheck) ?  BST_CHECKED : BST_UNCHECKED), (LPARAM) 0); 
} 
 
BOOL DlgItemIsChecked(HWND hDlg, int nIDDlgItem) 
{ 
return ((SendDlgItemMessage(hDlg, nIDDlgItem, BM_GETCHECK, (WPARAM) 0, (LPARAM) 0) == BST_CHECKED) ? TRUE : FALSE); 
} 
 
void EnableDlgButton(HWND hDlg, int nIDDlgItem, BOOL bEnable) 
{ 
EnableWindow(GetDlgItem(hDlg, nIDDlgItem), bEnable); 
}