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.

1856 lines
67 KiB

  1. //=============================================================================
  2. // FILE: TransportParser.cpp
  3. //
  4. // Description: DPlay v8 Transport protocol parser
  5. //
  6. //
  7. // Modification History:
  8. //
  9. // Michael Milirud 08/Aug/2000 Created
  10. //=============================================================================
  11. // uncomment to enable full parsing of DPlay Transport layer
  12. //#define PARSE_DPLAY_TRANSPORT
  13. //==================//
  14. // Standard headers //
  15. //==================//
  16. #include <string>
  17. //=====================//
  18. // Proprietary headers //
  19. //=====================//
  20. // Prototypes
  21. #include "TransportParser.hpp"
  22. // Transport protocol header
  23. #include "Frames.h"
  24. typedef UNALIGNED struct dataframe_big DFBIG, *PDFBIG;
  25. typedef UNALIGNED struct sackframe_big8 SFBIG8, *PSFBIG8;
  26. struct dataframe_big
  27. {
  28. BYTE bCommand;
  29. BYTE bControl;
  30. BYTE bSeq;
  31. BYTE bNRcv;
  32. ULONG rgMask[4];
  33. };
  34. struct sackframe_big8
  35. {
  36. BYTE bCommand; // As above
  37. BYTE bExtOpcode; // As above
  38. BYTE bFlags; // Additional flags for sack frame
  39. BYTE bRetry;
  40. BYTE bNSeq; // Since this frame has no sequence number, this is the next Seq we
  41. BYTE bNRcv; // As above
  42. BYTE bReserved1; // We shipped DX8 with bad packing, so these were actually there
  43. BYTE bReserved2; // We shipped DX8 with bad packing, so these were actually there
  44. DWORD tTimestamp; // Local stamp when packet arrived
  45. ULONG rgMask[4];
  46. };
  47. namespace
  48. {
  49. HPROTOCOL g_hTransportProtocol;
  50. typedef __int64 QWORD;
  51. //================//
  52. // DCommand field //-------------------------------------------------------------------------------------------------
  53. //================//
  54. LABELED_BIT g_arr_DCommandBitLabels[] =
  55. { { 0, "INVALID", "Dataframe" }, // PACKET_COMMAND_DATA
  56. { 1, "Unreliable", "Reliable" }, // PACKET_COMMAND_RELIABLE
  57. { 2, "Nonsequenced", "Sequenced" }, // PACKET_COMMAND_SEQUENTIAL
  58. { 3, "ACK can be delayed", "ACK now" }, // PACKET_COMMAND_POLL
  59. { 4, "Not the first fragment of the message", "First fragment of the message" }, // PACKET_COMMAND_NEW_MSG
  60. { 5, "Not the last fragment of the message", "Last fragment of the message" }, // PACKET_COMMAND_END_MSG
  61. { 6, "User packet", "DirectPlay packet" }, // PACKET_COMMAND_USER_1
  62. { 7, "Data packet", "Voice packet" } }; // PACKET_COMMAND_USER_2
  63. SET g_LabeledDCommandBitSet = { sizeof(g_arr_DCommandBitLabels) / sizeof(LABELED_BIT), g_arr_DCommandBitLabels };
  64. //===============//
  65. // Control field //--------------------------------------------------------------------------------------------------
  66. //===============//
  67. LABELED_BIT g_arr_ControlBitLabels[] =
  68. { { 0, "Original (not a retry)", "Retry" }, // PACKET_CONTROL_RETRY
  69. { 1, "Don't correlate", "Correlate" }, // PACKET_CONTROL_CORRELATE
  70. { 2, "Not a correlation response", "Correlation response" }, // PACKET_CONTROL_RESPONSE
  71. { 3, "Not the last packet in the stream", "Last packet in the stream" }, // PACKET_CONTROL_END_STREAM
  72. { 4, "Low DWORD of the RCVD mask is zero", "Low DWORD of the RCVD mask is nonzero" }, // PACKET_CONTROL_SACK_MASK1
  73. { 5, "High DWORD of the RCVD mask is zero", "High DWORD of the RCVD mask is nonzero" }, // PACKET_CONTROL_SACK_MASK2
  74. { 6, "Low DWORD of the DON'T CARE mask is zero", "Low DWORD of the DON'T CARE mask is nonzero" }, // PACKET_CONTROL_SEND_MASK1
  75. { 7, "High DWORD of the DON'T CARE mask is zero", "High DWORD of the DON'T CARE mask is nonzero" } }; // PACKET_CONTROL_SEND_MASK2
  76. SET g_LabeledControlBitSet = { sizeof(g_arr_ControlBitLabels) / sizeof(LABELED_BIT), g_arr_ControlBitLabels };
  77. //================//
  78. // CCommand field //-------------------------------------------------------------------------------------------------
  79. //================//
  80. LABELED_BIT g_arr_CCommandBitLabels[] =
  81. { { 0, "Command Frame (1/2)", "INVALID" }, // PACKET_COMMAND_DATA
  82. { 1, "Unreliable", "Reliable" }, // PACKET_COMMAND_RELIABLE
  83. { 2, "Nonsequenced", "Sequenced" }, // PACKET_COMMAND_SEQUENTIAL
  84. { 3, "ACK can be delayed", "ACK now" }, // PACKET_COMMAND_POLL
  85. { 4, "RESERVED", "RESERVED" },
  86. { 5, "RESERVED", "RESERVED" },
  87. { 6, "RESERVED", "RESERVED" },
  88. { 7, "INVALID", "Command Frame (2/2)" } };
  89. SET g_LabeledCCommandBitSet = { sizeof(g_arr_CCommandBitLabels) / sizeof(LABELED_BIT), g_arr_CCommandBitLabels };
  90. //=======================//
  91. // Extended Opcode field //------------------------------------------------------------------------------------------
  92. //=======================//
  93. LABELED_BYTE g_arr_ExOpcodeByteLabels[] = {
  94. { FRAME_EXOPCODE_CONNECT, "Establish a connection" },
  95. { FRAME_EXOPCODE_CONNECTED, "Connection request has been accepted" },
  96. { FRAME_EXOPCODE_HARD_DISCONNECT, "Connection has been hard disconnected" },
  97. { FRAME_EXOPCODE_SACK, "Selective Acknowledgement" } };
  98. SET g_LabeledExOpcodeByteSet = { sizeof(g_arr_ExOpcodeByteLabels) / sizeof(LABELED_BYTE), g_arr_ExOpcodeByteLabels };
  99. //==================//
  100. // SACK flags field //-----------------------------------------------------------------------------------------------
  101. //==================//
  102. LABELED_BIT g_arr_SACKFlagsBitLabels[] =
  103. { { 0, "Retry and/or Timestamp fields are invalid", "Retry and Timestamp fields are valid" }, // SACK_FLAGS_RESPONSE
  104. { 1, "Low DWORD of the RCVD mask is not present", "Low DWORD of the RCVD mask is present" }, // SACK_FLAGS_SACK_MASK1
  105. { 2, "High DWORD of the RCVD mask is not present", "High DWORD of the RCVD mask is present" }, // SACK_FLAGS_SACK_MASK2
  106. { 3, "Low DWORD of the DON'T CARE mask is not present", "Low DWORD of the DON'T CARE mask is present" }, // SACK_FLAGS_SEND_MASK1
  107. { 4, "High DWORD of the DON'T CARE mask is not present", "High DWORD of the DON'T CARE mask is present" } }; // SACK_FLAGS_SEND_MASK2
  108. SET g_LabeledSACKFlagsBitSet = { sizeof(g_arr_SACKFlagsBitLabels) / sizeof(LABELED_BIT), g_arr_SACKFlagsBitLabels };
  109. //==================//
  110. // Helper functions //===========================================================================
  111. //==================//
  112. enum BitmaskPart { LOW = 0, HIGH, ENTIRE };
  113. enum BitmaskType { RCVD, DONTCARE };
  114. std::string InterpretRCVDBitmask( BitmaskPart i_Part, BYTE i_byBase, UNALIGNED DWORD* i_pdwBitmask )
  115. {
  116. std::string strSummary = "Received Seq=";
  117. // [i_bBase+1 .. i_bBase+1+LENGTH]
  118. // RCVD bitmask doesn't include the base value, since receiver can't claim it didn't receive the next dataframe to be received (NRcv);
  119. if ( i_Part == HIGH )
  120. {
  121. // NOTE: +1 is needed to cross from MSB of the first DWORD TO LSB of the second
  122. i_byBase += 8*sizeof(DWORD)+1; // shift to LSB of the second DWORD
  123. }
  124. else
  125. {
  126. ++i_byBase;
  127. }
  128. QWORD qwBitMask = *i_pdwBitmask;
  129. if ( i_Part == ENTIRE )
  130. {
  131. qwBitMask |= *(i_pdwBitmask+1);
  132. }
  133. strSummary += "{";
  134. bool bFirst = true;
  135. // Processing from LSB to MSB
  136. for ( ; qwBitMask; qwBitMask >>= 1, ++i_byBase )
  137. {
  138. if ( qwBitMask & 1 )
  139. {
  140. if ( bFirst )
  141. {
  142. bFirst = false;
  143. }
  144. else
  145. {
  146. strSummary += ", ";
  147. }
  148. char arr_cBuffer[10];
  149. strSummary += _itoa(i_byBase, arr_cBuffer, 16);
  150. }
  151. }
  152. strSummary += "}";
  153. return strSummary;
  154. }// InterpretRCVDBitmask
  155. std::string InterpretDONTCAREBitmask( BitmaskPart i_Part, BYTE i_byBase, UNALIGNED DWORD* i_pdwBitmask )
  156. {
  157. std::string strSummary = "Cancelling Seq=";
  158. // [i_bBase-1-LENGTH .. i_bBase-1]
  159. // DON'T CARE doesn't include the base value, since transmitter can't resend/refuse resending a dataframe which is about to be sent next (NSeq).
  160. if ( i_Part == LOW )
  161. {
  162. i_byBase -= 8*sizeof(DWORD); // shift to MSB of the first DWORD
  163. }
  164. else
  165. {
  166. i_byBase -= 8*sizeof(QWORD); // shift to MSB of the second DWORD
  167. }
  168. QWORD qwBitMask = *i_pdwBitmask;
  169. if ( i_Part == ENTIRE )
  170. {
  171. qwBitMask |= *(i_pdwBitmask+1);
  172. }
  173. else
  174. {
  175. // QWORD.High = QWORD.Low; QWORD.Low = 0;
  176. qwBitMask <<= 8*sizeof(DWORD);
  177. }
  178. strSummary += "{";
  179. bool bFirst = true;
  180. // Processing from MSB to LSB
  181. for ( ; qwBitMask; ++i_byBase, qwBitMask <<= 1 )
  182. {
  183. if ( qwBitMask & 0x8000000000000000 )
  184. {
  185. if ( bFirst )
  186. {
  187. bFirst = false;
  188. }
  189. else
  190. {
  191. strSummary += ", ";
  192. }
  193. char arr_cBuffer[10];
  194. strSummary += _itoa(i_byBase, arr_cBuffer, 16);
  195. }
  196. }
  197. strSummary += "}";
  198. return strSummary;
  199. }// InterpretDONTCAREBitmask
  200. ////////////////////////////////
  201. // Custom Property Formatters //======================================================================================
  202. ////////////////////////////////
  203. // DESCRIPTION: Custom description formatter for the Transport packet summary
  204. //
  205. // ARGUMENTS: io_pProperyInstance - Data of the property's instance
  206. //
  207. // RETURNS: NOTHING
  208. //
  209. VOID WINAPIV FormatPropertyInstance_TransportSummary( LPPROPERTYINST io_pProperyInstance )
  210. {
  211. std::string strSummary;
  212. char arr_cBuffer[10];
  213. DFBIG& rDBigFrame = *reinterpret_cast<DFBIG*>(io_pProperyInstance->lpPropertyInstEx->lpData);
  214. if ( (rDBigFrame.bCommand & PACKET_COMMAND_DATA) == PACKET_COMMAND_DATA ) // DFrame
  215. {
  216. if ( *reinterpret_cast<BOOL*>(io_pProperyInstance->lpPropertyInstEx->Dword) )
  217. {
  218. strSummary = "KeepAlive";
  219. }
  220. else if ( (rDBigFrame.bCommand & PACKET_COMMAND_USER_2) == PACKET_COMMAND_USER_2 )
  221. {
  222. strSummary = "Voice";
  223. }
  224. else
  225. {
  226. strSummary = "User data";
  227. }
  228. #if defined(PARSE_DPLAY_TRANSPORT)
  229. strSummary += " : Seq=";
  230. strSummary += _itoa(rDBigFrame.bSeq, arr_cBuffer, 16);
  231. strSummary += ", NRcv=";
  232. strSummary += _itoa(rDBigFrame.bNRcv, arr_cBuffer, 16);
  233. #endif // PARSE_DPLAY_TRANSPORT
  234. if ( (rDBigFrame.bCommand & PACKET_COMMAND_NEW_MSG) == PACKET_COMMAND_NEW_MSG )
  235. {
  236. if ( (rDBigFrame.bCommand & PACKET_COMMAND_END_MSG) != PACKET_COMMAND_END_MSG )
  237. {
  238. strSummary += ", First fragment";
  239. }
  240. }
  241. else if ( (rDBigFrame.bCommand & PACKET_COMMAND_END_MSG) == PACKET_COMMAND_END_MSG )
  242. {
  243. strSummary += ", Last fragment";
  244. }
  245. if ( (rDBigFrame.bControl & PACKET_CONTROL_END_STREAM) == PACKET_CONTROL_END_STREAM )
  246. {
  247. strSummary += ", End of Stream";
  248. }
  249. if ( (rDBigFrame.bCommand & PACKET_COMMAND_POLL) == PACKET_COMMAND_POLL )
  250. {
  251. strSummary += ", ACK now";
  252. }
  253. if ( (rDBigFrame.bControl & PACKET_CONTROL_RETRY) == PACKET_CONTROL_RETRY )
  254. {
  255. strSummary += ", Retry";
  256. }
  257. if ( (rDBigFrame.bControl & PACKET_CONTROL_CORRELATE) == PACKET_CONTROL_CORRELATE )
  258. {
  259. strSummary += ", Correlate / Keep Alive";
  260. }
  261. int nBitMaskIndex = 0;
  262. if ( (rDBigFrame.bControl & PACKET_CONTROL_SACK_MASK1) == PACKET_CONTROL_SACK_MASK1 )
  263. {
  264. strSummary += ", ";
  265. if ( (rDBigFrame.bControl & PACKET_CONTROL_SACK_MASK2) == PACKET_CONTROL_SACK_MASK2 ) // Entire QWORD
  266. {
  267. strSummary += InterpretRCVDBitmask(ENTIRE, rDBigFrame.bNRcv, &rDBigFrame.rgMask[nBitMaskIndex]);
  268. nBitMaskIndex += 2;
  269. }
  270. else // Low DWORD only
  271. {
  272. strSummary += InterpretRCVDBitmask(LOW, rDBigFrame.bNRcv, &rDBigFrame.rgMask[nBitMaskIndex]);
  273. ++nBitMaskIndex;
  274. }
  275. }
  276. else if ( (rDBigFrame.bControl & PACKET_CONTROL_SACK_MASK2) == PACKET_CONTROL_SACK_MASK2 ) // High DWORD only
  277. {
  278. strSummary += ", " + InterpretRCVDBitmask(HIGH, rDBigFrame.bNRcv, &rDBigFrame.rgMask[nBitMaskIndex]);
  279. ++nBitMaskIndex;
  280. }
  281. if ( (rDBigFrame.bControl & PACKET_CONTROL_SEND_MASK1) == PACKET_CONTROL_SEND_MASK1 )
  282. {
  283. strSummary += ", ";
  284. if ( (rDBigFrame.bControl & PACKET_CONTROL_SEND_MASK2) == PACKET_CONTROL_SEND_MASK2 ) // Entire QWORD
  285. {
  286. strSummary += InterpretDONTCAREBitmask(ENTIRE, rDBigFrame.bSeq, &rDBigFrame.rgMask[nBitMaskIndex]);
  287. }
  288. else // Low DWORD only
  289. {
  290. strSummary += InterpretDONTCAREBitmask(LOW, rDBigFrame.bSeq, &rDBigFrame.rgMask[nBitMaskIndex]);
  291. }
  292. }
  293. else if ( (rDBigFrame.bControl & PACKET_CONTROL_SEND_MASK2) == PACKET_CONTROL_SEND_MASK2 ) // High DWORD only
  294. {
  295. strSummary += ", " + InterpretDONTCAREBitmask(HIGH, rDBigFrame.bSeq, &rDBigFrame.rgMask[nBitMaskIndex]);
  296. }
  297. }
  298. else
  299. {
  300. CFRAME& rCFrame = *reinterpret_cast<CFRAME*>(io_pProperyInstance->lpPropertyInstEx->lpData);
  301. if ( rCFrame.bExtOpcode == FRAME_EXOPCODE_SACK ) // SACK CFrame
  302. {
  303. SFBIG8* pSBigFrame = reinterpret_cast<SFBIG8*>(&rCFrame);
  304. enum { SACK_FLAGS_ALL_MASKS = SACK_FLAGS_SACK_MASK1 | SACK_FLAGS_SACK_MASK2 |
  305. SACK_FLAGS_SEND_MASK1 | SACK_FLAGS_SEND_MASK2 };
  306. if ( pSBigFrame->bFlags & SACK_FLAGS_ALL_MASKS ) // at least one bitmask field is present
  307. {
  308. strSummary = "Selective Acknowledgement";
  309. }
  310. else // if not a single bitmask is present
  311. {
  312. strSummary = "Acknowledgement";
  313. }
  314. #if defined(PARSE_DPLAY_TRANSPORT)
  315. strSummary += " : NSeq=";
  316. strSummary += _itoa(pSBigFrame->bNSeq, arr_cBuffer, 16);
  317. strSummary += ", NRcv=";
  318. strSummary += _itoa(pSBigFrame->bNRcv, arr_cBuffer, 16);
  319. #endif // PARSE_DPLAY_TRANSPORT
  320. if ( (pSBigFrame->bCommand & PACKET_COMMAND_POLL) == PACKET_COMMAND_POLL )
  321. {
  322. strSummary += ", ACK now";
  323. }
  324. if ( ((pSBigFrame->bFlags & SACK_FLAGS_RESPONSE) == SACK_FLAGS_RESPONSE) && pSBigFrame->bRetry )
  325. {
  326. strSummary += ", Retry";
  327. }
  328. int nBitMaskIndex = 0;
  329. UNALIGNED ULONG* pulMasks = 0;
  330. // This is a Protocol version 1.0 frame
  331. pulMasks = pSBigFrame->rgMask;
  332. if ( (pSBigFrame->bFlags & SACK_FLAGS_SACK_MASK1) == SACK_FLAGS_SACK_MASK1 )
  333. {
  334. strSummary += ", ";
  335. if ( (pSBigFrame->bFlags & SACK_FLAGS_SACK_MASK2) == SACK_FLAGS_SACK_MASK2 ) // Entire QWORD
  336. {
  337. strSummary += InterpretRCVDBitmask(ENTIRE, pSBigFrame->bNRcv, &pulMasks[nBitMaskIndex]);
  338. nBitMaskIndex += 2;
  339. }
  340. else // Low DWORD only
  341. {
  342. strSummary += InterpretRCVDBitmask(LOW, pSBigFrame->bNRcv, &pulMasks[nBitMaskIndex]);
  343. ++nBitMaskIndex;
  344. }
  345. }
  346. else if ( (pSBigFrame->bFlags & SACK_FLAGS_SACK_MASK2) == SACK_FLAGS_SACK_MASK2 ) // High DWORD only
  347. {
  348. strSummary += ", " + InterpretRCVDBitmask(HIGH, pSBigFrame->bNRcv, &pulMasks[nBitMaskIndex]);
  349. ++nBitMaskIndex;
  350. }
  351. if ( (pSBigFrame->bFlags & SACK_FLAGS_SEND_MASK1) == SACK_FLAGS_SEND_MASK1 )
  352. {
  353. strSummary += ", ";
  354. if ( (pSBigFrame->bFlags & SACK_FLAGS_SEND_MASK2) == SACK_FLAGS_SEND_MASK2 ) // Entire QWORD
  355. {
  356. strSummary += InterpretDONTCAREBitmask(ENTIRE, pSBigFrame->bNSeq, &pulMasks[nBitMaskIndex]);
  357. }
  358. else // Low DWORD only
  359. {
  360. strSummary += InterpretDONTCAREBitmask(LOW, pSBigFrame->bNSeq, &pulMasks[nBitMaskIndex]);
  361. }
  362. }
  363. else if ( (pSBigFrame->bFlags & SACK_FLAGS_SEND_MASK2) == SACK_FLAGS_SEND_MASK2 ) // High DWORD only
  364. {
  365. strSummary += ", " + InterpretDONTCAREBitmask(HIGH, pSBigFrame->bNSeq, &pulMasks[nBitMaskIndex]);
  366. }
  367. }
  368. else // Connection Control CFrame
  369. {
  370. strSummary = "Connection Control - ";
  371. for ( int n = 0; n < sizeof(g_arr_ExOpcodeByteLabels) / sizeof(LABELED_BYTE); ++ n )
  372. {
  373. if ( g_arr_ExOpcodeByteLabels[n].Value == rCFrame.bExtOpcode )
  374. {
  375. strSummary += g_arr_ExOpcodeByteLabels[n].Label;
  376. break;
  377. }
  378. }
  379. if ( (rCFrame.bCommand & PACKET_COMMAND_POLL) == PACKET_COMMAND_POLL )
  380. {
  381. strSummary += " : ACK now";
  382. }
  383. }
  384. }
  385. strcpy(io_pProperyInstance->szPropertyText, strSummary.c_str());
  386. } // FormatPropertyInstance_TransportSummary
  387. // DESCRIPTION: Custom description formatter for the dataframe's Command field summary
  388. //
  389. // ARGUMENTS: io_pProperyInstance - Data of the property's instance
  390. //
  391. // RETURNS: NOTHING
  392. //
  393. VOID WINAPIV FormatPropertyInstance_DCommandSummary( LPPROPERTYINST io_pProperyInstance )
  394. {
  395. BYTE bCommand = *reinterpret_cast<BYTE*>(io_pProperyInstance->lpData);
  396. std::string strSummary = "Command: ";
  397. strSummary += ( (bCommand & PACKET_COMMAND_RELIABLE) == PACKET_COMMAND_RELIABLE ) ? "Reliable" : "Unreliable";
  398. strSummary += ( (bCommand & PACKET_COMMAND_SEQUENTIAL) == PACKET_COMMAND_SEQUENTIAL ) ? ", Sequenced" : ", Nonsequenced";
  399. strSummary += ( (bCommand & PACKET_COMMAND_POLL) == PACKET_COMMAND_POLL ) ? ", Must be ACK'ed immediately" : ", ACK can be delayed";
  400. if ( (bCommand & PACKET_COMMAND_NEW_MSG) == PACKET_COMMAND_NEW_MSG )
  401. {
  402. if ( (bCommand & PACKET_COMMAND_END_MSG) != PACKET_COMMAND_END_MSG )
  403. {
  404. strSummary += ", First fragment of the message";
  405. }
  406. }
  407. else if ( (bCommand & PACKET_COMMAND_END_MSG) == PACKET_COMMAND_END_MSG )
  408. {
  409. strSummary += ", Last fragment of the message";
  410. }
  411. strSummary += ( (bCommand & PACKET_COMMAND_USER_1) == PACKET_COMMAND_USER_1 ) ? ", DirectPlay packet" : ", User packet";
  412. strSummary += ( (bCommand & PACKET_COMMAND_USER_2) == PACKET_COMMAND_USER_2 ) ? ", Voice packet" : ", Data packet";
  413. strcpy(io_pProperyInstance->szPropertyText, strSummary.c_str());
  414. } // FormatPropertyInstance_DCommandSummary
  415. // DESCRIPTION: Custom description formatter for the Command Frame's Command field summary
  416. //
  417. // ARGUMENTS: io_pProperyInstance - Data of the property's instance
  418. //
  419. // RETURNS: NOTHING
  420. //
  421. VOID WINAPIV FormatPropertyInstance_CCommandSummary( LPPROPERTYINST io_pProperyInstance )
  422. {
  423. BYTE bCommand = *reinterpret_cast<BYTE*>(io_pProperyInstance->lpData);
  424. std::string strSummary = "Command: ";
  425. strSummary += ( (bCommand & PACKET_COMMAND_RELIABLE) == PACKET_COMMAND_RELIABLE ) ? "Reliable" : "Unreliable";
  426. strSummary += ( (bCommand & PACKET_COMMAND_SEQUENTIAL) == PACKET_COMMAND_SEQUENTIAL ) ? ", Sequenced" : ", Nonsequenced";
  427. strSummary += ( (bCommand & PACKET_COMMAND_POLL) == PACKET_COMMAND_POLL ) ? ", Must be ACK'ed immediately" : ", ACK can be delayed";
  428. strcpy(io_pProperyInstance->szPropertyText, strSummary.c_str());
  429. } // FormatPropertyInstance_CCommandSummary
  430. // DESCRIPTION: Custom description formatter for the dataframe's Control field summary
  431. //
  432. // ARGUMENTS: io_pProperyInstance - Data of the property's instance
  433. //
  434. // RETURNS: NOTHING
  435. //
  436. VOID WINAPIV FormatPropertyInstance_ControlSummary( LPPROPERTYINST io_pProperyInstance )
  437. {
  438. BYTE bControl = *reinterpret_cast<BYTE*>(io_pProperyInstance->lpData);
  439. std::string strSummary = "Control: ";
  440. if ( (bControl & PACKET_CONTROL_RETRY) == PACKET_CONTROL_RETRY )
  441. {
  442. strSummary += "Retry";
  443. }
  444. else
  445. {
  446. strSummary += "Original";
  447. }
  448. if ( (bControl & PACKET_CONTROL_CORRELATE) == PACKET_CONTROL_CORRELATE )
  449. {
  450. strSummary += ", Correlate / KeepAlive";
  451. }
  452. if ( (bControl & PACKET_CONTROL_END_STREAM) == PACKET_CONTROL_END_STREAM )
  453. {
  454. strSummary += ", Last packet in the stream";
  455. }
  456. if ( ( (bControl & PACKET_CONTROL_SACK_MASK1) == PACKET_CONTROL_SACK_MASK1 ) ||
  457. ( (bControl & PACKET_CONTROL_SACK_MASK2) == PACKET_CONTROL_SACK_MASK2 ) )
  458. {
  459. strSummary += "RCVD bitmask is nonzero";
  460. }
  461. if ( ( (bControl & PACKET_CONTROL_SEND_MASK1) == PACKET_CONTROL_SEND_MASK1 ) ||
  462. ( (bControl & PACKET_CONTROL_SEND_MASK2) == PACKET_CONTROL_SEND_MASK2 ) )
  463. {
  464. strSummary += ", DON'T CARE bitmask is nonzero";
  465. }
  466. strcpy(io_pProperyInstance->szPropertyText, strSummary.c_str());
  467. } // FormatPropertyInstance_ControlSummary
  468. // DESCRIPTION: Custom description formatter for the Command Frame's SACK Flags field summary
  469. //
  470. // ARGUMENTS: io_pProperyInstance - Data of the property's instance
  471. //
  472. // RETURNS: NOTHING
  473. //
  474. VOID WINAPIV FormatPropertyInstance_SACKFlagsSummary( LPPROPERTYINST io_pProperyInstance )
  475. {
  476. BYTE bSACKFlags = *reinterpret_cast<BYTE*>(io_pProperyInstance->lpData);
  477. std::string strSummary = "SACK Flags: ";
  478. strSummary += ( (bSACKFlags & SACK_FLAGS_RESPONSE) == SACK_FLAGS_RESPONSE ) ? "Retry and Timestamp fields are valid" :
  479. "Retry and/or Timestamp fields are invalid";
  480. if ( ( (bSACKFlags & SACK_FLAGS_SACK_MASK1) == SACK_FLAGS_SACK_MASK1 ) ||
  481. ( (bSACKFlags & SACK_FLAGS_SACK_MASK2) == SACK_FLAGS_SACK_MASK2 ) )
  482. {
  483. strSummary += ", RCVD bitmask is nonzero";
  484. }
  485. else
  486. {
  487. strSummary += ", no RCVD bitmask";
  488. }
  489. if ( ( (bSACKFlags & SACK_FLAGS_SEND_MASK1) == SACK_FLAGS_SEND_MASK1 ) ||
  490. ( (bSACKFlags & SACK_FLAGS_SEND_MASK2) == SACK_FLAGS_SEND_MASK2 ) )
  491. {
  492. strSummary += ", DON'T CARE bitmask is nonzero";
  493. }
  494. else
  495. {
  496. strSummary += ", no DON'T CARE bitmask";
  497. }
  498. strcpy(io_pProperyInstance->szPropertyText, strSummary.c_str());
  499. } // FormatPropertyInstance_SACKFlagsSummary
  500. struct SSACKBitmaskContext
  501. {
  502. BYTE byBase;
  503. BitmaskPart Part;
  504. BitmaskType Type;
  505. BYTE byBit;
  506. };
  507. // DESCRIPTION: Custom description formatter for the Selective Acknowledgement Frame's RCVD bitmask's low/high DWORD summary
  508. //
  509. // ARGUMENTS: io_pProperyInstance - Data of the property's instance
  510. //
  511. // RETURNS: NOTHING
  512. //
  513. VOID WINAPIV FormatPropertyInstance_SACKBitmaskDWORDSummary( LPPROPERTYINST io_pProperyInstance )
  514. {
  515. DWORD dwBitmask = *reinterpret_cast<DWORD*>(io_pProperyInstance->lpPropertyInstEx->lpData);
  516. SSACKBitmaskContext& rBitmaskContext = *reinterpret_cast<SSACKBitmaskContext*>(io_pProperyInstance->lpPropertyInstEx->Byte);
  517. std::string strSummary = ( rBitmaskContext.Part == LOW ? "Low" : "High" );
  518. strSummary += " DWORD of ";
  519. strSummary += ( rBitmaskContext.Type == RCVD ? "RCVD" : "DON'T CARE" );
  520. strSummary += " bitmask: ";
  521. strSummary += ( ( rBitmaskContext.Type == RCVD ) ? InterpretRCVDBitmask(rBitmaskContext.Part, rBitmaskContext.byBase, &dwBitmask) :
  522. InterpretDONTCAREBitmask(rBitmaskContext.Part, rBitmaskContext.byBase, &dwBitmask) );
  523. strcpy(io_pProperyInstance->szPropertyText, strSummary.c_str());
  524. } // FormatPropertyInstance_SACKBitmaskDWORDSummary
  525. // DESCRIPTION: Custom description formatter for the bitmask's low/high DWORD summary
  526. //
  527. // ARGUMENTS: io_pProperyInstance - Data of the property's instance
  528. //
  529. // RETURNS: NOTHING
  530. //
  531. VOID WINAPIV FormatPropertyInstance_DWORDBitmaskEntry( LPPROPERTYINST io_pProperyInstance )
  532. {
  533. DWORD dwBitmask = *reinterpret_cast<DWORD*>(io_pProperyInstance->lpPropertyInstEx->lpData);
  534. SSACKBitmaskContext& rBitmaskContext = *reinterpret_cast<SSACKBitmaskContext*>(io_pProperyInstance->lpPropertyInstEx->Byte);
  535. BYTE byBase = rBitmaskContext.byBase;
  536. BYTE byBit = rBitmaskContext.byBit;
  537. switch ( rBitmaskContext.Type )
  538. {
  539. case RCVD:
  540. {
  541. // [i_bBase+1 .. i_bBase+1+LENGTH]
  542. // RCVD bitmask doesn't include the base value, since receiver can't claim it didn't receive the next dataframe to be received (NRcv);
  543. if ( rBitmaskContext.Part == HIGH )
  544. {
  545. // NOTE: +1 is needed to cross from MSB of the first DWORD TO LSB of the second
  546. byBase += 8*sizeof(DWORD)+1; // shift to LSB of the second DWORD
  547. }
  548. else
  549. {
  550. ++byBase;
  551. }
  552. byBase += byBit;
  553. break;
  554. }
  555. case DONTCARE:
  556. {
  557. // [i_bBase-1-LENGTH .. i_bBase-1]
  558. // DON'T CARE doesn't include the base value, since transmitter can't resend/refuse resending a dataframe which is about to be sent next (NSeq).
  559. if ( rBitmaskContext.Part == HIGH )
  560. {
  561. byBase -= 8*sizeof(DWORD); // shift to MSB of the first DWORD
  562. }
  563. else
  564. {
  565. --byBase;
  566. }
  567. byBase -= byBit;
  568. break;
  569. }
  570. default:
  571. // TODO: ASSERT HERE (SHOULD NEVER HAPPEN)
  572. break;
  573. }
  574. static DWORD arr_dwFlags[] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008,
  575. 0x00000010, 0x00000020, 0x00000040, 0x00000080,
  576. 0x00000100, 0x00000200, 0x00000400, 0x00000800,
  577. 0x00001000, 0x00002000, 0x00004000, 0x00008000,
  578. 0x00010000, 0x00020000, 0x00040000, 0x00080000,
  579. 0x00100000, 0x00200000, 0x00400000, 0x00800000,
  580. 0x01000000, 0x02000000, 0x04000000, 0x08000000,
  581. 0x10000000, 0x20000000, 0x40000000, 0x80000000 };
  582. char arr_cBuffer[100];
  583. char arr_cTemplate[] = "................................ = %s %d (%d%c%d)";
  584. arr_cTemplate[31-byBit] = ( (dwBitmask & arr_dwFlags[byBit]) ? '1' : '0' );
  585. switch ( rBitmaskContext.Type )
  586. {
  587. case RCVD:
  588. {
  589. sprintf(arr_cBuffer, arr_cTemplate, ((dwBitmask & arr_dwFlags[byBit]) ? "Received" : "Did not receive"), byBase, rBitmaskContext.byBase, '+', byBit+1);
  590. ++byBase;
  591. break;
  592. }
  593. case DONTCARE:
  594. {
  595. sprintf(arr_cBuffer, arr_cTemplate, ((dwBitmask & arr_dwFlags[byBit]) ? "Cancelling" : "Successfully transmitted"), byBase, rBitmaskContext.byBase, '-', byBit+1);
  596. --byBase;
  597. break;
  598. }
  599. }
  600. strcpy(io_pProperyInstance->szPropertyText, arr_cBuffer);
  601. } // FormatPropertyInstance_DWORDBitmaskEntry
  602. //==================//
  603. // Properties table //-----------------------------------------------------------------------------------------------
  604. //==================//
  605. PROPERTYINFO g_arr_TransportProperties[] =
  606. {
  607. // Transport packet summary property (TRANSPORT_SUMMARY)
  608. {
  609. 0, // handle placeholder (MBZ)
  610. 0, // reserved (MBZ)
  611. "", // label
  612. "DPlay Direct Network packet", // status-bar comment
  613. PROP_TYPE_SUMMARY, // data type
  614. PROP_QUAL_NONE, // data type qualifier
  615. NULL, // labeled bit set
  616. 512, // description's maximum length
  617. FormatPropertyInstance_TransportSummary // generic formatter
  618. },
  619. // DCommand field summary property (TRANSPORT_DCOMMAND_SUMMARY)
  620. {
  621. 0, // handle placeholder (MBZ)
  622. 0, // reserved (MBZ)
  623. "", // label
  624. "Command field summary", // status-bar comment
  625. PROP_TYPE_SUMMARY, // data type
  626. PROP_QUAL_NONE, // data type qualifier.
  627. NULL, // labeled bit set
  628. 512, // description's maximum length
  629. FormatPropertyInstance_DCommandSummary // generic formatter
  630. },
  631. // DCommand field property (TRANSPORT_DCOMMAND)
  632. {
  633. 0, // handle placeholder (MBZ)
  634. 0, // reserved (MBZ)
  635. "", // label
  636. "Command field", // status-bar comment
  637. PROP_TYPE_BYTE, // data type
  638. PROP_QUAL_FLAGS, // data type qualifier.
  639. &g_LabeledDCommandBitSet, // labeled bit set
  640. 512, // description's maximum length
  641. FormatPropertyInstance // generic formatter
  642. },
  643. // Control field summary property (TRANSPORT_CONTROL_SUMMARY)
  644. {
  645. 0, // handle placeholder (MBZ)
  646. 0, // reserved (MBZ)
  647. "", // label
  648. "Control field summary", // status-bar comment
  649. PROP_TYPE_SUMMARY, // data type
  650. PROP_QUAL_NONE, // data type qualifier.
  651. NULL, // labeled bit set
  652. 512, // description's maximum length
  653. FormatPropertyInstance_ControlSummary // generic formatter
  654. },
  655. // Control field property (TRANSPORT_CONTROL)
  656. {
  657. 0, // handle placeholder (MBZ)
  658. 0, // reserved (MBZ)
  659. "Control", // label
  660. "Control field", // status-bar comment
  661. PROP_TYPE_BYTE, // data type
  662. PROP_QUAL_FLAGS, // data type qualifier.
  663. &g_LabeledControlBitSet, // labeled byte set
  664. 512, // description's maximum length
  665. FormatPropertyInstance // generic formatter
  666. },
  667. // Packet sequence number property (TRANSPORT_SEQNUM)
  668. //
  669. // INFO: This number is incremented for each _new_ packet sent. If an endpoint retransmits
  670. // a packet, it uses the same sequence number it did the first time it sent it (base value for the DON'T CARE bitmask).
  671. {
  672. 0, // handle placeholder (MBZ)
  673. 0, // reserved (MBZ)
  674. "Seq: Highest dataframe # sent (base value for the DON'T CARE bitmask)", // label
  675. "Highest dataframe # sent field", // status-bar comment
  676. PROP_TYPE_BYTE, // data type
  677. PROP_QUAL_NONE, // data type qualifier.
  678. NULL, // no data qualifiers
  679. 512, // description's maximum length
  680. FormatPropertyInstance // generic formatter
  681. },
  682. // Next receive number property (TRANSPORT_NEXTRECVNUM)
  683. //
  684. // INFO: Acknowledges every packet with a sequence number up to but not including this number (base value for the RCVD bitmask)
  685. {
  686. 0, // handle placeholder (MBZ)
  687. 0, // reserved (MBZ)
  688. "NRcv: Next dataframe # to be received (base value for the RCVD bitmask)", // label
  689. "Next dataframe # to be received field", // status-bar comment
  690. PROP_TYPE_BYTE, // data type
  691. PROP_QUAL_NONE, // data type qualifier.
  692. NULL, // no data qualifiers
  693. 512, // description's maximum length
  694. FormatPropertyInstance // generic formatter
  695. },
  696. // CCommand field property (TRANSPORT_CCOMMAND_SUMMARY)
  697. {
  698. 0, // handle placeholder (MBZ)
  699. 0, // reserved (MBZ)
  700. "", // label
  701. "Command field summary", // status-bar comment
  702. PROP_TYPE_SUMMARY, // data type
  703. PROP_QUAL_NONE, // data type qualifier.
  704. NULL, // labeled bit set
  705. 512, // description's maximum length
  706. FormatPropertyInstance_CCommandSummary // generic formatter
  707. },
  708. // CCommand field property (TRANSPORT_CCOMMAND)
  709. {
  710. 0, // handle placeholder (MBZ)
  711. 0, // reserved (MBZ)
  712. "", // label
  713. "Command field", // status-bar comment
  714. PROP_TYPE_BYTE, // data type
  715. PROP_QUAL_FLAGS, // data type qualifier.
  716. &g_LabeledCCommandBitSet, // labeled bit set
  717. 512, // description's maximum length
  718. FormatPropertyInstance // generic formatter
  719. },
  720. // Extended opcode field property (TRANSPORT_EXOPCODE)
  721. {
  722. 0, // handle placeholder (MBZ)
  723. 0, // reserved (MBZ)
  724. "Extended opcode", // label
  725. "Extended opcode field", // status-bar comment
  726. PROP_TYPE_BYTE, // data type
  727. PROP_QUAL_LABELED_SET, // data type qualifier.
  728. &g_LabeledExOpcodeByteSet, // labeled byte set
  729. 512, // description's maximum length
  730. FormatPropertyInstance // generic formatter
  731. },
  732. // Message ID field property (TRANSPORT_MSGID)
  733. {
  734. 0, // handle placeholder (MBZ)
  735. 0, // reserved (MBZ)
  736. "Message ID", // label
  737. "Message ID field", // status-bar comment
  738. PROP_TYPE_BYTE, // data type
  739. PROP_QUAL_NONE, // data type qualifier.
  740. NULL, // no data qualifiers
  741. 512, // description's maximum length
  742. FormatPropertyInstance // generic formatter
  743. },
  744. // Response ID field propery (TRANSPORT_RSPID)
  745. {
  746. 0, // handle placeholder (MBZ)
  747. 0, // reserved (MBZ)
  748. "Response ID", // label
  749. "Response ID field", // status-bar comment
  750. PROP_TYPE_BYTE, // data type
  751. PROP_QUAL_NONE, // data type qualifier.
  752. NULL, // no data qualifiers
  753. 512, // description's maximum length
  754. FormatPropertyInstance // generic formatter
  755. },
  756. // Protocol version field property (TRANSPORT_VERSION)
  757. //
  758. // INFO: Makes sure both endpoints use the same version of the protocol.
  759. {
  760. 0, // handle placeholder (MBZ)
  761. 0, // reserved (MBZ)
  762. "Version", // label
  763. "Version field", // status-bar comment
  764. PROP_TYPE_DWORD, // data type
  765. PROP_QUAL_NONE, // data type qualifier.
  766. NULL, // no data qualifiers
  767. 512, // description's maximum length
  768. FormatPropertyInstance // generic formatter
  769. },
  770. // Session ID field property (TRANSPORT_SESSIONID)
  771. {
  772. 0, // handle placeholder (MBZ)
  773. 0, // reserved (MBZ)
  774. "Session ID", // label
  775. "Session ID field", // status-bar comment
  776. PROP_TYPE_DWORD, // data type
  777. PROP_QUAL_NONE, // data type qualifier.
  778. NULL, // no data qualifiers
  779. 512, // description's maximum length
  780. FormatPropertyInstance // generic formatter
  781. },
  782. // Time stamp field property (TRANSPORT_TIMESTAMP)
  783. {
  784. 0, // handle placeholder (MBZ)
  785. 0, // reserved (MBZ)
  786. "Time stamp", // label
  787. "Time stamp field", // status-bar comment
  788. PROP_TYPE_DWORD, // data type
  789. PROP_QUAL_NONE, // data type qualifier.
  790. NULL, // no data qualifiers
  791. 512, // description's maximum length
  792. FormatPropertyInstance // generic formatter
  793. },
  794. // SACK flags field property (TRANSPORT_SACKFIELDS_SUMMARY)
  795. {
  796. 0, // handle placeholder (MBZ)
  797. 0, // reserved (MBZ)
  798. "", // label
  799. "SACK flags summary", // status-bar comment
  800. PROP_TYPE_SUMMARY, // data type
  801. PROP_QUAL_NONE, // data type qualifier.
  802. NULL, // labeled byte set
  803. 512, // description's maximum length
  804. FormatPropertyInstance_SACKFlagsSummary // generic formatter
  805. },
  806. // SACK flags field property (TRANSPORT_SACKFIELDS)
  807. {
  808. 0, // handle placeholder (MBZ)
  809. 0, // reserved (MBZ)
  810. "", // label
  811. "SACK flags field", // status-bar comment
  812. PROP_TYPE_BYTE, // data type
  813. PROP_QUAL_FLAGS, // data type qualifier.
  814. &g_LabeledSACKFlagsBitSet, // labeled byte set
  815. 512, // description's maximum length
  816. FormatPropertyInstance // generic formatter
  817. },
  818. // Retry field property (TRANSPORT_RETRY)
  819. {
  820. 0, // handle placeholder (MBZ)
  821. 0, // reserved (MBZ)
  822. "Retry", // label
  823. "Retry field", // status-bar comment
  824. PROP_TYPE_BYTE, // data type
  825. PROP_QUAL_NONE, // data type qualifier.
  826. NULL, // no data qualifiers
  827. 512, // description's maximum length
  828. FormatPropertyInstance // generic formatter
  829. },
  830. // Next sequence number field property (TRANSPORT_NEXTSEQNUM)
  831. //
  832. // INFO: Sequence number of the next DFrame to be sent (base value for the DON'T CARE bitmask)
  833. {
  834. 0, // handle placeholder (MBZ)
  835. 0, // reserved (MBZ)
  836. "NSeq: Next dataframe # to be sent (base value for the DON'T CARE bitmask)", // label
  837. "Next dataframe # to be sent field", // status-bar comment
  838. PROP_TYPE_BYTE, // data type
  839. PROP_QUAL_NONE, // data type qualifier.
  840. NULL, // no data qualifiers
  841. 512, // description's maximum length
  842. FormatPropertyInstance // generic formatter
  843. },
  844. // Low DWORD of the Selective-ACK RCVD Mask summary (TRANSPORT_RCVDMASK1_SUMMARY)
  845. {
  846. 0, // handle placeholder (MBZ)
  847. 0, // reserved (MBZ)
  848. "", // label
  849. "Low DWORD of the RCVD mask summary", // status-bar comment
  850. PROP_TYPE_SUMMARY, // data type
  851. PROP_QUAL_NONE, // data type qualifier.
  852. NULL, // labeled byte set
  853. 512, // description's maximum length
  854. FormatPropertyInstance_SACKBitmaskDWORDSummary // generic formatter
  855. },
  856. // Low DWORD of the Selective-ACK RCVD Mask property (TRANSPORT_RCVDMASK1)
  857. {
  858. 0, // handle placeholder (MBZ)
  859. 0, // reserved (MBZ)
  860. "Low DWORD of the RCVD mask", // label
  861. "Low DWORD of the RCVD mask field", // status-bar comment
  862. PROP_TYPE_DWORD, // data type
  863. PROP_QUAL_NONE, // data type qualifier.
  864. NULL, // labeled bit set
  865. 3072, // description's maximum length
  866. FormatPropertyInstance_DWORDBitmaskEntry // generic formatter
  867. },
  868. // High DWORD of the Selective-ACK RCVD Mask summary (TRANSPORT_RCVDMASK2_SUMMARY)
  869. {
  870. 0, // handle placeholder (MBZ)
  871. 0, // reserved (MBZ)
  872. "", // label
  873. "High DWORD of the RCVD mask summary", // status-bar comment
  874. PROP_TYPE_SUMMARY, // data type
  875. PROP_QUAL_NONE, // data type qualifier.
  876. NULL, // labeled byte set
  877. 512, // description's maximum length
  878. FormatPropertyInstance_SACKBitmaskDWORDSummary // generic formatter
  879. },
  880. // High DWORD of Selective-ACK RCVD Mask property (TRANSPORT_RCVDMASK2)
  881. {
  882. 0, // handle placeholder (MBZ)
  883. 0, // reserved (MBZ)
  884. "High DWORD of the RCVD mask", // label
  885. "High DWORD of the RCVD mask field", // status-bar comment
  886. PROP_TYPE_DWORD, // data type
  887. PROP_QUAL_NONE, // data type qualifier.
  888. NULL, // labeled bit set
  889. 3072, // description's maximum length
  890. FormatPropertyInstance_DWORDBitmaskEntry // generic formatter
  891. },
  892. // Low DWORD of the Selective-ACK DON'T CARE Mask summary (TRANSPORT_DONTCAREMASK1_SUMMARY)
  893. {
  894. 0, // handle placeholder (MBZ)
  895. 0, // reserved (MBZ)
  896. "", // label
  897. "Low DWORD of the DON'T CARE mask summary", // status-bar comment
  898. PROP_TYPE_SUMMARY, // data type
  899. PROP_QUAL_NONE, // data type qualifier.
  900. NULL, // labeled byte set
  901. 512, // description's maximum length
  902. FormatPropertyInstance_SACKBitmaskDWORDSummary // generic formatter
  903. },
  904. // Low DWORD of the Selective-ACK DON'T CARE Mask property (TRANSPORT_DONTCAREMASK1)
  905. {
  906. 0, // handle placeholder (MBZ)
  907. 0, // reserved (MBZ)
  908. "Low DWORD of the DON'T CARE mask", // label
  909. "Low DWORD of the DON'T CARE mask field", // status-bar comment
  910. PROP_TYPE_DWORD, // data type
  911. PROP_QUAL_NONE, // data type qualifier.
  912. NULL, // labeled bit set
  913. 3072, // description's maximum length
  914. FormatPropertyInstance_DWORDBitmaskEntry // generic formatter
  915. },
  916. // High DWORD of the Selective-ACK DON'T CARE Mask summary (TRANSPORT_DONTCAREMASK2_SUMMARY)
  917. {
  918. 0, // handle placeholder (MBZ)
  919. 0, // reserved (MBZ)
  920. "", // label
  921. "High DWORD of the DON'T CARE mask summary", // status-bar comment
  922. PROP_TYPE_SUMMARY, // data type
  923. PROP_QUAL_NONE, // data type qualifier.
  924. NULL, // labeled byte set
  925. 512, // description's maximum length
  926. FormatPropertyInstance_SACKBitmaskDWORDSummary // generic formatter
  927. },
  928. // High DWORD of the Selective-ACK DON'T CARE Mask property (TRANSPORT_DONTCAREMASK2)
  929. {
  930. 0, // handle placeholder (MBZ)
  931. 0, // reserved (MBZ)
  932. "High DWORD of the DON'T CARE mask", // label
  933. "High DWORD of the DON'T CARE mask field", // status-bar comment
  934. PROP_TYPE_DWORD, // data type
  935. PROP_QUAL_NONE, // data type qualifier.
  936. NULL, // labeled bit set
  937. 3072, // description's maximum length
  938. FormatPropertyInstance_DWORDBitmaskEntry // generic formatter
  939. },
  940. // Compression Type property (VOICE_USERDATA)
  941. {
  942. 0, // handle placeholder (MBZ)
  943. 0, // reserved (MBZ)
  944. "User Data", // label
  945. "User Data", // status-bar comment
  946. PROP_TYPE_RAW_DATA, // data type (GUID)
  947. PROP_QUAL_NONE, // data type qualifier.
  948. NULL, // labeled bit set
  949. 64, // description's maximum length
  950. FormatPropertyInstance // generic formatter
  951. }
  952. };
  953. enum
  954. {
  955. nNUM_OF_TRANSPORT_PROPS = sizeof(g_arr_TransportProperties) / sizeof(PROPERTYINFO)
  956. };
  957. // Properties' indices
  958. enum
  959. {
  960. TRANSPORT_SUMMARY = 0,
  961. TRANSPORT_DCOMMAND_SUMMARY,
  962. TRANSPORT_DCOMMAND,
  963. TRANSPORT_CONTROL_SUMMARY,
  964. TRANSPORT_CONTROL,
  965. TRANSPORT_SEQNUM,
  966. TRANSPORT_NEXTRECVNUM,
  967. TRANSPORT_CCOMMAND_SUMMARY,
  968. TRANSPORT_CCOMMAND,
  969. TRANSPORT_EXOPCODE,
  970. TRANSPORT_MSGID,
  971. TRANSPORT_RSPID,
  972. TRANSPORT_VERSION,
  973. TRANSPORT_SESSIONID,
  974. TRANSPORT_TIMESTAMP,
  975. TRANSPORT_SACKFIELDS_SUMMARY,
  976. TRANSPORT_SACKFIELDS,
  977. TRANSPORT_RETRY,
  978. TRANSPORT_NEXTSEQNUM,
  979. TRANSPORT_RCVDMASK1_SUMMARY,
  980. TRANSPORT_RCVDMASK1,
  981. TRANSPORT_RCVDMASK2_SUMMARY,
  982. TRANSPORT_RCVDMASK2,
  983. TRANSPORT_DONTCAREMASK1_SUMMARY,
  984. TRANSPORT_DONTCAREMASK1,
  985. TRANSPORT_DONTCAREMASK2_SUMMARY,
  986. TRANSPORT_DONTCAREMASK2,
  987. TRANSPORT_USERDATA
  988. };
  989. } // anonymous namespace
  990. // DESCRIPTION: Creates and fills-in a properties database for the protocol.
  991. // Network Monitor uses this database to determine which properties the protocol supports.
  992. //
  993. // ARGUMENTS: i_hTransportProtocol - The handle of the protocol provided by the Network Monitor.
  994. //
  995. // RETURNS: NOTHING
  996. //
  997. DPLAYPARSER_API VOID BHAPI TransportRegister( HPROTOCOL i_hTransportProtocol )
  998. {
  999. CreatePropertyDatabase(i_hTransportProtocol, nNUM_OF_TRANSPORT_PROPS);
  1000. // Add the properties to the database
  1001. for( int nProp=0; nProp < nNUM_OF_TRANSPORT_PROPS; ++nProp )
  1002. {
  1003. AddProperty(i_hTransportProtocol, &g_arr_TransportProperties[nProp]);
  1004. }
  1005. } // TransportRegister
  1006. // DESCRIPTION: Frees the resources used to create the protocol property database.
  1007. //
  1008. // ARGUMENTS: i_hTransportProtocol - The handle of the protocol provided by the Network Monitor.
  1009. //
  1010. // RETURNS: NOTHING
  1011. //
  1012. DPLAYPARSER_API VOID WINAPI TransportDeregister( HPROTOCOL i_hProtocol )
  1013. {
  1014. DestroyPropertyDatabase(i_hProtocol);
  1015. } // TransportDeregister
  1016. namespace
  1017. {
  1018. // DESCRIPTION: Parses the Transport frame to find its size (in bytes) NOT including the user data
  1019. //
  1020. // ARGUMENTS: i_pbTransportFrame - Pointer to the start of the unclaimed data. Typically, the unclaimed data is located
  1021. // in the middle of a frame because a previous parser has claimed data before this parser.
  1022. //
  1023. // RETURNS: Size of the specified Transport frame (in bytes)
  1024. //
  1025. int TransportHeaderSize( BYTE* i_pbTransportFrame )
  1026. {
  1027. int arr_nNumOfBits[] = { /*00 = 0x0000*/ 0, /*01 = 0x0001*/ 1, /*02 = 0x0010*/ 1, /*03 = 0x0011*/ 2,
  1028. /*04 = 0x0100*/ 1, /*05 = 0x0101*/ 2, /*06 = 0x0110*/ 2, /*07 = 0x0111*/ 3,
  1029. /*08 = 0x1000*/ 1, /*09 = 0x1001*/ 2, /*10 = 0x1010*/ 2, /*11 = 0x1011*/ 3,
  1030. /*12 = 0x1100*/ 2, /*13 = 0x1101*/ 3, /*14 = 0x1110*/ 3, /*15 = 0x1111*/ 4 };
  1031. const DFRAME& rDFrame = *reinterpret_cast<DFRAME*>(i_pbTransportFrame);
  1032. if ( (rDFrame.bCommand & PACKET_COMMAND_DATA) == PACKET_COMMAND_DATA ) // DFrame
  1033. {
  1034. return sizeof(rDFrame) + sizeof(DWORD)*arr_nNumOfBits[rDFrame.bControl >> 4];
  1035. }
  1036. else
  1037. {
  1038. const CFRAME& rCFrame = *reinterpret_cast<CFRAME*>(i_pbTransportFrame);
  1039. if ( rCFrame.bExtOpcode == FRAME_EXOPCODE_SACK ) // SACK CFrame
  1040. {
  1041. const SFBIG8* pSFrame = reinterpret_cast<SFBIG8*>(i_pbTransportFrame);
  1042. ULONG ulMaskSize = sizeof(DWORD)*arr_nNumOfBits[(pSFrame->bFlags >> 1) & 0x0F];
  1043. // This is a Protocol version 1.0 frame
  1044. return sizeof(SACKFRAME8) + ulMaskSize;
  1045. }
  1046. else // Connection Control CFrame
  1047. {
  1048. return sizeof(rCFrame);
  1049. }
  1050. }
  1051. } // TransportHeaderSize
  1052. } // Anonymous namespace
  1053. // DESCRIPTION: Indicates whether a piece of data is recognized as the protocol that the parser detects.
  1054. //
  1055. // ARGUMENTS: i_hFrame - The handle to the frame that contains the data.
  1056. // i_pbMacFrame - The pointer to the first byte of the frame; the pointer provides a way to view
  1057. // the data that the other parsers recognize.
  1058. // i_pbTransportFrame - Pointer to the start of the unclaimed data. Typically, the unclaimed data is located
  1059. // in the middle of a frame because a previous parser has claimed data before this parser.
  1060. // i_dwMacType - MAC value of the first protocol in a frame. Typically, the i_dwMacType value is used
  1061. // when the parser must identify the first protocol in the frame. Can be one of the following:
  1062. // MAC_TYPE_ETHERNET = 802.3, MAC_TYPE_TOKENRING = 802.5, MAC_TYPE_FDDI ANSI = X3T9.5.
  1063. // i_dwBytesLeft - The remaining number of bytes from a location in the frame to the end of the frame.
  1064. // i_hPrevProtocol - Handle of the previous protocol.
  1065. // i_dwPrevProtOffset - Offset of the previous protocol (from the beginning of the frame).
  1066. // o_pdwProtocolStatus - Protocol status indicator. Must be one of the following: PROTOCOL_STATUS_RECOGNIZED,
  1067. // PROTOCOL_STATUS_NOT_RECOGNIZED, PROTOCOL_STATUS_CLAIMED, PROTOCOL_STATUS_NEXT_PROTOCOL.
  1068. // o_phNextProtocol - Placeholder for the handle of the next protocol. This parameter is set when the parser identifies
  1069. // the protocol that follows its own protocol.
  1070. // io_pdwptrInstData - On input, a pointer to the instance data from the previous protocol.
  1071. // On output, a pointer to the instance data for the current protocol.
  1072. //
  1073. // RETURNS: If the function is successful, the return value is a pointer to the first byte after the recognized parser data.
  1074. // If the parser claims all the remaining data, the return value is NULL. If the function is unsuccessful, the return
  1075. // value is the initial value of the i_pbTransportFrame parameter.
  1076. //
  1077. DPLAYPARSER_API BYTE* BHAPI TransportRecognizeFrame( HFRAME i_hFrame,
  1078. ULPBYTE i_upbMacFrame,
  1079. ULPBYTE i_upbTransportFrame,
  1080. DWORD i_dwMacType,
  1081. DWORD i_dwBytesLeft,
  1082. HPROTOCOL i_hPrevProtocol,
  1083. DWORD i_dwPrevProtOffset,
  1084. LPDWORD o_pdwProtocolStatus,
  1085. LPHPROTOCOL o_phNextProtocol,
  1086. PDWORD_PTR io_pdwptrInstData )
  1087. {
  1088. // Validate the amount of unclaimed data
  1089. enum
  1090. {
  1091. nMIN_TransportHeaderSize = min(min(sizeof(DFRAME), sizeof(CFRAME)), sizeof(SACKFRAME8))
  1092. };
  1093. // Validate the packet as DPlay Transport type
  1094. if ( i_dwBytesLeft < nMIN_TransportHeaderSize )
  1095. {
  1096. // Assume the unclaimed data is not recognizable
  1097. *o_pdwProtocolStatus = PROTOCOL_STATUS_NOT_RECOGNIZED;
  1098. return i_upbTransportFrame;
  1099. }
  1100. // Check if we are dealing with a DPlay Voice packet
  1101. enum
  1102. {
  1103. PACKET_COMMAND_SESSION = PACKET_COMMAND_DATA | PACKET_COMMAND_USER_1,
  1104. PACKET_COMMAND_VOICE = PACKET_COMMAND_DATA | PACKET_COMMAND_USER_1 | PACKET_COMMAND_USER_2
  1105. };
  1106. const DFRAME& rDFrame = *reinterpret_cast<DFRAME*>(i_upbTransportFrame);
  1107. *o_pdwProtocolStatus = PROTOCOL_STATUS_NEXT_PROTOCOL;
  1108. // Let upper protocol's parser know if the message is a non-initial fragment of a fragmented message
  1109. *io_pdwptrInstData = ((rDFrame.bCommand & PACKET_COMMAND_NEW_MSG) == PACKET_COMMAND_NEW_MSG);
  1110. if ( (rDFrame.bCommand & PACKET_COMMAND_VOICE) == PACKET_COMMAND_VOICE )
  1111. {
  1112. // Notify NetMon about the handoff protocol
  1113. *o_phNextProtocol = GetProtocolFromName("DPLAYVOICE");
  1114. }
  1115. else if ( (rDFrame.bCommand & PACKET_COMMAND_SESSION) == PACKET_COMMAND_SESSION )
  1116. {
  1117. // Notify NetMon about the handoff protocol
  1118. *o_phNextProtocol = GetProtocolFromName("DPLAYSESSION");
  1119. }
  1120. else
  1121. {
  1122. *o_pdwProtocolStatus = PROTOCOL_STATUS_RECOGNIZED;
  1123. *o_phNextProtocol = NULL;
  1124. }
  1125. return i_upbTransportFrame + TransportHeaderSize(i_upbTransportFrame);
  1126. } // TransportRecognizeFrame
  1127. //=======================================//
  1128. // Attaching properties helper functions //
  1129. //=======================================//
  1130. namespace
  1131. {
  1132. // DESCRIPTION: Maps the DWORD bitmask properties on a per-bit basis.
  1133. //
  1134. // ARGUMENTS: i_hFrame - Handle of the frame that is being parsed.
  1135. // i_nPropertyIndex - Index of the property in the global properties table.
  1136. // i_pdwBitmask - Pointer to the value to which the property is being attached.
  1137. // i_byBase - Base value from which the entry value is calculated.
  1138. // i_Part - LOW or HIGH part of the QWORD bitmask.
  1139. // i_Type - RCVD or DONTCARE type of the bitmask.
  1140. // i_byLevel - Level in the detail pane tree.
  1141. //
  1142. // RETURNS: NOTHING
  1143. //
  1144. VOID WINAPIV AttachBitmaskDWORDProperties( HFRAME i_hFrame, int i_nPropertyIndex, UNALIGNED DWORD* i_pdwBitmask, BYTE i_byBase,
  1145. BitmaskPart i_Part, BitmaskType i_Type, BYTE i_byLevel )
  1146. {
  1147. for ( BYTE byBit = 0; byBit < 32; ++byBit )
  1148. {
  1149. SSACKBitmaskContext BitmaskContext = { i_byBase, i_Part, i_Type, byBit };
  1150. AttachPropertyInstanceEx(i_hFrame, g_arr_TransportProperties[i_nPropertyIndex].hProperty,
  1151. sizeof(*i_pdwBitmask), i_pdwBitmask,
  1152. sizeof(BitmaskContext), &BitmaskContext,
  1153. 0, i_byLevel, 0);
  1154. }
  1155. } // AttachBitmaskDWORDProperties
  1156. // DESCRIPTION: Maps the Data-Frame properties that exist in a piece of recognized data to specific locations.
  1157. //
  1158. // ARGUMENTS: i_hFrame - Handle of the frame that is being parsed.
  1159. // i_pbDFrame - Pointer to the start of the recognized data.
  1160. //
  1161. // RETURNS: NOTHING
  1162. //
  1163. void AttachDFRAMEProperties( HFRAME i_hFrame,
  1164. BYTE* i_pbDFrame )
  1165. {
  1166. //=======================================//
  1167. // Processing the core dataframe fields //
  1168. //=======================================//
  1169. //
  1170. DFRAME& rDFrame = *reinterpret_cast<DFRAME*>(i_pbDFrame);
  1171. // DCommand summary
  1172. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_DCOMMAND_SUMMARY].hProperty,
  1173. sizeof(rDFrame.bCommand), &rDFrame.bCommand, 0, 1, 0);
  1174. // DCommand field
  1175. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_DCOMMAND].hProperty,
  1176. sizeof(rDFrame.bCommand), &rDFrame.bCommand, 0, 2, 0);
  1177. // Control summary
  1178. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_CONTROL_SUMMARY].hProperty,
  1179. sizeof(rDFrame.bControl), &rDFrame.bControl, 0, 1, 0);
  1180. // Control field
  1181. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_CONTROL].hProperty,
  1182. sizeof(rDFrame.bControl), &rDFrame.bControl, 0, 2, 0);
  1183. // Sequence number field
  1184. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_SEQNUM].hProperty,
  1185. sizeof(rDFrame.bSeq), &rDFrame.bSeq, 0, 1, 0);
  1186. // Next receive number field
  1187. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_NEXTRECVNUM].hProperty,
  1188. sizeof(rDFrame.bNRcv), &rDFrame.bNRcv, 0, 1, 0);
  1189. //==================================================//
  1190. // Processing the optional dataframe bitmask fields //
  1191. //==================================================//
  1192. //
  1193. UNALIGNED DFBIG& rDBigFrame = *reinterpret_cast<UNALIGNED DFBIG *>(i_pbDFrame);
  1194. int nBitMaskIndex = 0;
  1195. if ( (rDFrame.bControl & PACKET_CONTROL_SACK_MASK1) == PACKET_CONTROL_SACK_MASK1 )
  1196. {
  1197. SSACKBitmaskContext LowRCVDContext = { rDBigFrame.bNRcv, LOW, RCVD, NULL };
  1198. // Low DWORD of Selective-ACK RCVD Mask summary (TRANSPORT_RCVDMASK1_SUMMARY)
  1199. AttachPropertyInstanceEx(i_hFrame, g_arr_TransportProperties[TRANSPORT_RCVDMASK1_SUMMARY].hProperty,
  1200. sizeof(rDBigFrame.rgMask[nBitMaskIndex]), &rDBigFrame.rgMask[nBitMaskIndex],
  1201. sizeof(LowRCVDContext), &LowRCVDContext,
  1202. 0, 1, 0);
  1203. // Low DWORD of Selective-ACK RCVD Mask field (TRANSPORT_RCVDMASK1)
  1204. AttachBitmaskDWORDProperties(i_hFrame, TRANSPORT_RCVDMASK1, &rDBigFrame.rgMask[nBitMaskIndex], rDBigFrame.bNRcv, LOW, RCVD, 2);
  1205. ++nBitMaskIndex;
  1206. }
  1207. if ( (rDFrame.bControl & PACKET_CONTROL_SACK_MASK2) == PACKET_CONTROL_SACK_MASK2 )
  1208. {
  1209. SSACKBitmaskContext HighRCVDContext = { rDBigFrame.bNRcv, HIGH, RCVD, NULL };
  1210. // High DWORD of Selective-ACK RCVD Mask summary (TRANSPORT_RCVDMASK2_SUMMARY)
  1211. AttachPropertyInstanceEx(i_hFrame, g_arr_TransportProperties[TRANSPORT_RCVDMASK2_SUMMARY].hProperty,
  1212. sizeof(rDBigFrame.rgMask[nBitMaskIndex]), &rDBigFrame.rgMask[nBitMaskIndex],
  1213. sizeof(HighRCVDContext), &HighRCVDContext,
  1214. 0, 1, 0);
  1215. // High DWORD of Selective-ACK RCVD Mask field (TRANSPORT_RCVDMASK2)
  1216. AttachBitmaskDWORDProperties(i_hFrame, TRANSPORT_RCVDMASK2, &rDBigFrame.rgMask[nBitMaskIndex], rDBigFrame.bNRcv, HIGH, RCVD, 2);
  1217. ++nBitMaskIndex;
  1218. }
  1219. if ( (rDFrame.bControl & PACKET_CONTROL_SEND_MASK1) == PACKET_CONTROL_SEND_MASK1 )
  1220. {
  1221. SSACKBitmaskContext LowDONTCAREContext = { rDBigFrame.bSeq, LOW, DONTCARE, NULL };
  1222. // Low DWORD of Selective-ACK DON'T CARE Mask summary (TRANSPORT_DONTCAREMASK1_SUMMARY)
  1223. AttachPropertyInstanceEx(i_hFrame, g_arr_TransportProperties[TRANSPORT_DONTCAREMASK1_SUMMARY].hProperty,
  1224. sizeof(rDBigFrame.rgMask[nBitMaskIndex]), &rDBigFrame.rgMask[nBitMaskIndex],
  1225. sizeof(LowDONTCAREContext), &LowDONTCAREContext,
  1226. 0, 1, 0);
  1227. // Low DWORD of Selective-ACK RCVD Mask field (TRANSPORT_DONTCAREMASK1)
  1228. AttachBitmaskDWORDProperties(i_hFrame, TRANSPORT_RCVDMASK1, &rDBigFrame.rgMask[nBitMaskIndex], rDBigFrame.bSeq, LOW, DONTCARE, 2);
  1229. ++nBitMaskIndex;
  1230. }
  1231. if ( (rDFrame.bControl & PACKET_CONTROL_SEND_MASK2) == PACKET_CONTROL_SEND_MASK2 )
  1232. {
  1233. SSACKBitmaskContext HighDONTCAREContext = { rDBigFrame.bSeq, HIGH, DONTCARE, NULL };
  1234. // High DWORD of Selective-ACK DON'T CARE Mask summary (TRANSPORT_DONTCAREMASK2_SUMMARY)
  1235. AttachPropertyInstanceEx(i_hFrame, g_arr_TransportProperties[TRANSPORT_DONTCAREMASK2_SUMMARY].hProperty,
  1236. sizeof(rDBigFrame.rgMask[nBitMaskIndex]), &rDBigFrame.rgMask[nBitMaskIndex],
  1237. sizeof(HighDONTCAREContext), &HighDONTCAREContext,
  1238. 0, 1, 0);
  1239. // High DWORD of Selective-ACK RCVD Mask field (TRANSPORT_DONTCAREMASK2)
  1240. AttachBitmaskDWORDProperties(i_hFrame, TRANSPORT_RCVDMASK2, &rDBigFrame.rgMask[nBitMaskIndex], rDBigFrame.bSeq, HIGH, DONTCARE, 2);
  1241. }
  1242. } // AttachDFRAMEProperties
  1243. // DESCRIPTION: Maps the Command-Frame properties that exist in a piece of recognized data to specific locations.
  1244. //
  1245. // ARGUMENTS: i_hFrame - Handle of the frame that is being parsed.
  1246. // i_pbCFrame - Pointer to the start of the recognized data.
  1247. //
  1248. // RETURNS: NOTHING
  1249. //
  1250. void AttachCFRAMEProperties( HFRAME i_hFrame,
  1251. BYTE* i_pbCFrame)
  1252. {
  1253. // Processing the core command frame fields
  1254. //
  1255. CFRAME& rCFrame = *reinterpret_cast<CFRAME*>(i_pbCFrame);
  1256. // CCommand summary
  1257. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_CCOMMAND_SUMMARY].hProperty,
  1258. sizeof(rCFrame.bCommand), &rCFrame.bCommand, 0, 1, 0);
  1259. // CCommand field
  1260. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_CCOMMAND].hProperty,
  1261. sizeof(rCFrame.bCommand), &rCFrame.bCommand, 0, 2, 0);
  1262. // ExtOpcode field
  1263. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_EXOPCODE].hProperty,
  1264. sizeof(rCFrame.bExtOpcode), &rCFrame.bExtOpcode, 0, 1, 0);
  1265. if ( rCFrame.bExtOpcode == FRAME_EXOPCODE_SACK )
  1266. {
  1267. //=======================================================//
  1268. // Processing the Selective Acknowledgement Command frame fields //
  1269. //=======================================================//
  1270. //
  1271. SFBIG8* pSFrame = reinterpret_cast<SFBIG8*>(i_pbCFrame);
  1272. // SACK flags summary
  1273. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_SACKFIELDS_SUMMARY].hProperty,
  1274. sizeof(pSFrame->bFlags), &pSFrame->bFlags, 0, 1, 0);
  1275. // SACK flags field
  1276. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_SACKFIELDS].hProperty,
  1277. sizeof(pSFrame->bFlags), &pSFrame->bFlags, 0, 2, 0);
  1278. // Retry field
  1279. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_RETRY].hProperty,
  1280. sizeof(pSFrame->bRetry), &pSFrame->bRetry, 0, 1, 0);
  1281. // Next sequence number field
  1282. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_NEXTSEQNUM].hProperty,
  1283. sizeof(pSFrame->bNSeq), &pSFrame->bNSeq, 0, 1, 0);
  1284. // Next receive number field
  1285. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_NEXTRECVNUM].hProperty,
  1286. sizeof(pSFrame->bNRcv), &pSFrame->bNRcv, 0, 1, 0);
  1287. UNALIGNED ULONG* pulMasks = 0;
  1288. // This is a Protocol version 1.0 frame
  1289. // Timestamp field
  1290. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_TIMESTAMP].hProperty,
  1291. sizeof(pSFrame->tTimestamp), &pSFrame->tTimestamp, 0, 1, 0);
  1292. pulMasks = pSFrame->rgMask;
  1293. //================================================================================//
  1294. // Processing the optional Selective Acknowledgement Command frame bitmask fields //
  1295. //================================================================================//
  1296. //
  1297. int nBitMaskIndex = 0;
  1298. if ( (pSFrame->bFlags & SACK_FLAGS_SACK_MASK1) == SACK_FLAGS_SACK_MASK1 )
  1299. {
  1300. SSACKBitmaskContext LowRCVDContext = { pSFrame->bNRcv, LOW, RCVD, NULL };
  1301. // Low DWORD of Selective-ACK RCVD Mask summary (TRANSPORT_RCVDMASK1_SUMMARY)
  1302. AttachPropertyInstanceEx(i_hFrame, g_arr_TransportProperties[TRANSPORT_RCVDMASK1_SUMMARY].hProperty,
  1303. sizeof(pulMasks[nBitMaskIndex]), &pulMasks[nBitMaskIndex],
  1304. sizeof(LowRCVDContext), &LowRCVDContext,
  1305. 0, 1, 0);
  1306. // Low DWORD of Selective-ACK RCVD Mask field (TRANSPORT_RCVDMASK1)
  1307. AttachBitmaskDWORDProperties(i_hFrame, TRANSPORT_RCVDMASK1, &pulMasks[nBitMaskIndex], pSFrame->bNRcv, LOW, RCVD, 2);
  1308. ++nBitMaskIndex;
  1309. }
  1310. if ( (pSFrame->bFlags & SACK_FLAGS_SACK_MASK2) == SACK_FLAGS_SACK_MASK2 )
  1311. {
  1312. SSACKBitmaskContext HighRCVDContext = { pSFrame->bNRcv, HIGH, RCVD, NULL };
  1313. // High DWORD of Selective-ACK RCVD Mask summary (TRANSPORT_RCVDMASK2_SUMMARY)
  1314. AttachPropertyInstanceEx(i_hFrame, g_arr_TransportProperties[TRANSPORT_RCVDMASK2_SUMMARY].hProperty,
  1315. sizeof(pulMasks[nBitMaskIndex]), &pulMasks[nBitMaskIndex],
  1316. sizeof(HighRCVDContext), &HighRCVDContext,
  1317. 0, 1, 0);
  1318. // High DWORD of Selective-ACK RCVD Mask field (TRANSPORT_RCVDMASK2)
  1319. AttachBitmaskDWORDProperties(i_hFrame, TRANSPORT_RCVDMASK2, &pulMasks[nBitMaskIndex], pSFrame->bNRcv, HIGH, RCVD, 2);
  1320. ++nBitMaskIndex;
  1321. }
  1322. if ( (pSFrame->bFlags & SACK_FLAGS_SEND_MASK1) == SACK_FLAGS_SEND_MASK1 )
  1323. {
  1324. SSACKBitmaskContext LowDONTCAREContext = { pSFrame->bNSeq, LOW, DONTCARE, NULL };
  1325. // Low DWORD of Selective-ACK DON'T CARE Mask summary (TRANSPORT_DONTCAREMASK1_SUMMARY)
  1326. AttachPropertyInstanceEx(i_hFrame, g_arr_TransportProperties[TRANSPORT_DONTCAREMASK1_SUMMARY].hProperty,
  1327. sizeof(pulMasks[nBitMaskIndex]), &pulMasks[nBitMaskIndex],
  1328. sizeof(LowDONTCAREContext), &LowDONTCAREContext,
  1329. 0, 1, 0);
  1330. // Low DWORD of Selective-ACK RCVD Mask field (TRANSPORT_DONTCAREMASK1)
  1331. AttachBitmaskDWORDProperties(i_hFrame, TRANSPORT_RCVDMASK1, &pulMasks[nBitMaskIndex], pSFrame->bNSeq, LOW, DONTCARE, 2);
  1332. ++nBitMaskIndex;
  1333. }
  1334. if ( (pSFrame->bFlags & SACK_FLAGS_SEND_MASK2) == SACK_FLAGS_SEND_MASK2 )
  1335. {
  1336. SSACKBitmaskContext HighDONTCAREContext = { pSFrame->bNSeq, HIGH, DONTCARE, NULL };
  1337. // High DWORD of Selective-ACK DON'T CARE Mask summary (TRANSPORT_DONTCAREMASK2_SUMMARY)
  1338. AttachPropertyInstanceEx(i_hFrame, g_arr_TransportProperties[TRANSPORT_DONTCAREMASK2_SUMMARY].hProperty,
  1339. sizeof(pulMasks[nBitMaskIndex]), &pulMasks[nBitMaskIndex],
  1340. sizeof(HighDONTCAREContext), &HighDONTCAREContext,
  1341. 0, 1, 0);
  1342. // High DWORD of Selective-ACK RCVD Mask field (TRANSPORT_DONTCAREMASK2)
  1343. AttachBitmaskDWORDProperties(i_hFrame, TRANSPORT_RCVDMASK2, &pulMasks[nBitMaskIndex], pSFrame->bNSeq, HIGH, DONTCARE, 2);
  1344. ++nBitMaskIndex;
  1345. }
  1346. }
  1347. else
  1348. {
  1349. //========================================================//
  1350. // Processing the Connection Control Command frame fields //
  1351. //========================================================//
  1352. // Message ID field
  1353. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_MSGID].hProperty,
  1354. sizeof(rCFrame.bMsgID), &rCFrame.bMsgID, 0, 1, 0);
  1355. // Response ID field
  1356. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_RSPID].hProperty,
  1357. sizeof(rCFrame.bRspID), &rCFrame.bRspID, 0, 1, 0);
  1358. // Version number field
  1359. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_VERSION].hProperty,
  1360. sizeof(rCFrame.dwVersion), &rCFrame.dwVersion, 0, 1, 0);
  1361. // Session ID field
  1362. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_SESSIONID].hProperty,
  1363. sizeof(rCFrame.dwSessID), &rCFrame.dwSessID, 0, 1, 0);
  1364. // Timestamp field
  1365. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_TIMESTAMP].hProperty,
  1366. sizeof(rCFrame.tTimestamp), &rCFrame.tTimestamp, 0, 1, 0);
  1367. }
  1368. } // AttachCFRAMEProperties
  1369. // Platform independent memory accessor of big endian words
  1370. inline WORD ReadBigEndianWord( BYTE* i_pbData )
  1371. {
  1372. return (*i_pbData << 8) | *(i_pbData+1);
  1373. }
  1374. } // Anonymous namespace
  1375. // DESCRIPTION: Maps the properties that exist in a piece of recognized data to specific locations.
  1376. //
  1377. // ARGUMENTS: i_hFrame - Handle of the frame that is being parsed.
  1378. // i_pbMacFram - Pointer to the first byte in the frame.
  1379. // i_pbTransportFrame - Pointer to the start of the recognized data.
  1380. // i_dwMacType - MAC value of the first protocol in a frame. Typically, the i_dwMacType value is used
  1381. // when the parser must identify the first protocol in the frame. Can be one of the following:
  1382. // MAC_TYPE_ETHERNET = 802.3, MAC_TYPE_TOKENRING = 802.5, MAC_TYPE_FDDI ANSI = X3T9.5.
  1383. // i_dwBytesLeft - The remaining number of bytes in a frame (starting from the beginning of the recognized data).
  1384. // i_hPrevProtocol - Handle of the previous protocol.
  1385. // i_dwPrevProtOffset - Offset of the previous protocol (starting from the beginning of the frame).
  1386. // i_dwptrInstData - Pointer to the instance data that the previous protocol provides.
  1387. //
  1388. // RETURNS: Must return NULL
  1389. //
  1390. DPLAYPARSER_API BYTE* BHAPI TransportAttachProperties( HFRAME i_hFrame,
  1391. ULPBYTE i_upbMacFrame,
  1392. ULPBYTE i_upbTransportFrame,
  1393. DWORD i_dwMacType,
  1394. DWORD i_dwBytesLeft,
  1395. HPROTOCOL i_hPrevProtocol,
  1396. DWORD i_dwPrevProtOffset,
  1397. DWORD_PTR i_dwptrInstData )
  1398. {
  1399. // TODO: Use HelpID in AttachPropertyInstance
  1400. // Check if the packet is a KeepAlive
  1401. const size_t sztTransportHeaderSize = TransportHeaderSize(i_upbTransportFrame);
  1402. const DFRAME& rDFrame = *reinterpret_cast<DFRAME*>(i_upbTransportFrame);
  1403. size_t sztTransportFrameSize = i_dwptrInstData;
  1404. // If an empty dataframe and not the last packet in the stream, than it's a KeepAlive
  1405. BOOL bKeepAlive = ( (sztTransportHeaderSize == sztTransportFrameSize) &&
  1406. ((rDFrame.bControl & PACKET_CONTROL_END_STREAM) != PACKET_CONTROL_END_STREAM) );
  1407. //===================//
  1408. // Attach Properties //
  1409. //===================//
  1410. //
  1411. // Transport summary line
  1412. AttachPropertyInstanceEx(i_hFrame, g_arr_TransportProperties[TRANSPORT_SUMMARY].hProperty,
  1413. sztTransportHeaderSize, i_upbTransportFrame,
  1414. sizeof(BOOL), &bKeepAlive,
  1415. 0, 0, 0);
  1416. #if defined(PARSE_DPLAY_TRANSPORT)
  1417. if ( (rDFrame.bCommand & PACKET_COMMAND_DATA) == PACKET_COMMAND_DATA )
  1418. {
  1419. AttachDFRAMEProperties(i_hFrame, i_upbTransportFrame);
  1420. enum
  1421. {
  1422. USERDATA_BITMASK = ~(PACKET_COMMAND_USER_1 | PACKET_COMMAND_USER_2)
  1423. };
  1424. if ( (rDFrame.bCommand | USERDATA_BITMASK) == USERDATA_BITMASK )
  1425. {
  1426. // User data (TRANSPORT_USERDATA)
  1427. AttachPropertyInstance(i_hFrame, g_arr_TransportProperties[TRANSPORT_USERDATA].hProperty,
  1428. sztTransportFrameSize - sztTransportHeaderSize, i_upbTransportFrame + sztTransportHeaderSize, 0, 1, 0);
  1429. }
  1430. }
  1431. else
  1432. {
  1433. AttachCFRAMEProperties(i_hFrame, i_upbTransportFrame);
  1434. }
  1435. #endif // PARSE_DPLAY_TRANSPORT
  1436. return NULL;
  1437. } // TransportAttachProperties
  1438. // DESCRIPTION: Formats the data that is displayed in the details pane of the Network Monitor UI.
  1439. //
  1440. // ARGUMENTS: i_hFrame - Handle of the frame that is being parsed.
  1441. // i_pbMacFrame - Pointer to the first byte of a frame.
  1442. // i_pbCoreFrame - Pointer to the beginning of the protocol data in a frame.
  1443. // i_dwPropertyInsts - Number of PROPERTYINST structures provided by lpPropInst.
  1444. // i_pPropInst - Pointer to an array of PROPERTYINST structures.
  1445. //
  1446. // RETURNS: If the function is successful, the return value is a pointer to the first byte after the recognized data in a frame,
  1447. // or NULL if the recognized data is the last piece of data in a frame. If the function is unsuccessful, the return value
  1448. // is the initial value of i_pbTransportFrame.
  1449. //
  1450. DPLAYPARSER_API DWORD BHAPI TransportFormatProperties( HFRAME i_hFrame,
  1451. ULPBYTE i_upbMacFrame,
  1452. ULPBYTE i_upbTransportFrame,
  1453. DWORD i_dwPropertyInsts,
  1454. LPPROPERTYINST i_pPropInst )
  1455. {
  1456. // Loop through the property instances...
  1457. while( i_dwPropertyInsts-- > 0)
  1458. {
  1459. // ...and call the formatter for each
  1460. reinterpret_cast<FORMAT>(i_pPropInst->lpPropertyInfo->InstanceData)(i_pPropInst);
  1461. ++i_pPropInst;
  1462. }
  1463. return NMERR_SUCCESS;
  1464. }
  1465. // DESCRIPTION: Notifies Network Monitor that Transport protocol parser exists.
  1466. //
  1467. // ARGUMENTS: NONE
  1468. //
  1469. // RETURNS: TRUE - success, FALSE - failure
  1470. //
  1471. bool CreateTransportProtocol( void )
  1472. {
  1473. // The entry points to the export functions that Network Monitor uses to operate the parser
  1474. ENTRYPOINTS TransportEntryPoints =
  1475. {
  1476. // TransportParser Entry Points
  1477. TransportRegister,
  1478. TransportDeregister,
  1479. TransportRecognizeFrame,
  1480. TransportAttachProperties,
  1481. TransportFormatProperties
  1482. };
  1483. // The first active instance of this parser needs to register with the kernel
  1484. g_hTransportProtocol = CreateProtocol("DPLAYTRANSPORT", &TransportEntryPoints, ENTRYPOINTS_SIZE);
  1485. return (g_hTransportProtocol ? TRUE : FALSE);
  1486. } // CreateTransportProtocol
  1487. // DESCRIPTION: Removes the Transport protocol parser from the Network Monitor's database of parsers
  1488. //
  1489. // ARGUMENTS: NONE
  1490. //
  1491. // RETURNS: NOTHING
  1492. //
  1493. void DestroyTransportProtocol( void )
  1494. {
  1495. DestroyProtocol(g_hTransportProtocol);
  1496. } // DestroyTransportProtocol