Use MAC address documentation range in filter examples
[metze/wireshark/wip.git] / epan / dissectors / packet-mq-pcf.c
index 449898d5d037c2ed5bc4a7e77df9ca0037ead39a..484f2aee4b27056d9d8d858e505a83bae04cc80c 100644 (file)
@@ -2,8 +2,7 @@
  * Routines for IBM WebSphere MQ PCF packet dissection
  *
  * metatech <metatech@flashmail.com>
- *
- * $Id$
+ * robionekenobi <robionekenobi@bluewin.ch>
  *
  * Wireshark - Network traffic analyzer
  * By Gerald Combs <gerald@wireshark.org>
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 /*  MQ PCF in a nutshell
-*
-*   The MQ Programmable Command Formats API allows remotely configuring a queue manager.
-*   
-*   MQ PCF documentation is called "WebSphere MQ Programmable Command Formats and Administration Interface" 
+ *
+ *   The MQ Programmable Command Formats API allows remotely configuring a queue manager.
+ *
+ *   MQ PCF documentation is called "WebSphere MQ Programmable Command Formats and Administration Interface"
 */
 
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
 
-#include <string.h>
+#include <math.h>
 
-#include <glib.h>
 #include <epan/packet.h>
+#include <epan/expert.h>
+#include <epan/prefs.h>
+#include <epan/strutil.h>
+
 #include "packet-mq.h"
 
+void proto_register_mqpcf(void);
+void proto_reg_handoff_mqpcf(void);
+
+#define PCF_MAX_PARM 999
+#define PCF_MAX_LIST 20000
+
+guint mq_pcf_maxprm = PCF_MAX_PARM;
+guint mq_pcf_maxlst = PCF_MAX_LIST;
+
 static int proto_mqpcf = -1;
+
 static int hf_mqpcf_cfh_type = -1;
 static int hf_mqpcf_cfh_length = -1;
 static int hf_mqpcf_cfh_version = -1;
 static int hf_mqpcf_cfh_command = -1;
-static int hf_mqpcf_cfh_msgseqnumber = -1;
+static int hf_mqpcf_cfh_MsgSeqNbr = -1;
 static int hf_mqpcf_cfh_control = -1;
 static int hf_mqpcf_cfh_compcode = -1;
 static int hf_mqpcf_cfh_reason = -1;
-static int hf_mqpcf_cfh_paramcount = -1;
+static int hf_mqpcf_cfh_ParmCount = -1;
+
+static int hf_mq_pcf_prmtyp = -1;
+static int hf_mq_pcf_prmlen = -1;
+static int hf_mq_pcf_prmid = -1;
+static int hf_mq_pcf_prmidnovals = -1;
+static int hf_mq_pcf_filterop = -1;
+static int hf_mq_pcf_prmccsid = -1;
+static int hf_mq_pcf_prmstrlen = -1;
+static int hf_mq_pcf_prmcount = -1;
+static int hf_mq_pcf_prmunused = -1;
+
+static int hf_mq_pcf_string = -1;
+static int hf_mq_pcf_stringlist = -1;
+static int hf_mq_pcf_int = -1;
+static int hf_mq_pcf_intlist = -1;
+static int hf_mq_pcf_bytestring = -1;
+static int hf_mq_pcf_int64 = -1;
+static int hf_mq_pcf_int64list = -1;
+
+static expert_field ei_mq_pcf_prmln0 = EI_INIT;
+static expert_field ei_mq_pcf_MaxInt = EI_INIT;
+static expert_field ei_mq_pcf_MaxStr = EI_INIT;
+static expert_field ei_mq_pcf_MaxI64 = EI_INIT;
+static expert_field ei_mq_pcf_MaxPrm = EI_INIT;
+static expert_field ei_mq_pcf_PrmCnt = EI_INIT;
 
+static gint ett_mqpcf_prm = -1;
 static gint ett_mqpcf = -1;
 static gint ett_mqpcf_cfh = -1;
 
-#define MQ_FMT_ADMIN    "MQADMIN "
-#define MQ_FMT_EVENT    "MQEVENT "
-#define MQ_FMT_PCF      "MQPCF   "
-
-#define MQ_ENC_INTEGER_NORMAL    0x00000001
-#define MQ_ENC_INTEGER_REVERSED  0x00000002
-
-#define MQ_CMD_NONE                     0
-#define MQ_CMD_CHANGE_Q_MGR             1 
-#define MQ_CMD_INQUIRE_Q_MGR            2 
-#define MQ_CMD_CHANGE_PROCESS           3 
-#define MQ_CMD_COPY_PROCESS             4 
-#define MQ_CMD_CREATE_PROCESS           5 
-#define MQ_CMD_DELETE_PROCESS           6 
-#define MQ_CMD_INQUIRE_PROCESS          7 
-#define MQ_CMD_CHANGE_Q                 8 
-#define MQ_CMD_CLEAR_Q                  9 
-#define MQ_CMD_COPY_Q                  10 
-#define MQ_CMD_CREATE_Q                11 
-#define MQ_CMD_DELETE_Q                12 
-#define MQ_CMD_INQUIRE_Q               13 
-#define MQ_CMD_RESET_Q_STATS           17 
-#define MQ_CMD_INQUIRE_Q_NAMES         18 
-#define MQ_CMD_INQUIRE_PROCESS_NAMES   19 
-#define MQ_CMD_INQUIRE_CHANNEL_NAMES   20 
-#define MQ_CMD_CHANGE_CHANNEL          21 
-#define MQ_CMD_COPY_CHANNEL            22 
-#define MQ_CMD_CREATE_CHANNEL          23 
-#define MQ_CMD_DELETE_CHANNEL          24 
-#define MQ_CMD_INQUIRE_CHANNEL         25 
-#define MQ_CMD_PING_CHANNEL            26 
-#define MQ_CMD_RESET_CHANNEL           27 
-#define MQ_CMD_START_CHANNEL           28 
-#define MQ_CMD_STOP_CHANNEL            29 
-#define MQ_CMD_START_CHANNEL_INIT      30 
-#define MQ_CMD_START_CHANNEL_LISTENER  31 
-#define MQ_CMD_CHANGE_NAMELIST         32 
-#define MQ_CMD_COPY_NAMELIST           33 
-#define MQ_CMD_CREATE_NAMELIST         34 
-#define MQ_CMD_DELETE_NAMELIST         35 
-#define MQ_CMD_INQUIRE_NAMELIST        36 
-#define MQ_CMD_INQUIRE_NAMELIST_NAMES  37 
-#define MQ_CMD_ESCAPE                  38 
-#define MQ_CMD_RESOLVE_CHANNEL         39 
-#define MQ_CMD_PING_Q_MGR              40 
-#define MQ_CMD_INQUIRE_Q_STATUS        41 
-#define MQ_CMD_INQUIRE_CHANNEL_STATUS  42 
-#define MQ_CMD_CONFIG_EVENT            43 
-#define MQ_CMD_Q_MGR_EVENT             44 
-#define MQ_CMD_PERFM_EVENT             45 
-#define MQ_CMD_CHANNEL_EVENT           46 
-#define MQ_CMD_DELETE_PUBLICATION      60
-#define MQ_CMD_DEREGISTER_PUBLISHER    61
-#define MQ_CMD_DEREGISTER_SUBSCRIBER   62
-#define MQ_CMD_PUBLISH                 63
-#define MQ_CMD_REGISTER_PUBLISHER      64
-#define MQ_CMD_REGISTER_SUBSCRIBER     65
-#define MQ_CMD_REQUEST_UPDATE          66
-#define MQ_CMD_BROKER_INTERNAL         67
-#define MQ_CMD_INQUIRE_CLUSTER_Q_MGR   70 
-#define MQ_CMD_RESUME_Q_MGR_CLUSTER    71 
-#define MQ_CMD_SUSPEND_Q_MGR_CLUSTER   72 
-#define MQ_CMD_REFRESH_CLUSTER         73 
-#define MQ_CMD_RESET_CLUSTER           74 
-#define MQ_CMD_REFRESH_SECURITY        78 
-#define MQ_CMD_CHANGE_AUTH_INFO        79 
-#define MQ_CMD_COPY_AUTH_INFO          80 
-#define MQ_CMD_CREATE_AUTH_INFO        81 
-#define MQ_CMD_DELETE_AUTH_INFO        82 
-#define MQ_CMD_INQUIRE_AUTH_INFO       83 
-#define MQ_CMD_INQUIRE_AUTH_INFO_NAMES 84 
-
 #define MQ_TEXT_CFH   "MQ Command Format Header"
 
-static const value_string mqpcf_opcode_vals[] = {
-  { MQ_CMD_NONE,                            "NONE" },
-  { MQ_CMD_CHANGE_Q_MGR,                    "CHANGE_Q_MGR" },
-  { MQ_CMD_INQUIRE_Q_MGR,                   "INQUIRE_Q_MGR" },
-  { MQ_CMD_CHANGE_PROCESS,                  "CHANGE_PROCESS" },
-  { MQ_CMD_COPY_PROCESS,                    "COPY_PROCESS" },
-  { MQ_CMD_CREATE_PROCESS,                  "CREATE_PROCESS" },
-  { MQ_CMD_DELETE_PROCESS,                  "DELETE_PROCESS" },
-  { MQ_CMD_INQUIRE_PROCESS,                 "INQUIRE_PROCESS" },
-  { MQ_CMD_CHANGE_Q,                        "CHANGE_Q" },
-  { MQ_CMD_CLEAR_Q,                         "CLEAR_Q" },
-  { MQ_CMD_COPY_Q,                          "COPY_Q" },
-  { MQ_CMD_CREATE_Q,                        "CREATE_Q" },
-  { MQ_CMD_DELETE_Q,                        "DELETE_Q" },
-  { MQ_CMD_INQUIRE_Q,                       "INQUIRE_Q" },
-  { MQ_CMD_RESET_Q_STATS,                   "RESET_Q_STATS" },
-  { MQ_CMD_INQUIRE_Q_NAMES,                 "INQUIRE_Q_NAMES" },
-  { MQ_CMD_INQUIRE_PROCESS_NAMES,           "INQUIRE_PROCESS_NAMES" },
-  { MQ_CMD_INQUIRE_CHANNEL_NAMES,           "INQUIRE_CHANNEL_NAMES" },
-  { MQ_CMD_CHANGE_CHANNEL,                  "CHANGE_CHANNEL" },
-  { MQ_CMD_COPY_CHANNEL,                    "COPY_CHANNEL" },
-  { MQ_CMD_CREATE_CHANNEL,                  "CREATE_CHANNEL" },
-  { MQ_CMD_DELETE_CHANNEL,                  "DELETE_CHANNEL" },
-  { MQ_CMD_INQUIRE_CHANNEL,                 "INQUIRE_CHANNEL" },
-  { MQ_CMD_PING_CHANNEL,                    "PING_CHANNEL" },
-  { MQ_CMD_RESET_CHANNEL,                   "RESET_CHANNEL" },
-  { MQ_CMD_START_CHANNEL,                   "START_CHANNEL" },
-  { MQ_CMD_STOP_CHANNEL,                    "STOP_CHANNEL" },
-  { MQ_CMD_START_CHANNEL_INIT,              "START_CHANNEL_INIT" },
-  { MQ_CMD_START_CHANNEL_LISTENER,          "START_CHANNEL_LISTENER" },
-  { MQ_CMD_CHANGE_NAMELIST,                 "CHANGE_NAMELIST" },
-  { MQ_CMD_CREATE_NAMELIST,                 "CREATE_NAMELIST" },
-  { MQ_CMD_DELETE_NAMELIST,                 "DELETE_NAMELIST" },
-  { MQ_CMD_INQUIRE_NAMELIST,                "INQUIRE_NAMELIST" },
-  { MQ_CMD_INQUIRE_NAMELIST_NAMES,          "INQUIRE_NAMELIST_NAMES" },
-  { MQ_CMD_ESCAPE,                          "ESCAPE" },
-  { MQ_CMD_RESOLVE_CHANNEL,                 "RESOLVE_CHANNEL" },
-  { MQ_CMD_PING_Q_MGR,                      "PING_Q_MGR" },
-  { MQ_CMD_INQUIRE_Q_STATUS,                "INQUIRE_Q_STATUS" },
-  { MQ_CMD_INQUIRE_CHANNEL_STATUS,          "INQUIRE_CHANNEL_STATUS" },
-  { MQ_CMD_CONFIG_EVENT,                    "CONFIG_EVENT" },
-  { MQ_CMD_Q_MGR_EVENT,                     "Q_MGR_EVENT" },
-  { MQ_CMD_PERFM_EVENT,                     "PERFM_EVENT" },
-  { MQ_CMD_CHANNEL_EVENT,                   "CHANNEL_EVENT" },
-  { MQ_CMD_DELETE_PUBLICATION,              "DELETE_PUBLICATION" },
-  { MQ_CMD_DEREGISTER_PUBLISHER,            "DEREGISTER_PUBLISHER" },
-  { MQ_CMD_DEREGISTER_SUBSCRIBER,           "DEREGISTER_SUBSCRIBER" },
-  { MQ_CMD_PUBLISH,                         "PUBLISH" },
-  { MQ_CMD_REGISTER_PUBLISHER,              "REGISTER_PUBLISHER" },
-  { MQ_CMD_REGISTER_SUBSCRIBER,             "REGISTER_SUBSCRIBER" },
-  { MQ_CMD_REQUEST_UPDATE,                  "REQUEST_UPDATE" },
-  { MQ_CMD_BROKER_INTERNAL,                 "BROKER_INTERNAL" },
-  { MQ_CMD_INQUIRE_CLUSTER_Q_MGR,           "INQUIRE_CLUSTER_Q_MGR" },
-  { MQ_CMD_RESUME_Q_MGR_CLUSTER,            "RESUME_Q_MGR_CLUSTER" },
-  { MQ_CMD_SUSPEND_Q_MGR_CLUSTER,           "SUSPEND_Q_MGR_CLUSTER" },
-  { MQ_CMD_REFRESH_CLUSTER,                 "REFRESH_CLUSTER" },
-  { MQ_CMD_REFRESH_SECURITY,                "REFRESH_SECURITY" },
-  { MQ_CMD_CHANGE_AUTH_INFO,                "CHANGE_AUTH_INFO" },
-  { MQ_CMD_COPY_AUTH_INFO,                  "COPY_AUTH_INFO" },
-  { MQ_CMD_CREATE_AUTH_INFO,                "CREATE_AUTH_INFO" },
-  { MQ_CMD_DELETE_AUTH_INFO,                "DELETE_AUTH_INFO" },
-  { MQ_CMD_INQUIRE_AUTH_INFO,               "INQUIRE_AUTH_INFO" },
-  { MQ_CMD_INQUIRE_AUTH_INFO_NAMES,         "INQUIRE_AUTH_INFO_NAMES" },
-  { 0,          NULL }
-};
-
-static guint32 tvb_get_guint32_endian(tvbuff_t *a_tvb, gint a_iOffset, gboolean a_bLittleEndian)
+static guint32 dissect_mqpcf_getDigits(guint uCnt)
 {
-       guint32 iResult;
-       if (a_bLittleEndian)
-               iResult = tvb_get_letohl(a_tvb, a_iOffset);
-       else
-               iResult =  tvb_get_ntohl(a_tvb, a_iOffset);
-       return iResult;
+    return (guint32)(log10( (double)uCnt ) + 1);
+}
+/*
+* Here we get a special value_string, that return another value_string
+* pointer instead of string value. This let us use the try_val_to_str
+* to get val_to_str value from the value of a parameter on a more
+* easier way than using switch cases
+*/
+static const guint8 *dissect_mqpcf_parm_getintval(guint uPrm, guint uVal)
+{
+    const value_string *pVs;
+    pVs = (const value_string *)try_val_to_str_ext(uPrm, GET_VALS_EXTP(MQCFINT_Parse));
+
+    if (pVs)
+    {
+        return (const guint8 *)try_val_to_str(uVal, pVs);
+    }
+    return NULL;
 }
 
-static void
-dissect_mqpcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static void dissect_mqpcf_parm_int(tvbuff_t *tvb, proto_tree *tree, guint offset, guint uPrm,
+                                   guint uVal, int hfindex, guint iCnt, guint iMaxCnt,
+                                   guint iDigit, gboolean bParse)
 {
-       proto_tree      *mq_tree = NULL;
-       proto_tree      *mqroot_tree = NULL;
-       proto_item      *ti = NULL;
-       gint offset = 0;
-       struct mqinfo* mqinfo = pinfo->private_data;
-       gboolean bLittleEndian;
-       bLittleEndian = ((mqinfo->encoding & MQ_ENC_INTEGER_REVERSED) != 0) ? TRUE : FALSE;
-
-       if (check_col(pinfo->cinfo, COL_PROTOCOL)) col_set_str(pinfo->cinfo, COL_PROTOCOL, "MQ PCF");     
-       if (check_col(pinfo->cinfo, COL_INFO)) col_clear(pinfo->cinfo, COL_INFO);         
-       if (tvb_length(tvb) >= 36)
-       {
-               gint iSizeMQCFH = 36;
-               guint32 iCommand = tvb_get_guint32_endian(tvb, offset + 12, bLittleEndian);
-
-               if (check_col(pinfo->cinfo, COL_INFO)) 
-               {
-                       col_append_str(pinfo->cinfo, COL_INFO, val_to_str(iCommand, mqpcf_opcode_vals, "Unknown (0x%02x)"));
-               }
-
-               if (tree)
-               {
-                       ti = proto_tree_add_item(tree, proto_mqpcf, tvb, offset, -1, FALSE);
-                       proto_item_append_text(ti, " (%s)", val_to_str(iCommand, mqpcf_opcode_vals, "Unknown (0x%02x)"));
-                       mqroot_tree = proto_item_add_subtree(ti, ett_mqpcf);
-
-                       ti = proto_tree_add_text(mqroot_tree, tvb, offset, iSizeMQCFH, MQ_TEXT_CFH);
-                       mq_tree = proto_item_add_subtree(ti, ett_mqpcf_cfh);
-
-                       proto_tree_add_item(mq_tree, hf_mqpcf_cfh_type, tvb, offset + 0, 4, bLittleEndian);
-                       proto_tree_add_item(mq_tree, hf_mqpcf_cfh_length, tvb, offset + 4, 4, bLittleEndian);
-                       proto_tree_add_item(mq_tree, hf_mqpcf_cfh_version, tvb, offset + 8, 4, bLittleEndian);
-                       proto_tree_add_item(mq_tree, hf_mqpcf_cfh_command, tvb, offset + 12, 4, bLittleEndian);
-                       proto_tree_add_item(mq_tree, hf_mqpcf_cfh_msgseqnumber, tvb, offset + 16, 4, bLittleEndian);
-                       proto_tree_add_item(mq_tree, hf_mqpcf_cfh_control, tvb, offset + 20, 4, bLittleEndian);
-                       proto_tree_add_item(mq_tree, hf_mqpcf_cfh_compcode, tvb, offset + 24, 4, bLittleEndian);
-                       proto_tree_add_item(mq_tree, hf_mqpcf_cfh_reason, tvb, offset + 28, 4, bLittleEndian);
-                       proto_tree_add_item(mq_tree, hf_mqpcf_cfh_paramcount, tvb, offset + 32, 4, bLittleEndian);
-               }
-               offset += iSizeMQCFH;
-       }
+    header_field_info *hfinfo;
+    const guint8 *pVal = NULL;
+
+    if (bParse)
+        pVal = dissect_mqpcf_parm_getintval(uPrm, uVal);
+
+    hfinfo = proto_registrar_get_nth(hfindex);
+
+    if (iMaxCnt > 1)
+    {
+        if (pVal)
+        {
+            proto_tree_add_int_format(tree, hfindex, tvb, offset, 4, uVal,
+                "%s[%*d]: %8x-(%9d)-%s", hfinfo->name, iDigit, iCnt, uVal, uVal, pVal);
+        }
+        else
+        {
+            proto_tree_add_int_format(tree, hfindex, tvb, offset, 4, uVal,
+                "%s[%*d]: %8x-(%9d)", hfinfo->name, iDigit, iCnt, uVal, uVal);
+        }
+    }
+    else
+    {
+        if (pVal)
+        {
+            proto_tree_add_int_format_value(tree, hfindex, tvb, offset, 4, uVal,
+                "%8x-(%9d)-%s", uVal, uVal, pVal);
+        }
+        else
+        {
+            proto_tree_add_int_format_value(tree, hfindex, tvb, offset, 4, uVal,
+                "%8x-(%9d)", uVal, uVal);
+        }
+    }
 }
 
-static gboolean
-dissect_mqpcf_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+void dissect_mqpcf_parm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mq_tree,
+                        guint offset, guint32 uCount, guint bLittleEndian, gboolean bParse)
 {
-       if (tvb_length(tvb) >= 36)
-       {
-               struct mqinfo* mqinfo = pinfo->private_data;
-               if (strncmp((const char*)mqinfo->format, MQ_FMT_ADMIN, 8) == 0
-                       || strncmp((const char*)mqinfo->format, MQ_FMT_EVENT, 8) == 0
-                       || strncmp((const char*)mqinfo->format, MQ_FMT_PCF, 8) == 0)
-               {
-                       /* Dissect the packet */
-                       dissect_mqpcf(tvb, pinfo, tree);
-                       return TRUE;
-               }
-       }
-       return FALSE;
+    guint32 u    = 0;
+    guint32 tOfs = 0;
+    guint32 uLenF;
+    char    strPrm[256];
+    guint32 uTyp;
+    guint32 uLen = 0;
+    guint32 uPrm;
+    guint32 uCnt;
+    guint32 uCCS;
+    guint32 uSLn;
+    guint32 uVal;
+    guint64 uVal64;
+    guint32 uDig;
+
+    const char sMaxLst[] = " Max # of List reached. DECODE interrupted   (actual %u of %u)";
+    const char sPrmLn0[] = " MQPrm[%3u] has a zero length. DECODE Failed (MQPrm Count: %u)";
+    const char sMaxPrm[] = " Max # of Parm reached. DECODE interrupted   (actual %u of %u)";
+    const char sPrmCnt[] = " Cnt=-1 and Length(%u) < 16. DECODE interrupted for elem %u";
+
+    proto_item *ti   = NULL;
+    proto_tree *tree = NULL;
+
+    if (uCount == (guint32)-1)
+    {
+        guint32 xOfs = offset;
+
+        uCnt = 0;
+        while (tvb_reported_length_remaining(tvb, xOfs) >= 16)
+        {
+            uLen = tvb_get_guint32(tvb, xOfs + 4, bLittleEndian);
+            if (uLen < 16)
+            {
+                proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_PrmCnt, tvb, xOfs, 16, sPrmCnt, uLen, uCnt);
+                break;
+            }
+            uCnt++;
+            xOfs += uLen;
+        }
+        uCount = uCnt;
+    }
+
+    uDig = dissect_mqpcf_getDigits(uCount);
+
+    for (u = 0; u < uCount && u < mq_pcf_maxprm; u++)
+    {
+        tOfs = offset;
+        uTyp = tvb_get_guint32(tvb, offset    , bLittleEndian);
+        uLen = tvb_get_guint32(tvb, offset + 4, bLittleEndian);
+        if (uLen == 0)
+        {
+            proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_prmln0, tvb, offset, 12, sPrmLn0, u+1, uCount);
+            u = uCount;
+            break;
+        }
+        uPrm = tvb_get_guint32(tvb, offset + 8, bLittleEndian);
+        uLenF = 12;
+
+        if (bParse)
+            g_snprintf(strPrm, (gulong)sizeof(strPrm) - 1, " %-s[%*u] {%2d-%-15.15s} %8x/%5d-%-30.30s",
+                "MQPrm", uDig, u+1,
+                uTyp, val_to_str_ext_const(uTyp, GET_VALS_EXTP(PrmTyp), "      Unknown") + 6,
+                uPrm, uPrm, val_to_str_ext_const(uPrm, GET_VALS_EXTP(PrmId), "Unknown"));
+        else
+            g_snprintf(strPrm, (gulong)sizeof(strPrm) - 1, " %-s[%*u] {%2d-%-15.15s} %8x/%5d",
+                "XtraD", uDig, u+1,
+                uTyp, val_to_str_ext_const(uTyp, GET_VALS_EXTP(PrmTyp), "      Unknown") + 6,
+                uPrm, uPrm);
+
+        switch (uTyp)
+        {
+        case MQ_MQCFT_NONE:
+            break;
+        case MQ_MQCFT_COMMAND:
+            break;
+        case MQ_MQCFT_RESPONSE:
+            break;
+        case MQ_MQCFT_INTEGER:
+            {
+                const guint8 *pVal = NULL;
+                uVal = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
+                if (bParse)
+                    pVal = dissect_mqpcf_parm_getintval(uPrm, uVal);
+
+                if (pVal)
+                {
+                    tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL,
+                                                             "%s %8x-(%9d) %s", strPrm, uVal, uVal, pVal);
+                }
+                else
+                {
+                    tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL,
+                                                             "%s %8x-(%9d)", strPrm, uVal, uVal);
+                }
+
+                proto_tree_add_item(tree, hf_mq_pcf_prmtyp, tvb, offset    , 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmlen, tvb, offset + 4, 4, bLittleEndian);
+                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
+
+                dissect_mqpcf_parm_int(tvb, tree, offset+uLenF, uPrm, uVal, hf_mq_pcf_int, 0, 0, 0, bParse);
+            }
+            break;
+        case MQ_MQCFT_STRING:
+            {
+                guint8 *sStr;
+
+                uCCS = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
+                uSLn = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian);
+                sStr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8,
+                    uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC);
+                if (*sStr)
+                    strip_trailing_blanks(sStr, uSLn);
+                if (*sStr)
+                    format_text_chr(sStr, strlen((const char *)sStr), '.');
+
+                tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s", strPrm, sStr);
+
+                proto_tree_add_item(tree, hf_mq_pcf_prmtyp   , tvb, offset     , 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmlen   , tvb, offset +  4, 4, bLittleEndian);
+                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 12, 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 16, 4, bLittleEndian);
+
+                proto_tree_add_item(tree, hf_mq_pcf_string, tvb, offset + uLenF + 8, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC);
+            }
+            break;
+        case MQ_MQCFT_INTEGER_LIST:
+            {
+                guint32 u2;
+                guint32 uDigit = 0;
+
+                uCnt = tvb_get_guint32(tvb, offset+uLenF, bLittleEndian);
+                uDigit = dissect_mqpcf_getDigits(uCnt);
+
+                tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, &ti, "%s Cnt(%d)", strPrm, uCnt);
+
+                proto_tree_add_item(tree, hf_mq_pcf_prmtyp  , tvb, offset     , 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmlen  , tvb, offset +  4, 4, bLittleEndian);
+                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmcount, tvb, offset + 12, 4, bLittleEndian);
+
+                offset += uLenF+4;
+                for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++)
+                {
+                    uVal = tvb_get_guint32(tvb, offset, bLittleEndian);
+                    dissect_mqpcf_parm_int(tvb, tree, offset, uPrm, uVal, hf_mq_pcf_intlist, u2+1, uCnt, uDigit, bParse);
+                    offset += 4;
+                }
+                if (u2 != uCnt)
+                {
+                    proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_MaxInt, tvb, offset, (uCnt- u2) * 4, sMaxLst, u2, uCnt);
+                }
+            }
+            break;
+        case MQ_MQCFT_STRING_LIST:
+            {
+                guint32  u2;
+                guint32  uDigit;
+                guint8  *sStr;
+                header_field_info *hfinfo;
+
+                hfinfo = proto_registrar_get_nth(hf_mq_pcf_stringlist);
+
+                uCCS = tvb_get_guint32(tvb, offset + uLenF    , bLittleEndian);
+                uCnt = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian);
+                uSLn = tvb_get_guint32(tvb, offset + uLenF + 8, bLittleEndian);
+
+                tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s Cnt(%d)", strPrm, uCnt);
+
+                proto_tree_add_item(tree, hf_mq_pcf_prmtyp   , tvb, offset     , 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmlen   , tvb, offset +  4, 4, bLittleEndian);
+                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 12, 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmcount , tvb, offset + 16, 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 20, 4, bLittleEndian);
+
+                uDigit = dissect_mqpcf_getDigits(uCnt);
+
+                offset += uLenF+12;
+                for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++)
+                {
+                    sStr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset,
+                        uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC);
+                    if (*sStr)
+                        strip_trailing_blanks(sStr, uSLn);
+                    if (*sStr)
+                        format_text_chr(sStr, strlen((const char *)sStr),  '.');
+
+                    proto_tree_add_string_format(tree, hf_mq_pcf_stringlist, tvb, offset, uSLn, (const char *)sStr,
+                        "%s[%*d]: %s", hfinfo->name, uDigit, u2+1, sStr);
+                    offset += uSLn;
+                }
+                if (u2 != uCnt)
+                {
+                    proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_MaxStr, tvb, offset,(uCnt - u2) * uSLn, sMaxLst, u2, uCnt);
+                }
+            }
+            break;
+        case MQ_MQCFT_EVENT:
+            break;
+        case MQ_MQCFT_USER:
+            {
+                tree = proto_tree_add_subtree(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, strPrm);
+
+                proto_tree_add_item(tree, hf_mq_pcf_prmtyp   , tvb, offset     , 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmlen   , tvb, offset +  4, 4, bLittleEndian);
+
+                proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + 8, uLen - 8, bLittleEndian);
+            }
+            break;
+        case MQ_MQCFT_BYTE_STRING:
+            {
+                uSLn = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
+                if (uSLn)
+                {
+                    guint8 *sStrA = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 4, uSLn, ENC_ASCII) , uSLn, '.');
+                    guint8 *sStrE = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 4, uSLn, ENC_EBCDIC), uSLn, '.');
+                    if (uSLn > 35)
+                    {
+                        tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL,
+                                                        "%s [Truncated] A(%-.35s) E(%-.35s)", strPrm, sStrA, sStrE);
+                    }
+                    else
+                    {
+                        tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL,
+                                                        "%s A(%s) E(%s)", strPrm, sStrA, sStrE);
+                    }
+                }
+                else
+                {
+                    tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s <MISSING>", strPrm);
+                }
+
+                proto_tree_add_item(tree, hf_mq_pcf_prmtyp   , tvb, offset     , 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmlen   , tvb, offset +  4, 4, bLittleEndian);
+                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 12, 4, bLittleEndian);
+
+                proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + uLenF + 4 , uSLn, bLittleEndian);
+            }
+            break;
+        case MQ_MQCFT_TRACE_ROUTE:
+            break;
+        case MQ_MQCFT_REPORT:
+            break;
+        case MQ_MQCFT_INTEGER_FILTER:
+            {
+                guint32 uOpe;
+
+                uOpe = tvb_get_guint32(tvb, offset + uLenF    , bLittleEndian);
+                uVal = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian);
+
+                tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s %8x-(%9d)",
+                    strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), "       Unknown (0x%02x)")+7, uVal, uVal);
+
+                proto_tree_add_item(tree, hf_mq_pcf_prmtyp   , tvb, offset     , 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmlen   , tvb, offset +  4, 4, bLittleEndian);
+                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian);
+
+                proto_tree_add_item(tree, hf_mq_pcf_int, tvb, offset + uLenF + 4, 4, bLittleEndian);
+            }
+            break;
+        case MQ_MQCFT_STRING_FILTER:
+            {
+                guint8 *sStr;
+                guint32 uOpe;
+
+                uOpe = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
+                uCCS = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian);
+                uSLn = tvb_get_guint32(tvb, offset + uLenF + 8, bLittleEndian);
+                sStr = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 12, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC), uSLn, '.');
+                strip_trailing_blanks(sStr, uSLn);
+
+                tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s %s",
+                    strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), "       Unknown (0x%02x)")+7, sStr);
+
+                proto_tree_add_item(tree, hf_mq_pcf_prmtyp   , tvb, offset     , 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmlen   , tvb, offset +  4, 4, bLittleEndian);
+                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 16, 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 20, 4, bLittleEndian);
+
+                proto_tree_add_item(tree, hf_mq_pcf_string, tvb, offset + uLenF + 12, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC);
+            }
+            break;
+        case MQ_MQCFT_BYTE_STRING_FILTER:
+            {
+                guint32 uOpe;
+                uOpe = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
+                uSLn = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian);
+                if (uSLn)
+                {
+                    guint8 *sStrA = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8, uSLn, ENC_ASCII), uSLn, '.');
+                    guint8 *sStrE = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8, uSLn, ENC_EBCDIC), uSLn, '.');
+                    tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s A(%s) E(%s)",
+                        strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), "       Unknown (0x%02x)")+7, sStrA, sStrE);
+                }
+                else
+                {
+                    tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s <MISSING>",
+                        strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), "       Unknown (0x%02x)")+7);
+                }
+
+                proto_tree_add_item(tree, hf_mq_pcf_prmtyp   , tvb, offset     , 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmlen   , tvb, offset +  4, 4, bLittleEndian);
+                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 16, 4, bLittleEndian);
+
+                proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + uLenF + 8 , uSLn, bLittleEndian);
+            }
+            break;
+        case MQ_MQCFT_COMMAND_XR:
+            break;
+        case MQ_MQCFT_XR_MSG:
+            break;
+        case MQ_MQCFT_XR_ITEM:
+            break;
+        case MQ_MQCFT_XR_SUMMARY:
+            break;
+        case MQ_MQCFT_GROUP:
+            break;
+        case MQ_MQCFT_STATISTICS:
+            break;
+        case MQ_MQCFT_ACCOUNTING:
+            break;
+        case MQ_MQCFT_INTEGER64:
+            {
+                uVal64 = tvb_get_guint64(tvb, offset + uLenF + 4, bLittleEndian);
+                tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL,
+                    "%s %" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)", strPrm, uVal64, uVal64);
+
+                proto_tree_add_item(tree, hf_mq_pcf_prmtyp   , tvb, offset     , 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmlen   , tvb, offset +  4, 4, bLittleEndian);
+                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmunused, tvb, offset + 12, 4, bLittleEndian);
+
+                proto_tree_add_item(tree, hf_mq_pcf_int64, tvb, offset + uLenF + 4, 8, bLittleEndian);
+            }
+            break;
+        case MQ_MQCFT_INTEGER64_LIST:
+            {
+                guint32 u2;
+                guint32 uDigit;
+                header_field_info *hfinfo;
+
+                hfinfo = proto_registrar_get_nth(hf_mq_pcf_int64list);
+
+                uCnt = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
+                tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s Cnt(%d)", strPrm, uCnt);
+                uDigit = dissect_mqpcf_getDigits(uCnt);
+
+                proto_tree_add_item(tree, hf_mq_pcf_prmtyp  , tvb, offset     , 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmlen  , tvb, offset +  4, 4, bLittleEndian);
+                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
+                proto_tree_add_item(tree, hf_mq_pcf_prmcount, tvb, offset + 12, 4, bLittleEndian);
+
+                offset += uLenF + 4;
+                for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++)
+                {
+                    uVal64 = tvb_get_guint64(tvb, offset, bLittleEndian);
+                    proto_tree_add_int64_format(tree, hf_mq_pcf_int64list, tvb, offset, 8, uVal64,
+                        "%s[%*d]: %" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)",
+                        hfinfo->name, uDigit, u2+1, uVal64, uVal64);
+                    offset += 8;
+                }
+                if (u2 != uCnt)
+                {
+                    proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_MaxI64, tvb, offset, (uCnt - u2) * 8, sMaxLst, u2, uCnt);
+                }
+            }
+            break;
+        }
+        offset = tOfs+uLen;
+    }
+    if (u != uCount)
+    {
+        proto_tree_add_expert_format(mq_tree, pinfo, &ei_mq_pcf_MaxPrm, tvb, offset, tvb_reported_length_remaining(tvb, offset), sMaxPrm, u, uCount);
+    }
 }
 
-void
-proto_register_mqpcf(void)
+static void dissect_mqpcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, mq_parm_t* p_mq_parm)
 {
-  static hf_register_info hf[] = {
-   { &hf_mqpcf_cfh_type,
-      { "Type", "mqpcf.cfh.type", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH type", HFILL }},
+    gint offset = 0;
+    gboolean bLittleEndian;
+
+    bLittleEndian = ((p_mq_parm->mq_cur_ccsid.encod & MQ_MQENC_INTEGER_MASK) == MQ_MQENC_INTEGER_REVERSED) ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN;
+
+    if (tvb_reported_length(tvb) >= 36)
+    {
+        gint iSizeMQCFH = 36;
+        guint32 iCommand = tvb_get_guint32(tvb, offset + 12, bLittleEndian);
+
+        if (tree)
+        {
+            proto_item *ti;
+            proto_tree *mq_tree;
+            proto_tree *mqroot_tree;
+            char        sTmp[256];
+            guint32     uCnt;
+            guint32     uTyp;
+            guint32     uCmd;
+            guint32     uCC;
+            guint32     uRC;
+
+            uTyp = tvb_get_guint32(tvb, offset     , bLittleEndian);
+            uCmd = tvb_get_guint32(tvb, offset + 12, bLittleEndian);
+            uCC  = tvb_get_guint32(tvb, offset + 24, bLittleEndian);
+            uRC  = tvb_get_guint32(tvb, offset + 28, bLittleEndian);
+            uCnt = tvb_get_guint32(tvb, offset + 32, bLittleEndian);
+
+            if (uCC || uRC)
+            {
+                g_snprintf(sTmp, (gulong)sizeof(sTmp)-1, " %-s [%d-%s] {%d-%s} PrmCnt(%d) CC(%d-%s) RC(%d-%s)",
+                    MQ_TEXT_CFH,
+                    uTyp, val_to_str_const(uTyp, GET_VALSV(mqcft), "Unknown"),
+                    uCmd, val_to_str_ext_const(uCmd, GET_VALS_EXTP(mqcmd), "Unknown"),
+                    uCnt,
+                    uCC, val_to_str_const(uCC, GET_VALSV(mqcc), "Unknown"),
+                    uRC, val_to_str_ext_const(uRC, GET_VALS_EXTP(mqrc), "Unknown"));
+            }
+            else
+            {
+                g_snprintf(sTmp, (gulong)sizeof(sTmp)-1, " %-s [%d-%s] {%d-%s} PrmCnt(%d)",
+                    MQ_TEXT_CFH,
+                    uTyp, val_to_str_const(uTyp, GET_VALSV(mqcft), "Unknown"),
+                    uCmd, val_to_str_ext_const(uCmd, GET_VALS_EXTP(mqcmd), "Unknown"),
+                    uCnt);
+            }
+
+            ti = proto_tree_add_item(tree, proto_mqpcf, tvb, offset, -1, ENC_NA);
+
+            proto_item_append_text(ti, " (%s)", val_to_str_ext_const(iCommand, GET_VALS_EXTP(mqcmd), "Unknown (0x%02x)"));
+            mqroot_tree = proto_item_add_subtree(ti, ett_mqpcf);
 
-   { &hf_mqpcf_cfh_length,
-      { "Length", "mqpcf.cfh.length", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH length", HFILL }},
+            mq_tree = proto_tree_add_subtree(mqroot_tree, tvb, offset, iSizeMQCFH, ett_mqpcf_cfh, NULL, sTmp);
 
-   { &hf_mqpcf_cfh_version,
-      { "Version", "mqpcf.cfh.version", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH version", HFILL }},
+            proto_tree_add_item(mq_tree, hf_mqpcf_cfh_type     , tvb, offset +  0, 4, bLittleEndian);
+            proto_tree_add_item(mq_tree, hf_mqpcf_cfh_length   , tvb, offset +  4, 4, bLittleEndian);
+            proto_tree_add_item(mq_tree, hf_mqpcf_cfh_version  , tvb, offset +  8, 4, bLittleEndian);
+            proto_tree_add_item(mq_tree, hf_mqpcf_cfh_command  , tvb, offset + 12, 4, bLittleEndian);
+            proto_tree_add_item(mq_tree, hf_mqpcf_cfh_MsgSeqNbr, tvb, offset + 16, 4, bLittleEndian);
+            proto_tree_add_item(mq_tree, hf_mqpcf_cfh_control  , tvb, offset + 20, 4, bLittleEndian);
+            proto_tree_add_item(mq_tree, hf_mqpcf_cfh_compcode , tvb, offset + 24, 4, bLittleEndian);
+            proto_tree_add_item(mq_tree, hf_mqpcf_cfh_reason   , tvb, offset + 28, 4, bLittleEndian);
+            proto_tree_add_item(mq_tree, hf_mqpcf_cfh_ParmCount, tvb, offset + 32, 4, bLittleEndian);
+            dissect_mqpcf_parm(tvb, pinfo, mqroot_tree, offset + iSizeMQCFH, uCnt, bLittleEndian, TRUE);
+        }
+    }
+}
+
+static gboolean dissect_mqpcf_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+{
+    if (data && tvb_reported_length(tvb) >= 36)
+    {
+        mq_parm_t *p_mq_parm = (mq_parm_t *)data;
+        if (strncmp((const char*)p_mq_parm->mq_format, MQ_MQFMT_ADMIN, 8) == 0
+            || strncmp((const char*)p_mq_parm->mq_format, MQ_MQFMT_EVENT, 8) == 0
+            || strncmp((const char*)p_mq_parm->mq_format, MQ_MQFMT_PCF, 8) == 0)
+        {
+            /* Dissect the packet */
+            dissect_mqpcf(tvb, pinfo, tree, p_mq_parm);
+            return TRUE;
+        }
+        if (strncmp((const char *)p_mq_parm->mq_format, "LPOO", 4) == 0)
+        {
+            gboolean bLittleEndian;
+            bLittleEndian = ((p_mq_parm->mq_cur_ccsid.encod & MQ_MQENC_INTEGER_MASK) == MQ_MQENC_INTEGER_REVERSED) ? ENC_LITTLE_ENDIAN:ENC_BIG_ENDIAN;
+            dissect_mqpcf_parm(tvb, pinfo, tree, 0, (guint32)-1, bLittleEndian, FALSE);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+void proto_register_mqpcf(void)
+{
+    expert_module_t *expert_mqpcf;
 
-   { &hf_mqpcf_cfh_command,
-      { "Command", "mqpcf.cfh.command", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH command", HFILL }},
+    static hf_register_info hf[] =
+    {
+        { &hf_mqpcf_cfh_type     , { "Type.....", "mqpcf.cfh.type"      , FT_UINT32, BASE_DEC, VALS(mq_mqcft_vals), 0x0, "CFH type", HFILL }},
+        { &hf_mqpcf_cfh_length   , { "Length...", "mqpcf.cfh.length"    , FT_UINT32, BASE_DEC, NULL, 0x0, "CFH length", HFILL }},
+        { &hf_mqpcf_cfh_version  , { "Version..", "mqpcf.cfh.version"   , FT_UINT32, BASE_DEC, NULL, 0x0, "CFH version", HFILL }},
+        { &hf_mqpcf_cfh_command  , { "Command..", "mqpcf.cfh.command"   , FT_UINT32, BASE_DEC | BASE_EXT_STRING, &mq_mqcmd_xvals, 0x0, "CFH command", HFILL }},
+        { &hf_mqpcf_cfh_MsgSeqNbr, { "MsgSeqNbr", "mqpcf.cfh.MsgSeqNbr" , FT_UINT32, BASE_DEC, NULL, 0x0, "CFH message sequence number", HFILL }},
+        { &hf_mqpcf_cfh_control  , { "Control..", "mqpcf.cfh.control"   , FT_UINT32, BASE_DEC, VALS(mq_CtlOpt_vals), 0x0, "CFH control", HFILL }},
+        { &hf_mqpcf_cfh_compcode , { "CompCode.", "mqpcf.cfh.compcode"  , FT_UINT32, BASE_DEC, VALS(mq_mqcc_vals), 0x0, "CFH completion code", HFILL }},
+        { &hf_mqpcf_cfh_reason   , { "ReasCode.", "mqpcf.cfh.reasoncode", FT_UINT32, BASE_DEC | BASE_EXT_STRING, &mq_mqrc_xvals, 0x0, "CFH reason code", HFILL }},
+        { &hf_mqpcf_cfh_ParmCount, { "ParmCount", "mqpcf.cfh.ParmCount" , FT_UINT32, BASE_DEC, NULL, 0x0, "CFH parameter count", HFILL }},
 
-   { &hf_mqpcf_cfh_msgseqnumber,
-      { "Message sequence number", "mqpcf.cfh.msgseqnumber", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH message sequence number", HFILL }},
+        { &hf_mq_pcf_prmtyp      , { "ParmTyp..", "mqpcf.parm.type"      , FT_UINT32 , BASE_DEC | BASE_EXT_STRING, &mq_PrmTyp_xvals, 0x0, "MQPCF parameter type", HFILL }},
+        { &hf_mq_pcf_prmlen      , { "ParmLen..", "mqpcf.parm.len"       , FT_UINT32 , BASE_DEC, NULL, 0x0, "MQPCF parameter length", HFILL }},
+        { &hf_mq_pcf_prmid       , { "ParmID...", "mqpcf.parm.id"        , FT_UINT32 , BASE_DEC | BASE_EXT_STRING, &mq_PrmId_xvals, 0x0, "MQPCF parameter id", HFILL }},
+        { &hf_mq_pcf_prmidnovals , { "ParmID...", "mqpcf.parm.idNoVals"  , FT_UINT32 , BASE_HEX_DEC, NULL, 0x0, "MQPCF parameter id No Vals", HFILL }},
+        { &hf_mq_pcf_filterop    , { "FilterOP.", "mqpcf.filter.op"      , FT_UINT32 , BASE_DEC, VALS(mq_FilterOP_vals), 0x0, "MQPCF Filter operator", HFILL }},
+        { &hf_mq_pcf_prmccsid    , { "ParmCCSID", "mqpcf.parm.ccsid"     , FT_UINT32 , BASE_DEC | BASE_RANGE_STRING, RVALS(mq_ccsid_rvals), 0x0, "MQPCF parameter ccsid", HFILL }},
+        { &hf_mq_pcf_prmstrlen   , { "ParmStrLn", "mqpcf.parm.strlen"    , FT_UINT32 , BASE_DEC, NULL, 0x0, "MQPCF parameter strlen", HFILL }},
+        { &hf_mq_pcf_prmcount    , { "ParmCount", "mqpcf.parm.count"     , FT_UINT32 , BASE_DEC, NULL, 0x0, "MQPCF parameter count", HFILL }},
+        { &hf_mq_pcf_prmunused   , { "ParmUnuse", "mqpcf.parm.unused"    , FT_UINT32 , BASE_DEC, NULL, 0x0, "MQPCF parameter unused", HFILL }},
+        { &hf_mq_pcf_string      , { "String...", "mqpcf.parm.string"    , FT_STRINGZ, BASE_NONE, NULL, 0x0, "MQPCF parameter string", HFILL }},
+        { &hf_mq_pcf_stringlist  , { "StrList..", "mqpcf.parm.stringlist", FT_STRINGZ, BASE_NONE, NULL, 0x0, "MQPCF parameter string list", HFILL }},
+        { &hf_mq_pcf_int         , { "Integer..", "mqpcf.parm.int"       , FT_INT32  , BASE_DEC, NULL, 0x0, "MQPCF parameter int", HFILL }},
+        { &hf_mq_pcf_intlist     , { "IntList..", "mqpcf.parm.intlist"   , FT_INT32  , BASE_DEC, NULL, 0x0, "MQPCF parameter int list", HFILL }},
+        { &hf_mq_pcf_bytestring  , { "ByteStr..", "mqpcf.parm.bytestring", FT_BYTES  , BASE_NONE, NULL, 0x0, "MQPCF parameter byte string", HFILL }},
+        { &hf_mq_pcf_int64       , { "Int64....", "mqpcf.parm.int64"     , FT_INT64  , BASE_DEC, NULL, 0x0, "MQPCF parameter int64", HFILL }},
+        { &hf_mq_pcf_int64list   , { "Int64List", "mqpcf.parm.int64list" , FT_INT64  , BASE_DEC, NULL, 0x0, "MQPCF parameter int64 list", HFILL }},
+    };
+    static gint *ett[] =
+    {
+        &ett_mqpcf,
+        &ett_mqpcf_prm,
+        &ett_mqpcf_cfh,
+    };
+    static ei_register_info ei[] =
+    {
+        { &ei_mq_pcf_prmln0, { "mqpcf.parm.len0"     , PI_MALFORMED, PI_ERROR, "MQPCF Parameter length is 0", EXPFILL }},
+        { &ei_mq_pcf_MaxInt, { "mqpcf.parm.IntList"  , PI_UNDECODED, PI_WARN , "MQPCF Parameter Integer list exhausted", EXPFILL }},
+        { &ei_mq_pcf_MaxStr, { "mqpcf.parm.StrList"  , PI_UNDECODED, PI_WARN , "MQPCF Parameter String list exhausted", EXPFILL }},
+        { &ei_mq_pcf_MaxI64, { "mqpcf.parm.Int64List", PI_UNDECODED, PI_WARN , "MQPCF Parameter Int64 list exhausted", EXPFILL }},
+        { &ei_mq_pcf_MaxPrm, { "mqpcf.parm.MaxPrm"   , PI_UNDECODED, PI_WARN , "MQPCF Max number of parameter exhausted", EXPFILL }},
+        { &ei_mq_pcf_PrmCnt, { "mqpcf.parm.PrmCnt"   , PI_UNDECODED, PI_WARN , "MQPCF Unkn Parm Cnt Length invalid", EXPFILL }},
+    };
 
-   { &hf_mqpcf_cfh_control,
-      { "Control", "mqpcf.cfh.control", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH control", HFILL }},
+    module_t *mq_pcf_module;
 
-   { &hf_mqpcf_cfh_compcode,
-      { "Completion code", "mqpcf.cfh.compcode", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH completion code", HFILL }},
+    proto_mqpcf = proto_register_protocol("WebSphere MQ Programmable Command Formats", "MQ PCF", "mqpcf");
+    proto_register_field_array(proto_mqpcf, hf, array_length(hf));
+    proto_register_subtree_array(ett, array_length(ett));
 
-   { &hf_mqpcf_cfh_reason,
-      { "Reason code", "mqpcf.cfh.reasoncode", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH reason code", HFILL }},
+    expert_mqpcf = expert_register_protocol(proto_mqpcf);
+    expert_register_field_array(expert_mqpcf, ei, array_length(ei));
 
-   { &hf_mqpcf_cfh_paramcount,
-      { "Parameter count", "mqpcf.cfh.paramcount", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH parameter count", HFILL }}
-  };
-  static gint *ett[] = {
-    &ett_mqpcf,
-    &ett_mqpcf_cfh,
-  };
+    mq_pcf_module = prefs_register_protocol(proto_mqpcf, NULL);
+    prefs_register_uint_preference(mq_pcf_module, "maxprm",
+        "Set the maximun number of parameter in the PCF to decode",
+        "When dissecting PCF there can be a lot of parameters."
+        " You can limit the number of parameter decoded, before it continue with the next PCF.",
+        10, &mq_pcf_maxprm);
+    prefs_register_uint_preference(mq_pcf_module, "maxlst",
+        "Set the maximun number of Parameter List that are displayed",
+        "When dissecting a parameter of a PCFm, if it is a StringList, IntegerList or Integer64 List, "
+        " You can limit the number of element displayed, before it continue with the next Parameter.",
+        10, &mq_pcf_maxlst);
 
-  proto_mqpcf = proto_register_protocol("WebSphere MQ Programmable Command Formats", "MQ PCF", "mqpcf");
-  proto_register_field_array(proto_mqpcf, hf, array_length(hf));
-  proto_register_subtree_array(ett, array_length(ett));
 }
 
-void
-proto_reg_handoff_mqpcf(void)
+void proto_reg_handoff_mqpcf(void)
 {
-       heur_dissector_add("mq", dissect_mqpcf_heur, proto_mqpcf);
+    heur_dissector_add("mq", dissect_mqpcf_heur, "WebSphere MQ PCF", "mqpcf_mq", proto_mqpcf, HEURISTIC_ENABLE);
 }
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */