windows-nt/Source/XPSP1/NT/multimedia/directx/dplay/tools/parsers/spparser.cpp
2020-09-26 16:20:57 +08:00

911 lines
29 KiB
C++

//=============================================================================
// FILE: SPParser.cpp
//
// Description: DirectPlay Service Provider Parser
//
//
// Modification History:
//
// Michael Milirud 08/Aug/2000 Created
//=============================================================================
//#define FRAME_NAMES
//#define FRAME_DROPS
//==================//
// Standard headers //
//==================//
#include <winsock2.h>
#include <wsipx.h>
#include <tchar.h>
//=====================//
// Proprietary headers //
//=====================//
#include "dpaddr.h" // DPNA_DEFAULT_PORT definition
// Prototypes
#include "SPParser.hpp"
namespace DPlaySP
{
// SP protocol header
#include "MessageStructures.h"
} // DPlaySP namespace
namespace
{
HPROTOCOL g_hSPProtocol;
//=============================//
// Return Address Family field //-----------------------------------------------------------------------------------
//=============================//
LABELED_BYTE arr_RetAddrFamilyByteLabels[] = { { AF_IPX, "IPX protocol" },
{ AF_INET, "IP protocol" } };
SET LabeledRetAddrFamilyByteSet = { sizeof(arr_RetAddrFamilyByteLabels) / sizeof(LABELED_BYTE), arr_RetAddrFamilyByteLabels };
//================//
// Data Tag field //------------------------------------------------------------------------------------------------
//================//
LABELED_BYTE arr_CommandByteLabels[] = { { ESCAPED_USER_DATA_KIND, "DPlay v8 Transport data follows" },
{ ENUM_DATA_KIND, "Enumeration Query" },
{ ENUM_RESPONSE_DATA_KIND, "Response to Enumeration Query" },
{ PROXIED_ENUM_DATA_KIND, "Proxied Enumeration Query" } };
SET LabeledCommandByteSet = { sizeof(arr_CommandByteLabels) / sizeof(LABELED_BYTE), arr_CommandByteLabels };
////////////////////////////////
// Custom Property Formatters //=====================================================================================
////////////////////////////////
// DESCRIPTION: Custom description formatter for the Service Provider packet summary
//
// ARGUMENTS: io_pProperyInstance - Data of the property's instance
//
// RETURNS: NOTHING
//
VOID WINAPIV FormatPropertyInstance_SPSummary( LPPROPERTYINST io_pProperyInstance )
{
using namespace DPlaySP;
// Check what SP frame we are dealing with
PREPEND_BUFFER& rSPFrame = *reinterpret_cast<PREPEND_BUFFER*>(io_pProperyInstance->lpData);
//
switch ( rSPFrame.GenericHeader.bSPCommandByte )
{
case ENUM_DATA_KIND: // Service Provider Query
{
strcpy(io_pProperyInstance->szPropertyText, "Enumeration Request");
break;
}
case ENUM_RESPONSE_DATA_KIND: // Service Provider Response
{
strcpy(io_pProperyInstance->szPropertyText, "Enumeration Response");
break;
}
case PROXIED_ENUM_DATA_KIND: // Service Provider Proxied Query
{
strcpy(io_pProperyInstance->szPropertyText, "Proxied Enumeration Request");
break;
}
case ESCAPED_USER_DATA_KIND: // DPlay v8 Transport protocol frame follows
default:
{
strcpy(io_pProperyInstance->szPropertyText, "User Data");
break;
}
}
} // FormatPropertyInstance_SPSummary
//==================//
// Properties table //-----------------------------------------------------------------------------------------------
//==================//
PROPERTYINFO g_arr_SPProperties[] =
{
// SP packet summary property (SP_SUMMARY)
{
0, // handle placeholder (MBZ)
0, // reserved (MBZ)
"", // label
"DPlay Service Provider packet", // status-bar comment
PROP_TYPE_SUMMARY, // data type
PROP_QUAL_NONE, // data type qualifier
NULL, // labeled bit set
512, // description's maximum length
FormatPropertyInstance_SPSummary // generic formatter
},
// Leading Zero property (SP_LEADZERO)
{
0, // handle placeholder (MBZ)
0, // reserved (MBZ)
"Leading zero tag", // label
"Leading zero tag field", // status-bar comment
PROP_TYPE_BYTE, // data type
PROP_QUAL_NONE, // data type qualifier.
NULL, // labeled byte set
64, // description's maximum length
FormatPropertyInstance // generic formatter
},
// Data Tag property (SP_COMMAND)
{
0, // handle placeholder (MBZ)
0, // reserved (MBZ)
"Command", // label
"Command field", // status-bar comment
PROP_TYPE_BYTE, // data type
PROP_QUAL_LABELED_SET, // data type qualifier.
&LabeledCommandByteSet, // labeled byte set
512, // description's maximum length
FormatPropertyInstance // generic formatter
},
// Enumeration Key property (SP_ENUMPAYLOAD)
{
0, // handle placeholder (MBZ)
0, // reserved (MBZ)
"Enum Payload", // label
"Enumeration Payload field", // status-bar comment
PROP_TYPE_WORD, // data type
PROP_QUAL_NONE, // data type qualifier.
NULL, // labeled byte set
64, // description's maximum length
FormatPropertyInstance // generic formatter
},
// Enumeration Key property (SP_ENUMKEY)
{
0, // handle placeholder (MBZ)
0, // reserved (MBZ)
"Enum Key", // label
"Enumeration Key field", // status-bar comment
PROP_TYPE_WORD, // data type
PROP_QUAL_NONE, // data type qualifier.
NULL, // labeled byte set
64, // description's maximum length
FormatPropertyInstance // generic formatter
},
// Enumeration Response Key property (SP_ENUMRESPKEY)
{
0, // handle placeholder (MBZ)
0, // reserved (MBZ)
"Enum Response Key", // label
"Enumeration Response Key", // status-bar comment
PROP_TYPE_WORD, // data type
PROP_QUAL_NONE, // data type qualifier.
NULL, // labeled byte set
64, // description's maximum length
FormatPropertyInstance // generic formatter
},
// Enumeration Response Key property (SP_RTTINDEX)
{
0, // handle placeholder (MBZ)
0, // reserved (MBZ)
"RTT Index", // label
"RTT Index field", // status-bar comment
PROP_TYPE_WORD, // data type
PROP_QUAL_NONE, // data type qualifier.
NULL, // labeled byte set
64, // description's maximum length
FormatPropertyInstance // generic formatter
},
// Size of the return address property (SP_RETADDRSIZE)
{
0, // handle placeholder (MBZ)
0, // reserved (MBZ)
"Return Address's Size", // label
"Size of the return address", // status-bar comment
PROP_TYPE_BYTE, // data type
PROP_QUAL_NONE, // data type qualifier.
NULL, // labeled byte set
64, // description's maximum length
FormatPropertyInstance // generic formatter
},
// Return Address Socket Family property (SP_RETADDRFAMILY)
{
0, // handle placeholder (MBZ)
0, // reserved (MBZ)
"Socket Family", // label
"Socket Family field", // status-bar comment
PROP_TYPE_WORD, // data type
PROP_QUAL_LABELED_SET, // data type qualifier.
&LabeledRetAddrFamilyByteSet, // labeled byte set
512, // description's maximum length
FormatPropertyInstance // generic formatter
},
// Return Address Socket Family property (SP_RETADDR_IPX)
{
0, // handle placeholder (MBZ)
0, // reserved (MBZ)
"IPX Address", // label
"IPX Address field", // status-bar comment
PROP_TYPE_IPX_ADDRESS, // data type
PROP_QUAL_NONE, // data type qualifier.
NULL, // labeled byte set
64, // description's maximum length
FormatPropertyInstance // generic formatter
},
// Return Address Socket (SP_RETADDRSOCKET_IPX)
{
0, // handle placeholder (MBZ)
0, // reserved (MBZ)
"Socket", // label
"Socket field", // status-bar comment
PROP_TYPE_WORD, // data type
PROP_QUAL_NONE, // data type qualifier.
NULL, // labeled byte set
64, // description's maximum length
FormatPropertyInstance // generic formatter
},
// Return Address Socket Family property (SP_RETADDR_IP)
{
0, // handle placeholder (MBZ)
0, // reserved (MBZ)
"IP Address", // label
"IP Address field", // status-bar comment
PROP_TYPE_IP_ADDRESS, // data type
PROP_QUAL_NONE, // data type qualifier.
NULL, // labeled byte set
64, // description's maximum length
FormatPropertyInstance // generic formatter
},
// Return Address Socket (SP_RETADDRPORT_IP)
{
0, // handle placeholder (MBZ)
0, // reserved (MBZ)
"Port", // label
"Port field", // status-bar comment
PROP_TYPE_WORD, // data type
PROP_QUAL_NONE, // data type qualifier.
NULL, // labeled byte set
64, // description's maximum length
FormatPropertyInstance // generic formatter
},
// User Data (SP_USERDATA)
{
0, // handle placeholder (MBZ)
0, // reserved (MBZ)
"User Data", // label
"User Data", // status-bar comment
PROP_TYPE_RAW_DATA, // data type
PROP_QUAL_NONE, // data type qualifier.
NULL, // labeled bit set
64, // description's maximum length
FormatPropertyInstance // generic formatter
}
};
enum
{
nNUM_OF_SP_PROPS = sizeof(g_arr_SPProperties) / sizeof(PROPERTYINFO)
};
// Properties' indices
enum
{
SP_SUMMARY = 0,
SP_LEADZERO,
SP_COMMAND,
SP_ENUMPAYLOAD,
SP_ENUMKEY,
SP_ENUMRESPKEY,
SP_RTTINDEX,
SP_RETADDRSIZE,
SP_RETADDRFAMILY,
SP_RETADDR_IPX,
SP_RETADDRSOCKET_IPX,
SP_RETADDR_IP,
SP_RETADDRPORT_IP,
SP_USERDATA
};
// Platform independent memory accessor of big endian words
inline WORD ReadBigEndianWord( BYTE* i_pbData )
{
return (*i_pbData << 8) | *(i_pbData+1);
}
// DESCRIPTION: DPlay packet validation predicate.
//
// ARGUMENTS: i_hFrame - The handle to the frame that contains the data.
// i_hPrevProtocol - Handle of the previous protocol.
// i_pbMacFrame - The pointer to the first byte of the frame; the pointer provides a way to view
// the data that the other parsers recognize.
//
// RETURNS: DPlay packet = TRUE; NOT a DPlay packet = FALSE
//
bool IsDPlayPacket( HFRAME i_hFrame, HPROTOCOL i_hPrevProtocol, LPBYTE i_pbMacFrame )
{
LPPROTOCOLINFO pPrevProtocolInfo = GetProtocolInfo(i_hPrevProtocol);
DWORD dwPrevProtocolOffset = GetProtocolStartOffsetHandle(i_hFrame, i_hPrevProtocol);
WORD wSrcPort, wDstPort;
if ( strncmp(reinterpret_cast<char*>(pPrevProtocolInfo->ProtocolName), "UDP", sizeof(pPrevProtocolInfo->ProtocolName)) == 0 )
{
// Extracting the source and destination ports of the packet from its UDP header
wSrcPort = ReadBigEndianWord(i_pbMacFrame + dwPrevProtocolOffset);
wDstPort = ReadBigEndianWord(i_pbMacFrame + dwPrevProtocolOffset + 2);
}
else if ( strncmp(reinterpret_cast<char*>(pPrevProtocolInfo->ProtocolName), "IPX", sizeof(pPrevProtocolInfo->ProtocolName)) == 0 )
{
// Extracting the source and destination ports of the packet from its IPX header
wSrcPort = ReadBigEndianWord(i_pbMacFrame + dwPrevProtocolOffset + 16); // source address socket
wDstPort = ReadBigEndianWord(i_pbMacFrame + dwPrevProtocolOffset + 28); // destination address socket
}
else
{
// Should never happen!
return false;
}
//===========//
// Constants //
//===========//
//
static bool bTriedRetrievingUserPorts = false;
static bool bRetrievedUserPorts = false;
static DWORD dwMinUserPort, dwMaxUserPort;
// Retrieval from the registry is attempted only once
if ( !bTriedRetrievingUserPorts )
{
bTriedRetrievingUserPorts = true;
HKEY hKey = NULL;
if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Microsoft\\DirectPlay\\Parsers"), 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
DWORD dwType = NULL;
DWORD dwCount = sizeof(DWORD);
if (RegQueryValueEx(hKey, _T("MinUserPort"), NULL, &dwType, (LPBYTE)&dwMinUserPort, &dwCount) == ERROR_SUCCESS &&
RegQueryValueEx(hKey, _T("MaxUserPort"), NULL, &dwType, (LPBYTE)&dwMaxUserPort, &dwCount) == ERROR_SUCCESS )
{
bRetrievedUserPorts = true;
}
RegCloseKey(hKey);
}
}
if ( bRetrievedUserPorts &&
((wSrcPort >= dwMinUserPort) && (wSrcPort <= dwMaxUserPort)) &&
((wDstPort >= dwMinUserPort) && (wDstPort <= dwMaxUserPort)) )
{
// Is a valid DPlay packet
return true;
}
// Make sure both endpoints are using the SP port range [2302, 2400], or the DPNServer port {6073}, or [MinUsePort, MaxUserPort] (if provided by the user)
WORD wPort = wSrcPort;
for ( int nPorts = 0; nPorts < 2; ++nPorts, wPort = wDstPort )
{
if (
(
!bRetrievedUserPorts ||
(wPort < dwMinUserPort) ||
(wPort > dwMaxUserPort)
)
&&
(
(wPort < BASE_DPLAY8_PORT) ||
(wPort > MAX_DPLAY8_PORT)
)
&&
(
wPort != DPNA_DPNSVR_PORT
)
)
{
// Not a valid DPlay packet
return false;
}
}
// Is a valid DPlay packet
return true;
} // IsDPlayPacket
} // anonymous namespace
// DESCRIPTION: Creates and fills-in a properties database for the protocol.
// Network Monitor uses this database to determine which properties the protocol supports.
//
// ARGUMENTS: i_hSPProtocol - The handle of the protocol provided by the Network Monitor.
//
// RETURNS: NOTHING
//
DPLAYPARSER_API VOID BHAPI SPRegister( HPROTOCOL i_hSPProtocol )
{
CreatePropertyDatabase(i_hSPProtocol, nNUM_OF_SP_PROPS);
// Add the properties to the database
for( int nProp=0; nProp < nNUM_OF_SP_PROPS; ++nProp )
{
AddProperty(i_hSPProtocol, &g_arr_SPProperties[nProp]);
}
} // SPRegister
// DESCRIPTION: Frees the resources used to create the protocol property database.
//
// ARGUMENTS: i_hSPProtocol - The handle of the protocol provided by the Network Monitor.
//
// RETURNS: NOTHING
//
DPLAYPARSER_API VOID WINAPI SPDeregister( HPROTOCOL i_hProtocol )
{
DestroyPropertyDatabase(i_hProtocol);
} // SPDeregister
namespace
{
// DESCRIPTION: Parses the SP frame to find its size (in bytes) NOT including the user data
//
// ARGUMENTS: i_pbSPFrame - Pointer to the start of the unclaimed data. Typically, the unclaimed data is located
// in the middle of a frame because a previous parser has claimed data before this parser.
//
// RETURNS: Size of the specified SP frame (in bytes)
//
int SPHeaderSize( LPBYTE i_pbSPFrame )
{
using namespace DPlaySP;
// Check what SP frame we are dealing with
PREPEND_BUFFER& rSPFrame = *reinterpret_cast<PREPEND_BUFFER*>(i_pbSPFrame);
//
switch ( rSPFrame.GenericHeader.bSPCommandByte )
{
case ENUM_DATA_KIND: // Service Provider Query
{
return sizeof(rSPFrame.EnumDataHeader);
}
case ENUM_RESPONSE_DATA_KIND: // Service Provider Response
{
return sizeof(rSPFrame.EnumResponseDataHeader);
}
case PROXIED_ENUM_DATA_KIND: // Service Provider Proxied Query
{
return sizeof(rSPFrame.ProxiedEnumDataHeader);
}
case ESCAPED_USER_DATA_KIND: // user data starting with zero
{
return sizeof(rSPFrame.EscapedUserDataHeader);
}
default: // user data starting with a nonzero byte
{
return 0; // no header
}
}
} // SPHeaderSize
} // Anonymous namespace
// DESCRIPTION: Indicates whether a piece of data is recognized as the protocol that the parser detects.
//
// ARGUMENTS: i_hFrame - The handle to the frame that contains the data.
// i_pbMacFrame - The pointer to the first byte of the frame; the pointer provides a way to view
// the data that the other parsers recognize.
// i_pbSPFrame - Pointer to the start of the unclaimed data. Typically, the unclaimed data is located
// in the middle of a frame because a previous parser has claimed data before this parser.
// i_dwMacType - MAC value of the first protocol in a frame. Typically, the i_dwMacType value is used
// when the parser must identify the first protocol in the frame. Can be one of the following:
// MAC_TYPE_ETHERNET = 802.3, MAC_TYPE_TOKENRING = 802.5, MAC_TYPE_FDDI ANSI = X3T9.5.
// i_dwBytesLeft - The remaining number of bytes from a location in the frame to the end of the frame.
// i_hPrevProtocol - Handle of the previous protocol.
// i_dwPrevProtOffset - Offset of the previous protocol (from the beginning of the frame).
// o_pdwProtocolStatus - Protocol status indicator. Must be one of the following: PROTOCOL_STATUS_RECOGNIZED,
// PROTOCOL_STATUS_NOT_RECOGNIZED, PROTOCOL_STATUS_CLAIMED, PROTOCOL_STATUS_NEXT_PROTOCOL.
// o_phNextProtocol - Placeholder for the handle of the next protocol. This parameter is set when the parser identifies
// the protocol that follows its own protocol.
// io_pdwptrInstData - On input, a pointer to the instance data from the previous protocol.
// On output, a pointer to the instance data for the current protocol.
//
// RETURNS: If the function is successful, the return value is a pointer to the first byte after the recognized parser data.
// If the parser claims all the remaining data, the return value is NULL. If the function is unsuccessful, the return
// value is the initial value of the i_pbSPFrame parameter.
//
DPLAYPARSER_API LPBYTE BHAPI SPRecognizeFrame( HFRAME i_hFrame,
ULPBYTE i_upbMacFrame,
ULPBYTE i_upbSPFrame,
DWORD i_dwMacType,
DWORD i_dwBytesLeft,
HPROTOCOL i_hPrevProtocol,
DWORD i_dwPrevProtOffset,
LPDWORD o_pdwProtocolStatus,
LPHPROTOCOL o_phNextProtocol,
PDWORD_PTR io_pdwptrInstData )
{
using namespace DPlaySP;
// Validate the amount of unclaimed data
enum
{
nMIN_SPHeaderSize = sizeof(PREPEND_BUFFER::_GENERIC_HEADER)
};
// Validate the packet as DPlay SP type
if ( (i_dwBytesLeft < nMIN_SPHeaderSize) ||
!IsDPlayPacket(i_hFrame, i_hPrevProtocol, i_upbMacFrame) )
{
// Assume the unclaimed data is not recognizable
*o_pdwProtocolStatus = PROTOCOL_STATUS_NOT_RECOGNIZED;
return i_upbSPFrame;
}
//==========================//
// Get the DPlay frame size //
//==========================//
LPPROTOCOLINFO pPrevProtocolInfo = GetProtocolInfo(i_hPrevProtocol);
WORD wDPlayFrameSize = 0;
if ( strncmp(reinterpret_cast<char*>(pPrevProtocolInfo->ProtocolName), "UDP", sizeof(pPrevProtocolInfo->ProtocolName)) == 0 )
{
// Extracting the UDP frame size
WORD wUDPFrameSize = ReadBigEndianWord(i_upbMacFrame + i_dwPrevProtOffset + 4);
enum { nUDP_HEADER_SIZE = 8 };
wDPlayFrameSize = wUDPFrameSize - nUDP_HEADER_SIZE;
}
else if ( strncmp(reinterpret_cast<char*>(pPrevProtocolInfo->ProtocolName), "IPX", sizeof(pPrevProtocolInfo->ProtocolName)) == 0 )
{
// Extracting the IPX frame size
WORD wIPXFrameSize = ReadBigEndianWord(i_upbMacFrame + i_dwPrevProtOffset + 2); // source address socket
enum { nIPX_HEADER_SIZE = 30 };
wDPlayFrameSize = wIPXFrameSize - nIPX_HEADER_SIZE;
}
else
{
; // TODO: ASSERT HERE
}
// Pass along the size of the Transport frame
DWORD_PTR dwptrTransportFrameSize = wDPlayFrameSize - SPHeaderSize(i_upbSPFrame);
*io_pdwptrInstData = dwptrTransportFrameSize;
PREPEND_BUFFER& rSPFrame = *reinterpret_cast<PREPEND_BUFFER*>(i_upbSPFrame);
if ( rSPFrame.GenericHeader.bSPLeadByte == SP_HEADER_LEAD_BYTE ) // SP packet
{
*o_pdwProtocolStatus = PROTOCOL_STATUS_RECOGNIZED;
*o_phNextProtocol = NULL;
if ( rSPFrame.GenericHeader.bSPCommandByte == ESCAPED_USER_DATA_KIND ) // user data starting with zero (non-DPlay v8 Transport packet)
{
*o_pdwProtocolStatus = PROTOCOL_STATUS_RECOGNIZED;
return i_upbSPFrame + sizeof(PREPEND_BUFFER::_ESCAPED_USER_DATA_HEADER);
}
}
else // user data (DPlay v8 Transport packet)
{
// Notify NetMon about the handoff protocol
*o_pdwProtocolStatus = PROTOCOL_STATUS_NEXT_PROTOCOL;
*o_phNextProtocol = GetProtocolFromName("DPLAYTRANSPORT");
return i_upbSPFrame;
}
// Claim the rest of the data
return NULL;
} // SPRecognizeFrame
// DESCRIPTION: Maps the properties that exist in a piece of recognized data to specific locations.
//
// ARGUMENTS: i_hFrame - Handle of the frame that is being parsed.
// i_pbMacFram - Pointer to the first byte in the frame.
// i_pbSPFrame - Pointer to the start of the recognized data.
// i_dwMacType - MAC value of the first protocol in a frame. Typically, the i_dwMacType value is used
// when the parser must identify the first protocol in the frame. Can be one of the following:
// MAC_TYPE_ETHERNET = 802.3, MAC_TYPE_TOKENRING = 802.5, MAC_TYPE_FDDI ANSI = X3T9.5.
// i_dwBytesLeft - The remaining number of bytes in a frame (starting from the beginning of the recognized data).
// i_hPrevProtocol - Handle of the previous protocol.
// i_dwPrevProtOffset - Offset of the previous protocol (starting from the beginning of the frame).
// i_dwptrInstData - Pointer to the instance data that the previous protocol provides.
//
// RETURNS: Must return NULL
//
DPLAYPARSER_API LPBYTE BHAPI SPAttachProperties( HFRAME i_hFrame,
ULPBYTE i_upbMacFrame,
ULPBYTE i_upbSPFrame,
DWORD i_dwMacType,
DWORD i_dwBytesLeft,
HPROTOCOL i_hPrevProtocol,
DWORD i_dwPrevProtOffset,
DWORD_PTR i_dwptrInstData )
{
using namespace DPlaySP;
//===================//
// Attach Properties //
//===================//
// Summary line
AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_SUMMARY].hProperty,
i_dwBytesLeft, i_upbSPFrame, 0, 0, 0);
// Protection against NetMon
if ( *i_upbSPFrame )
{
return NULL;
}
// Check what SP frame we are dealing with
PREPEND_BUFFER& rSPFrame = *reinterpret_cast<PREPEND_BUFFER*>(i_upbSPFrame);
// Leading Zero tag field
AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_LEADZERO].hProperty,
sizeof(rSPFrame.GenericHeader.bSPLeadByte), &rSPFrame.GenericHeader.bSPLeadByte, 0, 1, 0);
// Command field
AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_COMMAND].hProperty,
sizeof(rSPFrame.GenericHeader.bSPCommandByte), &rSPFrame.GenericHeader.bSPCommandByte, 0, 1, 0);
switch ( rSPFrame.GenericHeader.bSPCommandByte )
{
case ESCAPED_USER_DATA_KIND: // user data starting with zero
{
break;
}
case ENUM_DATA_KIND: // Service Provider's Enumeration Request
{
// Enum payload field
AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_ENUMPAYLOAD].hProperty,
sizeof(rSPFrame.EnumDataHeader.wEnumPayload), &rSPFrame.EnumDataHeader.wEnumPayload, 0, 1, 0);
// Enum Key field
DWORD dwEnumKey = rSPFrame.EnumDataHeader.wEnumPayload & ~ENUM_RTT_MASK;
AttachPropertyInstanceEx(i_hFrame, g_arr_SPProperties[SP_ENUMKEY].hProperty,
sizeof(rSPFrame.EnumDataHeader.wEnumPayload), &rSPFrame.EnumDataHeader.wEnumPayload,
sizeof(dwEnumKey), &dwEnumKey,
0, 2, 0);
// RTT index field
BYTE byRTTIndex = rSPFrame.EnumDataHeader.wEnumPayload & ENUM_RTT_MASK;
AttachPropertyInstanceEx(i_hFrame, g_arr_SPProperties[SP_RTTINDEX].hProperty,
sizeof(rSPFrame.EnumDataHeader.wEnumPayload), &rSPFrame.EnumDataHeader.wEnumPayload,
sizeof(byRTTIndex), &byRTTIndex,
0, 2, 0);
break;
}
case ENUM_RESPONSE_DATA_KIND: // Service Provider's Enumeration Response
{
// Enum payload field
AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_ENUMPAYLOAD].hProperty,
sizeof(rSPFrame.EnumResponseDataHeader.wEnumResponsePayload), &rSPFrame.EnumResponseDataHeader.wEnumResponsePayload, 0, 1, 0);
// Enum Key field
DWORD dwEnumKey = rSPFrame.EnumResponseDataHeader.wEnumResponsePayload & ~ENUM_RTT_MASK;
AttachPropertyInstanceEx(i_hFrame, g_arr_SPProperties[SP_ENUMRESPKEY].hProperty,
sizeof(rSPFrame.EnumResponseDataHeader.wEnumResponsePayload), &rSPFrame.EnumResponseDataHeader.wEnumResponsePayload,
sizeof(dwEnumKey), &dwEnumKey,
0, 2, 0);
// RTT index field
BYTE byRTTIndex = rSPFrame.EnumDataHeader.wEnumPayload & ENUM_RTT_MASK;
AttachPropertyInstanceEx(i_hFrame, g_arr_SPProperties[SP_RTTINDEX].hProperty,
sizeof(rSPFrame.EnumResponseDataHeader.wEnumResponsePayload), &rSPFrame.EnumResponseDataHeader.wEnumResponsePayload,
sizeof(byRTTIndex), &byRTTIndex,
0, 2, 0);
break;
}
case PROXIED_ENUM_DATA_KIND: // Service Provider's Proxied Enumeration Query
{
// Return Address Size field
AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDRSIZE].hProperty,
sizeof(rSPFrame.ProxiedEnumDataHeader.ReturnAddress), &rSPFrame.ProxiedEnumDataHeader.ReturnAddress, 0, 1, 0);
// Enum Key field
AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_ENUMKEY].hProperty,
sizeof(rSPFrame.ProxiedEnumDataHeader.wEnumKey), &rSPFrame.ProxiedEnumDataHeader.wEnumKey, 0, 1, 0);
// Return Address Socket Address Family field
AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDRFAMILY].hProperty,
sizeof(rSPFrame.ProxiedEnumDataHeader.ReturnAddress.sa_family), &rSPFrame.ProxiedEnumDataHeader.ReturnAddress.sa_family, 0, 1, 0);
switch ( rSPFrame.ProxiedEnumDataHeader.ReturnAddress.sa_family )
{
case AF_IPX:
{
SOCKADDR_IPX& rIPXAddress = *reinterpret_cast<SOCKADDR_IPX*>(&rSPFrame.ProxiedEnumDataHeader.ReturnAddress);
// Return Address field (IPX Network Number + Node Number)
AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDR_IPX].hProperty,
sizeof(rIPXAddress.sa_netnum) + sizeof(rIPXAddress.sa_nodenum), &rIPXAddress.sa_netnum, 0, 1, 0);
// Return Address Socket Address IPX Socket Number field
AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDRSOCKET_IPX].hProperty,
sizeof(rIPXAddress.sa_socket), &rIPXAddress.sa_socket, 0, 1, 0);
break;
}
case AF_INET:
{
SOCKADDR_IN& rIPAddress = *reinterpret_cast<SOCKADDR_IN*>(&rSPFrame.ProxiedEnumDataHeader.ReturnAddress);
// Return Address field (IP Address)
AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDR_IP].hProperty,
sizeof(rIPAddress.sin_addr), &rIPAddress.sin_addr, 0, 1, 0);
// Return Address Port field
AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_RETADDRPORT_IP].hProperty,
sizeof(rIPAddress.sin_port), &rIPAddress.sin_port, 0, 1, 0);
break;
}
default:
{
// TODO: DPF(0, "Unknown socket type!");
break;
}
}
break;
}
}
size_t sztSPHeaderSize = SPHeaderSize(i_upbSPFrame);
if ( i_dwBytesLeft > sztSPHeaderSize )
{
size_t sztUserDataSize = i_dwBytesLeft - sztSPHeaderSize;
// User data
AttachPropertyInstance(i_hFrame, g_arr_SPProperties[SP_USERDATA].hProperty,
sztUserDataSize, i_upbSPFrame + sztSPHeaderSize, 0, 1, 0);
}
return NULL;
} // SPAttachProperties
// DESCRIPTION: Formats the data that is displayed in the details pane of the Network Monitor UI.
//
// ARGUMENTS: i_hFrame - Handle of the frame that is being parsed.
// i_pbMacFrame - Pointer to the first byte of a frame.
// i_pbCoreFrame - Pointer to the beginning of the protocol data in a frame.
// i_dwPropertyInsts - Number of PROPERTYINST structures provided by lpPropInst.
// i_pPropInst - Pointer to an array of PROPERTYINST structures.
//
// RETURNS: If the function is successful, the return value is a pointer to the first byte after the recognized data in a frame,
// or NULL if the recognized data is the last piece of data in a frame. If the function is unsuccessful, the return value
// is the initial value of i_pbSPFrame.
//
DPLAYPARSER_API DWORD BHAPI SPFormatProperties( HFRAME i_hFrame,
ULPBYTE i_upbMacFrame,
ULPBYTE i_upbSPFrame,
DWORD i_dwPropertyInsts,
LPPROPERTYINST i_pPropInst )
{
// Loop through the property instances...
while( i_dwPropertyInsts-- > 0)
{
// ...and call the formatter for each
reinterpret_cast<FORMAT>(i_pPropInst->lpPropertyInfo->InstanceData)(i_pPropInst);
++i_pPropInst;
}
// TODO: MAKE SURE THIS SHOULD NOT BE TRUE
return NMERR_SUCCESS;
} // SPFormatProperties
// DESCRIPTION: Notifies Network Monitor that DPlay v8 Transport protocol parser exists.
//
// ARGUMENTS: NONE
//
// RETURNS: TRUE - success, FALSE - failure
//
bool CreateSPProtocol( void )
{
// The entry points to the export functions that Network Monitor uses to operate the parser
ENTRYPOINTS SPEntryPoints =
{
// SPParser Entry Points
SPRegister,
SPDeregister,
SPRecognizeFrame,
SPAttachProperties,
SPFormatProperties
};
// The first active instance of this parser needs to register with the kernel
g_hSPProtocol = CreateProtocol("DPLAYSP", &SPEntryPoints, ENTRYPOINTS_SIZE);
return (g_hSPProtocol ? TRUE : FALSE);
} // CreateSPProtocol
// DESCRIPTION: Removes the DPlay v8 Transport protocol parser from the Network Monitor's database of parsers
//
// ARGUMENTS: NONE
//
// RETURNS: NOTHING
//
void DestroySPProtocol( void )
{
DestroyProtocol(g_hSPProtocol);
} // DestroySPProtocol