home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / dpslots / dpslots.cpp < prev    next >
C/C++ Source or Header  |  1997-07-14  |  8KB  |  320 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1997 Microsoft Corporation.  All Rights Reserved.
  4.  *
  5.  *  File:       dpslots.cpp
  6.  *  Content:    common dpslots code
  7.  *
  8.  ***************************************************************************/
  9.  
  10. #include <windows.h>
  11. #include <windowsx.h>
  12. #include <stdio.h>
  13.  
  14. #include "dpslots.h"
  15. #include "resource.h"
  16.  
  17. // globals
  18. HANDLE            ghReceiveThread = NULL;            // handle of receive thread
  19. DWORD            gidReceiveThread = 0;            // id of receive thread
  20. HANDLE            ghKillReceiveEvent = NULL;        // event used to kill receive thread
  21. HINSTANCE        ghInstance = NULL;                // application instance
  22. CHAR            gszDatabaseName[MAXSTRLEN];        // database name
  23.  
  24. // prototypes
  25. HRESULT            SetupConnection(HINSTANCE hInstance, LPDPLAYINFO lpDPInfo);
  26. HRESULT            ShutdownConnection(LPDPLAYINFO lpDPInfo);
  27. DWORD WINAPI    ReceiveThread(LPVOID lpThreadParameter);
  28. HRESULT            ReceiveMessage(LPDPLAYINFO lpDPInfo);
  29. void            HandleSystemMessage(LPDPLAYINFO lpDPInfo, LPDPMSG_GENERIC lpMsg, DWORD dwMsgSize,
  30.                                     DPID idFrom, DPID idTo);
  31. void            HandleApplicationMessage(LPDPLAYINFO lpDPInfo, LPDPMSG_GENERIC lpMsg, DWORD dwMsgSize,
  32.                                          DPID idFrom, DPID idTo);
  33.  
  34. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  35.                    LPSTR lpCmdLine, int nCmdShow )
  36. {
  37.     DPLAYINFO    DPInfo;
  38.     int            iResult = 0;
  39.     HRESULT        hr;
  40.  
  41.     ghInstance = hInstance;
  42.     srand(GetTickCount());
  43.     lstrcpy(gszDatabaseName, DEFAULTDATABASE);
  44.  
  45.     // Initialize COM library
  46.     hr = CoInitialize(NULL);
  47.     if (FAILED(hr))
  48.         goto FAILURE;
  49.  
  50.     // setup the connection
  51.     hr = SetupConnection(hInstance, &DPInfo);
  52.     if FAILED(hr)
  53.         goto FAILURE;
  54.  
  55.     // show the server window
  56.     if (DPInfo.bIsHost)
  57.     {
  58.         iResult = DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_SERVERDIALOG), NULL, (DLGPROC) ServerWndProc, (LPARAM) &DPInfo);
  59.     }
  60.  
  61.     // show the client window
  62.     else
  63.     {
  64.         iResult = DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_CLIENTDIALOG), NULL, (DLGPROC) ClientWndProc, (LPARAM) &DPInfo);
  65.     }
  66.  
  67. FAILURE:
  68.     // shut down the connection
  69.     hr = ShutdownConnection(&DPInfo);
  70.  
  71.     // Uninitialize the COM library
  72.     CoUninitialize();
  73.  
  74.     return (iResult);
  75. }
  76.  
  77. HRESULT SetupConnection(HINSTANCE hInstance, LPDPLAYINFO lpDPInfo)
  78. {
  79.     HRESULT        hr;
  80.  
  81.     ZeroMemory(lpDPInfo, sizeof(DPLAYINFO));
  82.  
  83.     // create event used by DirectPlay to signal a message has arrived
  84.     lpDPInfo->hPlayerEvent = CreateEvent(NULL,        // no security
  85.                                          FALSE,        // auto reset
  86.                                          FALSE,        // initial event reset
  87.                                          NULL);        // no name
  88.     if (lpDPInfo->hPlayerEvent == NULL)
  89.     {
  90.         hr = DPERR_NOMEMORY;
  91.         goto FAILURE;
  92.     }
  93.  
  94.     // create event used to signal that the receive thread should exit
  95.     ghKillReceiveEvent = CreateEvent(NULL,        // no security
  96.                                      FALSE,        // auto reset
  97.                                      FALSE,        // initial event reset
  98.                                      NULL);        // no name
  99.     if (ghKillReceiveEvent == NULL)
  100.     {
  101.         hr = DPERR_NOMEMORY;
  102.         goto FAILURE;
  103.     }
  104.  
  105.     // create thread to receive player messages
  106.     ghReceiveThread = CreateThread(NULL,            // default security
  107.                                    0,                // default stack size
  108.                                    ReceiveThread,    // pointer to thread routine
  109.                                    lpDPInfo,        // argument for thread
  110.                                    0,                // start it right away
  111.                                    &gidReceiveThread);
  112.     if (ghReceiveThread == NULL)
  113.     {
  114.         hr = DPERR_NOMEMORY;
  115.         goto FAILURE;
  116.     }
  117.  
  118.     // try to connect using the lobby
  119.     hr = ConnectUsingLobby(lpDPInfo);
  120.     if FAILED(hr)
  121.     {
  122.         // if the error returned is DPERR_NOTLOBBIED, that means we
  123.         // were not launched by a lobby and we should ask the user for
  124.         // connection settings. If any other error is returned it means
  125.         // we were launched by a lobby but there was an error making the
  126.         // connection.
  127.  
  128.         if (hr != DPERR_NOTLOBBIED)
  129.             ErrorBox("Could not connect using lobby because of error 0x%08X", hr);
  130.  
  131.         // if there is no lobby connection, ask the user for settings
  132.         hr = ConnectUsingDialog(hInstance, lpDPInfo);
  133.         if FAILED(hr)
  134.             goto FAILURE;
  135.     }
  136.  
  137.     return (DP_OK);    
  138.  
  139. FAILURE:
  140.     ShutdownConnection(lpDPInfo);
  141.  
  142.     return (hr);
  143. }
  144.  
  145. HRESULT ShutdownConnection(LPDPLAYINFO lpDPInfo)
  146. {
  147.     if (ghReceiveThread)
  148.     {
  149.         // wake up receive thread and wait for it to quit
  150.         SetEvent(ghKillReceiveEvent);
  151.         WaitForSingleObject(ghReceiveThread, INFINITE);
  152.  
  153.         CloseHandle(ghReceiveThread);
  154.         ghReceiveThread = NULL;
  155.     }
  156.  
  157.     if (ghKillReceiveEvent)
  158.     {
  159.         CloseHandle(ghKillReceiveEvent);
  160.         ghKillReceiveEvent = NULL;
  161.     }
  162.  
  163.     if (lpDPInfo->lpDirectPlay3A)
  164.     {
  165.         if (lpDPInfo->dpidPlayer)
  166.         {
  167.             lpDPInfo->lpDirectPlay3A->DestroyPlayer(lpDPInfo->dpidPlayer);
  168.             lpDPInfo->dpidPlayer = 0;
  169.         }
  170.         lpDPInfo->lpDirectPlay3A->Close();
  171.         lpDPInfo->lpDirectPlay3A->Release();
  172.         lpDPInfo->lpDirectPlay3A = NULL;
  173.     }
  174.  
  175.     if (lpDPInfo->hPlayerEvent)
  176.     {
  177.         CloseHandle(lpDPInfo->hPlayerEvent);
  178.         lpDPInfo->hPlayerEvent = NULL;
  179.     }
  180.  
  181.     return (DP_OK);
  182. }
  183.  
  184. DWORD WINAPI ReceiveThread(LPVOID lpThreadParameter)
  185. {
  186.     LPDPLAYINFO    lpDPInfo = (LPDPLAYINFO) lpThreadParameter;
  187.     HANDLE        eventHandles[2];
  188.  
  189.     eventHandles[0] = lpDPInfo->hPlayerEvent;
  190.     eventHandles[1] = ghKillReceiveEvent;
  191.  
  192.     // loop waiting for player events. If the kill event is signaled
  193.     // the thread will exit
  194.     while (WaitForMultipleObjects(2, eventHandles, FALSE, INFINITE) == WAIT_OBJECT_0)
  195.     {
  196.         // receive any messages in the queue
  197.         ReceiveMessage(lpDPInfo);
  198.     }
  199.  
  200.     ExitThread(0);
  201.  
  202.     return (0);
  203. }
  204.  
  205. HRESULT ReceiveMessage(LPDPLAYINFO lpDPInfo)
  206. {
  207.     DPID                idFrom, idTo;
  208.     LPVOID                lpvMsgBuffer;
  209.     DWORD                dwMsgBufferSize;
  210.     HRESULT                hr;
  211.  
  212.     lpvMsgBuffer = NULL;
  213.     dwMsgBufferSize = 0;
  214.  
  215.     // loop to read all messages in queue
  216.     do
  217.     {
  218.         // loop until a single message is successfully read
  219.         do
  220.         {
  221.             // read messages from any player, including system player
  222.             idFrom = 0;
  223.             idTo = 0;
  224.  
  225.             hr = lpDPInfo->lpDirectPlay3A->Receive(&idFrom, &idTo, DPRECEIVE_ALL,
  226.                                                    lpvMsgBuffer, &dwMsgBufferSize);
  227.  
  228.             // not enough room, so resize buffer
  229.             if (hr == DPERR_BUFFERTOOSMALL)
  230.             {
  231.                 if (lpvMsgBuffer)
  232.                     GlobalFreePtr(lpvMsgBuffer);
  233.                 lpvMsgBuffer = GlobalAllocPtr(GHND, dwMsgBufferSize);
  234.                 if (lpvMsgBuffer == NULL)
  235.                     hr = DPERR_OUTOFMEMORY;
  236.             }
  237.         } while (hr == DPERR_BUFFERTOOSMALL);
  238.  
  239.         if ((SUCCEEDED(hr)) &&                            // successfully read a message
  240.             (dwMsgBufferSize >= sizeof(DPMSG_GENERIC)))    // and it is big enough
  241.         {
  242.             // check for system message
  243.             if (idFrom == DPID_SYSMSG)
  244.             {
  245.                 HandleSystemMessage(lpDPInfo, (LPDPMSG_GENERIC) lpvMsgBuffer,
  246.                                     dwMsgBufferSize, idFrom, idTo);
  247.             }
  248.             else
  249.             {
  250.                 HandleApplicationMessage(lpDPInfo, (LPDPMSG_GENERIC) lpvMsgBuffer,
  251.                                          dwMsgBufferSize, idFrom, idTo);
  252.             }
  253.         }
  254.     } while (SUCCEEDED(hr));
  255.  
  256.     // free any memory we created
  257.     if (lpvMsgBuffer)
  258.         GlobalFreePtr(lpvMsgBuffer);
  259.  
  260.     return (DP_OK);
  261. }
  262.  
  263. void HandleSystemMessage(LPDPLAYINFO lpDPInfo, LPDPMSG_GENERIC lpMsg, DWORD dwMsgSize,
  264.                          DPID idFrom, DPID idTo)
  265. {
  266.     if (lpDPInfo->bIsHost)
  267.     {
  268.         ServerSystemMessage(lpDPInfo, lpMsg, dwMsgSize, idFrom, idTo);
  269.     }
  270.     else
  271.     {
  272.         ClientSystemMessage(lpDPInfo, lpMsg, dwMsgSize, idFrom, idTo);
  273.     }
  274. }
  275.  
  276. void HandleApplicationMessage(LPDPLAYINFO lpDPInfo, LPDPMSG_GENERIC lpMsg, DWORD dwMsgSize,
  277.                               DPID idFrom, DPID idTo)
  278. {
  279.     // When using a secure session we should not get any messages here
  280.     // because encrypted messages come through as system messages. Therefore,
  281.     // it is a security hole to process messages here.
  282.  
  283.     if (lpDPInfo->bIsSecure)
  284.         return;
  285.  
  286.     if (lpDPInfo->bIsHost)
  287.     {
  288.         ServerApplicationMessage(lpDPInfo, lpMsg, dwMsgSize, idFrom, idTo);
  289.     }
  290.     else
  291.     {
  292.         ClientApplicationMessage(lpDPInfo, lpMsg, dwMsgSize, idFrom, idTo);
  293.     }
  294. }
  295.  
  296. void ErrorBox(LPSTR lpszErrorStr, HRESULT hr)
  297. {
  298.     CHAR    szStr[200];
  299.  
  300.     wsprintf(szStr, lpszErrorStr, hr);
  301.  
  302.     MessageBox(NULL, szStr, "Error", MB_OK);
  303. }
  304.  
  305. void CheckDlgItem(HWND hDlg, int nIDDlgItem, BOOL bCheck)
  306. {
  307.     SendDlgItemMessage(hDlg, nIDDlgItem, BM_SETCHECK,
  308.                        (WPARAM) ((bCheck) ?  BST_CHECKED : BST_UNCHECKED), (LPARAM) 0);
  309. }
  310.  
  311. BOOL DlgItemIsChecked(HWND hDlg, int nIDDlgItem)
  312. {
  313.     return ((SendDlgItemMessage(hDlg, nIDDlgItem, BM_GETCHECK, (WPARAM) 0, (LPARAM) 0) == BST_CHECKED) ? TRUE : FALSE);
  314. }
  315.  
  316. void EnableDlgButton(HWND hDlg, int nIDDlgItem, BOOL bEnable)
  317. {
  318.     EnableWindow(GetDlgItem(hDlg, nIDDlgItem), bEnable);
  319. }
  320.