def parseMsg( cls, msgBlob=None, dialect=SMB2_DIALECT_MIN ):
    """Decompose wire data and return an _SMB2_Header object.

    Input:
      cls     - This class.
      msgBlob - An array of at least 64 bytes, representing an SMB2+
                message in wire format.
      dialect - The minimum dialect under which to parse the header.

    Output:
      An <_SMB2_Header> object.

    Errors:
      AssertionError  - Thrown if:
                        + The length of <msgBlob> is less than the
                          minimum of 64 bytes.
                        + The command code parsed from the message is
                          not a valid command code.
                        + The given dialect is not known.
      ValueError      - Thrown if the packet cannot possibly contain a
                        valid SMB2+ message header.  This exception is
                        raised if either the ProtocolId field doesn't
                        contain the correct string, or if the
                        StructureSize value is incorrect.

    Notes:
      - This function does not parse SMB3 Transform Headers.  An SMB3
        Transform header will be rejected with a ValueError.
      - Beyond the basics of verifying that ProtocolId and StructureSize
        are correct, this function does _no_ validation of the input.
    """
    # Fundamental sanity check.
    assert( SMB2_HDR_SIZE <= len( msgBlob ) ), "Incomplete message header."

    # Parse it.  Use the simple sync response format.
    tup = cls._format_SMB2_StatTreeId.unpack( msgBlob[:SMB2_HDR_SIZE] )

    # Look for trouble.
    if( SMB2_MSG_PROTOCOL != tup[0] ):
      raise ValueError( "Malformed SMB2 ProtocolId: [%s]." % repr( tup[0] ) )
    elif( SMB2_HDR_SIZE != tup[1] ):
      s = "The SMB2 Header StructureSize must be 64, not %d." % tup[1]
      raise ValueError( s )

    # Create and populate a header record instance.
    hdr = cls( tup[4], dialect )
    hdr._creditCharge  = tup[2]
    # 3: Status/ChannelSeq/Reserved1; see below
    hdr.command        = tup[4]
    hdr._creditReqResp = tup[5]
    hdr._flags         = tup[6]
    hdr._nextCommand   = tup[7]
    hdr._messageId     = tup[8]
    # 9, 10: Reserved2/TreeId/AsyncId; see below
    hdr._sessionId     = tup[11]
    hdr._signature     = tup[12]

    # Handle the overloaded fields.
    if( hdr.flagReply or (dialect < SMB2_DIALECT_300) ):
      hdr._status = tup[3]
    else:
      hdr._channelSeq, hdr._reserved1 = cls._format_2H.unpack( msgBlob[8:12] )

    if( hdr.flagAsync ):
      hdr._asyncId = cls._format_Q.unpack( msgBlob[32:40] )
    else:
      hdr._reserved2 = tup[9]
      hdr._treeId    = tup[10]

    # All done.
    return( hdr )