SERVER.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:14k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1997 Microsoft Corporation.  All Rights Reserved.
  4.  *
  5.  *  File:       server.cpp
  6.  *  Content: Slot machine server using DirectPlay.
  7.  *
  8.  ***************************************************************************/
  9. #include <windows.h>
  10. #include <windowsx.h>
  11. #include <stdio.h>
  12. #include "dpslots.h"
  13. #include "resource.h"
  14. // constants
  15. const UINT MAX_RECORD_LENGTH = 256; // max database record size
  16. const DWORD INDEX_JACKPOT = 3; // index of jackpot image
  17. const DWORD INDEX_SPOILER = 5; // index of spoiler image
  18. // window messages
  19. const UINT WM_USER_ADDSTRING = WM_USER + 257; // add string to log window
  20. // structures
  21. typedef struct {
  22. DWORD dwBalance; // account record from database
  23. } ACCOUNTINFO, *LPACCOUNTINFO;
  24. // globals
  25. HWND ghServerWnd = NULL; // main window
  26. FILE *glpFile = NULL; // database file
  27. // prototypes
  28. HRESULT HandleBalanceRequest(LPDPLAYINFO lpDPInfo, LPMSG_BALANCEREQUEST lpBalance, DPID idTo);
  29. HRESULT HandleSpinRequest(LPDPLAYINFO lpDPInfo, LPMSG_SPINREQUEST lpBalance, DPID idTo);
  30. void LogRequest(LPSTR lpszFormat, LPDPACCOUNTDESC lpAccountDesc, DWORD dwValue);
  31. LONG GetAmountWonOrLost(DWORD dwAmountBet, DWORD dwIndex[]);
  32. FILE* OpenAccountDB(LPSTR lpszDBName);
  33. void CloseAccountDB(FILE *lpFile);
  34. BOOL QueryAccount(FILE *lpFile, LPSTR lpszAccountID, LPACCOUNTINFO lpAccountInfo);
  35. BOOL UpdateAccount(FILE *lpFile, LPSTR lpszAccountID, LPACCOUNTINFO lpAccountInfo);
  36. HRESULT GetAccountDesc(LPDPLAYINFO lpDPInfo, DPID idPlayer, LPDPACCOUNTDESC *lplpAccountDesc);
  37. BOOL CALLBACK ServerWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  38. {
  39. static LPDPLAYINFO lpDPInfo = NULL;
  40. static UINT idTimer = 0;
  41. static FILE *lpFile = NULL;
  42. DWORD dwTextLen;
  43.     switch(uMsg)
  44.     {
  45.     case WM_INITDIALOG:
  46.         // save the connection info pointer
  47.         lpDPInfo = (LPDPLAYINFO) lParam;
  48. // store global window
  49. ghServerWnd = hWnd;
  50. // open account database
  51. glpFile = OpenAccountDB(gszDatabaseName);
  52. break;
  53.     case WM_DESTROY:
  54. // stop the timer
  55. if (idTimer)
  56. {
  57. KillTimer(hWnd, idTimer); 
  58. idTimer = 0;
  59. }
  60. // close account database
  61. if (glpFile)
  62. CloseAccountDB(glpFile);
  63. ghServerWnd = NULL;
  64.         break;
  65. // this is a user-defined message used to add strings to the log window
  66. case WM_USER_ADDSTRING:
  67. // get length of text in log window
  68. dwTextLen = SendDlgItemMessage(hWnd, IDC_LOGEDIT, WM_GETTEXTLENGTH,
  69.    (WPARAM) 0, (LPARAM) 0);
  70. // put selection at end
  71. dwTextLen = SendDlgItemMessage(hWnd, IDC_LOGEDIT, EM_SETSEL,
  72.    (WPARAM) dwTextLen, (LPARAM) dwTextLen);
  73. // add string in lParam to log window
  74. SendDlgItemMessage(hWnd, IDC_LOGEDIT, EM_REPLACESEL,
  75. (WPARAM) FALSE, (LPARAM) lParam);
  76. GlobalFreePtr((LPVOID) lParam);
  77. break;
  78. case WM_COMMAND:
  79.         switch(LOWORD(wParam))
  80.         {
  81.         case IDCANCEL:
  82. EndDialog(hWnd, FALSE);
  83.             break;
  84. }
  85. break;
  86. }
  87.     // Allow for default processing
  88.     return FALSE;
  89. }
  90. void ServerApplicationMessage(LPDPLAYINFO lpDPInfo, LPDPMSG_GENERIC lpMsg, DWORD dwMsgSize,
  91.   DPID idFrom, DPID idTo)
  92. {
  93. switch (lpMsg->dwType)
  94. {
  95.     case BALANCEREQUEST:
  96. HandleBalanceRequest(lpDPInfo, (LPMSG_BALANCEREQUEST)lpMsg, idFrom);
  97.         break;
  98.     case SPINREQUEST:
  99. HandleSpinRequest(lpDPInfo, (LPMSG_SPINREQUEST)lpMsg, idFrom);
  100.         break;
  101.     default:
  102.         break; 
  103. }
  104. }
  105. void ServerSystemMessage(LPDPLAYINFO lpDPInfo, LPDPMSG_GENERIC lpMsg, DWORD dwMsgSize,
  106.  DPID idFrom, DPID idTo)
  107. {
  108.     // The body of each case is there so you can set a breakpoint and examine
  109.     // the contents of the message received.
  110. switch (lpMsg->dwType)
  111. {
  112. case DPSYS_CREATEPLAYERORGROUP:
  113.         {
  114.             LPDPMSG_CREATEPLAYERORGROUP lp = (LPDPMSG_CREATEPLAYERORGROUP) lpMsg;
  115.         }
  116. break;
  117. case DPSYS_DESTROYPLAYERORGROUP:
  118.         {
  119.             LPDPMSG_DESTROYPLAYERORGROUP lp = (LPDPMSG_DESTROYPLAYERORGROUP)lpMsg;
  120.         }
  121. break;
  122. case DPSYS_ADDPLAYERTOGROUP:
  123.         {
  124.             LPDPMSG_ADDPLAYERTOGROUP lp = (LPDPMSG_ADDPLAYERTOGROUP)lpMsg;
  125.         }
  126. break;
  127. case DPSYS_DELETEPLAYERFROMGROUP:
  128.         {
  129.             LPDPMSG_DELETEPLAYERFROMGROUP lp = (LPDPMSG_DELETEPLAYERFROMGROUP)lpMsg;
  130.         }
  131. break;
  132. case DPSYS_SESSIONLOST:
  133.         {
  134.             LPDPMSG_SESSIONLOST lp = (LPDPMSG_SESSIONLOST)lpMsg;
  135.         }
  136. break;
  137. case DPSYS_HOST:
  138.         {
  139.             LPDPMSG_HOST lp = (LPDPMSG_HOST)lpMsg;
  140.         }
  141. break;
  142. case DPSYS_SETPLAYERORGROUPDATA:
  143.         {
  144.             LPDPMSG_SETPLAYERORGROUPDATA lp = (LPDPMSG_SETPLAYERORGROUPDATA)lpMsg;
  145.         }
  146. break;
  147. case DPSYS_SETPLAYERORGROUPNAME:
  148.         {
  149.             LPDPMSG_SETPLAYERORGROUPNAME lp = (LPDPMSG_SETPLAYERORGROUPNAME)lpMsg;
  150.         }
  151. break;
  152. case DPSYS_SECUREMESSAGE:
  153.         {
  154.             LPDPMSG_SECUREMESSAGE lp = (LPDPMSG_SECUREMESSAGE)lpMsg;
  155. ServerApplicationMessage(lpDPInfo, (LPDPMSG_GENERIC) lp->lpData, lp->dwDataSize,
  156.   lp->dpIdFrom, idTo);
  157.         }
  158. break;
  159. }
  160. }
  161. HRESULT HandleBalanceRequest(LPDPLAYINFO lpDPInfo, LPMSG_BALANCEREQUEST lpBalance, DPID idTo)
  162. {
  163.     MSG_BALANCERESPONSE Msg;
  164. LPDPACCOUNTDESC lpAccountDesc = NULL;
  165. ACCOUNTINFO AccountInfo;
  166. HRESULT hr;
  167. // create balance response message
  168. ZeroMemory(&Msg, sizeof(MSG_BALANCERESPONSE));
  169. Msg.dwType = BALANCERESPONSE;
  170. // get account description for this player
  171. hr = GetAccountDesc(lpDPInfo, idTo, &lpAccountDesc);
  172.     if FAILED(hr)
  173. goto FAILURE;
  174. // get account information from database using account ID
  175. if ((glpFile == NULL) ||
  176. (!QueryAccount(glpFile, lpAccountDesc->lpszAccountIDA, &AccountInfo)))
  177. {
  178. hr = DPERR_ACCESSDENIED;
  179. goto FAILURE;
  180. }
  181. // return balance from database
  182. Msg.dwBalance = AccountInfo.dwBalance;
  183. FAILURE:
  184. Msg.hr = hr;
  185. if FAILED(Msg.hr)
  186. LogRequest("Balance request for "%s" failed: 0x%08Xrn", lpAccountDesc, Msg.hr);
  187. else
  188. LogRequest("Balance request for "%s" returned $%drn", lpAccountDesc, Msg.dwBalance);
  189. if (lpAccountDesc)
  190. GlobalFreePtr(lpAccountDesc);
  191. // send the message
  192.     return (lpDPInfo->lpDirectPlay3A->Send(lpDPInfo->dpidPlayer,
  193. idTo, SENDFLAGS(lpDPInfo->bIsSecure),
  194. &Msg, sizeof(MSG_BALANCERESPONSE)));
  195. }
  196. HRESULT HandleSpinRequest(LPDPLAYINFO lpDPInfo, LPMSG_SPINREQUEST lpSpin, DPID idTo)
  197. {
  198.     MSG_SPINRESPONSE Msg;
  199. LPDPACCOUNTDESC lpAccountDesc = NULL;
  200. ACCOUNTINFO AccountInfo;
  201. DWORD i;
  202. HRESULT hr;
  203. // create spin response message
  204.     ZeroMemory(&Msg, sizeof(MSG_SPINRESPONSE));
  205.     Msg.dwType = SPINRESPONSE;
  206. // get account description for this player
  207. hr = GetAccountDesc(lpDPInfo, idTo, &lpAccountDesc);
  208.     if FAILED(hr)
  209. goto FAILURE;
  210. // get account information from database using account ID
  211. if ((glpFile == NULL) ||
  212. (!QueryAccount(glpFile, lpAccountDesc->lpszAccountIDA, &AccountInfo)))
  213. {
  214. hr = DPERR_ACCESSDENIED;
  215. goto FAILURE;
  216. }
  217. // bet exceeds balance in database
  218. if (lpSpin->dwAmountBet > AccountInfo.dwBalance)
  219. {
  220. hr = DPERR_UNAVAILABLE;
  221. goto FAILURE;
  222. }
  223. // generate new slot settings
  224. for (i = 0; i < NUMWHEELS; i++)
  225. Msg.dwIndex[i] = ((DWORD)rand()) % SLOTSPERWHEEL;
  226. // determine amount won or lost
  227. Msg.dwAmountWonOrLost = GetAmountWonOrLost(lpSpin->dwAmountBet, Msg.dwIndex);
  228. // update account info in database for this player
  229. AccountInfo.dwBalance += Msg.dwAmountWonOrLost;
  230. if (!UpdateAccount(glpFile, lpAccountDesc->lpszAccountIDA, &AccountInfo))
  231. {
  232. hr = DPERR_ACCESSDENIED;
  233. goto FAILURE;
  234. }
  235. // send new balance back
  236.     Msg.dwBalance = AccountInfo.dwBalance;
  237. FAILURE:
  238. Msg.hr = hr;
  239. if FAILED(Msg.hr)
  240. LogRequest("Spin request for "%s" failed: 0x%08Xrn", lpAccountDesc, Msg.hr);
  241. else
  242. LogRequest("Spin request for "%s" returned $%drn", lpAccountDesc, Msg.dwAmountWonOrLost);
  243. if (lpAccountDesc)
  244. GlobalFreePtr(lpAccountDesc);
  245. // send the message
  246.     return (lpDPInfo->lpDirectPlay3A->Send(lpDPInfo->dpidPlayer,
  247. idTo, SENDFLAGS(lpDPInfo->bIsSecure),
  248. &Msg, sizeof(MSG_SPINRESPONSE)));
  249. }
  250. void LogRequest(LPSTR lpszFormat, LPDPACCOUNTDESC lpAccountDesc, DWORD dwValue)
  251. {
  252. LPSTR lpszStr;
  253. LPSTR lpszAccountID;
  254. // make sure we have an account ID
  255. if (lpAccountDesc == NULL)
  256. lpszAccountID = "unknown";
  257. else
  258. lpszAccountID = lpAccountDesc->lpszAccountIDA;
  259. // create a buffer for the output string, account string and a numeric value
  260. lpszStr = (LPSTR) GlobalAllocPtr(GHND, strlen(lpszFormat) + strlen(lpszAccountID) + 10);
  261. if (lpszStr == NULL)
  262. return;
  263. // format the string to log
  264. wsprintf(lpszStr, lpszFormat, lpszAccountID, dwValue);
  265. // log it - main wnd proc will dispose of the string
  266. PostMessage(ghServerWnd, WM_USER_ADDSTRING, (WPARAM) 0, (LPARAM) lpszStr);
  267. }
  268. LONG GetAmountWonOrLost(DWORD dwAmountBet, DWORD dwIndex[])
  269. {
  270. LONG    nMultiplier;
  271. // check for jackpot
  272. if ((dwIndex[0] == INDEX_JACKPOT) &&
  273. (dwIndex[1] == INDEX_JACKPOT) &&
  274. (dwIndex[2] == INDEX_JACKPOT))
  275. {
  276. nMultiplier = 100;
  277. }
  278. // three in a row
  279. else if ((dwIndex[0] == dwIndex[1]) &&
  280.  (dwIndex[1] == dwIndex[2]))
  281. {
  282. nMultiplier = 25;
  283. }
  284. // first two match
  285. else if (dwIndex[0] == dwIndex[1])
  286. {
  287. nMultiplier = 5;
  288. }
  289. // you lose!
  290. else
  291. nMultiplier = -1;
  292. // any spoiler and you lose
  293. if ((dwIndex[0] == INDEX_SPOILER) ||
  294. (dwIndex[1] == INDEX_SPOILER) ||
  295. (dwIndex[2] == INDEX_SPOILER))
  296. {
  297. nMultiplier = -1;
  298. }
  299. // return amount won or lost
  300. return (dwAmountBet * nMultiplier);
  301. }
  302. FILE* OpenAccountDB(LPSTR lpszDBName)
  303. {
  304. FILE *lpFile;
  305. lpFile = fopen(lpszDBName, "r+b");
  306. return (lpFile);
  307. }
  308. void CloseAccountDB(FILE *lpFile)
  309. {
  310. fclose(lpFile);
  311. }
  312. BOOL GetRecord(FILE *lpFile, LPSTR lpszKey, LPSTR lpszRecord)
  313. {
  314. rewind(lpFile);
  315. while (fgets(lpszRecord, MAX_RECORD_LENGTH, lpFile))
  316. {
  317. _strupr(lpszRecord);
  318. if (!strncmp(lpszRecord, lpszKey, strlen(lpszKey)))
  319. return (TRUE);
  320. }
  321. return (FALSE);
  322. }
  323. BOOL PutRecord(FILE *lpFile, LPSTR lpszKey, LPSTR lpszRecord)
  324. {
  325. CHAR szLine[MAX_RECORD_LENGTH];
  326. DWORD dwRecordIndex;
  327. rewind(lpFile);
  328. dwRecordIndex = 0;
  329. while (fgets(szLine, MAX_RECORD_LENGTH, lpFile))
  330. {
  331. _strupr(szLine);
  332. if (!strncmp(szLine, lpszKey, strlen(lpszKey)))
  333. {
  334. fseek(lpFile, dwRecordIndex, SEEK_SET);
  335. fputs(lpszRecord, lpFile);
  336. return (TRUE);
  337. }
  338. dwRecordIndex += strlen(szLine);
  339. }
  340. return (FALSE);
  341. }
  342. BOOL QueryAccount(FILE *lpFile, LPSTR lpszAccountID, LPACCOUNTINFO lpAccountInfo)
  343. {
  344.     CHAR szBuffer[MAX_RECORD_LENGTH];
  345.     CHAR *lpToken;
  346.     if (!GetRecord(lpFile, lpszAccountID, szBuffer))
  347.     {
  348.         return FALSE;
  349.     }
  350.     lpToken = strtok(szBuffer, ",");
  351.     if (lpToken)
  352.     {
  353.         lpToken = strtok(NULL, "n");
  354.         if (lpToken)
  355.         {
  356.             lpAccountInfo->dwBalance = atoi(lpToken);
  357.         }
  358.     }
  359.     return TRUE;
  360. }
  361. BOOL UpdateAccount(FILE *lpFile, LPSTR lpszAccountID, LPACCOUNTINFO lpAccountInfo)
  362. {
  363.     CHAR szBuffer[MAX_RECORD_LENGTH];
  364.     if (!GetRecord(lpFile, lpszAccountID, szBuffer))
  365.     {
  366.         return FALSE;
  367.     }
  368. sprintf(szBuffer, "%s,%8d", lpszAccountID, lpAccountInfo->dwBalance);
  369. return (PutRecord(lpFile, lpszAccountID, szBuffer));
  370. }
  371. HRESULT GetSecureAccountDesc(LPDPLAYINFO lpDPInfo, DPID idPlayer, LPDPACCOUNTDESC *lplpAccountDesc)
  372. {
  373. LPDPACCOUNTDESC lpAccountDesc = NULL;
  374. DWORD dwAccountDescSize;
  375. HRESULT hr;
  376. // get size of account description
  377. hr = lpDPInfo->lpDirectPlay3A->GetPlayerAccount(idPlayer, 0,
  378. NULL, &dwAccountDescSize);
  379. if (hr != DPERR_BUFFERTOOSMALL)
  380. goto FAILURE;
  381. // make room for it
  382. lpAccountDesc = (LPDPACCOUNTDESC) GlobalAllocPtr(GHND, dwAccountDescSize);
  383. if (lpAccountDesc == NULL)
  384. {
  385. hr = DPERR_OUTOFMEMORY;
  386. goto FAILURE;
  387. }
  388. // get the account description for this player
  389. hr = lpDPInfo->lpDirectPlay3A->GetPlayerAccount(idPlayer, 0,
  390. lpAccountDesc, &dwAccountDescSize);
  391. if FAILED(hr)
  392. goto FAILURE;
  393. // return account description
  394. _strupr(lpAccountDesc->lpszAccountIDA);
  395. *lplpAccountDesc = lpAccountDesc;
  396. lpAccountDesc = NULL;
  397. FAILURE:
  398. if (lpAccountDesc)
  399. GlobalFreePtr(lpAccountDesc);
  400. return (hr);
  401. }
  402. HRESULT GetUnsecureAccountDesc(LPDPLAYINFO lpDPInfo, DPID idPlayer, LPDPACCOUNTDESC *lplpAccountDesc)
  403. {
  404. LPDPACCOUNTDESC lpAccountDesc = NULL;
  405. DWORD dwAccountDescSize;
  406. LPDPNAME lpName;
  407. HRESULT hr;
  408. // get size of player name
  409. hr = lpDPInfo->lpDirectPlay3A->GetPlayerName(idPlayer,
  410. NULL, &dwAccountDescSize);
  411. if (hr != DPERR_BUFFERTOOSMALL)
  412. goto FAILURE;
  413. // make room for it
  414. lpAccountDesc = (LPDPACCOUNTDESC) GlobalAllocPtr(GHND, sizeof(DPACCOUNTDESC) + dwAccountDescSize);
  415. if (lpAccountDesc == NULL)
  416. {
  417. hr = DPERR_OUTOFMEMORY;
  418. goto FAILURE;
  419. }
  420. // get the player name
  421. lpName = (LPDPNAME) (((LPSTR)lpAccountDesc) + sizeof(DPACCOUNTDESC));
  422. hr = lpDPInfo->lpDirectPlay3A->GetPlayerName(idPlayer,
  423. lpName, &dwAccountDescSize);
  424. if FAILED(hr)
  425. goto FAILURE;
  426. // return account description
  427. lpAccountDesc->lpszAccountIDA = lpName->lpszShortNameA;
  428. _strupr(lpAccountDesc->lpszAccountIDA);
  429. *lplpAccountDesc = lpAccountDesc;
  430. lpAccountDesc = NULL;
  431. FAILURE:
  432. if (lpAccountDesc)
  433. GlobalFreePtr(lpAccountDesc);
  434. return (hr);
  435. }
  436. HRESULT GetAccountDesc(LPDPLAYINFO lpDPInfo, DPID idPlayer, LPDPACCOUNTDESC *lplpAccountDesc)
  437. {
  438. HRESULT hr;
  439. if (lpDPInfo->bIsSecure)
  440. {
  441. hr = GetSecureAccountDesc(lpDPInfo, idPlayer, lplpAccountDesc);
  442. }
  443. else
  444. {
  445. hr = GetUnsecureAccountDesc(lpDPInfo, idPlayer, lplpAccountDesc);
  446. }
  447. return (hr);
  448. }