Fix coverity 268, 269, 546, 547, 548, 549 by checking for null return
[obnox/wireshark/wip.git] / epan / dissectors / packet-vnc.c
index dbc2abf745fb673632037a56b355c358a643888c..310768d4eb859bf1cd706b28339301df26c7dd93 100644 (file)
 # include "config.h"
 #endif
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
 #include <glib.h>
 
 #include <epan/conversation.h>
 #include <epan/emem.h>
 #include <epan/packet.h>
 #include <epan/prefs.h>
+#include <epan/expert.h>
 #include "packet-x11-keysym.h" /* This contains the X11 value_string
                                * "keysym_vals_source" that VNC also uses. */
 
 typedef enum {
-       INVALID  = 0,
-       NONE     = 1,
-       VNC      = 2,
-       RA2      = 5,
-       RA2ne    = 6,
-       TIGHT    = 16,
-       ULTRA    = 17,
-       TLS      = 18,
-       VENCRYPT = 19
-} security_types_e;
-
-static const value_string security_types_vs[] = {
-       { INVALID,  "Invalid"  },
-       { NONE,  "None"     },
-       { VNC,  "VNC"      },
-       { RA2,  "RA2"      },
-       { RA2ne,  "RA2ne"    },
-       { TIGHT, "Tight"    },
-       { ULTRA, "Ultra"    },
-       { TLS, "TLS"      },
-       { VENCRYPT, "VeNCrypt" },
-       { 0,  NULL       }
+       VNC_SECURITY_TYPE_INVALID       =  0,
+       VNC_SECURITY_TYPE_NONE          =  1,
+       VNC_SECURITY_TYPE_VNC           =  2,
+       VNC_SECURITY_TYPE_RA2           =  5,
+       VNC_SECURITY_TYPE_RA2ne         =  6,
+       VNC_SECURITY_TYPE_TIGHT         = 16,
+       VNC_SECURITY_TYPE_ULTRA         = 17,
+       VNC_SECURITY_TYPE_TLS           = 18,
+       VNC_SECURITY_TYPE_VENCRYPT      = 19,
+       VNC_SECURITY_TYPE_GTK_VNC_SASL  = 20,
+       VNC_SECURITY_TYPE_MD5_HASH_AUTH = 21,
+       VNC_SECURITY_TYPE_XVP           = 22,
+       VNC_TIGHT_AUTH_TGHT_ULGNAUTH    = 119,
+       VNC_TIGHT_AUTH_TGHT_XTRNAUTH    = 130
+} vnc_security_types_e;
+
+static const value_string vnc_security_types_vs[] = {
+       { VNC_SECURITY_TYPE_INVALID,      "Invalid"      },
+       { VNC_SECURITY_TYPE_NONE,         "None"         },
+       { VNC_SECURITY_TYPE_VNC,          "VNC"          },
+       { VNC_SECURITY_TYPE_RA2,          "RA2"          },
+       { VNC_SECURITY_TYPE_RA2ne,        "RA2ne"        },
+       { VNC_SECURITY_TYPE_TIGHT,        "Tight"        },
+       { VNC_SECURITY_TYPE_ULTRA,        "Ultra"        },
+       { VNC_SECURITY_TYPE_TLS,          "TLS"          },
+       { VNC_SECURITY_TYPE_VENCRYPT,     "VeNCrypt"     },
+       { VNC_SECURITY_TYPE_GTK_VNC_SASL, "GTK-VNC SASL" },
+       { 0,  NULL                     }
 };
 
-static const value_string auth_result_vs[] = {
-       { 0, "OK"     },
-       { 1, "Failed" },
-       { 0,  NULL    }
+static const true_false_string auth_result_tfs = {
+       "Failed",
+       "OK"
 };
 
 static const value_string yes_no_vs[] = {
@@ -96,62 +98,157 @@ static const value_string yes_no_vs[] = {
        { 0,  NULL }
 };
 
-static const value_string client_message_types_vs[] = {
-       { 0, "Set Pixel Format"           },
-       { 2, "Set Encodings"              },
-       { 3, "Framebuffer Update Request" },
-       { 4, "Key Event"                  },
-       { 5, "Pointer Event"              },
-       { 6, "Cut Text"                   },
-       { 0,  NULL                        }
+typedef enum {
+       VNC_CLIENT_MESSAGE_TYPE_SET_PIXEL_FORMAT        = 0,
+       VNC_CLIENT_MESSAGE_TYPE_SET_ENCODING            = 2,
+       VNC_CLIENT_MESSAGE_TYPE_FRAMEBUF_UPDATE_REQ     = 3,
+       VNC_CLIENT_MESSAGE_TYPE_KEY_EVENT               = 4,
+       VNC_CLIENT_MESSAGE_TYPE_POINTER_EVENT           = 5,
+       VNC_CLIENT_MESSAGE_TYPE_CLIENT_CUT_TEXT         = 6,
+} vnc_client_message_types_e;
+
+static const value_string vnc_client_message_types_vs[] = {
+       { VNC_CLIENT_MESSAGE_TYPE_SET_PIXEL_FORMAT,    "Set Pixel Format"               },
+       { VNC_CLIENT_MESSAGE_TYPE_SET_ENCODING,        "Set Encodings"                  },
+       { VNC_CLIENT_MESSAGE_TYPE_FRAMEBUF_UPDATE_REQ, "Framebuffer Update Request"     },
+       { VNC_CLIENT_MESSAGE_TYPE_KEY_EVENT,           "Key Event"                      },
+       { VNC_CLIENT_MESSAGE_TYPE_POINTER_EVENT,       "Pointer Event"                  },
+       { VNC_CLIENT_MESSAGE_TYPE_CLIENT_CUT_TEXT,     "Cut Text"                       },
+       { 0,  NULL                                                                      }
 };
 
-static const value_string server_message_types_vs[] = {
-       { 0, "Framebuffer Update"   },
-       { 1, "Set Colormap Entries" },
-       { 2, "Ring Bell"            },
-       { 3, "Cut Text"             },
-       { 0,  NULL                  }
+typedef enum {
+       VNC_SERVER_MESSAGE_TYPE_FRAMEBUFFER_UPDATE   = 0,
+       VNC_SERVER_MESSAGE_TYPE_SET_COLORMAP_ENTRIES = 1,
+       VNC_SERVER_MESSAGE_TYPE_RING_BELL            = 2,
+       VNC_SERVER_MESSAGE_TYPE_CUT_TEXT             = 3,
+} vnc_server_message_types_e;
+
+static const value_string vnc_server_message_types_vs[] = {
+       { VNC_SERVER_MESSAGE_TYPE_FRAMEBUFFER_UPDATE,   "Framebuffer Update"   },
+       { VNC_SERVER_MESSAGE_TYPE_SET_COLORMAP_ENTRIES, "Set Colormap Entries" },
+       { VNC_SERVER_MESSAGE_TYPE_RING_BELL,            "Ring Bell"            },
+       { VNC_SERVER_MESSAGE_TYPE_CUT_TEXT,             "Cut Text"             },
+       { 0,  NULL                                                             }
 };
 
-static const value_string button_mask_vs[] = {
-       { 0, "Not pressed" },
-       { 1, "Pressed"     },
-       { 0,  NULL         }
+static const true_false_string button_mask_tfs = {
+       "Pressed",
+       "Not pressed"
 };
 
 typedef enum {
-       ENCODING_DESKTOP_SIZE   = -223,
-       ENCODING_LAST_RECT      = -224,
-       ENCODING_POINTER_POS    = -232,
-       ENCODING_RICH_CURSOR    = -239,
-       ENCODING_X_CURSOR       = -240,
-       ENCODING_RAW            = 0,
-       ENCODING_COPY_RECT      = 1,
-       ENCODING_RRE            = 2,
-       ENCODING_CORRE          = 4,
-       ENCODING_HEXTILE        = 5,
-       ENCODING_ZLIB           = 6,
-       ENCODING_TIGHT          = 7,
-       ENCODING_ZLIBHEX        = 8,
-       ENCODING_RLE            = 16
-} encoding_type_e;
+       VNC_ENCODING_TYPE_DESKTOP_SIZE      = 0xFFFFFF21,
+       VNC_ENCODING_TYPE_LAST_RECT         = 0xFFFFFF20,
+       VNC_ENCODING_TYPE_POINTER_POS       = 0xFFFFFF18,
+       VNC_ENCODING_TYPE_RICH_CURSOR       = 0xFFFFFF11,
+       VNC_ENCODING_TYPE_X_CURSOR          = 0xFFFFFF10,
+       VNC_ENCODING_TYPE_RAW               =   0,
+       VNC_ENCODING_TYPE_COPY_RECT         =   1,
+       VNC_ENCODING_TYPE_RRE               =   2,
+       VNC_ENCODING_TYPE_CORRE             =   4,
+       VNC_ENCODING_TYPE_HEXTILE           =   5,
+       VNC_ENCODING_TYPE_ZLIB              =   6,
+       VNC_ENCODING_TYPE_TIGHT             =   7,
+       VNC_ENCODING_TYPE_ZLIBHEX           =   8,
+       VNC_ENCODING_TYPE_ULTRA             =   9,
+       VNC_ENCODING_TYPE_TRLE              =  15,
+       VNC_ENCODING_TYPE_RLE               =  16,
+       VNC_ENCODING_TYPE_HITACHI_ZYWRLE    =  17,
+       VNC_ENCODING_TYPE_JPEG_0            = -32,
+       VNC_ENCODING_TYPE_JPEG_1            = -31,
+       VNC_ENCODING_TYPE_JPEG_2            = -30,
+       VNC_ENCODING_TYPE_JPEG_3            = -29,
+       VNC_ENCODING_TYPE_JPEG_4            = -28,
+       VNC_ENCODING_TYPE_JPEG_5            = -27,
+       VNC_ENCODING_TYPE_JPEG_6            = -26,
+       VNC_ENCODING_TYPE_JPEG_7            = -25,
+       VNC_ENCODING_TYPE_JPEG_8            = -24,
+       VNC_ENCODING_TYPE_JPEG_9            = -23,
+       VNC_ENCODING_TYPE_COMPRESSION_0     = 0xFFFFFF00,
+       VNC_ENCODING_TYPE_COMPRESSION_1     = 0xFFFFFF01,
+       VNC_ENCODING_TYPE_COMPRESSION_2     = 0xFFFFFF02,
+       VNC_ENCODING_TYPE_COMPRESSION_3     = 0xFFFFFF03,
+       VNC_ENCODING_TYPE_COMPRESSION_4     = 0xFFFFFF04,
+       VNC_ENCODING_TYPE_COMPRESSION_5     = 0xFFFFFF05,
+       VNC_ENCODING_TYPE_COMPRESSION_6     = 0xFFFFFF06,
+       VNC_ENCODING_TYPE_COMPRESSION_7     = 0xFFFFFF07,
+       VNC_ENCODING_TYPE_COMPRESSION_8     = 0xFFFFFF08,
+       VNC_ENCODING_TYPE_COMPRESSION_9     = 0xFFFFFF09,
+       VNC_ENCODING_TYPE_WMVi              = 0x574D5669,
+       VNC_ENCODING_TYPE_CACHE             = 0xFFFF0000,
+       VNC_ENCODING_TYPE_CACHE_ENABLE      = 0xFFFF0001,
+       VNC_ENCODING_TYPE_XOR_ZLIB          = 0xFFFF0002,
+       VNC_ENCODING_TYPE_XOR_MONO_ZLIB     = 0xFFFF0003,
+       VNC_ENCODING_TYPE_XOR_MULTI_ZLIB    = 0xFFFF0004,
+       VNC_ENCODING_TYPE_SOLID_COLOR       = 0xFFFF0005,
+       VNC_ENCODING_TYPE_XOR_ENABLE        = 0xFFFF0006,
+       VNC_ENCODING_TYPE_CACHE_ZIP         = 0xFFFF0007,
+       VNC_ENCODING_TYPE_SOL_MONO_ZIP      = 0xFFFF0008,
+       VNC_ENCODING_TYPE_ULTRA_ZIP         = 0xFFFF0009,
+       VNC_ENCODING_TYPE_SERVER_STATE      = 0xFFFF8000,
+       VNC_ENCODING_TYPE_ENABLE_KEEP_ALIVE = 0xFFFF8001,
+       VNC_ENCODING_TYPE_FTP_PROTO_VER     = 0xFFFF8002,
+       VNC_ENCODING_TYPE_POINTER_CHANGE    = -257,
+       VNC_ENCODING_TYPE_EXT_KEY_EVENT     = -258,
+       VNC_ENCODING_TYPE_AUDIO             =  259,
+       VNC_ENCODING_TYPE_DESKTOP_NAME      = -307,
+       VNC_ENCODING_TYPE_EXTENDED_DESK_SIZE= -308
+} vnc_encoding_type_e;
 
 static const value_string encoding_types_vs[] = {
-       { ENCODING_DESKTOP_SIZE,        "DesktopSize (pseudo)" },
-       { ENCODING_LAST_RECT,           "LastRect (pseudo)"    },
-       { ENCODING_POINTER_POS,         "Pointer pos (pseudo)" },
-       { ENCODING_RICH_CURSOR,         "Rich Cursor (pseudo)" },
-       { ENCODING_X_CURSOR,            "X Cursor (pseudo)"    },
-       { ENCODING_RAW,                 "Raw"                  },
-       { ENCODING_COPY_RECT,           "CopyRect"             },
-       { ENCODING_RRE,                 "RRE"                  },
-       { ENCODING_CORRE,               "CoRRE"                },
-       { ENCODING_HEXTILE,             "Hextile"              },
-       { ENCODING_ZLIB,                "Zlib"                 },
-       { ENCODING_TIGHT,               "Tight"                },
-       { ENCODING_ZLIBHEX,             "ZlibHex"              },
-       { ENCODING_RLE,                 "ZRLE"                 },
+       { VNC_ENCODING_TYPE_DESKTOP_SIZE,       "DesktopSize (pseudo)" },
+       { VNC_ENCODING_TYPE_LAST_RECT,          "LastRect (pseudo)"    },
+       { VNC_ENCODING_TYPE_POINTER_POS,        "Pointer pos (pseudo)" },
+       { VNC_ENCODING_TYPE_RICH_CURSOR,        "Rich Cursor (pseudo)" },
+       { VNC_ENCODING_TYPE_X_CURSOR,           "X Cursor (pseudo)"    },
+       { VNC_ENCODING_TYPE_RAW,                "Raw"                  },
+       { VNC_ENCODING_TYPE_COPY_RECT,          "CopyRect"             },
+       { VNC_ENCODING_TYPE_RRE,                "RRE"                  },
+       { VNC_ENCODING_TYPE_CORRE,              "CoRRE"                },
+       { VNC_ENCODING_TYPE_HEXTILE,            "Hextile"              },
+       { VNC_ENCODING_TYPE_ZLIB,               "Zlib"                 },
+       { VNC_ENCODING_TYPE_TIGHT,              "Tight"                },
+       { VNC_ENCODING_TYPE_ZLIBHEX,            "ZlibHex"              },
+       { VNC_ENCODING_TYPE_ULTRA,              "Ultra"                },
+       { VNC_ENCODING_TYPE_RLE,                "ZRLE"                 },
+       { VNC_ENCODING_TYPE_HITACHI_ZYWRLE,     "Hitachi ZYWRLE"       },
+       { VNC_ENCODING_TYPE_JPEG_0,             "JPEG quality level 0" },
+       { VNC_ENCODING_TYPE_JPEG_1,             "JPEG quality level 1" },
+       { VNC_ENCODING_TYPE_JPEG_2,             "JPEG quality level 2" },
+       { VNC_ENCODING_TYPE_JPEG_3,             "JPEG quality level 3" },
+       { VNC_ENCODING_TYPE_JPEG_4,             "JPEG quality level 4" },
+       { VNC_ENCODING_TYPE_JPEG_5,             "JPEG quality level 5" },
+       { VNC_ENCODING_TYPE_JPEG_6,             "JPEG quality level 6" },
+       { VNC_ENCODING_TYPE_JPEG_7,             "JPEG quality level 7" },
+       { VNC_ENCODING_TYPE_JPEG_8,             "JPEG quality level 8" },
+       { VNC_ENCODING_TYPE_JPEG_9,             "JPEG quality level 9" },
+       { VNC_ENCODING_TYPE_COMPRESSION_0,      "Compression level 0"  },
+       { VNC_ENCODING_TYPE_COMPRESSION_1,      "Compression level 1"  },
+       { VNC_ENCODING_TYPE_COMPRESSION_2,      "Compression level 2"  },
+       { VNC_ENCODING_TYPE_COMPRESSION_3,      "Compression level 3"  },
+       { VNC_ENCODING_TYPE_COMPRESSION_4,      "Compression level 4"  },
+       { VNC_ENCODING_TYPE_COMPRESSION_5,      "Compression level 5"  },
+       { VNC_ENCODING_TYPE_COMPRESSION_6,      "Compression level 6"  },
+       { VNC_ENCODING_TYPE_COMPRESSION_7,      "Compression level 7"  },
+       { VNC_ENCODING_TYPE_COMPRESSION_8,      "Compression level 8"  },
+       { VNC_ENCODING_TYPE_COMPRESSION_9,      "Compression level 9"  },
+       /* FIXME understand for real what the below mean. Taken from Ultra VNC source code */
+/*     { VNC_ENCODING_TYPE_CACHE,     */
+       { VNC_ENCODING_TYPE_CACHE_ENABLE,       "Enable Caching"},
+/*     { VNC_ENCODING_TYPE_XOR_ZLIB,
+       { VNC_ENCODING_TYPE_XOR_MONO_ZLIB,
+       { VNC_ENCODING_TYPE_XOR_MULTI_ZLIB,
+       { VNC_ENCODING_TYPE_SOLID_COLOR,
+       { VNC_ENCODING_TYPE_XOR_ENABLE,
+       { VNC_ENCODING_TYPE_CACHE_ZIP,
+       { VNC_ENCODING_TYPE_SOL_MONO_ZIP,
+       { VNC_ENCODING_TYPE_ULTRA_ZIP,
+*/     { VNC_ENCODING_TYPE_SERVER_STATE,       "Server State"         },
+       { VNC_ENCODING_TYPE_ENABLE_KEEP_ALIVE,  "Enable Keep Alive"    },
+       { VNC_ENCODING_TYPE_FTP_PROTO_VER,      "FTP protocol version" },
+       { VNC_ENCODING_TYPE_EXTENDED_DESK_SIZE, "Extended Desktop Size"},
+       { VNC_ENCODING_TYPE_DESKTOP_NAME,       "Desktop Name"         },
        { 0,                            NULL                   }
 };
 
@@ -183,36 +280,33 @@ static const value_string tight_filter_ids_vs[] = {
 
 
 typedef enum {
-       SERVER_VERSION,
-       CLIENT_VERSION,
+       VNC_SESSION_STATE_SERVER_VERSION,
+       VNC_SESSION_STATE_CLIENT_VERSION,
 
-       SECURITY,
-       SECURITY_TYPES,
+       VNC_SESSION_STATE_SECURITY,
+       VNC_SESSION_STATE_SECURITY_TYPES,
 
-       TIGHT_TUNNELING_CAPABILITIES,
-       TIGHT_TUNNEL_TYPE_REPLY,
-       TIGHT_AUTH_CAPABILITIES,
-       TIGHT_AUTH_TYPE_REPLY,
-       TIGHT_AUTH_TYPE_AND_VENDOR_CODE,
-       TIGHT_UNKNOWN_PACKET3,
+       VNC_SESSION_STATE_TIGHT_TUNNELING_CAPABILITIES,
+       VNC_SESSION_STATE_TIGHT_TUNNEL_TYPE_REPLY,
+       VNC_SESSION_STATE_TIGHT_AUTH_CAPABILITIES,
+       VNC_SESSION_STATE_TIGHT_AUTH_TYPE_REPLY,
+       VNC_SESSION_STATE_TIGHT_UNKNOWN_PACKET3,
 
-       VNC_AUTHENTICATION_CHALLENGE,
-       VNC_AUTHENTICATION_RESPONSE,
+       VNC_SESSION_STATE_VNC_AUTHENTICATION_CHALLENGE,
+       VNC_SESSION_STATE_VNC_AUTHENTICATION_RESPONSE,
 
-       SECURITY_RESULT,
+       VNC_SESSION_STATE_SECURITY_RESULT,
 
-       CLIENT_INIT,
-       SERVER_INIT,
+       VNC_SESSION_STATE_CLIENT_INIT,
+       VNC_SESSION_STATE_SERVER_INIT,
 
-       TIGHT_INTERACTION_CAPS,
-       TIGHT_INTERACTION_CAPS_LIST,
+       VNC_SESSION_STATE_TIGHT_INTERACTION_CAPS,
 
-       NORMAL_TRAFFIC
+       VNC_SESSION_STATE_NORMAL_TRAFFIC
 } vnc_session_state_e;
 
 /* This structure will be tied to each conversation. */
 typedef struct {
-       guint8 security_type_selected;
        gdouble server_proto_ver, client_proto_ver;
        vnc_session_state_e vnc_next_state;
        guint32 server_port;
@@ -220,14 +314,16 @@ typedef struct {
        gint num_server_message_types;
        gint num_client_message_types;
        gint num_encoding_types;
+       guint8 security_type_selected;
+       gboolean tight_enabled;
 } vnc_conversation_t;
 
 /* This structure will be tied to each packet */
 typedef struct {
-       guint8 bytes_per_pixel;
-       guint8 depth;
        vnc_session_state_e state;
        gint preferred_encoding;
+       guint8 bytes_per_pixel;
+       guint8 depth;
 } vnc_packet_t;
 
 void proto_reg_handoff_vnc(void);
@@ -257,35 +353,35 @@ static void vnc_client_cut_text(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
 static guint vnc_server_framebuffer_update(tvbuff_t *tvb, packet_info *pinfo,
                                           gint *offset, proto_tree *tree);
 static guint vnc_raw_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
-                             proto_tree *tree, guint16 width, guint16 height);
+                             proto_tree *tree, const guint16 width, const guint16 height);
 static guint vnc_copyrect_encoding(tvbuff_t *tvb, packet_info *pinfo,
                                   gint *offset, proto_tree *tree,
-                                  guint16 width, guint16 height);
+                                  const guint16 width, const guint16 height);
 static guint vnc_rre_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
-                             proto_tree *tree, guint16 width, guint16 height);
+                             proto_tree *tree, const guint16 width, const guint16 height);
 static guint vnc_hextile_encoding(tvbuff_t *tvb, packet_info *pinfo,
                                  gint *offset, proto_tree *tree,
-                                 guint16 width, guint16 height);
+                                 const guint16 width, const guint16 height);
 static guint vnc_zrle_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
-                              proto_tree *tree, guint16 width, guint16 height);
+                              proto_tree *tree, const guint16 width, const guint16 height);
 static guint vnc_tight_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
-                               proto_tree *tree, guint16 width, guint16 height);
+                               proto_tree *tree, const guint16 width, const guint16 height);
 static guint vnc_rich_cursor_encoding(tvbuff_t *tvb, packet_info *pinfo,
-                                     gint *offset, proto_tree *tree, guint16 width,
-                                     guint16 height);
+                                     gint *offset, proto_tree *tree, const guint16 width,
+                                     const guint16 height);
 static guint vnc_x_cursor_encoding(tvbuff_t *tvb, packet_info *pinfo,
-                                  gint *offset, proto_tree *tree, guint16 width,
-                                  guint16 height);
+                                  gint *offset, proto_tree *tree, const guint16 width,
+                                  const guint16 height);
 static guint vnc_server_set_colormap_entries(tvbuff_t *tvb, packet_info *pinfo,
                                             gint *offset, proto_tree *tree);
 static void vnc_server_ring_bell(tvbuff_t *tvb, packet_info *pinfo,
                                 gint *offset, proto_tree *tree);
 static guint vnc_server_cut_text(tvbuff_t *tvb, packet_info *pinfo,
                                 gint *offset, proto_tree *tree);
-static void vnc_set_bytes_per_pixel(packet_info *pinfo, guint8 bytes_per_pixel);
-static void vnc_set_depth(packet_info *pinfo, guint8 depth);
-static guint8 vnc_get_bytes_per_pixel(packet_info *pinfo);
-
+static void vnc_set_bytes_per_pixel(const packet_info *pinfo, const guint8 bytes_per_pixel);
+static void vnc_set_depth(const packet_info *pinfo, const guint8 depth);
+static guint8 vnc_get_bytes_per_pixel(const packet_info *pinfo);
+static guint32 vnc_extended_desktop_size(tvbuff_t *tvb, gint *offset, proto_tree *tree);
 
 #define DEST_PORT_VNC pinfo->destport == 5500 || pinfo->destport == 5501 || \
                pinfo->destport == 5900 || pinfo->destport == 5901 ||   \
@@ -295,7 +391,6 @@ static guint8 vnc_get_bytes_per_pixel(packet_info *pinfo);
        if(a > (guint)tvb_length_remaining(tvb, *offset))       \
                return a;
 
-
 /* Variables for our preferences */
 static guint vnc_preference_alternate_port = 0;
 
@@ -330,7 +425,12 @@ static int hf_vnc_server_green_shift = -1;
 static int hf_vnc_server_blue_shift = -1;
 static int hf_vnc_desktop_name = -1;
 static int hf_vnc_desktop_name_len = -1;
-
+static int hf_vnc_desktop_screen_id = -1;
+static int hf_vnc_desktop_screen_x = -1;
+static int hf_vnc_desktop_screen_y = -1;
+static int hf_vnc_desktop_screen_width = -1;
+static int hf_vnc_desktop_screen_height = -1;
+static int hf_vnc_desktop_screen_flags = -1;
 static int hf_vnc_num_server_message_types = -1;
 static int hf_vnc_num_client_message_types = -1;
 static int hf_vnc_num_encoding_types = -1;
@@ -389,8 +489,7 @@ static int hf_vnc_tight_tunnel_type = -1;
 
 /* Authentication capabilities (TightVNC extension) */
 static int hf_vnc_tight_num_auth_types = -1;
-static int hf_vnc_tight_auth_type = -1;
-
+static int hf_vnc_tight_auth_code = -1;
 /* TightVNC capabilities */
 static int hf_vnc_tight_server_message_type = -1;
 static int hf_vnc_tight_server_vendor = -1;
@@ -507,11 +606,13 @@ static gint ett_vnc_hextile_subrect = -1;
 static gint ett_vnc_zrle_subencoding = -1;
 static gint ett_vnc_colormap_num_groups = -1;
 static gint ett_vnc_colormap_color_group = -1;
+static gint ett_vnc_desktop_screen = -1;
 
 /* Global so they keep their value between packets */
 guint8 vnc_bytes_per_pixel;
 guint8 vnc_depth;
 
+
 static dissector_handle_t vnc_handle;
 
 /* Code to dissect the packets */
@@ -528,29 +629,19 @@ dissect_vnc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        conversation_t *conversation;
        vnc_conversation_t *per_conversation_info;
 
-       conversation = find_conversation(pinfo->fd->num, &pinfo->src,
-                                        &pinfo->dst, pinfo->ptype,
-                                        pinfo->srcport, pinfo->destport, 0);
-
-       if(!conversation) {  /* Conversation does not exist yet - create it */
-               conversation = conversation_new(pinfo->fd->num, &pinfo->src,
-                                               &pinfo->dst, pinfo->ptype,
-                                               pinfo->srcport,
-                                               pinfo->destport, 0);
-       }
+       conversation = find_or_create_conversation(pinfo);
 
        /* Retrieve information from conversation, or add it if it isn't
         * there yet */
-       per_conversation_info = conversation_get_proto_data(conversation,
-                                                           proto_vnc);
+       per_conversation_info = conversation_get_proto_data(conversation, proto_vnc);
        if(!per_conversation_info) {
                per_conversation_info = se_alloc(sizeof(vnc_conversation_t));
-               
-               per_conversation_info->vnc_next_state = SERVER_VERSION;
-               per_conversation_info->security_type_selected = INVALID;
 
-               conversation_add_proto_data(conversation, proto_vnc,
-                                           per_conversation_info);
+               per_conversation_info->vnc_next_state = VNC_SESSION_STATE_SERVER_VERSION;
+               per_conversation_info->security_type_selected = VNC_SECURITY_TYPE_INVALID;
+               per_conversation_info->tight_enabled = FALSE;
+
+               conversation_add_proto_data(conversation, proto_vnc, per_conversation_info);
        }
 
 
@@ -575,7 +666,7 @@ dissect_vnc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        vnc_set_bytes_per_pixel(pinfo, vnc_bytes_per_pixel);
        vnc_set_depth(pinfo, vnc_depth);
 
-       if(!ret) {      
+       if(!ret) {
                if(DEST_PORT_VNC || per_conversation_info->server_port == pinfo->destport)
                        vnc_client_to_server(tvb, pinfo, &offset, vnc_tree);
                else
@@ -590,17 +681,19 @@ process_vendor(proto_tree *tree, gint hfindex, tvbuff_t *tvb, gint offset)
        gchar *vendor;
        proto_item *ti;
 
-       vendor = tvb_get_ephemeral_string(tvb, offset, 4);
+       if (tree) {
+               vendor = tvb_get_ephemeral_string(tvb, offset, 4);
+
+               ti = proto_tree_add_string(tree, hfindex, tvb, offset, 4, vendor);
 
-       ti = proto_tree_add_string(tree, hfindex, tvb, offset, 4, vendor);
+               if(g_ascii_strcasecmp(vendor, "STDV") == 0)
+                       proto_item_append_text(ti, " (Standard VNC vendor)");
+               else if(g_ascii_strcasecmp(vendor, "TRDV") == 0)
+                       proto_item_append_text(ti, " (Tridia VNC vendor)");
+               else if(g_ascii_strcasecmp(vendor, "TGHT") == 0)
+                       proto_item_append_text(ti, " (Tight VNC vendor)");
+       }
 
-       if(g_ascii_strcasecmp(vendor, "STDV") == 0)
-               proto_item_append_text(ti, " (Standard VNC vendor)");
-       else if(g_ascii_strcasecmp(vendor, "TRDV") == 0)
-               proto_item_append_text(ti, " (Tridia VNC vendor)");
-       else if(g_ascii_strcasecmp(vendor, "TGHT") == 0)
-               proto_item_append_text(ti, " (Tight VNC vendor)");
-                       
        offset += 4;
        return offset;
 }
@@ -609,10 +702,9 @@ process_vendor(proto_tree *tree, gint hfindex, tvbuff_t *tvb, gint offset)
 static gint
 process_tight_capabilities(proto_tree *tree,
                           gint type_index, gint vendor_index, gint name_index,
-                          tvbuff_t *tvb, gint offset, gint num_capabilities)
+                          tvbuff_t *tvb, gint offset, const gint num_capabilities)
 {
        gint i;
-
        /* See vnc_unixsrc/include/rfbproto.h:rfbCapabilityInfo */
 
        for (i = 0; i < num_capabilities; i++) {
@@ -632,7 +724,7 @@ process_tight_capabilities(proto_tree *tree,
 }
 
 /* Returns true if this looks like a client or server version packet: 12 bytes, in the format "RFB xxx.yyy\n" .
-* Will check for the 12 bytes exact length, the 'RFB ' string and that it ends with a '\n'. 
+* Will check for the 12 bytes exact length, the 'RFB ' string and that it ends with a '\n'.
 * The exact 'xxx.yyy' is checked later, by trying to convert it to a double using g_ascii_strtod.
 */
 static gboolean
@@ -641,7 +733,7 @@ vnc_is_client_or_server_version_message(tvbuff_t *tvb)
        if(tvb_length(tvb) != 12) {
                return FALSE;
        }
-       
+
        if(tvb_strncaseeql(tvb, 0, "RFB ", 4) != 0) {
                return FALSE;
        }
@@ -649,20 +741,20 @@ vnc_is_client_or_server_version_message(tvbuff_t *tvb)
        if((tvb_get_guint8(tvb, 7) != 0x2e) || (tvb_get_guint8(tvb,11) != 0xa)) {
                return FALSE;
        }
-       
+
        return TRUE;
 }
 
 static gboolean test_vnc_protocol(tvbuff_t *tvb, packet_info *pinfo,
-                                       proto_tree *tree)
+                                 proto_tree *tree)
 {
        conversation_t *conversation;
-       
+
        if (vnc_is_client_or_server_version_message(tvb)) {
                conversation = conversation_new(pinfo->fd->num, &pinfo->src,
-                                                                               &pinfo->dst, pinfo->ptype,
-                                                                               pinfo->srcport,
-                                                                               pinfo->destport, 0);
+                                               &pinfo->dst, pinfo->ptype,
+                                               pinfo->srcport,
+                                               pinfo->destport, 0);
                conversation_set_dissector(conversation, vnc_handle);
                dissect_vnc(tvb, pinfo, tree);
                return TRUE;
@@ -677,7 +769,7 @@ vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo, gint offset,
                     *per_conversation_info)
 {
        guint8 num_security_types;
-       guint32 desktop_name_len, auth_result, text_len;
+       guint32 desktop_name_len, auth_result, text_len, auth_code;
        vnc_packet_t *per_packet_info;
        gint num_tunnel_types;
        gint num_auth_types;
@@ -691,91 +783,88 @@ vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo, gint offset,
                per_packet_info->preferred_encoding = -1;
 
                p_add_proto_data(pinfo->fd, proto_vnc, per_packet_info);
-       } 
-               
+       }
+
        /* Packet dissection follows */
        switch(per_packet_info->state) {
 
-       case SERVER_VERSION :
+       case VNC_SESSION_STATE_SERVER_VERSION :
                if (!vnc_is_client_or_server_version_message(tvb))
                        return TRUE; /* we still hope to get a SERVER_VERSION message some day. Do not proceed yet */
-                       
+
                proto_tree_add_item(tree, hf_vnc_server_proto_ver, tvb, 4,
-                                               7, FALSE);
+                                   7, FALSE);
                per_conversation_info->server_proto_ver =
-                       g_ascii_strtod((char *)tvb_get_ephemeral_string(tvb, 4, 7),
-                                NULL);
+                       g_ascii_strtod((char *)tvb_get_ephemeral_string(tvb, 4, 7), NULL);
                per_conversation_info->server_port = pinfo->srcport;
-               
+
                if (check_col(pinfo->cinfo, COL_INFO))
                        col_add_fstr(pinfo->cinfo, COL_INFO,
                                     "Server protocol version: %s",
                                     tvb_format_text(tvb, 4, 7));
-               
-               per_conversation_info->vnc_next_state = CLIENT_VERSION;
+
+               per_conversation_info->vnc_next_state = VNC_SESSION_STATE_CLIENT_VERSION;
                break;
-               
-       case CLIENT_VERSION :
+
+       case VNC_SESSION_STATE_CLIENT_VERSION :
                if (!vnc_is_client_or_server_version_message(tvb))
                        return TRUE; /* we still hope to get a CLIENT_VERSION message some day. Do not proceed yet */
-               
+
                proto_tree_add_item(tree, hf_vnc_client_proto_ver, tvb,
-                                       4, 7, FALSE);
+                                   4, 7, FALSE);
                per_conversation_info->client_proto_ver =
-                       g_ascii_strtod((char *)tvb_get_ephemeral_string(tvb, 4, 7),
-                                NULL);
-               
+                       g_ascii_strtod((char *)tvb_get_ephemeral_string(tvb, 4, 7), NULL);
+
                if (check_col(pinfo->cinfo, COL_INFO))
                        col_add_fstr(pinfo->cinfo, COL_INFO,
                                     "Client protocol version: %s",
                                     tvb_format_text(tvb, 4, 7));
-               
-               per_conversation_info->vnc_next_state = SECURITY;
+
+               per_conversation_info->vnc_next_state = VNC_SESSION_STATE_SECURITY;
                break;
 
-       case SECURITY :
+       case VNC_SESSION_STATE_SECURITY :
                col_set_str(pinfo->cinfo, COL_INFO, "Security types supported");
-               
+
                /* We're checking against the client protocol version because
                 * the client is the final decider on which version to use
                 * after the server offers the highest version it supports. */
-               
+
                if(per_conversation_info->client_proto_ver >= 3.007) {
                        num_security_types = tvb_get_guint8(tvb, offset);
                        if (tree) {
                                proto_tree_add_item(tree,
-                                       hf_vnc_num_security_types, tvb,
-                                       offset, 1, FALSE);
+                                                   hf_vnc_num_security_types,
+                                                   tvb, offset, 1, FALSE);
 
                                for(offset = 1; offset <= num_security_types; offset++){
                                        proto_tree_add_item(tree,
-                                               hf_vnc_security_type, tvb,
-                                               offset, 1, FALSE);
+                                                           hf_vnc_security_type, tvb,
+                                                           offset, 1, FALSE);
                                }
                        }
-                       per_conversation_info->vnc_next_state = SECURITY_TYPES; 
+                       per_conversation_info->vnc_next_state = VNC_SESSION_STATE_SECURITY_TYPES;
                } else {
                        /* Version < 3.007: The server decides the
                         * authentication type for us to use */
-                       proto_tree_add_item(tree,
-                               hf_vnc_server_security_type, tvb,
-                               offset, 4, FALSE);
+                       proto_tree_add_item(tree, hf_vnc_server_security_type,
+                                           tvb, offset, 4, FALSE);
                        /* The cast below is possible since in older versions of the protocol the only possible values are 0,1,2 */
                        per_conversation_info->security_type_selected = (guint8)tvb_get_ntohl(tvb, offset);
                        switch(per_conversation_info->security_type_selected) {
 
-                       case INVALID:
+                       case VNC_SECURITY_TYPE_INVALID:
                                /* TODO: In this case (INVALID) the connection has failed */
                                /* and there should be an error string describing the error */
-                               per_conversation_info->vnc_next_state = SECURITY_TYPES;
+                               per_conversation_info->vnc_next_state = VNC_SESSION_STATE_SECURITY_TYPES;
                                break;
 
-                       case NONE:
-                               per_conversation_info->vnc_next_state = CLIENT_INIT;
+                       case VNC_SECURITY_TYPE_NONE:
+                               per_conversation_info->vnc_next_state = VNC_SESSION_STATE_CLIENT_INIT;
                                break;
 
-                       case VNC:
-                               per_conversation_info->vnc_next_state = VNC_AUTHENTICATION_CHALLENGE;
+                       case VNC_SECURITY_TYPE_VNC:
+                               per_conversation_info->vnc_next_state = VNC_SESSION_STATE_VNC_AUTHENTICATION_CHALLENGE;
                                break;
 
                        default:
@@ -786,33 +875,33 @@ vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo, gint offset,
 
                break;
 
-       case SECURITY_TYPES :
+       case VNC_SESSION_STATE_SECURITY_TYPES :
                col_set_str(pinfo->cinfo, COL_INFO, "Authentication type selected by client");
-               proto_tree_add_item(tree, hf_vnc_client_security_type, tvb,
-                                                       offset, 1, FALSE);
+               proto_tree_add_item(tree, hf_vnc_client_security_type, tvb, offset, 1, FALSE);
                per_conversation_info->security_type_selected =
                        tvb_get_guint8(tvb, offset);
 
                switch(per_conversation_info->security_type_selected) {
 
-               case NONE :
+               case VNC_SECURITY_TYPE_NONE :
                        if(per_conversation_info->client_proto_ver >= 3.008)
                                per_conversation_info->vnc_next_state =
-                                       SECURITY_RESULT;
+                                       VNC_SESSION_STATE_SECURITY_RESULT;
                        else
                                per_conversation_info->vnc_next_state =
-                                       CLIENT_INIT;
+                                       VNC_SESSION_STATE_CLIENT_INIT;
 
                        break;
 
-               case VNC :
+               case VNC_SECURITY_TYPE_VNC :
                        per_conversation_info->vnc_next_state =
-                               VNC_AUTHENTICATION_CHALLENGE;
+                               VNC_SESSION_STATE_VNC_AUTHENTICATION_CHALLENGE;
                        break;
 
-               case TIGHT :
+               case VNC_SECURITY_TYPE_TIGHT :
                        per_conversation_info->vnc_next_state =
-                               TIGHT_TUNNELING_CAPABILITIES;
+                               VNC_SESSION_STATE_TIGHT_TUNNELING_CAPABILITIES;
+                       per_conversation_info->tight_enabled = TRUE;
                        break;
 
                default :
@@ -822,40 +911,40 @@ vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo, gint offset,
 
                break;
 
-       case TIGHT_TUNNELING_CAPABILITIES :
+       case VNC_SESSION_STATE_TIGHT_TUNNELING_CAPABILITIES :
+       {
+               gint i;
+
                col_set_str(pinfo->cinfo, COL_INFO, "TightVNC tunneling capabilities supported");
 
                proto_tree_add_item(tree, hf_vnc_tight_num_tunnel_types, tvb, offset, 4, FALSE);
                num_tunnel_types = tvb_get_ntohl(tvb, offset);
-               offset += 4;
 
-               {
-                       gint i;
+               offset += 4;
 
-                       for(i = 0; i < num_tunnel_types; i++) {
-                               /* TightVNC and Xvnc don't support any tunnel capabilities yet, but each capability
-                                * is 16 bytes, so skip them.
-                                */
+               for(i = 0; i < num_tunnel_types; i++) {
+                       /* TightVNC and Xvnc don't support any tunnel capabilities yet, but each capability
+                        * is 16 bytes, so skip them.
+                        */
 
-                               proto_tree_add_item(tree, hf_vnc_tight_tunnel_type, tvb, offset, 16, FALSE);
-                               offset += 16;
-                       }
+                       proto_tree_add_item(tree, hf_vnc_tight_tunnel_type, tvb, offset, 16, FALSE);
+                       offset += 16;
                }
 
                if (num_tunnel_types == 0)
-                       per_conversation_info->vnc_next_state = TIGHT_AUTH_CAPABILITIES;
+                       per_conversation_info->vnc_next_state = VNC_SESSION_STATE_TIGHT_AUTH_CAPABILITIES;
                else
-                       per_conversation_info->vnc_next_state = TIGHT_TUNNEL_TYPE_REPLY;
+                       per_conversation_info->vnc_next_state = VNC_SESSION_STATE_TIGHT_TUNNEL_TYPE_REPLY;
                break;
-
-       case TIGHT_TUNNEL_TYPE_REPLY:
+       }
+       case VNC_SESSION_STATE_TIGHT_TUNNEL_TYPE_REPLY:
                /* Neither TightVNC nor Xvnc implement this; they just have a placeholder that emits an error
                 * message and closes the connection (xserver/hw/vnc/auth.c:rfbProcessClientTunnelingType).
                 * We should actually never get here...
                 */
                break;
 
-       case TIGHT_AUTH_CAPABILITIES:
+       case VNC_SESSION_STATE_TIGHT_AUTH_CAPABILITIES:
                col_set_str(pinfo->cinfo, COL_INFO, "TightVNC authentication capabilities supported");
 
                proto_tree_add_item(tree, hf_vnc_tight_num_auth_types, tvb, offset, 4, FALSE);
@@ -864,79 +953,138 @@ vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo, gint offset,
 
                {
                        int i;
-
-                       for (i = 0; i < num_auth_types; i++) {
-                               /* See xserver/hw/vnc/auth.c:rfbSendAuthCaps()
-                                * We don't actually display the auth types for now.
-                                */
-                               proto_tree_add_item(tree, hf_vnc_tight_auth_type, tvb, offset, 16, FALSE);
-                               offset += 16;
+                       guint8 *vendor, *signature;
+                       for (i = 0; i < 1; i++) {
+                               auth_code = tvb_get_ntohl(tvb, offset);
+                               proto_tree_add_item(tree, hf_vnc_tight_auth_code, tvb, offset, 4, FALSE);
+                               offset += 4;
+                               vendor = tvb_get_ephemeral_string(tvb, offset, 4);
+                               process_vendor(tree, hf_vnc_tight_server_vendor, tvb, offset);
+                               offset += 4;
+                               signature = tvb_get_ephemeral_string(tvb, offset, 8);
+                               proto_tree_add_text(tree, tvb, offset, 8, "Signature: %s", signature);
+                               offset += 8;
+
+                               switch(auth_code) {
+                                       case VNC_SECURITY_TYPE_NONE:
+                                               if ((g_ascii_strcasecmp(vendor, "STDV") != 0) || (g_ascii_strcasecmp(signature, "NOAUTH__") != 0)) {
+                                               /* TODO: create a Expert Info */
+                                                       proto_tree_add_text(tree, tvb, offset, 0, "Authentication code does not match vendor or signature");
+                                               }
+                                               break;
+                                       case VNC_SECURITY_TYPE_VNC:
+                                               if ((g_ascii_strcasecmp(vendor, "STDV") != 0) || (g_ascii_strcasecmp(signature, "VNCAUTH_") != 0)) {
+                                               /* TODO: create a Expert Info */
+                                                       proto_tree_add_text(tree, tvb, offset, 0, "Authentication code does not match vendor or signature");
+                                               }
+                                               break;
+                                       case VNC_SECURITY_TYPE_VENCRYPT:
+                                               if ((g_ascii_strcasecmp(vendor, "VENC") != 0) || (g_ascii_strcasecmp(signature, "VENCRYPT") != 0)) {
+                                               /* TODO: create a Expert Info */
+                                                       proto_tree_add_text(tree, tvb, offset, 0, "Authentication code does not match vendor or signature");
+                                               }
+                                               break;
+                                       case VNC_SECURITY_TYPE_GTK_VNC_SASL:
+                                               if ((g_ascii_strcasecmp(vendor, "GTKV") != 0) || (g_ascii_strcasecmp(signature, "SASL____") != 0)) {
+                                               /* TODO: create a Expert Info */
+                                                       proto_tree_add_text(tree, tvb, offset, 0, "Authentication code does not match vendor or signature");
+                                               }
+                                               break;
+                                       case VNC_TIGHT_AUTH_TGHT_ULGNAUTH:
+                                               if ((g_ascii_strcasecmp(vendor, "TGHT") != 0) || (g_ascii_strcasecmp(signature, "ULGNAUTH") != 0)) {
+                                               /* TODO: create a Expert Info */
+                                                       proto_tree_add_text(tree, tvb, offset, 0, "Authentication code does not match vendor or signature");
+                                               }
+                                               break;
+                                       case VNC_TIGHT_AUTH_TGHT_XTRNAUTH:
+                                               if ((g_ascii_strcasecmp(vendor, "TGHT") != 0) || (g_ascii_strcasecmp(signature, "XTRNAUTH") != 0)) {
+                                               /* TODO: create a Expert Info */
+                                                       proto_tree_add_text(tree, tvb, offset, 0, "Authentication code does not match vendor or signature");
+                                               }
+                                               break;
+                                       default:
+                                               proto_tree_add_text(tree, tvb, offset, 0, "Unknown TIGHT VNC authentication");
+                                               break;
+                               }
                        }
                }
 
                if (num_auth_types == 0)
-                       per_conversation_info->vnc_next_state = CLIENT_INIT;
+                       per_conversation_info->vnc_next_state = VNC_SESSION_STATE_CLIENT_INIT;
                else
-                       per_conversation_info->vnc_next_state = TIGHT_AUTH_TYPE_REPLY;
+                       per_conversation_info->vnc_next_state = VNC_SESSION_STATE_TIGHT_AUTH_TYPE_REPLY;
                break;
 
-       case TIGHT_AUTH_TYPE_REPLY:
-               REPORT_DISSECTOR_BUG("Unimplemented case: TightVNC authentication reply");
-               /* FIXME: implement.  See xserver/hw/vnc/auth.c:rfbProcessClientAuthType() */
-               break;          
-
-       case TIGHT_AUTH_TYPE_AND_VENDOR_CODE :
-               col_set_str(pinfo->cinfo, COL_INFO, "Authentication type / vendor code");
-
-               proto_tree_add_item(tree, hf_vnc_server_security_type, tvb,
-                                   offset, 4, FALSE);          
+       case VNC_SESSION_STATE_TIGHT_AUTH_TYPE_REPLY:
+               col_set_str(pinfo->cinfo, COL_INFO, "TightVNC authentication type selected by client");
+               auth_code = tvb_get_ntohl(tvb, offset);
+               proto_tree_add_item(tree, hf_vnc_tight_auth_code, tvb, offset, 4, FALSE);
 
-               offset += 4;
-
-               offset = process_vendor(tree, hf_vnc_vendor_code, tvb, offset);
-
-               /* Display authentication method string */
-               proto_tree_add_item(tree, hf_vnc_security_type_string, tvb,
-                                   offset, 8, FALSE);
-
-               per_conversation_info->vnc_next_state =
-                       TIGHT_UNKNOWN_PACKET3;
+               switch(auth_code) {
+                       case VNC_SECURITY_TYPE_NONE:
+                               per_conversation_info->security_type_selected = VNC_SECURITY_TYPE_NONE;
+                               per_conversation_info->vnc_next_state = VNC_SESSION_STATE_CLIENT_INIT;
+                       break;
+                       case VNC_SECURITY_TYPE_VNC:
+                               per_conversation_info->security_type_selected = VNC_SECURITY_TYPE_VNC;
+                               per_conversation_info->vnc_next_state = VNC_SESSION_STATE_VNC_AUTHENTICATION_CHALLENGE;
+                       break;
+                       case VNC_SECURITY_TYPE_GTK_VNC_SASL:
+                               per_conversation_info->security_type_selected = VNC_SECURITY_TYPE_GTK_VNC_SASL;
+                               /* TODO: dissection not implemented yet */
+                               per_conversation_info->vnc_next_state = VNC_SESSION_STATE_TIGHT_UNKNOWN_PACKET3;
+                               break;
+                       case VNC_TIGHT_AUTH_TGHT_ULGNAUTH:
+                               per_conversation_info->security_type_selected = VNC_TIGHT_AUTH_TGHT_ULGNAUTH;
+                               /* TODO: dissection not implemented yet */
+                               per_conversation_info->vnc_next_state = VNC_SESSION_STATE_TIGHT_UNKNOWN_PACKET3;
+                               break;
+                       case VNC_TIGHT_AUTH_TGHT_XTRNAUTH:
+                               per_conversation_info->security_type_selected = VNC_TIGHT_AUTH_TGHT_XTRNAUTH;
+                               /* TODO: dissection not implemented yet */
+                               per_conversation_info->vnc_next_state = VNC_SESSION_STATE_TIGHT_UNKNOWN_PACKET3;
+                               break;
+                       default:
+                               proto_tree_add_text(tree, tvb, offset, 0, "Unknown authentication selected");
+                               per_conversation_info->vnc_next_state = VNC_SESSION_STATE_TIGHT_UNKNOWN_PACKET3;
+                               break;
+               }
 
                break;
-               
-       case TIGHT_UNKNOWN_PACKET3 :
+
+       case VNC_SESSION_STATE_TIGHT_UNKNOWN_PACKET3 :
                col_set_str(pinfo->cinfo, COL_INFO, "Unknown packet (TightVNC)");
-               
+
                proto_tree_add_text(tree, tvb, offset, -1,
                                    "Unknown packet (TightVNC)");
 
                per_conversation_info->vnc_next_state =
-                       VNC_AUTHENTICATION_CHALLENGE;
+                       VNC_SESSION_STATE_VNC_AUTHENTICATION_CHALLENGE;
 
                break;
 
-       case VNC_AUTHENTICATION_CHALLENGE :
+       case VNC_SESSION_STATE_VNC_AUTHENTICATION_CHALLENGE :
                col_set_str(pinfo->cinfo, COL_INFO, "Authentication challenge from server");
-               
+
                proto_tree_add_item(tree, hf_vnc_auth_challenge, tvb,
                                    offset, 16, FALSE);
 
                per_conversation_info->vnc_next_state =
-                       VNC_AUTHENTICATION_RESPONSE;
+                       VNC_SESSION_STATE_VNC_AUTHENTICATION_RESPONSE;
                break;
 
-       case VNC_AUTHENTICATION_RESPONSE :
+       case VNC_SESSION_STATE_VNC_AUTHENTICATION_RESPONSE :
                col_set_str(pinfo->cinfo, COL_INFO, "Authentication response from client");
-               
+
                proto_tree_add_item(tree, hf_vnc_auth_response, tvb,
                                    offset, 16, FALSE);
-               
-               per_conversation_info->vnc_next_state = SECURITY_RESULT;
+
+               per_conversation_info->vnc_next_state = VNC_SESSION_STATE_SECURITY_RESULT;
                break;
 
-       case SECURITY_RESULT :
+       case VNC_SESSION_STATE_SECURITY_RESULT :
                col_set_str(pinfo->cinfo, COL_INFO, "Authentication result");
-               
+
                proto_tree_add_item(tree, hf_vnc_auth_result, tvb, offset,
                                    4, FALSE);
                auth_result = tvb_get_ntohl(tvb, offset);
@@ -945,7 +1093,7 @@ vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo, gint offset,
                switch(auth_result) {
 
                case 0 : /* OK */
-                       per_conversation_info->vnc_next_state = CLIENT_INIT;
+                       per_conversation_info->vnc_next_state = VNC_SESSION_STATE_CLIENT_INIT;
                        break;
 
                case 1 : /* Failed */
@@ -953,34 +1101,33 @@ vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo, gint offset,
                                text_len = tvb_get_ntohl(tvb, offset);
                                proto_tree_add_text(tree, tvb, offset, 4, "Length of authentication error: %d", text_len);
                                offset += 4;
-                               
+
                                proto_tree_add_item(tree, hf_vnc_auth_error, tvb,
                                                    offset, text_len, FALSE);
-                               offset += text_len;
                        }
 
                        return TRUE; /* All versions: Do not continue
                                        processing VNC packets as connection
                                        will be closed after this packet. */
-                       
+
                        break;
                }
 
                break;
 
-       case CLIENT_INIT :
+       case VNC_SESSION_STATE_CLIENT_INIT :
                col_set_str(pinfo->cinfo, COL_INFO, "Share desktop flag");
 
                proto_tree_add_item(tree, hf_vnc_share_desktop_flag, tvb,
                                    offset, 1, FALSE);
-               
-               per_conversation_info->vnc_next_state = SERVER_INIT;
+
+               per_conversation_info->vnc_next_state = VNC_SESSION_STATE_SERVER_INIT;
 
                break;
-               
-       case SERVER_INIT :
+
+       case VNC_SESSION_STATE_SERVER_INIT :
                col_set_str(pinfo->cinfo, COL_INFO, "Server framebuffer parameters");
-              
+
                proto_tree_add_item(tree, hf_vnc_width, tvb, offset, 2,
                                    FALSE);
                offset += 2;
@@ -1034,8 +1181,8 @@ vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo, gint offset,
                proto_tree_add_item(tree, hf_vnc_padding,
                                    tvb, offset, 3, FALSE);
                offset += 3; /* Skip over 3 bytes of padding */
-               
-               if(tvb_length_remaining(tvb, offset) > 0) {
+
+               if(tvb_length_remaining(tvb, offset) > 4) {
                        /* Sometimes the desktop name & length is skipped */
                        proto_tree_add_item(tree, hf_vnc_desktop_name_len,
                                            tvb, offset, 4, FALSE);
@@ -1047,14 +1194,14 @@ vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo, gint offset,
                                            FALSE);
                }
 
-               if(per_conversation_info->security_type_selected == TIGHT)
+               if(per_conversation_info->tight_enabled == TRUE)
                        per_conversation_info->vnc_next_state =
-                               TIGHT_INTERACTION_CAPS;
+                               VNC_SESSION_STATE_TIGHT_INTERACTION_CAPS;
                else
-                       per_conversation_info->vnc_next_state = NORMAL_TRAFFIC;
+                       per_conversation_info->vnc_next_state = VNC_SESSION_STATE_NORMAL_TRAFFIC;
                break;
-               
-       case TIGHT_INTERACTION_CAPS :
+
+       case VNC_SESSION_STATE_TIGHT_INTERACTION_CAPS :
                col_set_str(pinfo->cinfo, COL_INFO, "TightVNC Interaction Capabilities");
 
                proto_tree_add_item(tree, hf_vnc_num_server_message_types,
@@ -1076,12 +1223,6 @@ vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo, gint offset,
                                    FALSE);
                offset += 2;
 
-               per_conversation_info->vnc_next_state = TIGHT_INTERACTION_CAPS_LIST;
-               break;
-
-       case TIGHT_INTERACTION_CAPS_LIST:
-               col_set_str(pinfo->cinfo, COL_INFO, "TightVNC Interaction Capabilities list");
-
                offset = process_tight_capabilities(tree,
                                                    hf_vnc_tight_server_message_type,
                                                    hf_vnc_tight_server_vendor,
@@ -1092,16 +1233,16 @@ vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo, gint offset,
                                                    hf_vnc_tight_client_vendor,
                                                    hf_vnc_tight_client_name,
                                                    tvb, offset, per_conversation_info->num_client_message_types);
-               offset = process_tight_capabilities(tree,
+               process_tight_capabilities(tree,
                                                    hf_vnc_tight_encoding_type,
                                                    hf_vnc_tight_encoding_vendor,
                                                    hf_vnc_tight_encoding_name,
                                                    tvb, offset, per_conversation_info->num_encoding_types);
 
-               per_conversation_info->vnc_next_state = NORMAL_TRAFFIC;
+               per_conversation_info->vnc_next_state = VNC_SESSION_STATE_NORMAL_TRAFFIC;
                break;
 
-       case NORMAL_TRAFFIC :
+       case VNC_SESSION_STATE_NORMAL_TRAFFIC :
                return FALSE;
        }
 
@@ -1129,42 +1270,41 @@ vnc_client_to_server(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
        *offset += 1;
 
        switch(message_type) {
-               
-       case 0 :
+
+       case VNC_CLIENT_MESSAGE_TYPE_SET_PIXEL_FORMAT :
                vnc_client_set_pixel_format(tvb, pinfo, offset,
                                            vnc_client_message_type_tree);
                break;
 
-       case 2 :
+       case VNC_CLIENT_MESSAGE_TYPE_SET_ENCODING :
                vnc_client_set_encodings(tvb, pinfo, offset,
                                         vnc_client_message_type_tree);
                break;
 
-       case 3 :
+       case VNC_CLIENT_MESSAGE_TYPE_FRAMEBUF_UPDATE_REQ :
                vnc_client_framebuffer_update_request(tvb, pinfo, offset,
                                                      vnc_client_message_type_tree);
                break;
 
-       case 4 :
+       case VNC_CLIENT_MESSAGE_TYPE_KEY_EVENT :
                vnc_client_key_event(tvb, pinfo, offset,
                                     vnc_client_message_type_tree);
                break;
 
-       case 5:
+       case VNC_CLIENT_MESSAGE_TYPE_POINTER_EVENT:
                vnc_client_pointer_event(tvb, pinfo, offset,
                                         vnc_client_message_type_tree);
                break;
 
-       case 6 :
+       case VNC_CLIENT_MESSAGE_TYPE_CLIENT_CUT_TEXT :
                vnc_client_cut_text(tvb, pinfo, offset,
                                    vnc_client_message_type_tree);
                break;
 
        default :
-               if (check_col(pinfo->cinfo, COL_INFO))
-                       col_append_fstr(pinfo->cinfo, COL_INFO,
-                                       "Unknown client message type (%u)",
-                                       message_type);
+               col_append_fstr(pinfo->cinfo, COL_INFO,
+                               "Unknown client message type (%u)",
+                               message_type);
                break;
        }
 }
@@ -1176,7 +1316,7 @@ vnc_server_to_client(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
        gint start_offset;
        guint8 message_type;
        gint bytes_needed = 0, length_remaining;
-       
+
        proto_item *ti=NULL;
        proto_tree *vnc_server_message_type_tree;
 
@@ -1193,22 +1333,22 @@ vnc_server_to_client(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
 
        switch(message_type) {
 
-       case 0 :
+       case VNC_SERVER_MESSAGE_TYPE_FRAMEBUFFER_UPDATE :
                bytes_needed =
                        vnc_server_framebuffer_update(tvb, pinfo, offset,
                                                      vnc_server_message_type_tree);
                break;
 
-       case 1 :
+       case VNC_SERVER_MESSAGE_TYPE_SET_COLORMAP_ENTRIES :
                bytes_needed = vnc_server_set_colormap_entries(tvb, pinfo, offset, vnc_server_message_type_tree);
                break;
 
-       case 2 :
+       case VNC_SERVER_MESSAGE_TYPE_RING_BELL :
                vnc_server_ring_bell(tvb, pinfo, offset,
                                     vnc_server_message_type_tree);
                break;
 
-       case 3 :
+       case VNC_SERVER_MESSAGE_TYPE_CUT_TEXT :
                bytes_needed = vnc_server_cut_text(tvb, pinfo, offset,
                                                   vnc_server_message_type_tree);
                break;
@@ -1235,11 +1375,11 @@ vnc_client_set_pixel_format(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
                            proto_tree *tree)
 {
        col_set_str(pinfo->cinfo, COL_INFO, "Client set pixel format");
-       
+
        proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset,
                            3, FALSE);
        *offset += 3; /* Skip over 3 bytes of padding */
-               
+
        proto_tree_add_item(tree, hf_vnc_client_bits_per_pixel, tvb, *offset,
                            1, FALSE);
        vnc_bytes_per_pixel = tvb_get_guint8(tvb, *offset)/8;
@@ -1284,8 +1424,7 @@ vnc_client_set_pixel_format(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
                            1, FALSE);
        *offset += 1;
 
-       proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset,
-                           3, FALSE);
+       proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 3, FALSE);
        *offset += 3; /* Skip over 3 bytes of padding */
 }
 
@@ -1299,6 +1438,8 @@ vnc_client_set_encodings(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
        vnc_packet_t *per_packet_info;
 
        per_packet_info = p_get_proto_data(pinfo->fd, proto_vnc);
+       /* Our calling function should have set the packet's proto data already */
+       DISSECTOR_ASSERT(per_packet_info != NULL);
 
        col_set_str(pinfo->cinfo, COL_INFO, "Client set encodings");
 
@@ -1329,12 +1470,12 @@ vnc_client_set_encodings(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
                        encoding = tvb_get_ntohl(tvb, *offset);
 
                        switch(encoding) {
-                       case ENCODING_RAW:
-                       case ENCODING_RRE:
-                       case ENCODING_CORRE:
-                       case ENCODING_HEXTILE:
-                       case ENCODING_ZLIB:
-                       case ENCODING_TIGHT:
+                       case VNC_ENCODING_TYPE_RAW:
+                       case VNC_ENCODING_TYPE_RRE:
+                       case VNC_ENCODING_TYPE_CORRE:
+                       case VNC_ENCODING_TYPE_HEXTILE:
+                       case VNC_ENCODING_TYPE_ZLIB:
+                       case VNC_ENCODING_TYPE_TIGHT:
                                per_packet_info->preferred_encoding = encoding;
                                break;
                        }
@@ -1344,7 +1485,7 @@ vnc_client_set_encodings(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
        }
 
        if (per_packet_info->preferred_encoding == -1)
-               per_packet_info->preferred_encoding = ENCODING_RAW;
+               per_packet_info->preferred_encoding = VNC_ENCODING_TYPE_RAW;
 }
 
 
@@ -1381,13 +1522,13 @@ vnc_client_key_event(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
                     proto_tree *tree)
 {
        col_set_str(pinfo->cinfo, COL_INFO, "Client key event");
-       
+
        proto_tree_add_item(tree, hf_vnc_key_down, tvb, *offset, 1, FALSE);
        *offset += 1;
-       
+
        proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 2, FALSE);
        *offset += 2; /* Skip over 2 bytes of padding */
-       
+
        proto_tree_add_item(tree, hf_vnc_key, tvb, *offset, 4, FALSE);
        *offset += 4;
 }
@@ -1398,7 +1539,7 @@ vnc_client_pointer_event(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
                         proto_tree *tree)
 {
        col_set_str(pinfo->cinfo, COL_INFO, "Client pointer event");
-       
+
        proto_tree_add_item(tree, hf_vnc_button_1_pos, tvb, *offset, 1, FALSE);
        proto_tree_add_item(tree, hf_vnc_button_2_pos, tvb, *offset, 1, FALSE);
        proto_tree_add_item(tree, hf_vnc_button_3_pos, tvb, *offset, 1, FALSE);
@@ -1408,10 +1549,10 @@ vnc_client_pointer_event(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
        proto_tree_add_item(tree, hf_vnc_button_7_pos, tvb, *offset, 1, FALSE);
        proto_tree_add_item(tree, hf_vnc_button_8_pos, tvb, *offset, 1, FALSE);
        *offset += 1;
-       
+
        proto_tree_add_item(tree, hf_vnc_pointer_x_pos, tvb, *offset, 2, FALSE);
        *offset += 2;
-       
+
        proto_tree_add_item(tree, hf_vnc_pointer_y_pos, tvb, *offset, 2, FALSE);
        *offset += 2;
 }
@@ -1444,26 +1585,36 @@ static guint
 vnc_server_framebuffer_update(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
                              proto_tree *tree)
 {
-       gint num_rects, i;
-       guint16 width, height;
+       gint i;
+       guint16 num_rects, width, height;
        guint bytes_needed = 0;
-       gint32 encoding_type;
+       guint32 encoding_type;
        proto_item *ti, *ti_x, *ti_y, *ti_width, *ti_height;
        proto_tree *vnc_rect_tree, *vnc_encoding_type_tree;
-       
-       col_set_str(pinfo->cinfo, COL_INFO, "Server framebuffer update");       
+
+       col_set_str(pinfo->cinfo, COL_INFO, "Server framebuffer update");
 
        proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 1, FALSE);
        *offset += 1;
-       
+
        num_rects = tvb_get_ntohs(tvb, *offset);
-       proto_tree_add_text(tree, tvb, *offset, 2, "Number of rectangles: %d",
-                           num_rects);
+       ti = proto_tree_add_text(tree, tvb, *offset, 2, "Number of rectangles: %d",
+                                num_rects);
+
+       if (num_rects > 5000) {
+               expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
+                                      "Too many rectangles, aborting dissection");
+               return(0);
+       }
+
        *offset += 2;
-       
-       for(i = 1; i <= num_rects; i++) {
 
-               VNC_BYTES_NEEDED(12);
+       /*  We know we need (at least) all these bytes, so ask for them now
+        *  (instead of 12 at a time...).
+        */
+       VNC_BYTES_NEEDED((guint)12*num_rects);
+
+       for(i = 1; i <= num_rects; i++) {
 
                ti = proto_tree_add_text(tree, tvb, *offset, 12,
                                         "Rectangle #%d", i);
@@ -1474,16 +1625,16 @@ vnc_server_framebuffer_update(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
                ti_x = proto_tree_add_item(vnc_rect_tree, hf_vnc_fb_update_x_pos,
                                           tvb, *offset, 2, FALSE);
                *offset += 2;
-               
+
                ti_y = proto_tree_add_item(vnc_rect_tree, hf_vnc_fb_update_y_pos,
                                           tvb, *offset, 2, FALSE);
                *offset += 2;
-               
+
                ti_width = proto_tree_add_item(vnc_rect_tree, hf_vnc_fb_update_width,
                                               tvb, *offset, 2, FALSE);
                width = tvb_get_ntohs(tvb, *offset);
                *offset += 2;
-               
+
                ti_height = proto_tree_add_item(vnc_rect_tree, hf_vnc_fb_update_height,
                                                tvb, *offset, 2, FALSE);
                height = tvb_get_ntohs(tvb, *offset);
@@ -1496,70 +1647,70 @@ vnc_server_framebuffer_update(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
                encoding_type = tvb_get_ntohl(tvb, *offset);
                *offset += 4;
 
-               if (encoding_type == ENCODING_LAST_RECT)
+               if (encoding_type == VNC_ENCODING_TYPE_LAST_RECT)
                        break; /* exit the loop */
 
                vnc_encoding_type_tree =
                        proto_item_add_subtree(ti, ett_vnc_encoding_type);
 
                switch(encoding_type) {
-                       
-               case ENCODING_RAW:
+
+               case VNC_ENCODING_TYPE_RAW:
                        bytes_needed = vnc_raw_encoding(tvb, pinfo, offset,
                                                        vnc_encoding_type_tree,
                                                        width, height);
                        break;
-                       
-               case ENCODING_COPY_RECT:
+
+               case VNC_ENCODING_TYPE_COPY_RECT:
                        bytes_needed =
                                vnc_copyrect_encoding(tvb, pinfo, offset,
                                                      vnc_encoding_type_tree,
                                                      width, height);
                        break;
-                       
-               case ENCODING_RRE:
-                       bytes_needed = 
+
+               case VNC_ENCODING_TYPE_RRE:
+                       bytes_needed =
                                vnc_rre_encoding(tvb, pinfo, offset,
                                                 vnc_encoding_type_tree,
                                                 width, height);
                        break;
-                       
-               case ENCODING_HEXTILE:
+
+               case VNC_ENCODING_TYPE_HEXTILE:
                        bytes_needed =
                                vnc_hextile_encoding(tvb, pinfo, offset,
                                                     vnc_encoding_type_tree,
                                                     width, height);
                        break;
-                       
-               case ENCODING_RLE:
+
+               case VNC_ENCODING_TYPE_RLE:
                        bytes_needed =
                                vnc_zrle_encoding(tvb, pinfo, offset,
                                                  vnc_encoding_type_tree,
                                                  width, height);
                        break;
 
-               case ENCODING_TIGHT:
+               case VNC_ENCODING_TYPE_TIGHT:
                        bytes_needed =
                                vnc_tight_encoding(tvb, pinfo, offset,
                                                   vnc_encoding_type_tree,
                                                   width, height);
                        break;
 
-               case ENCODING_RICH_CURSOR:
-               case ENCODING_X_CURSOR:
+               case VNC_ENCODING_TYPE_RICH_CURSOR:
+               case VNC_ENCODING_TYPE_X_CURSOR:
                        proto_item_append_text (ti_x,      " (hotspot X)");
                        proto_item_append_text (ti_y,      " (hotspot Y)");
                        proto_item_append_text (ti_width,  " (cursor width)");
                        proto_item_append_text (ti_height, " (cursor height)");
 
-                       if (encoding_type == ENCODING_RICH_CURSOR)
+                       if (encoding_type == VNC_ENCODING_TYPE_RICH_CURSOR)
                                bytes_needed = vnc_rich_cursor_encoding(tvb, pinfo, offset, vnc_encoding_type_tree, width, height);
                        else
                                bytes_needed = vnc_x_cursor_encoding(tvb, pinfo, offset, vnc_encoding_type_tree, width, height);
 
                        break;
 
-               case ENCODING_POINTER_POS:
+               case VNC_ENCODING_TYPE_POINTER_POS:
                        proto_item_append_text (ti_x,      " (pointer X)");
                        proto_item_append_text (ti_y,      " (pointer Y)");
                        proto_item_append_text (ti_width,  " (unused)");
@@ -1567,13 +1718,17 @@ vnc_server_framebuffer_update(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
                        bytes_needed = 0;
                        break;
 
-               case ENCODING_DESKTOP_SIZE:
+               case VNC_ENCODING_TYPE_DESKTOP_SIZE:
 
                        /* There is no payload for this message type */
 
                        bytes_needed = 0;
                        break;
 
+               case VNC_ENCODING_TYPE_EXTENDED_DESK_SIZE :
+                       bytes_needed = vnc_extended_desktop_size(tvb, offset, vnc_encoding_type_tree);
+                       break;
+
                }
 
                /* Check if the routines above requested more bytes to
@@ -1585,10 +1740,44 @@ vnc_server_framebuffer_update(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
        return 0;
 }
 
+static guint32
+vnc_extended_desktop_size(tvbuff_t *tvb, gint *offset, proto_tree *tree)
+{
+
+       guint8 i, num_of_screens;
+       proto_item *ti;
+       proto_tree *screen_tree;
+       
+       num_of_screens = tvb_get_guint8(tvb, *offset);
+       proto_tree_add_text(tree, tvb, *offset, 1, "Number of screens: %d", num_of_screens);
+       *offset += 1;
+       proto_tree_add_text(tree, tvb, *offset, 3, "Padding");
+       VNC_BYTES_NEEDED((guint32)(3 + (num_of_screens * 16)));
+       *offset += 3;
+       for(i = 1; i <= num_of_screens; i++) {
+               ti = proto_tree_add_text(tree, tvb, *offset, 16, "Screen #%u", i);
+               screen_tree = proto_item_add_subtree(ti, ett_vnc_desktop_screen);
+
+               proto_tree_add_item(screen_tree, hf_vnc_desktop_screen_id, tvb, *offset, 4, FALSE);
+               *offset += 4;
+               proto_tree_add_item(screen_tree, hf_vnc_desktop_screen_x, tvb, *offset, 2, FALSE);
+               *offset += 2;
+               proto_tree_add_item(screen_tree, hf_vnc_desktop_screen_y, tvb, *offset, 2, FALSE);
+               *offset += 2;
+               proto_tree_add_item(screen_tree, hf_vnc_desktop_screen_width, tvb, *offset, 2, FALSE);
+               *offset += 2;
+               proto_tree_add_item(screen_tree, hf_vnc_desktop_screen_height, tvb, *offset, 2, FALSE);
+               *offset += 2;
+               proto_tree_add_item(screen_tree, hf_vnc_desktop_screen_flags, tvb, *offset, 4, FALSE);
+               *offset += 4;
+       }
+       
+       return 0;
+}
 
 static guint
 vnc_raw_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
-                proto_tree *tree, guint16 width, guint16 height)
+                proto_tree *tree, const guint16 width, const guint16 height)
 {
        guint8 bytes_per_pixel = vnc_get_bytes_per_pixel(pinfo);
        guint length;
@@ -1596,7 +1785,7 @@ vnc_raw_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
        length = width * height * bytes_per_pixel;
        VNC_BYTES_NEEDED(length);
 
-       proto_tree_add_item(tree, hf_vnc_raw_pixel_data, tvb, *offset, 
+       proto_tree_add_item(tree, hf_vnc_raw_pixel_data, tvb, *offset,
                            length, FALSE);
        *offset += length;
 
@@ -1606,13 +1795,13 @@ vnc_raw_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
 
 static guint
 vnc_copyrect_encoding(tvbuff_t *tvb, packet_info *pinfo _U_, gint *offset,
-                     proto_tree *tree, guint16 width _U_, guint16 height _U_)
+                     proto_tree *tree, const guint16 width _U_, const guint16 height _U_)
 {
-       proto_tree_add_item(tree, hf_vnc_copyrect_src_x_pos, tvb, *offset, 
+       proto_tree_add_item(tree, hf_vnc_copyrect_src_x_pos, tvb, *offset,
                            2, FALSE);
        *offset += 2;
 
-       proto_tree_add_item(tree, hf_vnc_copyrect_src_y_pos, tvb, *offset, 
+       proto_tree_add_item(tree, hf_vnc_copyrect_src_y_pos, tvb, *offset,
                            2, FALSE);
        *offset += 2;
 
@@ -1622,7 +1811,7 @@ vnc_copyrect_encoding(tvbuff_t *tvb, packet_info *pinfo _U_, gint *offset,
 
 static guint
 vnc_rre_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
-                proto_tree *tree, guint16 width _U_, guint16 height _U_)
+                proto_tree *tree, const guint16 width _U_, const guint16 height _U_)
 {
        guint8 bytes_per_pixel = vnc_get_bytes_per_pixel(pinfo);
        guint32 num_subrects, i;
@@ -1631,19 +1820,29 @@ vnc_rre_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
        proto_tree *subrect_tree;
 
        VNC_BYTES_NEEDED(4);
-       proto_tree_add_item(tree, hf_vnc_rre_num_subrects, tvb, *offset, 
-                           4, FALSE);
+       ti = proto_tree_add_item(tree, hf_vnc_rre_num_subrects, tvb, *offset,
+                                4, FALSE);
        num_subrects = tvb_get_ntohl(tvb, *offset);
        *offset += 4;
 
+       if (num_subrects > 10000) {
+               expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
+                                      "Too many sub-rectangles, aborting dissection");
+               return(0);
+       }
+
+       *offset += 2;
        VNC_BYTES_NEEDED(bytes_per_pixel);
-       proto_tree_add_item(tree, hf_vnc_rre_bg_pixel, tvb, *offset, 
+       proto_tree_add_item(tree, hf_vnc_rre_bg_pixel, tvb, *offset,
                            bytes_per_pixel, FALSE);
        *offset += bytes_per_pixel;
 
+       /*  We know we need (at least) all these bytes, so ask for them now
+        *  (instead of a few at a time...).
+        */
+       bytes_needed = bytes_per_pixel + 8;
+       VNC_BYTES_NEEDED(bytes_needed * num_subrects);
        for(i = 1; i <= num_subrects; i++) {
-               bytes_needed = bytes_per_pixel + 8;
-               VNC_BYTES_NEEDED(bytes_needed);
 
                ti = proto_tree_add_text(tree, tvb, *offset, bytes_per_pixel +
                                         8, "Subrectangle #%d", i);
@@ -1677,11 +1876,11 @@ vnc_rre_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
 
 static guint
 vnc_hextile_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
-                    proto_tree *tree, guint16 width, guint16 height)
+                    proto_tree *tree, const guint16 width, const guint16 height)
 {
        guint8 bytes_per_pixel = vnc_get_bytes_per_pixel(pinfo);
        guint8 i, subencoding_mask, num_subrects, subrect_len;
-       guint length;
+       guint length, bytes_needed;
        proto_tree *subencoding_mask_tree, *subrect_tree, *num_subrects_tree;
        proto_item *ti;
 
@@ -1709,7 +1908,7 @@ vnc_hextile_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
                            hf_vnc_hextile_subrectscolored, tvb, *offset, 1,
                            FALSE);
        *offset += 1;
-       
+
        if(subencoding_mask & 0x1) { /* Raw */
                length = width * height * bytes_per_pixel;
 
@@ -1718,8 +1917,9 @@ vnc_hextile_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
                proto_tree_add_item(tree, hf_vnc_hextile_raw_value, tvb,
                                    *offset, length, FALSE);
                *offset += length;
-       } else { 
+       } else {
                if(subencoding_mask & 0x2) { /* Background Specified */
+                       VNC_BYTES_NEEDED(bytes_per_pixel);
                        proto_tree_add_item(tree, hf_vnc_hextile_bg_value,
                                            tvb, *offset, bytes_per_pixel,
                                            FALSE);
@@ -1727,6 +1927,7 @@ vnc_hextile_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
                }
 
                if(subencoding_mask & 0x4) { /* Foreground Specified */
+                       VNC_BYTES_NEEDED(bytes_per_pixel);
                        proto_tree_add_item(tree, hf_vnc_hextile_fg_value,
                                            tvb, *offset, bytes_per_pixel,
                                            FALSE);
@@ -1734,34 +1935,36 @@ vnc_hextile_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
                }
 
                if(subencoding_mask & 0x8) { /* Any Subrects */
+                       VNC_BYTES_NEEDED(3); /* 1 byte for number of subrects field, +2 at least for 1 subrect */
                        ti = proto_tree_add_item(tree,
                                                 hf_vnc_hextile_num_subrects,
                                                 tvb, *offset, 1,
                                                 FALSE);
                        num_subrects = tvb_get_guint8(tvb, *offset);
                        *offset += 1;
-                       
+
+                       if(subencoding_mask & 0x16)
+                               subrect_len = bytes_per_pixel + 2;
+                       else
+                               subrect_len = 2;
+                       bytes_needed = subrect_len * num_subrects;
+                       VNC_BYTES_NEEDED(bytes_needed);
+
                        num_subrects_tree =
                                proto_item_add_subtree(ti, ett_vnc_hextile_num_subrects);
 
                        for(i = 1; i <= num_subrects; i++) {
-
-                               if(subencoding_mask & 0x16) 
-                                       subrect_len = bytes_per_pixel + 2;
-                               else
-                                       subrect_len = 2;
-
                                ti = proto_tree_add_text(num_subrects_tree, tvb,
                                                         *offset, subrect_len,
                                                         "Subrectangle #%d", i);
 
-                               subrect_tree = 
+                               subrect_tree =
                                        proto_item_add_subtree(ti, ett_vnc_hextile_subrect);
 
                                if(subencoding_mask & 0x16) {
                                        /* Subrects Colored */
                                        proto_tree_add_item(subrect_tree, hf_vnc_hextile_subrect_pixel_value, tvb, *offset, bytes_per_pixel, FALSE);
-                                       
+
                                        *offset += bytes_per_pixel;
                                }
 
@@ -1780,18 +1983,17 @@ vnc_hextile_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
                        }
                }
        }
-
        return 0; /* bytes_needed */
 }
 
 #ifdef HAVE_LIBZ
 static guint
 vnc_zrle_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
-                 proto_tree *tree, guint16 width, guint16 height)
+                 proto_tree *tree, const guint16 width, const guint16 height)
 #else
 static guint
 vnc_zrle_encoding(tvbuff_t *tvb, packet_info *pinfo _U_, gint *offset,
-                 proto_tree *tree, guint16 width _U_, guint16 height _U_)
+                 proto_tree *tree, const guint16 width _U_, const guint16 height _U_)
 #endif
 {
        guint32 data_len;
@@ -1807,7 +2009,7 @@ vnc_zrle_encoding(tvbuff_t *tvb, packet_info *pinfo _U_, gint *offset,
 #endif
 
        VNC_BYTES_NEEDED(4);
-       proto_tree_add_item(tree, hf_vnc_zrle_len, tvb, *offset, 
+       proto_tree_add_item(tree, hf_vnc_zrle_len, tvb, *offset,
                            4, FALSE);
        data_len = tvb_get_ntohl(tvb, *offset);
 
@@ -1859,16 +2061,16 @@ vnc_zrle_encoding(tvbuff_t *tvb, packet_info *pinfo _U_, gint *offset,
                        proto_tree_add_item(zrle_subencoding_tree,
                                            hf_vnc_zrle_palette, uncomp_tvb,
                                            uncomp_offset, length, FALSE);
-               
+
                        /* XXX - Not complete! */
                }
-                       
+
        } else {
                proto_tree_add_text(tree, tvb, *offset, data_len,
                                    "Decompression of ZRLE data failed");
        }
 #endif /* HAVE_LIBZ */
-       
+
        *offset += data_len;
 
        return 0; /* bytes_needed */
@@ -1944,6 +2146,8 @@ process_tight_rect_filter_palette(tvbuff_t *tvb, packet_info *pinfo, gint *offse
        /* See TightVNC's vnc_unixsrc/vncviewer/tight.c:InitFilterPaletteBPP() */
 
        per_packet_info = p_get_proto_data(pinfo->fd, proto_vnc);
+       /* Our calling function should have set the packet's proto data already */
+       DISSECTOR_ASSERT(per_packet_info != NULL);
 
        VNC_BYTES_NEEDED(1);
        proto_tree_add_item(tree, hf_vnc_tight_palette_num_colors, tvb, *offset, 1, FALSE);
@@ -1974,7 +2178,7 @@ process_tight_rect_filter_palette(tvbuff_t *tvb, packet_info *pinfo, gint *offse
 
 static guint
 vnc_tight_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
-                  proto_tree *tree, guint16 width, guint16 height)
+                  proto_tree *tree, const guint16 width _U_, const guint16 height _U_)
 {
        vnc_packet_t *per_packet_info;
        guint8 comp_ctl;
@@ -1982,11 +2186,9 @@ vnc_tight_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
        gint bit_offset;
        gint bytes_needed = -1;
 
-       /* unused arguments */
-       (void) width;
-       (void) height;
-
        per_packet_info = p_get_proto_data(pinfo->fd, proto_vnc);
+       /* Our calling function should have set the packet's proto data already */
+       DISSECTOR_ASSERT(per_packet_info != NULL);
 
        /* See xserver/hw/vnc/rfbproto.h and grep for "Tight Encoding." for the following layout */
 
@@ -2035,8 +2237,8 @@ vnc_tight_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
        } else if (comp_ctl > TIGHT_RECT_MAX_VALUE) {
                /* invalid encoding */
 
-               proto_item_append_text(compression_type_ti, " (invalid encoding)");
-               DISSECTOR_ASSERT_NOT_REACHED();
+               expert_add_info_format(pinfo, compression_type_ti, PI_MALFORMED, PI_ERROR,
+                                      "Invalid encoding");
        } else {
                guint row_size;
                gint bits_per_pixel;
@@ -2114,7 +2316,7 @@ decode_cursor(tvbuff_t *tvb, gint *offset, proto_tree *tree,
        total_bytes = pixels_bytes + mask_bytes;
        VNC_BYTES_NEEDED (total_bytes);
 
-       proto_tree_add_item(tree, hf_vnc_cursor_encoding_pixels, tvb, *offset, 
+       proto_tree_add_item(tree, hf_vnc_cursor_encoding_pixels, tvb, *offset,
                            pixels_bytes, FALSE);
        *offset += pixels_bytes;
 
@@ -2128,7 +2330,7 @@ decode_cursor(tvbuff_t *tvb, gint *offset, proto_tree *tree,
 
 static guint
 vnc_rich_cursor_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
-                        proto_tree *tree, guint16 width, guint16 height)
+                        proto_tree *tree, const guint16 width, const guint16 height)
 {
        guint8 bytes_per_pixel = vnc_get_bytes_per_pixel(pinfo);
        guint pixels_bytes, mask_bytes;
@@ -2142,12 +2344,11 @@ vnc_rich_cursor_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
 
 
 static guint
-vnc_x_cursor_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
-                     proto_tree *tree, guint16 width, guint16 height)
+vnc_x_cursor_encoding(tvbuff_t *tvb, packet_info *pinfo _U_, gint *offset,
+                     proto_tree *tree, const guint16 width, const guint16 height)
 {
        gint bitmap_row_bytes = (width + 7) / 8;
        gint mask_bytes = bitmap_row_bytes * height;
-       (void) pinfo; /* unused argument */
 
        VNC_BYTES_NEEDED (6);
        proto_tree_add_item(tree, hf_vnc_cursor_x_fore_back, tvb, *offset, 6, FALSE);
@@ -2172,21 +2373,31 @@ vnc_server_set_colormap_entries(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
 
        number_of_colors = tvb_get_ntohs(tvb, 4);
 
-       bytes_needed = (number_of_colors * 6) + 5;
-       VNC_BYTES_NEEDED(bytes_needed);
-
-       ti = proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 1, FALSE);
+       VNC_BYTES_NEEDED(3);
+       proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 1, FALSE);
        *offset += 1; /* Skip over 1 byte of padding */
 
-       proto_tree_add_item(tree,
-                           hf_vnc_colormap_first_color,
+       proto_tree_add_item(tree, hf_vnc_colormap_first_color,
                            tvb, *offset, 2, FALSE);
        *offset += 2;
 
+       /*  XXX - this is 3 bytes into the tvb, but number_of_colors is set off
+        *  of 4 bytes in... Bug???
+        */
        ti = proto_tree_add_item(tree, hf_vnc_colormap_num_colors, tvb,
                                 *offset, 2, FALSE);
-       vnc_colormap_num_groups =
-               proto_item_add_subtree(ti, ett_vnc_colormap_num_groups);
+
+       if (number_of_colors > 10000) {
+               expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
+                                      "Too many colors (%d), aborting dissection",
+                                      number_of_colors);
+               return(0);
+       }
+
+       bytes_needed = (number_of_colors * 6) + 5;
+       VNC_BYTES_NEEDED(bytes_needed);
+
+       proto_item_add_subtree(ti, ett_vnc_colormap_num_groups);
 
        *offset += 2;
 
@@ -2194,7 +2405,7 @@ vnc_server_set_colormap_entries(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
                                *offset, number_of_colors * 6, FALSE);
        vnc_colormap_num_groups =
                proto_item_add_subtree(ti, ett_vnc_colormap_num_groups);
-       
+
        for(counter = 1; counter <= number_of_colors; counter++) {
                ti = proto_tree_add_text(vnc_colormap_num_groups, tvb,
                                         *offset, 6,
@@ -2237,15 +2448,21 @@ vnc_server_cut_text(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
                    proto_tree *tree)
 {
        guint32 text_len;
+       proto_item *pi;
 
        col_set_str(pinfo->cinfo, COL_INFO, "Server cut text");
 
        text_len = tvb_get_ntohl(tvb, *offset);
-       proto_tree_add_item(tree,
-                           hf_vnc_server_cut_text_len, tvb, *offset, 4,
+       pi = proto_tree_add_item(tree, hf_vnc_server_cut_text_len, tvb, *offset, 4,
                            FALSE);
        *offset += 4;
-       
+
+       if (text_len > 100000) {
+               expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR,
+                                      "Too much cut text, aborting dissection");
+               return(0);
+       }
+
        VNC_BYTES_NEEDED(text_len);
 
        proto_tree_add_item(tree, hf_vnc_server_cut_text, tvb, *offset,
@@ -2257,37 +2474,40 @@ vnc_server_cut_text(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
 
 
 static void
-vnc_set_bytes_per_pixel(packet_info *pinfo, guint8 bytes_per_pixel)
+vnc_set_bytes_per_pixel(const packet_info *pinfo, const guint8 bytes_per_pixel)
 {
        vnc_packet_t *per_packet_info;
 
-       /* The per_packet_info has already been created by the
-        * vnc_startup_messages() routine. */
        per_packet_info = p_get_proto_data(pinfo->fd, proto_vnc);
+       /* Our calling function should have set the packet's proto data already */
+       DISSECTOR_ASSERT(per_packet_info != NULL);
+
        per_packet_info->bytes_per_pixel = bytes_per_pixel;
 }
 
 
 static void
-vnc_set_depth(packet_info *pinfo, guint8 depth)
+vnc_set_depth(const packet_info *pinfo, const guint8 depth)
 {
        vnc_packet_t *per_packet_info;
 
-       /* The per_packet_info has already been created by the
-        * vnc_startup_messages() routine. */
        per_packet_info = p_get_proto_data(pinfo->fd, proto_vnc);
+       /* Our calling function should have set the packet's proto data already */
+       DISSECTOR_ASSERT(per_packet_info != NULL);
+
        per_packet_info->depth = depth;
 }
 
 
 static guint8
-vnc_get_bytes_per_pixel(packet_info *pinfo)
+vnc_get_bytes_per_pixel(const packet_info *pinfo)
 {
        vnc_packet_t *per_packet_info;
 
-       /* The per_packet_info has already been created by the
-        * vnc_startup_messages() routine. */
        per_packet_info = p_get_proto_data(pinfo->fd, proto_vnc);
+       /* Our calling function should have set the packet's proto data already */
+       DISSECTOR_ASSERT(per_packet_info != NULL);
+
        return per_packet_info->bytes_per_pixel;
 }
 
@@ -2323,17 +2543,17 @@ proto_register_vnc(void)
                },
                { &hf_vnc_security_type,
                  { "Security type", "vnc.security_type",
-                   FT_UINT8, BASE_DEC, VALS(security_types_vs), 0x0,
+                   FT_UINT8, BASE_DEC, VALS(vnc_security_types_vs), 0x0,
                    "Security types offered by the server (VNC versions => 3.007", HFILL }
                },
                { &hf_vnc_server_security_type,
                  { "Security type", "vnc.server_security_type",
-                   FT_UINT32, BASE_DEC, VALS(security_types_vs), 0x0,
+                   FT_UINT32, BASE_DEC, VALS(vnc_security_types_vs), 0x0,
                    "Security type mandated by the server", HFILL }
                },
                { &hf_vnc_client_security_type,
                  { "Security type selected", "vnc.client_security_type",
-                   FT_UINT8, BASE_DEC, VALS(security_types_vs), 0x0,
+                   FT_UINT8, BASE_DEC, VALS(vnc_security_types_vs), 0x0,
                    "Security type selected by the client", HFILL }
                },
                { &hf_vnc_tight_num_tunnel_types,
@@ -2351,10 +2571,10 @@ proto_register_vnc(void)
                    FT_UINT32, BASE_DEC, NULL, 0x0,
                    "Authentication types specific to TightVNC", HFILL }
                },
-               { &hf_vnc_tight_auth_type,
-                 { "Authentication type", "vnc.auth_type",
-                   FT_UINT8, BASE_DEC, NULL, 0x0,
-                   "Authentication type specific to TightVNC", HFILL }
+               { &hf_vnc_tight_auth_code,
+                 { "Authentication code", "vnc.tight_auth_code",
+                   FT_UINT32, BASE_DEC, VALS(vnc_security_types_vs), 0x0,
+                   "Authentication code specific to TightVNC", HFILL }
                },
                { &hf_vnc_tight_server_message_type,
                  { "Server message type (TightVNC)", "vnc.tight_server_message_type",
@@ -2388,7 +2608,7 @@ proto_register_vnc(void)
                },
                { &hf_vnc_tight_encoding_type,
                  { "Encoding type", "vnc.encoding_type",
-                   FT_INT32, BASE_DEC, NULL, 0x0,
+                   FT_INT32, BASE_DEC, VALS(encoding_types_vs), 0x0,
                    "Encoding type specific to TightVNC", HFILL }
                },
                { &hf_vnc_tight_encoding_vendor,
@@ -2483,7 +2703,7 @@ proto_register_vnc(void)
                },
                { &hf_vnc_auth_result,
                  { "Authentication result", "vnc.auth_result",
-                   FT_UINT32, BASE_DEC, VALS(auth_result_vs), 0x0,
+                   FT_BOOLEAN, 32, TFS(&auth_result_tfs), 0x1,
                    NULL, HFILL }
                },
                { &hf_vnc_auth_error,
@@ -2493,7 +2713,7 @@ proto_register_vnc(void)
                },
                { &hf_vnc_share_desktop_flag,
                  { "Share desktop flag", "vnc.share_desktop_flag",
-                   FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x0,
+                   FT_BOOLEAN, BASE_NONE, NULL, 0x0,
                    "Client's desire to share the server's desktop with other clients", HFILL }
                },
                { &hf_vnc_width,
@@ -2561,6 +2781,36 @@ proto_register_vnc(void)
                    FT_UINT32, BASE_DEC, NULL, 0x0,
                    "Length of desktop name in bytes", HFILL }
                },
+               { &hf_vnc_desktop_screen_id,
+                 { "Screen ID", "vnc.screen_id",
+                   FT_UINT32, BASE_DEC, NULL, 0x0,
+                   "ID of screen", HFILL }
+               },
+               { &hf_vnc_desktop_screen_x,
+                 { "Screen X position", "vnc.screen_x",
+                   FT_UINT16, BASE_DEC, NULL, 0x0,
+                   "X coordinate of screen", HFILL }
+               },
+               { &hf_vnc_desktop_screen_y,
+                 { "Screen Y position", "vnc.screen_y",
+                   FT_UINT16, BASE_DEC, NULL, 0x0,
+                   "Y coordinate of screen", HFILL }
+               },
+               { &hf_vnc_desktop_screen_width,
+                 { "Screen width", "vnc.screen_width",
+                   FT_UINT16, BASE_DEC, NULL, 0x0,
+                   "Width of screen", HFILL }
+               },
+               { &hf_vnc_desktop_screen_height,
+                 { "Screen height", "vnc.screen_height",
+                   FT_UINT16, BASE_DEC, NULL, 0x0,
+                   "Height of screen", HFILL }
+               },
+               { &hf_vnc_desktop_screen_flags,
+                 { "Screen flags", "vnc.screen_flags",
+                   FT_UINT32, BASE_DEC, NULL, 0x0,
+                   "Flags of screen", HFILL }
+               },
                { &hf_vnc_desktop_name,
                  { "Desktop name", "vnc.desktop_name",
                    FT_STRING, BASE_NONE, NULL, 0x0,
@@ -2583,7 +2833,7 @@ proto_register_vnc(void)
                },
                { &hf_vnc_client_message_type,
                  { "Client Message Type", "vnc.client_message_type",
-                   FT_UINT8, BASE_DEC, VALS(client_message_types_vs), 0x0,
+                   FT_UINT8, BASE_DEC, VALS(vnc_client_message_types_vs), 0x0,
                    "Message type from client", HFILL }
                },
                { &hf_vnc_client_bits_per_pixel,
@@ -2640,7 +2890,7 @@ proto_register_vnc(void)
                /* Client Key Event */
                { &hf_vnc_key_down,
                  { "Key down", "vnc.key_down",
-                   FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x0,
+                   FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x0,
                    "Specifies whether the key is being pressed or not", HFILL }
                },
                { &hf_vnc_key,
@@ -2652,42 +2902,42 @@ proto_register_vnc(void)
                /* Client Pointer Event */
                { &hf_vnc_button_1_pos,
                  { "Mouse button #1 position", "vnc.button_1_pos",
-                   FT_UINT8, BASE_DEC, VALS(button_mask_vs), 0x1,
+                   FT_BOOLEAN, 8, TFS(&button_mask_tfs), 0x1,
                    "Whether mouse button #1 is being pressed or not", HFILL }
                },
                { &hf_vnc_button_2_pos,
                  { "Mouse button #2 position", "vnc.button_2_pos",
-                   FT_UINT8, BASE_DEC, VALS(button_mask_vs), 0x2,
+                   FT_BOOLEAN, 8, TFS(&button_mask_tfs), 0x2,
                    "Whether mouse button #2 is being pressed or not", HFILL }
                },
                { &hf_vnc_button_3_pos,
                  { "Mouse button #3 position", "vnc.button_3_pos",
-                   FT_UINT8, BASE_DEC, VALS(button_mask_vs), 0x4,
+                   FT_BOOLEAN, 8, TFS(&button_mask_tfs), 0x4,
                    "Whether mouse button #3 is being pressed or not", HFILL }
                },
                { &hf_vnc_button_4_pos,
                  { "Mouse button #4 position", "vnc.button_4_pos",
-                   FT_UINT8, BASE_DEC, VALS(button_mask_vs), 0x8,
+                   FT_BOOLEAN, 8, TFS(&button_mask_tfs), 0x8,
                    "Whether mouse button #4 is being pressed or not", HFILL }
                },
                { &hf_vnc_button_5_pos,
                  { "Mouse button #5 position", "vnc.button_5_pos",
-                   FT_UINT8, BASE_DEC, VALS(button_mask_vs), 0x10,
+                   FT_BOOLEAN, 8, TFS(&button_mask_tfs), 0x10,
                    "Whether mouse button #5 is being pressed or not", HFILL }
                },
                { &hf_vnc_button_6_pos,
                  { "Mouse button #6 position", "vnc.button_6_pos",
-                   FT_UINT8, BASE_DEC, VALS(button_mask_vs), 0x20,
+                   FT_BOOLEAN, 8, TFS(&button_mask_tfs), 0x20,
                    "Whether mouse button #6 is being pressed or not", HFILL }
                },
                { &hf_vnc_button_7_pos,
                  { "Mouse button #7 position", "vnc.button_7_pos",
-                   FT_UINT8, BASE_DEC, VALS(button_mask_vs), 0x40,
+                   FT_BOOLEAN, 8, TFS(&button_mask_tfs), 0x40,
                    "Whether mouse button #7 is being pressed or not", HFILL }
                },
                { &hf_vnc_button_8_pos,
                  { "Mouse button #8 position", "vnc.button_8_pos",
-                   FT_UINT8, BASE_DEC, VALS(button_mask_vs), 0x80,
+                   FT_BOOLEAN, 8, TFS(&button_mask_tfs), 0x80,
                    "Whether mouse button #8 is being pressed or not", HFILL }
                },
                { &hf_vnc_pointer_x_pos,
@@ -2747,7 +2997,7 @@ proto_register_vnc(void)
                /********** Server Message Types **********/
                { &hf_vnc_server_message_type,
                  { "Server Message Type", "vnc.server_message_type",
-                   FT_UINT8, BASE_DEC, VALS(server_message_types_vs), 0x0,
+                   FT_UINT8, BASE_DEC, VALS(vnc_server_message_types_vs), 0x0,
                    "Message type from server", HFILL }
                },
 
@@ -2792,33 +3042,33 @@ proto_register_vnc(void)
                  { "Cursor encoding pixels", "vnc.cursor_encoding_pixels",
                    FT_BYTES, BASE_NONE, NULL, 0x0,
                    "Cursor encoding pixel data", HFILL }
-               },              
+               },
 
                { &hf_vnc_cursor_encoding_bitmask,
                  { "Cursor encoding bitmask", "vnc.cursor_encoding_bitmask",
                    FT_BYTES, BASE_NONE, NULL, 0x0,
                    "Cursor encoding pixel bitmask", HFILL }
-               },              
+               },
 
                /* Raw Encoding */
                { &hf_vnc_raw_pixel_data,
                  { "Pixel data", "vnc.raw_pixel_data",
                    FT_BYTES, BASE_NONE, NULL, 0x0,
                    "Raw pixel data.", HFILL }
-               },              
+               },
 
                /* CopyRect Encoding*/
                { &hf_vnc_copyrect_src_x_pos,
                  { "Source x position", "vnc.copyrect_src_x_pos",
                    FT_UINT16, BASE_DEC, NULL, 0x0,
                    "X position of the rectangle to copy from", HFILL }
-               },              
+               },
 
                { &hf_vnc_copyrect_src_y_pos,
                  { "Source y position", "vnc.copyrect_src_y_pos",
                    FT_UINT16, BASE_DEC, NULL, 0x0,
                    "Y position of the rectangle to copy from", HFILL }
-               },              
+               },
 
                /* RRE Encoding */
                { &hf_vnc_rre_num_subrects,
@@ -2869,23 +3119,23 @@ proto_register_vnc(void)
                  { "Subencoding type", "vnc.hextile_subencoding",
                    FT_UINT8, BASE_DEC, NULL, 0x0,
                    "Hextile subencoding type.", HFILL }
-               },              
+               },
 
                { &hf_vnc_hextile_raw,
                  { "Raw", "vnc.hextile_raw",
-                   FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x1,
+                   FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x1,
                    "Raw subencoding is used in this tile", HFILL }
-               },              
+               },
 
                { &hf_vnc_hextile_raw_value,
                  { "Raw pixel values", "vnc.hextile_raw_value",
                    FT_BYTES, BASE_NONE, NULL, 0x0,
                    "Raw subencoding pixel values", HFILL }
-               },              
+               },
 
                { &hf_vnc_hextile_bg,
                  { "Background Specified", "vnc.hextile_bg",
-                   FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x2,
+                   FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x2,
                    "Background Specified subencoding is used in this tile", HFILL }
                },
 
@@ -2897,9 +3147,9 @@ proto_register_vnc(void)
 
                { &hf_vnc_hextile_fg,
                  { "Foreground Specified", "vnc.hextile_fg",
-                   FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x4,
+                   FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x4,
                    "Foreground Specified subencoding is used in this tile", HFILL }
-               },              
+               },
 
                { &hf_vnc_hextile_fg_value,
                  { "Foreground pixel value", "vnc.hextile_fg_value",
@@ -2909,51 +3159,51 @@ proto_register_vnc(void)
 
                { &hf_vnc_hextile_anysubrects,
                  { "Any Subrects", "vnc.hextile_anysubrects",
-                   FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x8,
+                   FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x8,
                    "Any subrects subencoding is used in this tile", HFILL }
-               },              
+               },
 
                { &hf_vnc_hextile_num_subrects,
                  { "Number of subrectangles", "vnc.hextile_num_subrects",
                    FT_UINT8, BASE_DEC, NULL, 0x0,
                    "Number of subrectangles that follow", HFILL }
-               },              
+               },
 
                { &hf_vnc_hextile_subrectscolored,
                  { "Subrects Colored", "vnc.hextile_subrectscolored",
-                   FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x10,
+                   FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
                    "Subrects colored subencoding is used in this tile", HFILL }
-               },              
+               },
 
                { &hf_vnc_hextile_subrect_pixel_value,
                  { "Pixel value", "vnc.hextile_subrect_pixel_value",
                    FT_BYTES, BASE_NONE, NULL, 0x0,
                    "Pixel value of this subrectangle", HFILL }
-               },              
+               },
 
                { &hf_vnc_hextile_subrect_x_pos,
                  { "X position", "vnc.hextile_subrect_x_pos",
                    FT_UINT8, BASE_DEC, NULL, 0xF0, /* Top 4 bits */
                    "X position of this subrectangle", HFILL }
-               },              
+               },
 
                { &hf_vnc_hextile_subrect_y_pos,
                  { "Y position", "vnc.hextile_subrect_y_pos",
                    FT_UINT8, BASE_DEC, NULL, 0xF, /* Bottom 4 bits */
                    "Y position of this subrectangle", HFILL }
-               },              
+               },
 
                { &hf_vnc_hextile_subrect_width,
                  { "Width", "vnc.hextile_subrect_width",
                    FT_UINT8, BASE_DEC, NULL, 0xF0, /* Top 4 bits */
                    "Subrectangle width minus one", HFILL }
-               },              
+               },
 
                { &hf_vnc_hextile_subrect_height,
                  { "Height", "vnc.hextile_subrect_height",
                    FT_UINT8, BASE_DEC, NULL, 0xF, /* Bottom 4 bits */
                    "Subrectangle height minus one", HFILL }
-               },              
+               },
 
 
                /* ZRLE Encoding */
@@ -3005,13 +3255,13 @@ proto_register_vnc(void)
                    FT_UINT16, BASE_DEC, NULL, 0x0,
                    "First color that should be mapped to given RGB intensities", HFILL }
                },
-               
+
                { &hf_vnc_color_groups,
                  { "Color groups", "vnc.color_groups",
                    FT_NONE, BASE_NONE, NULL, 0x0,
-                   "Color groups", HFILL }
+                   NULL, HFILL }
                },
-               
+
                { &hf_vnc_colormap_num_colors,
                  { "Number of color groups", "vnc.colormap_groups",
                    FT_UINT16, BASE_DEC, NULL, 0x0,
@@ -3059,6 +3309,7 @@ proto_register_vnc(void)
                &ett_vnc_hextile_subrect,
                &ett_vnc_zrle_subencoding,
                &ett_vnc_colormap_num_groups,
+               &ett_vnc_desktop_screen,
                &ett_vnc_colormap_color_group
        };
 
@@ -3073,9 +3324,16 @@ proto_register_vnc(void)
        /* Register our preferences module */
        vnc_module = prefs_register_protocol(proto_vnc, proto_reg_handoff_vnc);
 
-       prefs_register_bool_preference(vnc_module, "desegment", "Reassemble VNC messages spanning multiple TCP segments.", "Whether the VNC dissector should reassemble messages spanning multiple TCP segments.  To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.", &vnc_preference_desegment);
+       prefs_register_bool_preference(vnc_module, "desegment",
+                                      "Reassemble VNC messages spanning multiple TCP segments.",
+                                      "Whether the VNC dissector should reassemble messages spanning "
+                                      "multiple TCP segments.  To use this option, you must also enable "
+                                      "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
+                                      &vnc_preference_desegment);
 
-       prefs_register_uint_preference(vnc_module, "alternate_port", "Alternate TCP port", "Decode this port's traffic as VNC in addition to the default ports (5500, 5501, 5900, 5901)", 10, &vnc_preference_alternate_port);
+       prefs_register_uint_preference(vnc_module, "alternate_port", "Alternate TCP port",
+                                      "Decode this port's traffic as VNC in addition to the default ports (5500, 5501, 5900, 5901)",
+                                      10, &vnc_preference_alternate_port);
 
 }
 
@@ -3093,11 +3351,11 @@ proto_reg_handoff_vnc(void)
        if(!inited) {
                vnc_handle = create_dissector_handle(dissect_vnc, proto_vnc);
 
-               dissector_add("tcp.port", 5500, vnc_handle);
-               dissector_add("tcp.port", 5501, vnc_handle);
-               dissector_add("tcp.port", 5900, vnc_handle);
-               dissector_add("tcp.port", 5901, vnc_handle);
-               
+               dissector_add_uint("tcp.port", 5500, vnc_handle);
+               dissector_add_uint("tcp.port", 5501, vnc_handle);
+               dissector_add_uint("tcp.port", 5900, vnc_handle);
+               dissector_add_uint("tcp.port", 5901, vnc_handle);
+
                heur_dissector_add("tcp", test_vnc_protocol, proto_vnc);
                /* We don't register a port for the VNC HTTP server because
                 * that simply provides a java program for download via the
@@ -3112,7 +3370,7 @@ proto_reg_handoff_vnc(void)
                   vnc_preference_alternate_port != 5900 &&
                   vnc_preference_alternate_port != 5901) {
                        if (vnc_preference_alternate_port_last != 0) {
-                               dissector_delete("tcp.port",
+                               dissector_delete_uint("tcp.port",
                                                 vnc_preference_alternate_port_last,
                                                 vnc_handle);
                        }
@@ -3122,11 +3380,10 @@ proto_reg_handoff_vnc(void)
 
                        /* Register the new port setting */
                        if (vnc_preference_alternate_port != 0) {
-                               dissector_add("tcp.port", 
+                               dissector_add_uint("tcp.port",
                                              vnc_preference_alternate_port,
                                              vnc_handle);
                        }
                }
-               heur_dissector_add("tcp", test_vnc_protocol, proto_vnc);
        }
 }