Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1462 lines
53 KiB

  1. //=============================================================================
  2. // FILE: VoiceParser.cpp
  3. //
  4. // Description: DirectPlay Service Provider Parser
  5. //
  6. //
  7. // Modification History:
  8. //
  9. // Michael Milirud 08/Aug/2000 Created
  10. //=============================================================================
  11. //==================//
  12. // Standard headers //
  13. //==================//
  14. #include <string>
  15. #include <winsock2.h>
  16. #include <wsipx.h>
  17. // DVoice.h, included by DVProt.h, will _define_ the Compression Type GUIDs.
  18. #include <initguid.h>
  19. //=====================//
  20. // Proprietary headers //
  21. //=====================//
  22. // Prototypes
  23. #include "VoiceParser.hpp"
  24. // Voice protocol header
  25. #include "DVoice.h"
  26. #include "DVProt.h"
  27. namespace
  28. {
  29. HPROTOCOL g_hVoiceProtocol;
  30. //====================//
  31. // Message Type field //---------------------------------------------------------------------------------------------
  32. //====================//
  33. LABELED_BYTE g_arr_MessageTypeByteLabels[] = { { DVMSGID_CONNECTREQUEST, "Establishing connection" },
  34. { DVMSGID_CONNECTREFUSE, "Connection request rejected" },
  35. { DVMSGID_CONNECTACCEPT, "Connection request granted" },
  36. { DVMSGID_SETTINGSCONFIRM, "Confirming support for the connection settings" },
  37. { DVMSGID_PLAYERLIST, "List of players in the session" },
  38. { DVMSGID_SPEECH, "Audio data" },
  39. { DVMSGID_SPEECHWITHTARGET, "Targeted audio data" },
  40. { DVMSGID_SPEECHWITHFROM, "Proxied audio data" },
  41. { DVMSGID_SETTARGETS, "Setting client's target" },
  42. { DVMSGID_CREATEVOICEPLAYER, "New player joined the session" },
  43. { DVMSGID_DELETEVOICEPLAYER, "Player left the session" },
  44. { DVMSGID_SESSIONLOST, "Session is lost" },
  45. { DVMSGID_DISCONNECTCONFIRM, "Disconnection notification acknowledged" },
  46. { DVMSGID_DISCONNECT, "Disconnecting" },
  47. { DVMSGID_PLAYERLIST, "Players list" } };
  48. SET g_LabeledMessageTypeByteSet = { sizeof(g_arr_MessageTypeByteLabels) / sizeof(LABELED_BYTE), g_arr_MessageTypeByteLabels };
  49. //===================//
  50. // Result Code field //----------------------------------------------------------------------------------------------
  51. //===================//
  52. LABELED_DWORD g_arr_ResultCodeDWordLabels[] = { { DVERR_BUFFERTOOSMALL, "Buffer is too small" },
  53. { DVERR_EXCEPTION, "Exception was thrown" },
  54. { DVERR_GENERIC, "Generic error" },
  55. { DVERR_INVALIDFLAGS, "Invalid flags" },
  56. { DVERR_INVALIDOBJECT, "Invalid object" },
  57. { DVERR_INVALIDPARAM, "Invalid parameter(s)" },
  58. { DVERR_INVALIDPLAYER, "Invalid player" },
  59. { DVERR_INVALIDGROUP, "Invalid group" },
  60. { DVERR_INVALIDHANDLE, "Invalid handle" },
  61. { DVERR_INVALIDPOINTER, "Invalid pointer" },
  62. { DVERR_OUTOFMEMORY, "Out of memory" },
  63. { DVERR_CONNECTABORTING, "Aborting connection" },
  64. { DVERR_CONNECTIONLOST, "Connection lost" },
  65. { DVERR_CONNECTABORTED, "Connection aborted" },
  66. { DVERR_CONNECTED, "Connected" },
  67. { DVERR_NOTCONNECTED, "Not connected" },
  68. { DVERR_NOTINITIALIZED, "Not initialized" },
  69. { DVERR_NOVOICESESSION, "No voice session" },
  70. { DVERR_NOTALLOWED, "Not allowed" },
  71. { DVERR_NOTHOSTING, "Not hosting" },
  72. { DVERR_NOTSUPPORTED, "Not supported" },
  73. { DVERR_NOINTERFACE, "No interface" },
  74. { DVERR_NOTBUFFERED, "Not buffered" },
  75. { DVERR_NOTRANSPORT, "No transport" },
  76. { DVERR_NOCALLBACK, "No callback" },
  77. { DVERR_NO3DSOUND, "No 3D sound" },
  78. { DVERR_NORECVOLAVAILABLE, "No recording volume available" },
  79. { DVERR_SESSIONLOST, "Session lost" },
  80. { DVERR_PENDING, "Pending" },
  81. { DVERR_INVALIDTARGET, "Invalid target" },
  82. { DVERR_TRANSPORTNOTHOST, "Transport is not hosting" },
  83. { DVERR_COMPRESSIONNOTSUPPORTED, "Compression is not supported" },
  84. { DVERR_ALREADYPENDING, "Already pending" },
  85. { DVERR_SOUNDINITFAILURE, "Sound initialization failed" },
  86. { DVERR_TIMEOUT, "Timeout" },
  87. { DVERR_ALREADYBUFFERED, "Already buffered" },
  88. { DVERR_HOSTING, "Hosting" },
  89. { DVERR_INVALIDDEVICE, "Invalid device" },
  90. { DVERR_RECORDSYSTEMERROR, "Record system error" },
  91. { DVERR_PLAYBACKSYSTEMERROR, "Playback system error" },
  92. { DVERR_SENDERROR, "Send error" },
  93. { DVERR_USERCANCEL, "Cancelled by user" },
  94. { DVERR_RUNSETUP, "Run setup" },
  95. { DVERR_INCOMPATIBLEVERSION, "Incompatible version" },
  96. { DVERR_INITIALIZED, "Initialized" },
  97. { DVERR_TRANSPORTNOTINIT, "Transport not initialized" },
  98. { DVERR_TRANSPORTNOSESSION, "Transport is not hosting or connecting" },
  99. { DVERR_TRANSPORTNOPLAYER, "Legacy DirectPlay local player has not yet been created" },
  100. { DVERR_USERBACK, "Back button was used improperly in the wizard" },
  101. { DVERR_INVALIDBUFFER, "Invalid buffer" },
  102. { DV_OK, "Success" } };
  103. SET g_LabeledResultCodeDWordSet = { sizeof(g_arr_ResultCodeDWordLabels) / sizeof(LABELED_DWORD), g_arr_ResultCodeDWordLabels };
  104. //====================//
  105. // Session Type field //---------------------------------------------------------------------------------------------
  106. //====================//
  107. LABELED_DWORD g_arr_SessionTypeDWordLabels[] = { { DVSESSIONTYPE_PEER, "Peer to peer" },
  108. { DVSESSIONTYPE_MIXING, "Mixing server" },
  109. { DVSESSIONTYPE_FORWARDING, "Forwarding server" },
  110. { DVSESSIONTYPE_ECHO, "Loopback" } };
  111. SET g_LabeledSessionTypeDWordSet = { sizeof(g_arr_SessionTypeDWordLabels) / sizeof(LABELED_DWORD), g_arr_SessionTypeDWordLabels };
  112. //====================//
  113. // Session Flags field //--------------------------------------------------------------------------------------------
  114. //====================//
  115. LABELED_BIT g_arr_SessionFlagsBitLabels[] = { { 1, "Host Migration enabled", "No Host Migration" }, // DVSESSION_NOHOSTMIGRATION
  116. { 2, "No Server Control Target mode", "Server Control Target mode" } }; // DVSESSION_SERVERCONTROLTARGET
  117. SET g_LabeledSessionFlagsBitSet = { sizeof(g_arr_SessionFlagsBitLabels) / sizeof(LABELED_BIT), g_arr_SessionFlagsBitLabels };
  118. //====================//
  119. // Player Flags field //---------------------------------------------------------------------------------------------
  120. //====================//
  121. LABELED_BIT g_arr_PlayerFlagsBitLabels[] = { { 1, "Player supports full-duplex connection", "Player only supports half-duplex connection" } }; // DVPLAYERCAPS_HALFDUPLEX
  122. SET g_LabeledPlayerFlagsBitSet = { sizeof(g_arr_PlayerFlagsBitLabels) / sizeof(LABELED_BIT), g_arr_PlayerFlagsBitLabels };
  123. //=====================//
  124. // Host Order ID field //--------------------------------------------------------------------------------------------
  125. //=====================//
  126. LABELED_DWORD g_arr_HostOrderDWordLabels[] = { { -1, "Hasn't been assigned by the host yet" } };
  127. SET g_LabeledHostOrderIDDWordSet = { sizeof(g_arr_HostOrderDWordLabels) / sizeof(LABELED_DWORD), g_arr_HostOrderDWordLabels };
  128. ////////////////////////////////
  129. // Custom Property Formatters //=====================================================================================
  130. ////////////////////////////////
  131. // DESCRIPTION: Custom description formatter for the Voice packet summary
  132. //
  133. // ARGUMENTS: io_pProperyInstance - Data of the property's instance
  134. //
  135. // RETURNS: NOTHING
  136. //
  137. VOID WINAPIV FormatPropertyInstance_VoiceSummary( LPPROPERTYINST io_pProperyInstance )
  138. {
  139. std::string strSummary;
  140. char arr_cBuffer[10];
  141. DVPROTOCOLMSG_FULLMESSAGE& rVoiceFrame = *reinterpret_cast<DVPROTOCOLMSG_FULLMESSAGE*>(io_pProperyInstance->lpData);
  142. DWORD dwType = rVoiceFrame.dvGeneric.dwType;
  143. // Message classification
  144. switch ( dwType )
  145. {
  146. case DVMSGID_CONNECTREQUEST:
  147. case DVMSGID_CONNECTREFUSE:
  148. case DVMSGID_CONNECTACCEPT:
  149. case DVMSGID_DISCONNECT:
  150. case DVMSGID_DISCONNECTCONFIRM:
  151. case DVMSGID_SETTINGSCONFIRM:
  152. {
  153. strSummary = "Connection Control : ";
  154. break;
  155. }
  156. case DVMSGID_SPEECH:
  157. case DVMSGID_SPEECHWITHTARGET:
  158. case DVMSGID_SPEECHWITHFROM:
  159. {
  160. strSummary = "Speech : ";
  161. break;
  162. }
  163. case DVMSGID_PLAYERLIST:
  164. case DVMSGID_SETTARGETS:
  165. case DVMSGID_CREATEVOICEPLAYER:
  166. case DVMSGID_DELETEVOICEPLAYER:
  167. case DVMSGID_SESSIONLOST:
  168. {
  169. strSummary = "Session Control : ";
  170. break;
  171. }
  172. default:
  173. {
  174. strSummary = "INVALID";
  175. break;
  176. }
  177. }
  178. // Message title
  179. switch ( dwType )
  180. {
  181. case DVMSGID_CREATEVOICEPLAYER:
  182. {
  183. strSummary += "Player ";
  184. strSummary += _itoa(rVoiceFrame.dvPlayerJoin.dvidID, arr_cBuffer, 16);
  185. strSummary += " joined the session";
  186. break;
  187. }
  188. default:
  189. {
  190. for ( int n = 0; n < sizeof(g_arr_MessageTypeByteLabels) / sizeof(LABELED_BYTE); ++n )
  191. {
  192. if ( g_arr_MessageTypeByteLabels[n].Value == dwType )
  193. {
  194. strSummary += g_arr_MessageTypeByteLabels[n].Label;
  195. break;
  196. }
  197. }
  198. break;
  199. }
  200. }
  201. // Message highlights
  202. switch ( dwType )
  203. {
  204. case DVMSGID_PLAYERLIST:
  205. {
  206. strSummary += " (";
  207. strSummary += _itoa(rVoiceFrame.dvPlayerList.dwNumEntries, arr_cBuffer, 10);
  208. strSummary += " players)";
  209. break;
  210. }
  211. case DVMSGID_CONNECTACCEPT:
  212. {
  213. strSummary += " (";
  214. for ( int n = 0; n < sizeof(g_arr_SessionTypeDWordLabels)/sizeof(LABELED_DWORD); ++n )
  215. {
  216. if ( g_arr_SessionTypeDWordLabels[n].Value == rVoiceFrame.dvConnectAccept.dwSessionType )
  217. {
  218. strSummary += g_arr_SessionTypeDWordLabels[n].Label;
  219. break;
  220. }
  221. }
  222. strSummary += ")";
  223. break;
  224. }
  225. case DVMSGID_SPEECH:
  226. case DVMSGID_SPEECHWITHTARGET:
  227. case DVMSGID_SPEECHWITHFROM:
  228. {
  229. strSummary += " [";
  230. strSummary += _itoa(rVoiceFrame.dvSpeech.bMsgNum, arr_cBuffer, 10);
  231. strSummary += ".";
  232. strSummary += _itoa(rVoiceFrame.dvSpeech.bSeqNum, arr_cBuffer, 10);
  233. strSummary += "]";
  234. break;
  235. }
  236. }
  237. strcpy(io_pProperyInstance->szPropertyText, strSummary.c_str());
  238. } // FormatPropertyInstance_VoiceSummary
  239. // DESCRIPTION: Custom description formatter for the Compression Type field
  240. //
  241. // ARGUMENTS: io_pProperyInstance - Data of the property's instance
  242. //
  243. // RETURNS: NOTHING
  244. //
  245. VOID WINAPIV FormatPropertyInstance_CompressionType( LPPROPERTYINST io_pProperyInstance )
  246. {
  247. std::string strSummary = "Compression Type = ";
  248. // Check what Voice frame we are dealing with
  249. REFGUID rguidCompressionType = *reinterpret_cast<GUID*>(io_pProperyInstance->lpData);
  250. if ( IsEqualGUID(rguidCompressionType, DPVCTGUID_TRUESPEECH) )
  251. {
  252. strSummary += "TrueSpeech(TM) (8.6kbps) ";
  253. }
  254. else if ( IsEqualGUID(rguidCompressionType, DPVCTGUID_GSM) )
  255. {
  256. strSummary += "Microsoft GSM 6.10 (13kbps) ";
  257. }
  258. else if ( IsEqualGUID(rguidCompressionType, DPVCTGUID_NONE) )
  259. {
  260. strSummary += "None ";
  261. }
  262. else if ( IsEqualGUID(rguidCompressionType, DPVCTGUID_ADPCM) )
  263. {
  264. strSummary += "Microsoft ADPCM (32.8kbps) ";
  265. }
  266. else if ( IsEqualGUID(rguidCompressionType, DPVCTGUID_SC03) )
  267. {
  268. strSummary += "Voxware SC03 (3.2kbps) ";
  269. }
  270. else if ( IsEqualGUID(rguidCompressionType, DPVCTGUID_SC06) )
  271. {
  272. strSummary += "Voxware SC06 (6.4kbps) ";
  273. }
  274. else if ( IsEqualGUID(rguidCompressionType, DPVCTGUID_VR12) )
  275. {
  276. strSummary += "Voxware VR12 (1.4kbps) ";
  277. }
  278. else
  279. {
  280. strSummary += "Uknown";
  281. }
  282. enum
  283. {
  284. nMAX_GUID_STRING = 50 // more than enough characters for a symbolic representation of a GUID
  285. };
  286. OLECHAR arr_wcGUID[nMAX_GUID_STRING];
  287. StringFromGUID2(rguidCompressionType, arr_wcGUID, sizeof(arr_wcGUID)/sizeof(TCHAR));
  288. char arr_cGUID[nMAX_GUID_STRING];
  289. WideCharToMultiByte(CP_ACP, 0, arr_wcGUID, -1, arr_cGUID, sizeof(arr_cGUID), NULL, NULL);
  290. strSummary += arr_cGUID;
  291. strcpy(io_pProperyInstance->szPropertyText, strSummary.c_str());
  292. } // FormatPropertyInstance_CompressionType
  293. // DESCRIPTION: Custom description formatter for the Players List summary
  294. //
  295. // ARGUMENTS: io_pProperyInstance - Data of the property's instance
  296. //
  297. // RETURNS: NOTHING
  298. //
  299. VOID WINAPIV FormatPropertyInstance_PlayersListSummary( LPPROPERTYINST io_pProperyInstance )
  300. {
  301. sprintf(io_pProperyInstance->szPropertyText, "List of %d players in the session", io_pProperyInstance->lpPropertyInstEx->Dword[0]);
  302. } // FormatPropertyInstance_PlayersListSummary
  303. // DESCRIPTION: Custom description formatter for the Player's Entry summary
  304. //
  305. // ARGUMENTS: io_pProperyInstance - Data of the property's instance
  306. //
  307. // RETURNS: NOTHING
  308. //
  309. VOID WINAPIV FormatPropertyInstance_PlayerEntrySummary( LPPROPERTYINST io_pProperyInstance )
  310. {
  311. DWORD* pdwData = io_pProperyInstance->lpPropertyInstEx->Dword;
  312. sprintf(io_pProperyInstance->szPropertyText, "Player %d out of %d", pdwData[0], pdwData[1]);
  313. } // FormatPropertyInstance_PlayerEntrySummary
  314. // DESCRIPTION: Custom description formatter for the Session Flags summary
  315. //
  316. // ARGUMENTS: io_pProperyInstance - Data of the property's instance
  317. //
  318. // RETURNS: NOTHING
  319. //
  320. VOID WINAPIV FormatPropertyInstance_SessionFlagsSummary( LPPROPERTYINST io_pProperyInstance )
  321. {
  322. std::string strSummary;
  323. if ( (*io_pProperyInstance->lpDword & DVSESSION_NOHOSTMIGRATION) == DVSESSION_NOHOSTMIGRATION )
  324. {
  325. strSummary = g_arr_SessionFlagsBitLabels[0].LabelOn;
  326. }
  327. else
  328. {
  329. strSummary = g_arr_SessionFlagsBitLabels[0].LabelOff;
  330. }
  331. strSummary += ", ";
  332. if ( (*io_pProperyInstance->lpDword & DVSESSION_SERVERCONTROLTARGET) == DVSESSION_SERVERCONTROLTARGET )
  333. {
  334. strSummary += g_arr_SessionFlagsBitLabels[1].LabelOn;
  335. }
  336. else
  337. {
  338. strSummary += g_arr_SessionFlagsBitLabels[1].LabelOff;
  339. }
  340. strcpy(io_pProperyInstance->szPropertyText, strSummary.c_str());
  341. } // FormatPropertyInstance_SessionFlagsSummary
  342. // DESCRIPTION: Custom description formatter for the Player's Entry summary
  343. //
  344. // ARGUMENTS: io_pProperyInstance - Data of the property's instance
  345. //
  346. // RETURNS: NOTHING
  347. //
  348. VOID WINAPIV FormatPropertyInstance_PlayerFlagsSummary( LPPROPERTYINST io_pProperyInstance )
  349. {
  350. std::string strSummary;
  351. if ( (*io_pProperyInstance->lpDword & DVSESSION_NOHOSTMIGRATION) == DVSESSION_NOHOSTMIGRATION )
  352. {
  353. strSummary = g_arr_PlayerFlagsBitLabels[0].LabelOn;
  354. }
  355. else
  356. {
  357. strSummary = g_arr_PlayerFlagsBitLabels[0].LabelOff;
  358. }
  359. strcpy(io_pProperyInstance->szPropertyText, strSummary.c_str());
  360. } // FormatPropertyInstance_PlayerFlagsSummary
  361. //==================//
  362. // Properties table //-----------------------------------------------------------------------------------------------
  363. //==================//
  364. PROPERTYINFO g_arr_VoiceProperties[] =
  365. {
  366. // VOICE packet summary property (VOICE_SUMMARY)
  367. {
  368. 0, // handle placeholder (MBZ)
  369. 0, // reserved (MBZ)
  370. "", // label
  371. "DPlay Voice packet", // status-bar comment
  372. PROP_TYPE_SUMMARY, // data type
  373. PROP_QUAL_NONE, // data type qualifier
  374. NULL, // labeled bit set
  375. 512, // description's maximum length
  376. FormatPropertyInstance_VoiceSummary // generic formatter
  377. },
  378. // Message Type property (VOICE_UNPARSABLEFRAGMENT)
  379. {
  380. 0, // handle placeholder (MBZ)
  381. 0, // reserved (MBZ)
  382. "This is a non-initial part of the fragmented Transport layer message and can not be parsed", // label
  383. "Unparsable fragment summary", // status-bar comment
  384. PROP_TYPE_SUMMARY, // data type
  385. PROP_QUAL_NONE, // data type qualifier.
  386. NULL, // labeled bit set
  387. 128, // description's maximum length
  388. FormatPropertyInstance // generic formatter
  389. },
  390. // Message Type property ((VOICE_INCOMPLETEMESSAGE)
  391. {
  392. 0, // handle placeholder (MBZ)
  393. 0, // reserved (MBZ)
  394. "The rest of the data needed to parse this message has been sent in a separate fragment and can not be parsed", // label
  395. "Incomplete message summary", // status-bar comment
  396. PROP_TYPE_SUMMARY, // data type
  397. PROP_QUAL_NONE, // data type qualifier.
  398. NULL, // labeled bit set
  399. 128, // description's maximum length
  400. FormatPropertyInstance // generic formatter
  401. },
  402. // Message Type property (VOICE_MESSAGETYPE)
  403. {
  404. 0, // handle placeholder (MBZ)
  405. 0, // reserved (MBZ)
  406. "Message Type", // label
  407. "Message Type field", // status-bar comment
  408. PROP_TYPE_BYTE, // data type
  409. PROP_QUAL_LABELED_SET, // data type qualifier.
  410. &g_LabeledMessageTypeByteSet, // labeled bit set
  411. 64, // description's maximum length
  412. FormatPropertyInstance // generic formatter
  413. },
  414. // Major Version property (VOICE_MAJORVERSION)
  415. {
  416. 0, // handle placeholder (MBZ)
  417. 0, // reserved (MBZ)
  418. "Major Version", // label
  419. "Major Version field", // status-bar comment
  420. PROP_TYPE_BYTE, // data type
  421. PROP_QUAL_NONE, // data type qualifier.
  422. NULL, // labeled bit set
  423. 64, // description's maximum length
  424. FormatPropertyInstance // generic formatter
  425. },
  426. // Minor Version property (VOICE_MINORVERSION)
  427. {
  428. 0, // handle placeholder (MBZ)
  429. 0, // reserved (MBZ)
  430. "Minor Version", // label
  431. "Minor Version field", // status-bar comment
  432. PROP_TYPE_BYTE, // data type
  433. PROP_QUAL_NONE, // data type qualifier.
  434. NULL, // labeled bit set
  435. 64, // description's maximum length
  436. FormatPropertyInstance // generic formatter
  437. },
  438. // Build Version property (VOICE_BUILDVERSION)
  439. {
  440. 0, // handle placeholder (MBZ)
  441. 0, // reserved (MBZ)
  442. "Build Version", // label
  443. "Build Version field", // status-bar comment
  444. PROP_TYPE_DWORD, // data type
  445. PROP_QUAL_NONE, // data type qualifier.
  446. NULL, // labeled bit set
  447. 64, // description's maximum length
  448. FormatPropertyInstance // generic formatter
  449. },
  450. // Result Code property (VOICE_RESULTCODE)
  451. {
  452. 0, // handle placeholder (MBZ)
  453. 0, // reserved (MBZ)
  454. "Result Code", // label
  455. "Result Code field", // status-bar comment
  456. PROP_TYPE_DWORD, // data type (HRESULT)
  457. PROP_QUAL_LABELED_SET, // data type qualifier.
  458. &g_LabeledResultCodeDWordSet, // labeled byte set
  459. 64, // description's maximum length
  460. FormatPropertyInstance // generic formatter
  461. },
  462. // Session Type property (VOICE_SESSIONTYPE)
  463. {
  464. 0, // handle placeholder (MBZ)
  465. 0, // reserved (MBZ)
  466. "Session Type", // label
  467. "Session Type field", // status-bar comment
  468. PROP_TYPE_DWORD, // data type
  469. PROP_QUAL_LABELED_SET, // data type qualifier.
  470. &g_LabeledSessionTypeDWordSet, // labeled byte set
  471. 64, // description's maximum length
  472. FormatPropertyInstance // generic formatter
  473. },
  474. // Session Flags property (VOICE_SESSIONFLAGS_SUMMARY)
  475. {
  476. 0, // handle placeholder (MBZ)
  477. 0, // reserved (MBZ)
  478. "", // label
  479. "Session Flags summary", // status-bar comment
  480. PROP_TYPE_SUMMARY, // data type
  481. PROP_QUAL_NONE, // data type qualifier.
  482. NULL, // labeled byte set
  483. 64, // description's maximum length
  484. FormatPropertyInstance_SessionFlagsSummary // generic formatter
  485. },
  486. // Session Flags property (VOICE_SESSIONFLAGS)
  487. {
  488. 0, // handle placeholder (MBZ)
  489. 0, // reserved (MBZ)
  490. "Session Flags", // label
  491. "Session Flags field", // status-bar comment
  492. PROP_TYPE_DWORD, // data type
  493. PROP_QUAL_FLAGS, // data type qualifier.
  494. &g_LabeledSessionFlagsBitSet, // labeled byte set
  495. 512, // description's maximum length
  496. FormatPropertyInstance // generic formatter
  497. },
  498. // Session Flags property (VOICE_PLAYERFLAGS_SUMMARY)
  499. {
  500. 0, // handle placeholder (MBZ)
  501. 0, // reserved (MBZ)
  502. "", // label
  503. "Player Flags summary", // status-bar comment
  504. PROP_TYPE_SUMMARY, // data type
  505. PROP_QUAL_NONE, // data type qualifier.
  506. NULL, // labeled byte set
  507. 64, // description's maximum length
  508. FormatPropertyInstance_PlayerFlagsSummary // generic formatter
  509. },
  510. // Session Flags property (VOICE_PLAYERFLAGS)
  511. {
  512. 0, // handle placeholder (MBZ)
  513. 0, // reserved (MBZ)
  514. "Player Flags", // label
  515. "Player Flags field", // status-bar comment
  516. PROP_TYPE_DWORD, // data type
  517. PROP_QUAL_FLAGS, // data type qualifier.
  518. &g_LabeledPlayerFlagsBitSet, // labeled byte set
  519. 512, // description's maximum length
  520. FormatPropertyInstance // generic formatter
  521. },
  522. // Number of Targets property (VOICE_NUMBEROFTARGETS)
  523. {
  524. 0, // handle placeholder (MBZ)
  525. 0, // reserved (MBZ)
  526. "Number of Targets", // label
  527. "Number of Targets field", // status-bar comment
  528. PROP_TYPE_DWORD, // data type
  529. PROP_QUAL_NONE, // data type qualifier.
  530. NULL, // labeled bit set
  531. 64, // description's maximum length
  532. FormatPropertyInstance // generic formatter
  533. },
  534. // Compression Type property (VOICE_COMPRESSIONTYPE)
  535. {
  536. 0, // handle placeholder (MBZ)
  537. 0, // reserved (MBZ)
  538. "Compression Type", // label
  539. "Compression Type field", // status-bar comment
  540. PROP_TYPE_RAW_DATA, // data type (GUID)
  541. PROP_QUAL_NONE, // data type qualifier.
  542. NULL, // labeled bit set
  543. 64, // description's maximum length
  544. FormatPropertyInstance_CompressionType // generic formatter
  545. },
  546. // Host Migration Sequence Number property (VOICE_HOSTORDERID)
  547. {
  548. 0, // handle placeholder (MBZ)
  549. 0, // reserved (MBZ)
  550. "Host Migration Sequence Number", // label
  551. "Host Migration Sequence Number field", // status-bar comment
  552. PROP_TYPE_DWORD, // data type
  553. PROP_QUAL_LABELED_SET, // data type qualifier.
  554. &g_LabeledHostOrderIDDWordSet, // labeled bit set
  555. 64, // description's maximum length
  556. FormatPropertyInstance // generic formatter
  557. },
  558. // Number of Players property (VOICE_NUMBEROFPLAYERS)
  559. {
  560. 0, // handle placeholder (MBZ)
  561. 0, // reserved (MBZ)
  562. "Number of Players", // label
  563. "Number of Players field", // status-bar comment
  564. PROP_TYPE_DWORD, // data type
  565. PROP_QUAL_NONE, // data type qualifier.
  566. NULL, // labeled bit set
  567. 64, // description's maximum length
  568. FormatPropertyInstance // generic formatter
  569. },
  570. // Player's summary property (VOICE_PLAYERLISTSUMMARY)
  571. {
  572. 0, // handle placeholder (MBZ)
  573. 0, // reserved (MBZ)
  574. "", // label
  575. "Player's list summary", // status-bar comment
  576. PROP_TYPE_SUMMARY, // data type
  577. PROP_QUAL_NONE, // data type qualifier.
  578. NULL, // labeled bit set
  579. 64, // description's maximum length
  580. FormatPropertyInstance_PlayersListSummary // generic formatter
  581. },
  582. // Player's summary property (VOICE_PLAYERSUMMARY)
  583. {
  584. 0, // handle placeholder (MBZ)
  585. 0, // reserved (MBZ)
  586. "", // label
  587. "Player's summary", // status-bar comment
  588. PROP_TYPE_SUMMARY, // data type
  589. PROP_QUAL_NONE, // data type qualifier.
  590. NULL, // labeled bit set
  591. 64, // description's maximum length
  592. FormatPropertyInstance_PlayerEntrySummary // generic formatter
  593. },
  594. // Player's ID property (VOICE_PLAYERID)
  595. {
  596. 0, // handle placeholder (MBZ)
  597. 0, // reserved (MBZ)
  598. "Player ID", // label
  599. "Player ID field", // status-bar comment
  600. PROP_TYPE_DWORD, // data type
  601. PROP_QUAL_NONE, // data type qualifier.
  602. NULL, // labeled bit set
  603. 64, // description's maximum length
  604. FormatPropertyInstance // generic formatter
  605. },
  606. // Player's ID property (VOICE_TARGETID)
  607. {
  608. 0, // handle placeholder (MBZ)
  609. 0, // reserved (MBZ)
  610. "Target ID", // label
  611. "Target ID field", // status-bar comment
  612. PROP_TYPE_DWORD, // data type
  613. PROP_QUAL_NONE, // data type qualifier.
  614. NULL, // labeled bit set
  615. 64, // description's maximum length
  616. FormatPropertyInstance // generic formatter
  617. },
  618. // Message Number property (VOICE_MESSAGENUMBER)
  619. {
  620. 0, // handle placeholder (MBZ)
  621. 0, // reserved (MBZ)
  622. "Message #", // label
  623. "Message Number field", // status-bar comment
  624. PROP_TYPE_BYTE, // data type
  625. PROP_QUAL_NONE, // data type qualifier.
  626. NULL, // labeled bit set
  627. 64, // description's maximum length
  628. FormatPropertyInstance // generic formatter
  629. },
  630. // Fragment Number property (VOICE_FRAGMENTNUMBER)
  631. {
  632. 0, // handle placeholder (MBZ)
  633. 0, // reserved (MBZ)
  634. "Fragment #", // label
  635. "Fragment Number field", // status-bar comment
  636. PROP_TYPE_BYTE, // data type
  637. PROP_QUAL_NONE, // data type qualifier.
  638. NULL, // labeled bit set
  639. 64, // description's maximum length
  640. FormatPropertyInstance // generic formatter
  641. },
  642. // Audio Data (VOICE_AUDIODATA)
  643. {
  644. 0, // handle placeholder (MBZ)
  645. 0, // reserved (MBZ)
  646. "Audio Data", // label
  647. "Audio Data", // status-bar comment
  648. PROP_TYPE_RAW_DATA, // data type (GUID)
  649. PROP_QUAL_NONE, // data type qualifier.
  650. NULL, // labeled bit set
  651. 64, // description's maximum length
  652. FormatPropertyInstance // generic formatter
  653. }
  654. };
  655. enum
  656. {
  657. nNUM_OF_VOICE_PROPS = sizeof(g_arr_VoiceProperties) / sizeof(PROPERTYINFO)
  658. };
  659. // Properties' indices
  660. enum
  661. {
  662. VOICE_SUMMARY = 0,
  663. VOICE_UNPARSABLEFRAGMENT,
  664. VOICE_INCOMPLETEMESSAGE,
  665. VOICE_MESSAGETYPE,
  666. VOICE_MAJORVERSION,
  667. VOICE_MINORVERSION,
  668. VOICE_BUILDVERSION,
  669. VOICE_RESULTCODE,
  670. VOICE_SESSIONTYPE,
  671. VOICE_SESSIONFLAGS_SUMMARY,
  672. VOICE_SESSIONFLAGS,
  673. VOICE_PLAYERFLAGS_SUMMARY,
  674. VOICE_PLAYERFLAGS,
  675. VOICE_NUMBEROFTARGETS,
  676. VOICE_COMPRESSIONTYPE,
  677. VOICE_HOSTORDERID,
  678. VOICE_NUMBEROFPLAYERS,
  679. VOICE_PLAYERLIST_SUMMARY,
  680. VOICE_PLAYERSUMMARY,
  681. VOICE_PLAYERID,
  682. VOICE_TARGETID,
  683. VOICE_MESSAGENUMBER,
  684. VOICE_FRAGMENTNUMBER,
  685. VOICE_AUDIODATA
  686. };
  687. } // anonymous namespace
  688. // DESCRIPTION: Creates and fills-in a properties database for the protocol.
  689. // Network Monitor uses this database to determine which properties the protocol supports.
  690. //
  691. // ARGUMENTS: i_hVoiceProtocol - The handle of the protocol provided by the Network Monitor.
  692. //
  693. // RETURNS: NOTHING
  694. //
  695. DPLAYPARSER_API VOID BHAPI VoiceRegister( HPROTOCOL i_hVoiceProtocol )
  696. {
  697. CreatePropertyDatabase(i_hVoiceProtocol, nNUM_OF_VOICE_PROPS);
  698. // Add the properties to the database
  699. for( int nProp=0; nProp < nNUM_OF_VOICE_PROPS; ++nProp )
  700. {
  701. AddProperty(i_hVoiceProtocol, &g_arr_VoiceProperties[nProp]);
  702. }
  703. } // VoiceRegister
  704. // DESCRIPTION: Frees the resources used to create the protocol property database.
  705. //
  706. // ARGUMENTS: i_hVoiceProtocol - The handle of the protocol provided by the Network Monitor.
  707. //
  708. // RETURNS: NOTHING
  709. //
  710. DPLAYPARSER_API VOID WINAPI VoiceDeregister( HPROTOCOL i_hProtocol )
  711. {
  712. DestroyPropertyDatabase(i_hProtocol);
  713. } // VoiceDeregister
  714. namespace
  715. {
  716. // DESCRIPTION: Parses the Voice frame to find its size (in bytes) NOT including the user data
  717. //
  718. // ARGUMENTS: i_pbVoiceFrame - Pointer to the start of the unclaimed data. Typically, the unclaimed data is located
  719. // in the middle of a frame because a previous parser has claimed data before this parser.
  720. //
  721. // RETURNS: Size of the Voiceecified Voice frame (in bytes)
  722. //
  723. int VoiceHeaderSize( LPBYTE i_pbVoiceFrame )
  724. {
  725. // Check what Voice frame we are dealing with
  726. const DVPROTOCOLMSG_FULLMESSAGE& rVoiceFrame = *reinterpret_cast<DVPROTOCOLMSG_FULLMESSAGE*>(i_pbVoiceFrame);
  727. switch ( rVoiceFrame.dvGeneric.dwType )
  728. {
  729. case DVMSGID_CONNECTREQUEST:
  730. {
  731. return sizeof(rVoiceFrame.dvConnectRequest);
  732. }
  733. case DVMSGID_CONNECTREFUSE:
  734. {
  735. return sizeof(rVoiceFrame.dvConnectRefuse);
  736. }
  737. case DVMSGID_CONNECTACCEPT:
  738. {
  739. return sizeof(rVoiceFrame.dvConnectAccept);
  740. }
  741. case DVMSGID_SETTINGSCONFIRM:
  742. {
  743. return sizeof(rVoiceFrame.dvSettingsConfirm);
  744. }
  745. case DVMSGID_PLAYERLIST:
  746. {
  747. return sizeof(rVoiceFrame.dvPlayerList);
  748. }
  749. case DVMSGID_SPEECH:
  750. {
  751. return sizeof(rVoiceFrame.dvSpeech);
  752. }
  753. case DVMSGID_SPEECHWITHTARGET:
  754. {
  755. return sizeof(rVoiceFrame.dvSpeechWithTarget);
  756. }
  757. case DVMSGID_SPEECHWITHFROM:
  758. {
  759. return sizeof(rVoiceFrame.dvSpeechWithFrom);
  760. }
  761. case DVMSGID_SETTARGETS:
  762. {
  763. return sizeof(rVoiceFrame.dvSetTarget);
  764. }
  765. case DVMSGID_CREATEVOICEPLAYER:
  766. {
  767. return sizeof(rVoiceFrame.dvPlayerJoin);
  768. }
  769. case DVMSGID_DELETEVOICEPLAYER:
  770. {
  771. return sizeof(rVoiceFrame.dvPlayerQuit);
  772. }
  773. case DVMSGID_SESSIONLOST:
  774. {
  775. return sizeof(rVoiceFrame.dvSessionLost);
  776. }
  777. case DVMSGID_DISCONNECTCONFIRM:
  778. case DVMSGID_DISCONNECT:
  779. {
  780. return sizeof(rVoiceFrame.dvDisconnect);
  781. }
  782. default:
  783. {
  784. return -1; // TODO: DPF(0, "Unknown voice frame!");
  785. }
  786. }
  787. } // VoiceHeaderSize
  788. } // Anonymous namespace
  789. // DESCRIPTION: Indicates whether a piece of data is recognized as the protocol that the parser detects.
  790. //
  791. // ARGUMENTS: i_hFrame - The handle to the frame that contains the data.
  792. // i_pbMacFrame - The pointer to the first byte of the frame; the pointer provides a way to view
  793. // the data that the other parsers recognize.
  794. // i_pbVoiceFrame - Pointer to the start of the unclaimed data. Typically, the unclaimed data is located
  795. // in the middle of a frame because a previous parser has claimed data before this parser.
  796. // i_dwMacType - MAC value of the first protocol in a frame. Typically, the i_dwMacType value is used
  797. // when the parser must identify the first protocol in the frame. Can be one of the following:
  798. // MAC_TYPE_ETHERNET = 802.3, MAC_TYPE_TOKENRING = 802.5, MAC_TYPE_FDDI ANSI = X3T9.5.
  799. // i_dwBytesLeft - The remaining number of bytes from a location in the frame to the end of the frame.
  800. // i_hPrevProtocol - Handle of the previous protocol.
  801. // i_dwPrevProtOffset - Offset of the previous protocol (from the beginning of the frame).
  802. // o_pdwProtocolStatus - Protocol status indicator. Must be one of the following: PROTOCOL_STATUS_RECOGNIZED,
  803. // PROTOCOL_STATUS_NOT_RECOGNIZED, PROTOCOL_STATUS_CLAIMED, PROTOCOL_STATUS_NEXT_PROTOCOL.
  804. // o_phNextProtocol - Placeholder for the handle of the next protocol. This parameter is set when the parser identifies
  805. // the protocol that follows its own protocol.
  806. // io_pdwptrInstData - On input, a pointer to the instance data from the previous protocol.
  807. // On output, a pointer to the instance data for the current protocol.
  808. //
  809. // RETURNS: If the function is successful, the return value is a pointer to the first byte after the recognized parser data.
  810. // If the parser claims all the remaining data, the return value is NULL. If the function is unsuccessful, the return
  811. // value is the initial value of the i_pbVoiceFrame parameter.
  812. //
  813. DPLAYPARSER_API LPBYTE BHAPI VoiceRecognizeFrame( HFRAME i_hFrame,
  814. ULPBYTE i_upbMacFrame,
  815. ULPBYTE i_upbyVoiceFrame,
  816. DWORD i_dwMacType,
  817. DWORD i_dwBytesLeft,
  818. HPROTOCOL i_hPrevProtocol,
  819. DWORD i_dwPrevProtOffset,
  820. LPDWORD o_pdwProtocolStatus,
  821. LPHPROTOCOL o_phNextProtocol,
  822. PDWORD_PTR io_pdwptrInstData )
  823. {
  824. // Validate the amount of unclaimed data
  825. enum
  826. {
  827. // TODO: CHANGE TO PROPER MIN SIZE
  828. nMIN_VoiceHeaderSize = sizeof(_DVPROTOCOLMSG_GENERIC),
  829. nNUMBER_OF_MSG_TYPES = sizeof(g_arr_MessageTypeByteLabels) / sizeof(LABELED_BYTE)
  830. };
  831. for ( int nTypeIndex = 0; nTypeIndex < nNUMBER_OF_MSG_TYPES; ++nTypeIndex )
  832. {
  833. if ( g_arr_MessageTypeByteLabels[nTypeIndex].Value == *i_upbyVoiceFrame )
  834. {
  835. break;
  836. }
  837. }
  838. // Validate the packet as DPlay Session type
  839. if ( ((i_dwBytesLeft >= nMIN_VoiceHeaderSize) && (nTypeIndex < nNUMBER_OF_MSG_TYPES)) || (*io_pdwptrInstData == 0) )
  840. {
  841. // Claim the remaining data
  842. *o_pdwProtocolStatus = PROTOCOL_STATUS_CLAIMED;
  843. return NULL;
  844. }
  845. // Assume the unclaimed data is not recognizable
  846. *o_pdwProtocolStatus = PROTOCOL_STATUS_NOT_RECOGNIZED;
  847. return i_upbyVoiceFrame;
  848. } // VoiceRecognizeFrame
  849. // DESCRIPTION: Maps the properties that exist in a piece of recognized data to Voiceecific locations.
  850. //
  851. // ARGUMENTS: i_hFrame - Handle of the frame that is being parsed.
  852. // i_pbMacFram - Pointer to the first byte in the frame.
  853. // i_pbVoiceFrame - Pointer to the start of the recognized data.
  854. // i_dwMacType - MAC value of the first protocol in a frame. Typically, the i_dwMacType value is used
  855. // when the parser must identify the first protocol in the frame. Can be one of the following:
  856. // MAC_TYPE_ETHERNET = 802.3, MAC_TYPE_TOKENRING = 802.5, MAC_TYPE_FDDI ANSI = X3T9.5.
  857. // i_dwBytesLeft - The remaining number of bytes in a frame (starting from the beginning of the recognized data).
  858. // i_hPrevProtocol - Handle of the previous protocol.
  859. // i_dwPrevProtOffset - Offset of the previous protocol (starting from the beginning of the frame).
  860. // i_dwptrInstData - Pointer to the instance data that the previous protocol provides.
  861. //
  862. // RETURNS: Must return NULL
  863. //
  864. DPLAYPARSER_API LPBYTE BHAPI VoiceAttachProperties( HFRAME i_hFrame,
  865. ULPBYTE i_upbyMacFrame,
  866. ULPBYTE i_upbyVoiceFrame,
  867. DWORD i_dwMacType,
  868. DWORD i_dwBytesLeft,
  869. HPROTOCOL i_hPrevProtocol,
  870. DWORD i_dwPrevProtOffset,
  871. DWORD_PTR i_dwptrInstData )
  872. {
  873. //===================//
  874. // Attach Properties //
  875. //===================//
  876. if ( i_dwptrInstData == 0 )
  877. {
  878. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_UNPARSABLEFRAGMENT].hProperty,
  879. i_dwBytesLeft, i_upbyVoiceFrame, 0, 0, 0);
  880. return NULL;
  881. }
  882. // Summary line
  883. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_SUMMARY].hProperty,
  884. VoiceHeaderSize(i_upbyVoiceFrame), i_upbyVoiceFrame, 0, 0, 0);
  885. // Check what Voice frame we are dealing with
  886. DVPROTOCOLMSG_FULLMESSAGE& rVoiceFrame = *reinterpret_cast<DVPROTOCOLMSG_FULLMESSAGE*>(i_upbyVoiceFrame);
  887. // Message type field
  888. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_MESSAGETYPE].hProperty,
  889. sizeof(rVoiceFrame.dvGeneric.dwType), &rVoiceFrame.dvGeneric.dwType, 0, 1, 0);
  890. __try
  891. {
  892. switch ( rVoiceFrame.dvGeneric.dwType )
  893. {
  894. case DVMSGID_CONNECTREQUEST:
  895. {
  896. // Major Version field
  897. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_MAJORVERSION].hProperty,
  898. sizeof(rVoiceFrame.dvConnectRequest.ucVersionMajor), &rVoiceFrame.dvConnectRequest.ucVersionMajor, 0, 1, 0);
  899. // Minor Version field
  900. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_MINORVERSION].hProperty,
  901. sizeof(rVoiceFrame.dvConnectRequest.ucVersionMinor), &rVoiceFrame.dvConnectRequest.ucVersionMinor, 0, 1, 0);
  902. // Build Version field
  903. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_BUILDVERSION].hProperty,
  904. sizeof(rVoiceFrame.dvConnectRequest.dwVersionBuild), &rVoiceFrame.dvConnectRequest.dwVersionBuild, 0, 1, 0);
  905. break;
  906. }
  907. case DVMSGID_CONNECTREFUSE:
  908. {
  909. // Result Code field
  910. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_RESULTCODE].hProperty,
  911. sizeof(rVoiceFrame.dvConnectRefuse.hresResult), &rVoiceFrame.dvConnectRefuse.hresResult, 0, 1, 0);
  912. // Major Version field
  913. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_MAJORVERSION].hProperty,
  914. sizeof(rVoiceFrame.dvConnectRefuse.ucVersionMajor), &rVoiceFrame.dvConnectRefuse.ucVersionMajor, 0, 1, 0);
  915. // Minor Version field
  916. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_MINORVERSION].hProperty,
  917. sizeof(rVoiceFrame.dvConnectRefuse.ucVersionMinor), &rVoiceFrame.dvConnectRefuse.ucVersionMinor, 0, 1, 0);
  918. // Build Version field
  919. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_BUILDVERSION].hProperty,
  920. sizeof(rVoiceFrame.dvConnectRefuse.dwVersionBuild), &rVoiceFrame.dvConnectRefuse.dwVersionBuild, 0, 1, 0);
  921. break;
  922. }
  923. case DVMSGID_CONNECTACCEPT:
  924. {
  925. // Session Type field
  926. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_SESSIONTYPE].hProperty,
  927. sizeof(rVoiceFrame.dvConnectAccept.dwSessionType), &rVoiceFrame.dvConnectAccept.dwSessionType, 0, 1, 0);
  928. // Major Version field
  929. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_MAJORVERSION].hProperty,
  930. sizeof(rVoiceFrame.dvConnectAccept.ucVersionMajor), &rVoiceFrame.dvConnectAccept.ucVersionMajor, 0, 1, 0);
  931. // Minor Version field
  932. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_MINORVERSION].hProperty,
  933. sizeof(rVoiceFrame.dvConnectAccept.ucVersionMinor), &rVoiceFrame.dvConnectAccept.ucVersionMinor, 0, 1, 0);
  934. // Build Version field
  935. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_BUILDVERSION].hProperty,
  936. sizeof(rVoiceFrame.dvConnectAccept.dwVersionBuild), &rVoiceFrame.dvConnectAccept.dwVersionBuild, 0, 1, 0);
  937. // Session Flags summary
  938. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_SESSIONFLAGS_SUMMARY].hProperty,
  939. sizeof(rVoiceFrame.dvConnectAccept.dwSessionFlags), &rVoiceFrame.dvConnectAccept.dwSessionFlags, 0, 1, 0);
  940. // Session Flags field
  941. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_SESSIONFLAGS].hProperty,
  942. sizeof(rVoiceFrame.dvConnectAccept.dwSessionFlags), &rVoiceFrame.dvConnectAccept.dwSessionFlags, 0, 2, 0);
  943. // Compression Type field
  944. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_COMPRESSIONTYPE].hProperty,
  945. sizeof(rVoiceFrame.dvConnectAccept.guidCT), &rVoiceFrame.dvConnectAccept.guidCT, 0, 1, 0);
  946. break;
  947. }
  948. case DVMSGID_SETTINGSCONFIRM:
  949. {
  950. // Player's Flags summary
  951. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_PLAYERFLAGS_SUMMARY].hProperty,
  952. sizeof(rVoiceFrame.dvSettingsConfirm.dwFlags), &rVoiceFrame.dvSettingsConfirm.dwFlags, 0, 1, 0);
  953. // Client Flags field
  954. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_PLAYERFLAGS].hProperty,
  955. sizeof(rVoiceFrame.dvSettingsConfirm.dwFlags), &rVoiceFrame.dvSettingsConfirm.dwFlags, 0, 2, 0);
  956. // Host Migration Sequence Number field
  957. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_HOSTORDERID].hProperty,
  958. sizeof(rVoiceFrame.dvSettingsConfirm.dwHostOrderID), &rVoiceFrame.dvSettingsConfirm.dwHostOrderID, 0, 1, 0);
  959. break;
  960. }
  961. case DVMSGID_PLAYERLIST:
  962. {
  963. // Host Order ID field
  964. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_HOSTORDERID].hProperty,
  965. sizeof(rVoiceFrame.dvPlayerList.dwHostOrderID), &rVoiceFrame.dvPlayerList.dwHostOrderID, 0, 1, 0);
  966. // Number of Players field
  967. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_NUMBEROFPLAYERS].hProperty,
  968. sizeof(rVoiceFrame.dvPlayerList.dwNumEntries), &rVoiceFrame.dvPlayerList.dwNumEntries, 0, 1, 0);
  969. // Player entries are following after the header
  970. DVPROTOCOLMSG_PLAYERLIST_ENTRY* pPlayerEntry =
  971. reinterpret_cast<DVPROTOCOLMSG_PLAYERLIST_ENTRY*>(&rVoiceFrame.dvPlayerList + 1);
  972. // Make sure the list doesn't overflow the boundaries of the frame
  973. DWORD dwNumEntries = rVoiceFrame.dvPlayerList.dwNumEntries;
  974. if ( reinterpret_cast<LPBYTE>(pPlayerEntry + dwNumEntries) - i_upbyVoiceFrame > static_cast<int>(i_dwBytesLeft) )
  975. {
  976. break;
  977. }
  978. // Player list summary
  979. AttachPropertyInstanceEx(i_hFrame, g_arr_VoiceProperties[VOICE_PLAYERLIST_SUMMARY].hProperty,
  980. dwNumEntries * sizeof(*pPlayerEntry), pPlayerEntry,
  981. sizeof(DWORD), &dwNumEntries,
  982. 0, 1, 0);
  983. // For every player entry in the list
  984. for ( int nEntry = 1; nEntry <= dwNumEntries; ++nEntry, ++pPlayerEntry )
  985. {
  986. // Player's summary
  987. struct
  988. {
  989. DWORD dwPlayerNum;
  990. DWORD dwTotalPlayer;
  991. }
  992. PlayerEntryData = { nEntry, dwNumEntries };
  993. AttachPropertyInstanceEx(i_hFrame, g_arr_VoiceProperties[VOICE_PLAYERSUMMARY].hProperty,
  994. sizeof(*pPlayerEntry), pPlayerEntry,
  995. sizeof(PlayerEntryData), &PlayerEntryData,
  996. 0, 2, 0);
  997. // Player's ID field
  998. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_PLAYERID].hProperty,
  999. sizeof(pPlayerEntry->dvidID), &pPlayerEntry->dvidID, 0, 3, 0);
  1000. // Player's Flags summary
  1001. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_PLAYERFLAGS_SUMMARY].hProperty,
  1002. sizeof(pPlayerEntry->dwPlayerFlags), &pPlayerEntry->dwPlayerFlags, 0, 3, 0);
  1003. // Player's Flags field
  1004. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_PLAYERFLAGS].hProperty,
  1005. sizeof(pPlayerEntry->dwPlayerFlags), &pPlayerEntry->dwPlayerFlags, 0, 4, 0);
  1006. // Host Migration Sequence Number field
  1007. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_HOSTORDERID].hProperty,
  1008. sizeof(pPlayerEntry->dwHostOrderID), &pPlayerEntry->dwHostOrderID, 0, 3, 0);
  1009. }
  1010. break;
  1011. }
  1012. case DVMSGID_SPEECH:
  1013. {
  1014. // Message Number field
  1015. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_MESSAGENUMBER].hProperty,
  1016. sizeof(rVoiceFrame.dvSpeech.bMsgNum), &rVoiceFrame.dvSpeech.bMsgNum, 0, 1, 0);
  1017. // Sequence Number field
  1018. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_FRAGMENTNUMBER].hProperty,
  1019. sizeof(rVoiceFrame.dvSpeech.bSeqNum), &rVoiceFrame.dvSpeech.bSeqNum, 0, 1, 0);
  1020. // Audio Data
  1021. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_AUDIODATA].hProperty,
  1022. i_dwBytesLeft-sizeof(rVoiceFrame.dvSpeech), &rVoiceFrame.dvSpeech + 1, 0, 1, 0);
  1023. break;
  1024. }
  1025. case DVMSGID_SPEECHWITHTARGET:
  1026. {
  1027. // Message Number field
  1028. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_MESSAGENUMBER].hProperty,
  1029. sizeof(rVoiceFrame.dvSpeechWithTarget.dvHeader.bMsgNum), &rVoiceFrame.dvSpeechWithTarget.dvHeader.bMsgNum, 0, 1, 0);
  1030. // Sequence Number field
  1031. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_FRAGMENTNUMBER].hProperty,
  1032. sizeof(rVoiceFrame.dvSpeechWithTarget.dvHeader.bSeqNum), &rVoiceFrame.dvSpeechWithTarget.dvHeader.bSeqNum, 0, 1, 0);
  1033. // Number of Targets field
  1034. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_NUMBEROFTARGETS].hProperty,
  1035. sizeof(rVoiceFrame.dvSpeechWithTarget.dwNumTargets), &rVoiceFrame.dvSpeechWithTarget.dwNumTargets, 0, 1, 0);
  1036. // Target ID entries are following after the header
  1037. DVID* pTargetID = reinterpret_cast<DVID*>(&rVoiceFrame.dvSpeechWithTarget + 1);
  1038. // Make sure the list doesn't overflow the boundaries of the frame
  1039. int nNumTargets = rVoiceFrame.dvSpeechWithTarget.dwNumTargets;
  1040. if ( reinterpret_cast<LPBYTE>(pTargetID + nNumTargets) - i_upbyVoiceFrame > static_cast<int>(i_dwBytesLeft) )
  1041. {
  1042. break;
  1043. }
  1044. // For every target ID entry in the list...
  1045. for ( ; nNumTargets; --nNumTargets, ++pTargetID )
  1046. {
  1047. // Target's ID field
  1048. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_TARGETID].hProperty,
  1049. sizeof(*pTargetID), pTargetID, 0, 1, 0);
  1050. }
  1051. // Audio Data
  1052. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_AUDIODATA].hProperty,
  1053. i_dwBytesLeft-sizeof(rVoiceFrame.dvSpeechWithTarget), &rVoiceFrame.dvSpeechWithTarget + 1, 0, 1, 0);
  1054. break;
  1055. }
  1056. case DVMSGID_SPEECHWITHFROM:
  1057. {
  1058. // Message Number field
  1059. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_MESSAGENUMBER].hProperty,
  1060. sizeof(rVoiceFrame.dvSpeechWithFrom.dvHeader.bMsgNum), &rVoiceFrame.dvSpeechWithFrom.dvHeader.bMsgNum, 0, 1, 0);
  1061. // Sequence Number field
  1062. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_FRAGMENTNUMBER].hProperty,
  1063. sizeof(rVoiceFrame.dvSpeechWithFrom.dvHeader.bSeqNum), &rVoiceFrame.dvSpeechWithFrom.dvHeader.bSeqNum, 0, 1, 0);
  1064. // Speaking Player's ID field
  1065. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_PLAYERID].hProperty,
  1066. sizeof(rVoiceFrame.dvSpeechWithFrom.dvidFrom), &rVoiceFrame.dvSpeechWithFrom.dvidFrom, 0, 1, 0);
  1067. // Audio Data
  1068. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_AUDIODATA].hProperty,
  1069. i_dwBytesLeft-sizeof(rVoiceFrame.dvSpeechWithFrom),
  1070. &rVoiceFrame.dvSpeechWithFrom + 1, 0, 1, 0);
  1071. break;
  1072. }
  1073. case DVMSGID_SETTARGETS:
  1074. {
  1075. // Number of Targets field
  1076. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_NUMBEROFTARGETS].hProperty,
  1077. sizeof(rVoiceFrame.dvSetTarget.dwNumTargets), &rVoiceFrame.dvSetTarget.dwNumTargets, 0, 1, 0);
  1078. break;
  1079. }
  1080. case DVMSGID_CREATEVOICEPLAYER:
  1081. {
  1082. // Player ID field
  1083. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_PLAYERID].hProperty,
  1084. sizeof(rVoiceFrame.dvPlayerJoin.dvidID), &rVoiceFrame.dvPlayerJoin.dvidID, 0, 1, 0);
  1085. // Player's Flags summary
  1086. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_PLAYERFLAGS_SUMMARY].hProperty,
  1087. sizeof(rVoiceFrame.dvPlayerJoin.dwFlags), &rVoiceFrame.dvPlayerJoin.dwFlags, 0, 1, 0);
  1088. // Player's Flags field
  1089. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_PLAYERFLAGS].hProperty,
  1090. sizeof(rVoiceFrame.dvPlayerJoin.dwFlags), &rVoiceFrame.dvPlayerJoin.dwFlags, 0, 2, 0);
  1091. // Host Order ID field
  1092. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_HOSTORDERID].hProperty,
  1093. sizeof(rVoiceFrame.dvPlayerJoin.dwHostOrderID), &rVoiceFrame.dvPlayerJoin.dwHostOrderID, 0, 1, 0);
  1094. break;
  1095. }
  1096. case DVMSGID_DELETEVOICEPLAYER:
  1097. {
  1098. // Player ID field
  1099. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_PLAYERID].hProperty,
  1100. sizeof(rVoiceFrame.dvPlayerJoin.dvidID), &rVoiceFrame.dvPlayerJoin.dvidID, 0, 1, 0);
  1101. break;
  1102. }
  1103. case DVMSGID_SESSIONLOST:
  1104. {
  1105. // Result Code field
  1106. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_RESULTCODE].hProperty,
  1107. sizeof(rVoiceFrame.dvSessionLost.hresReason), &rVoiceFrame.dvSessionLost.hresReason, 0, 1, 0);
  1108. break;
  1109. }
  1110. case DVMSGID_DISCONNECTCONFIRM:
  1111. case DVMSGID_DISCONNECT:
  1112. {
  1113. // Result Code field
  1114. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_RESULTCODE].hProperty,
  1115. sizeof(rVoiceFrame.dvDisconnect.hresDisconnect), &rVoiceFrame.dvDisconnect.hresDisconnect, 0, 1, 0);
  1116. break;
  1117. }
  1118. default:
  1119. {
  1120. break; // TODO: DPF(0, "Unknown voice frame!");
  1121. }
  1122. }
  1123. }
  1124. __except ( GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH )
  1125. {
  1126. AttachPropertyInstance(i_hFrame, g_arr_VoiceProperties[VOICE_INCOMPLETEMESSAGE].hProperty,
  1127. i_dwBytesLeft, i_upbyVoiceFrame, 0, 1, 0);
  1128. }
  1129. return NULL;
  1130. } // VoiceAttachProperties
  1131. // DESCRIPTION: Formats the data that is diVoicelayed in the details pane of the Network Monitor UI.
  1132. //
  1133. // ARGUMENTS: i_hFrame - Handle of the frame that is being parsed.
  1134. // i_pbMacFrame - Pointer to the first byte of a frame.
  1135. // i_pbCoreFrame - Pointer to the beginning of the protocol data in a frame.
  1136. // i_dwPropertyInsts - Number of PROPERTYINST structures provided by lpPropInst.
  1137. // i_pPropInst - Pointer to an array of PROPERTYINST structures.
  1138. //
  1139. // RETURNS: If the function is successful, the return value is a pointer to the first byte after the recognized data in a frame,
  1140. // or NULL if the recognized data is the last piece of data in a frame. If the function is unsuccessful, the return value
  1141. // is the initial value of i_upbyVoiceFrame.
  1142. //
  1143. DPLAYPARSER_API DWORD BHAPI VoiceFormatProperties( HFRAME i_hFrame,
  1144. ULPBYTE i_upbyMacFrame,
  1145. ULPBYTE i_upbyVoiceFrame,
  1146. DWORD i_dwPropertyInsts,
  1147. LPPROPERTYINST i_pPropInst )
  1148. {
  1149. // Loop through the property instances...
  1150. while( i_dwPropertyInsts-- > 0)
  1151. {
  1152. // ...and call the formatter for each
  1153. reinterpret_cast<FORMAT>(i_pPropInst->lpPropertyInfo->InstanceData)(i_pPropInst);
  1154. ++i_pPropInst;
  1155. }
  1156. // TODO: MAKE SURE THIS SHOULD NOT BE TRUE
  1157. return NMERR_SUCCESS;
  1158. } // VoiceFormatProperties
  1159. // DESCRIPTION: Notifies Network Monitor that DNET protocol parser exists.
  1160. //
  1161. // ARGUMENTS: NONE
  1162. //
  1163. // RETURNS: TRUE - success, FALSE - failure
  1164. //
  1165. bool CreateVoiceProtocol( void )
  1166. {
  1167. // The entry points to the export functions that Network Monitor uses to operate the parser
  1168. ENTRYPOINTS VoiceEntryPoints =
  1169. {
  1170. // VoiceParser Entry Points
  1171. VoiceRegister,
  1172. VoiceDeregister,
  1173. VoiceRecognizeFrame,
  1174. VoiceAttachProperties,
  1175. VoiceFormatProperties
  1176. };
  1177. // The first active instance of this parser needs to register with the kernel
  1178. g_hVoiceProtocol = CreateProtocol("DPLAYVOICE", &VoiceEntryPoints, ENTRYPOINTS_SIZE);
  1179. return (g_hVoiceProtocol ? TRUE : FALSE);
  1180. } // CreateVoiceProtocol
  1181. // DESCRIPTION: Removes the DNET protocol parser from the Network Monitor's database of parsers
  1182. //
  1183. // ARGUMENTS: NONE
  1184. //
  1185. // RETURNS: NOTHING
  1186. //
  1187. void DestroyVoiceProtocol( void )
  1188. {
  1189. DestroyProtocol(g_hVoiceProtocol);
  1190. } // DestroyVoiceProtocol