File: | builds/wireshark/wireshark/epan/dissectors/packet-rdp_egfx.c |
Warning: | line 524, column 4 Value stored to 'offset' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Packet-rdp_egfx.c |
2 | * Routines for the EGFX RDP channel |
3 | * Copyright 2021, David Fort <contact@hardening-consulting.com> |
4 | * |
5 | * Wireshark - Network traffic analyzer |
6 | * By Gerald Combs <gerald@wireshark.org> |
7 | * Copyright 1998 Gerald Combs |
8 | * |
9 | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | */ |
11 | |
12 | /* |
13 | * See: "[MS-RDPEGFX] " |
14 | */ |
15 | |
16 | #include "config.h" |
17 | |
18 | #include <epan/packet.h> |
19 | #include <epan/prefs.h> |
20 | #include <epan/conversation.h> |
21 | #include <epan/expert.h> |
22 | #include <epan/proto_data.h> |
23 | #include <epan/tvbuff_rdp.h> |
24 | #include <epan/crc32-tvb.h> |
25 | |
26 | #include "packet-rdp.h" |
27 | #include "packet-rdpudp.h" |
28 | |
29 | void proto_register_rdp_egfx(void); |
30 | void proto_reg_handoff_rdp_egfx(void); |
31 | |
32 | static int proto_rdp_egfx; |
33 | |
34 | static int hf_egfx_cmdId; |
35 | static int hf_egfx_flags; |
36 | static int hf_egfx_pduLength; |
37 | |
38 | static int hf_egfx_caps_capsSetCount; |
39 | static int hf_egfx_cap_version; |
40 | static int hf_egfx_cap_length; |
41 | |
42 | static int hf_egfx_reset_width; |
43 | static int hf_egfx_reset_height; |
44 | static int hf_egfx_reset_monitorCount; |
45 | static int hf_egfx_reset_monitorDefLeft; |
46 | static int hf_egfx_reset_monitorDefTop; |
47 | static int hf_egfx_reset_monitorDefRight; |
48 | static int hf_egfx_reset_monitorDefBottom; |
49 | static int hf_egfx_reset_monitorDefFlags; |
50 | |
51 | |
52 | static int hf_egfx_ack_queue_depth; |
53 | static int hf_egfx_ack_frame_id; |
54 | static int hf_egfx_ack_total_decoded; |
55 | static int hf_egfx_ack_frame_start; |
56 | static int hf_egfx_ack_frame_end; |
57 | |
58 | static int hf_egfx_ackqoe_frame_id; |
59 | static int hf_egfx_ackqoe_timestamp; |
60 | static int hf_egfx_ackqoe_timediffse; |
61 | static int hf_egfx_ackqoe_timediffedr; |
62 | static int hf_egfx_ackqoe_frame_start; |
63 | static int hf_egfx_ackqoe_frame_end; |
64 | |
65 | static int hf_egfx_start_timestamp; |
66 | static int hf_egfx_start_frameid; |
67 | static int hf_egfx_start_acked_in; |
68 | |
69 | static int hf_egfx_end_frameid; |
70 | static int hf_egfx_end_acked_in; |
71 | |
72 | static int hf_egfx_surfaceid; |
73 | |
74 | static int hf_egfx_watermark_width; |
75 | static int hf_egfx_watermark_height; |
76 | static int hf_egfx_watermark_pixelformat; |
77 | static int hf_egfx_watermark_opacity; |
78 | static int hf_egfx_watermark_hpadding; |
79 | static int hf_egfx_watermark_vpadding; |
80 | static int hf_egfx_watermark_imgsize; |
81 | static int hf_egfx_unknown_bytes; |
82 | |
83 | static int ett_rdp_egfx; |
84 | static int ett_egfx_caps; |
85 | static int ett_egfx_capsconfirm; |
86 | static int ett_egfx_cap; |
87 | static int ett_egfx_cap_version; |
88 | static int ett_egfx_ack; |
89 | static int ett_egfx_ackqoe; |
90 | static int ett_egfx_reset; |
91 | static int ett_egfx_monitors; |
92 | static int ett_egfx_monitordef; |
93 | static int ett_egfx_watermark; |
94 | static int ett_egfx_createsurface; |
95 | static int ett_egfx_mapsurfacetooutput; |
96 | static int ett_egfx_mapsurfacetowindow; |
97 | static int ett_egfx_mapsurfacetoscaledoutput; |
98 | static int ett_egfx_mapsurfacetoscaledwindow; |
99 | static int ett_egfx_wiretosurface1; |
100 | static int ett_egfx_wiretosurface2; |
101 | static int ett_egfx_protectsurface; |
102 | static int ett_egfx_surfacetosurface; |
103 | static int ett_egfx_surfacetocache; |
104 | static int ett_egfx_deletesurface; |
105 | static int ett_egfx_deleteencodingcontext; |
106 | |
107 | static expert_field ei_egfx_pdulen_invalid; |
108 | static expert_field ei_egfx_invalid_compression; |
109 | |
110 | |
111 | #define PNAME"RDP Graphic pipeline channel Protocol" "RDP Graphic pipeline channel Protocol" |
112 | #define PSNAME"EGFX" "EGFX" |
113 | #define PFNAME"rdp_egfx" "rdp_egfx" |
114 | |
115 | enum { |
116 | RDPGFX_CMDID_WIRETOSURFACE_1 = 0x0001, |
117 | RDPGFX_CMDID_WIRETOSURFACE_2 = 0x0002, |
118 | RDPGFX_CMDID_DELETEENCODINGCONTEXT = 0x0003, |
119 | RDPGFX_CMDID_SOLIDFILL = 0x0004, |
120 | RDPGFX_CMDID_SURFACETOSURFACE = 0x0005, |
121 | RDPGFX_CMDID_SURFACETOCACHE = 0x0006, |
122 | RDPGFX_CMDID_CACHETOSURFACE = 0x0007, |
123 | RDPGFX_CMDID_EVICTCACHEENTRY = 0x0008, |
124 | RDPGFX_CMDID_CREATESURFACE = 0x0009, |
125 | RDPGFX_CMDID_DELETESURFACE = 0x000a, |
126 | RDPGFX_CMDID_STARTFRAME = 0x000b, |
127 | RDPGFX_CMDID_ENDFRAME = 0x000c, |
128 | RDPGFX_CMDID_FRAMEACKNOWLEDGE = 0x000d, |
129 | RDPGFX_CMDID_RESETGRAPHICS = 0x000e, |
130 | RDPGFX_CMDID_MAPSURFACETOOUTPUT = 0x000f, |
131 | RDPGFX_CMDID_CACHEIMPORTOFFER = 0x0010, |
132 | RDPGFX_CMDID_CACHEIMPORTREPLY = 0x0011, |
133 | RDPGFX_CMDID_CAPSADVERTISE = 0x0012, |
134 | RDPGFX_CMDID_CAPSCONFIRM = 0x0013, |
135 | RDPGFX_CMDID_MAPSURFACETOWINDOW = 0x0015, |
136 | RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE = 0x0016, |
137 | RDPGFX_CMDID_MAPSURFACETOSCALEDOUTPUT = 0x0017, |
138 | RDPGFX_CMDID_MAPSURFACETOSCALEDWINDOW = 0x0018, |
139 | RDPGFX_CMDID_PROTECT_SURFACE = 0x0019, |
140 | RDPGFX_CMDID_WATERMARK = 0x001A, |
141 | }; |
142 | |
143 | enum { |
144 | RDPGFX_CAPVERSION_8 = 0x00080004, |
145 | RDPGFX_CAPVERSION_81 = 0x00080105, |
146 | RDPGFX_CAPVERSION_10 = 0x000A0002, |
147 | RDPGFX_CAPVERSION_101 = 0x000A0100, |
148 | RDPGFX_CAPVERSION_102 = 0x000A0200, |
149 | RDPGFX_CAPVERSION_103 = 0x000A0301, |
150 | RDPGFX_CAPVERSION_104 = 0x000A0400, |
151 | RDPGFX_CAPVERSION_105 = 0x000A0502, |
152 | RDPGFX_CAPVERSION_106_ERROR = 0x000A0600, |
153 | RDPGFX_CAPVERSION_106 = 0x000A0601, |
154 | RDPGFX_CAPVERSION_107 = 0x000A0701, |
155 | |
156 | RDPGFX_CAPVERSION_111 = 0x000b0101, |
157 | RDPGFX_CAPVERSION_112 = 0x000b0200, |
158 | RDPGFX_CAPVERSION_113 = 0x000b0300, |
159 | |
160 | }; |
161 | |
162 | static const value_string rdp_egfx_cmd_vals[] = { |
163 | { RDPGFX_CMDID_WIRETOSURFACE_1, "Wire to surface 1" }, |
164 | { RDPGFX_CMDID_WIRETOSURFACE_2, "Wire to surface 2" }, |
165 | { RDPGFX_CMDID_DELETEENCODINGCONTEXT, "delete encoding context" }, |
166 | { RDPGFX_CMDID_SOLIDFILL, "Solid fill" }, |
167 | { RDPGFX_CMDID_SURFACETOSURFACE, "Surface to surface" }, |
168 | { RDPGFX_CMDID_SURFACETOCACHE, "Surface to cache" }, |
169 | { RDPGFX_CMDID_CACHETOSURFACE, "Cache to surface" }, |
170 | { RDPGFX_CMDID_EVICTCACHEENTRY, "Evict cache entry" }, |
171 | { RDPGFX_CMDID_CREATESURFACE, "Create surface" }, |
172 | { RDPGFX_CMDID_DELETESURFACE, "Delete surface" }, |
173 | { RDPGFX_CMDID_STARTFRAME, "Start frame" }, |
174 | { RDPGFX_CMDID_ENDFRAME, "End frame" }, |
175 | { RDPGFX_CMDID_FRAMEACKNOWLEDGE, "Frame acknowledge" }, |
176 | { RDPGFX_CMDID_RESETGRAPHICS, "Reset graphics" }, |
177 | { RDPGFX_CMDID_MAPSURFACETOOUTPUT, "Map Surface to output" }, |
178 | { RDPGFX_CMDID_CACHEIMPORTOFFER, "Cache import offer" }, |
179 | { RDPGFX_CMDID_CACHEIMPORTREPLY, "Cache import reply" }, |
180 | { RDPGFX_CMDID_CAPSADVERTISE, "Caps advertise" }, |
181 | { RDPGFX_CMDID_CAPSCONFIRM, "Caps confirm" }, |
182 | { RDPGFX_CMDID_MAPSURFACETOWINDOW, "Map surface to window" }, |
183 | { RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE, "Qoe frame acknowledge" }, |
184 | { RDPGFX_CMDID_MAPSURFACETOSCALEDOUTPUT, "Map surface to scaled output" }, |
185 | { RDPGFX_CMDID_MAPSURFACETOSCALEDWINDOW, "Map surface to scaled window" }, |
186 | { RDPGFX_CMDID_PROTECT_SURFACE, "Protect surface" }, |
187 | { RDPGFX_CMDID_WATERMARK, "Watermark surface" }, |
188 | { 0x0, NULL((void*)0) }, |
189 | }; |
190 | |
191 | static const value_string rdp_egfx_caps_version_vals[] = { |
192 | { RDPGFX_CAPVERSION_8, "8.0" }, |
193 | { RDPGFX_CAPVERSION_81, "8.1" } , |
194 | { RDPGFX_CAPVERSION_10, "10.0" } , |
195 | { RDPGFX_CAPVERSION_101, "10.1" }, |
196 | { RDPGFX_CAPVERSION_102, "10.2" }, |
197 | { RDPGFX_CAPVERSION_103, "10.3" }, |
198 | { RDPGFX_CAPVERSION_104, "10.4" }, |
199 | { RDPGFX_CAPVERSION_105, "10.5" }, |
200 | { RDPGFX_CAPVERSION_106_ERROR, "10.6 bogus" }, |
201 | { RDPGFX_CAPVERSION_106, "10.6" }, |
202 | { RDPGFX_CAPVERSION_107, "10.7" }, |
203 | { RDPGFX_CAPVERSION_111, "11.1" }, |
204 | { RDPGFX_CAPVERSION_112, "11.2" }, |
205 | { RDPGFX_CAPVERSION_113, "11.3" }, |
206 | |
207 | { 0x0, NULL((void*)0) }, |
208 | }; |
209 | |
210 | static const value_string rdp_egfx_monitor_flags_vals[] = { |
211 | { 0x00000000, "is secondary" }, |
212 | { 0x00000001, "is primary" }, |
213 | { 0x0, NULL((void*)0) }, |
214 | }; |
215 | |
216 | |
217 | typedef struct { |
218 | zgfx_context_t *zgfx; |
219 | wmem_map_t *frames; |
220 | } egfx_conv_info_t; |
221 | |
222 | enum { |
223 | EGFX_PDU_KEY = 1 |
224 | }; |
225 | |
226 | typedef struct { |
227 | wmem_tree_t* pdus; |
228 | } egfx_pdu_info_t; |
229 | |
230 | typedef struct { |
231 | int startNum; |
232 | int endNum; |
233 | int ackNum; |
234 | } egfx_frame_t; |
235 | |
236 | static const char * |
237 | find_egfx_version(uint32_t v) { |
238 | const value_string *vs = rdp_egfx_caps_version_vals; |
239 | for ( ; vs->strptr; vs++) |
240 | if (vs->value == v) |
241 | return vs->strptr; |
242 | |
243 | return "<unknown>"; |
244 | } |
245 | |
246 | static egfx_conv_info_t * |
247 | egfx_get_conversation_data(packet_info *pinfo) |
248 | { |
249 | conversation_t *conversation, *conversation_tcp; |
250 | egfx_conv_info_t *info; |
251 | |
252 | conversation = find_or_create_conversation(pinfo); |
253 | |
254 | info = (egfx_conv_info_t *)conversation_get_proto_data(conversation, proto_rdp_egfx); |
255 | if (!info) { |
256 | conversation_tcp = rdp_find_tcp_conversation_from_udp(conversation); |
257 | if (conversation_tcp) |
258 | info = (egfx_conv_info_t *)conversation_get_proto_data(conversation_tcp, proto_rdp_egfx); |
259 | } |
260 | |
261 | if (info == NULL((void*)0)) { |
262 | info = wmem_new0(wmem_file_scope(), egfx_conv_info_t)((egfx_conv_info_t*)wmem_alloc0((wmem_file_scope()), sizeof(egfx_conv_info_t ))); |
263 | info->zgfx = zgfx_context_new(wmem_file_scope()); |
264 | info->frames = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal); |
265 | conversation_add_proto_data(conversation, proto_rdp_egfx, info); |
266 | } |
267 | |
268 | return info; |
269 | } |
270 | |
271 | |
272 | static int |
273 | dissect_rdp_egfx_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, egfx_conv_info_t *conv, void *data _U___attribute__((unused))) |
274 | { |
275 | proto_item *item; |
276 | proto_item *pi; |
277 | proto_tree *tree; |
278 | proto_tree *subtree; |
279 | int offset = 0; |
280 | uint32_t cmdId = 0; |
281 | uint32_t pduLength; |
282 | uint32_t i; |
283 | |
284 | parent_tree = proto_tree_get_root(parent_tree); |
285 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "EGFX"); |
286 | col_clear(pinfo->cinfo, COL_INFO); |
287 | |
288 | while (tvb_captured_length_remaining(tvb, offset) > 8) { |
289 | pduLength = tvb_get_uint32(tvb, offset + 4, ENC_LITTLE_ENDIAN0x80000000); |
290 | |
291 | item = proto_tree_add_item(parent_tree, proto_rdp_egfx, tvb, offset, pduLength, ENC_NA0x00000000); |
292 | tree = proto_item_add_subtree(item, ett_rdp_egfx); |
293 | |
294 | proto_tree_add_item_ret_uint(tree, hf_egfx_cmdId, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000, &cmdId); |
295 | offset += 2; |
296 | |
297 | proto_tree_add_item(tree, hf_egfx_flags, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
298 | offset += 2; |
299 | |
300 | proto_tree_add_item(tree, hf_egfx_pduLength, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000); |
301 | offset += 4; |
302 | |
303 | if (pduLength < 8) { |
304 | expert_add_info_format(pinfo, item, &ei_egfx_pdulen_invalid, "pduLength is %u, not < 8", pduLength); |
305 | return offset; |
306 | } |
307 | |
308 | int nextOffset = offset + (pduLength - 8); |
309 | switch (cmdId) { |
310 | case RDPGFX_CMDID_CAPSADVERTISE: { |
311 | uint16_t capsSetCount = tvb_get_uint16(tvb, offset, ENC_LITTLE_ENDIAN0x80000000); |
312 | |
313 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Caps advertise"); |
314 | proto_tree_add_item(tree, hf_egfx_caps_capsSetCount, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
315 | |
316 | subtree = proto_tree_add_subtree(tree, tvb, offset, pduLength-8, ett_egfx_caps, NULL((void*)0), "Caps"); |
317 | offset += 2; |
318 | |
319 | for (i = 0; i < capsSetCount; i++) { |
320 | uint32_t version = tvb_get_uint32(tvb, offset, ENC_LITTLE_ENDIAN0x80000000); |
321 | uint32_t capsDataLength = tvb_get_uint32(tvb, offset + 4, ENC_LITTLE_ENDIAN0x80000000); |
322 | proto_tree* vtree = proto_tree_add_subtree(subtree, tvb, offset, 8 + capsDataLength, ett_egfx_cap_version, NULL((void*)0), find_egfx_version(version)); |
323 | |
324 | proto_tree_add_item(vtree, hf_egfx_cap_version, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000); |
325 | offset += 4; |
326 | |
327 | proto_tree_add_item(vtree, hf_egfx_cap_length, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000); |
328 | offset += 4; |
329 | |
330 | offset += capsDataLength; |
331 | } |
332 | break; |
333 | } |
334 | |
335 | case RDPGFX_CMDID_CAPSCONFIRM: { |
336 | uint32_t capsDataLength; |
337 | |
338 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Caps confirm"); |
339 | |
340 | subtree = proto_tree_add_subtree(tree, tvb, offset, pduLength-8, ett_egfx_capsconfirm, NULL((void*)0), "Caps confirm"); |
341 | proto_tree_add_item(subtree, hf_egfx_cap_version, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000); |
342 | offset += 4; |
343 | |
344 | proto_tree_add_item_ret_uint(subtree, hf_egfx_cap_length, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000, &capsDataLength); |
345 | break; |
346 | } |
347 | |
348 | case RDPGFX_CMDID_RESETGRAPHICS: { |
349 | uint32_t nmonitor; |
350 | proto_tree *monitors_tree; |
351 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Reset graphics"); |
352 | |
353 | subtree = proto_tree_add_subtree(tree, tvb, offset, pduLength-8, ett_egfx_reset, NULL((void*)0), "Reset graphics"); |
354 | proto_tree_add_item(subtree, hf_egfx_reset_width, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000); |
355 | offset += 4; |
356 | |
357 | proto_tree_add_item(subtree, hf_egfx_reset_height, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000); |
358 | offset += 4; |
359 | |
360 | proto_tree_add_item_ret_uint(subtree, hf_egfx_reset_monitorCount, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000, &nmonitor); |
361 | offset += 4; |
362 | |
363 | monitors_tree = proto_tree_add_subtree(subtree, tvb, offset, nmonitor * 20, ett_egfx_monitors, NULL((void*)0), "Monitors"); |
364 | for (i = 0; i < nmonitor; i++) { |
365 | proto_item *monitor_tree; |
366 | uint32_t left, top, right, bottom; |
367 | left = tvb_get_uint32(tvb, offset, ENC_LITTLE_ENDIAN0x80000000); |
368 | top = tvb_get_uint32(tvb, offset+4, ENC_LITTLE_ENDIAN0x80000000); |
369 | right = tvb_get_uint32(tvb, offset+8, ENC_LITTLE_ENDIAN0x80000000); |
370 | bottom = tvb_get_uint32(tvb, offset+12, ENC_LITTLE_ENDIAN0x80000000); |
371 | |
372 | monitor_tree = proto_tree_add_subtree_format(monitors_tree, tvb, offset, 20, ett_egfx_monitordef, NULL((void*)0), |
373 | "(%d,%d) - (%d,%d)", left, top, right, bottom); |
374 | |
375 | proto_tree_add_item(monitor_tree, hf_egfx_reset_monitorDefLeft, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000); |
376 | offset += 4; |
377 | |
378 | proto_tree_add_item(monitor_tree, hf_egfx_reset_monitorDefTop, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000); |
379 | offset += 4; |
380 | |
381 | proto_tree_add_item(monitor_tree, hf_egfx_reset_monitorDefRight, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000); |
382 | offset += 4; |
383 | |
384 | proto_tree_add_item(monitor_tree, hf_egfx_reset_monitorDefBottom, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000); |
385 | offset += 4; |
386 | |
387 | proto_tree_add_item(monitor_tree, hf_egfx_reset_monitorDefFlags, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000); |
388 | offset += 4; |
389 | } |
390 | break; |
391 | } |
392 | |
393 | case RDPGFX_CMDID_STARTFRAME: { |
394 | uint32_t frameId; |
395 | egfx_frame_t *frame; |
396 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Start frame"); |
397 | proto_tree_add_item(tree, hf_egfx_start_timestamp, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000); |
398 | // TODO: dissect timestamp |
399 | offset += 4; |
400 | |
401 | proto_tree_add_item_ret_uint(tree, hf_egfx_start_frameid, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000, &frameId); |
402 | frame = wmem_map_lookup(conv->frames, GUINT_TO_POINTER(frameId)((gpointer) (gulong) (frameId))); |
403 | if (!frame) { |
404 | frame = wmem_alloc0(wmem_file_scope(), sizeof(*frame)); |
405 | frame->startNum = pinfo->num; |
406 | frame->endNum = -1; |
407 | frame->ackNum = -1; |
408 | wmem_map_insert(conv->frames, GUINT_TO_POINTER(frameId)((gpointer) (gulong) (frameId)), frame); |
409 | } |
410 | |
411 | if (PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && frame->ackNum != -1) { |
412 | pi = proto_tree_add_uint(tree, hf_egfx_start_acked_in, tvb, 0, 0, frame->ackNum); |
413 | proto_item_set_generated(pi); |
414 | } |
415 | break; |
416 | } |
417 | |
418 | case RDPGFX_CMDID_ENDFRAME: { |
419 | uint32_t frameId; |
420 | egfx_frame_t *frame; |
421 | |
422 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "End frame"); |
423 | proto_tree_add_item_ret_uint(tree, hf_egfx_end_frameid, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000, &frameId); |
424 | |
425 | frame = wmem_map_lookup(conv->frames, GUINT_TO_POINTER(frameId)((gpointer) (gulong) (frameId))); |
426 | if (!frame) { |
427 | frame = wmem_alloc0(wmem_file_scope(), sizeof(*frame)); |
428 | frame->startNum = -1; |
429 | frame->ackNum = -1; |
430 | wmem_map_insert(conv->frames, GUINT_TO_POINTER(frameId)((gpointer) (gulong) (frameId)), frame); |
431 | } |
432 | |
433 | frame->endNum = pinfo->num; |
434 | |
435 | if (PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && frame->ackNum != -1) { |
436 | pi = proto_tree_add_uint(tree, hf_egfx_end_acked_in, tvb, 0, 0, frame->ackNum); |
437 | proto_item_set_generated(pi); |
438 | } |
439 | |
440 | break; |
441 | } |
442 | |
443 | case RDPGFX_CMDID_FRAMEACKNOWLEDGE: { |
444 | uint32_t frameId; |
445 | egfx_frame_t *frame; |
446 | |
447 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Frame acknowledge"); |
448 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_egfx_ack, NULL((void*)0), "Frame acknowledge"); |
449 | proto_tree_add_item(subtree, hf_egfx_ack_queue_depth, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000); |
450 | offset += 4; |
451 | |
452 | proto_tree_add_item_ret_uint(subtree, hf_egfx_ack_frame_id, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000, &frameId); |
453 | offset += 4; |
454 | |
455 | proto_tree_add_item(subtree, hf_egfx_ack_total_decoded, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000); |
456 | |
457 | frame = wmem_map_lookup(conv->frames, GUINT_TO_POINTER(frameId)((gpointer) (gulong) (frameId))); |
458 | if (!frame) { |
459 | frame = wmem_alloc0(wmem_file_scope(), sizeof(*frame)); |
460 | frame->startNum = -1; |
461 | frame->endNum = -1; |
462 | frame->ackNum = frameId; |
463 | wmem_map_insert(conv->frames, GUINT_TO_POINTER(frameId)((gpointer) (gulong) (frameId)), frame); |
464 | } |
465 | |
466 | frame->ackNum = pinfo->num; |
467 | |
468 | if (PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && frame->startNum != -1) { |
469 | pi = proto_tree_add_uint(tree, hf_egfx_ack_frame_start, tvb, 0, 0, frame->startNum); |
470 | proto_item_set_generated(pi); |
471 | } |
472 | |
473 | if (PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && frame->endNum != -1) { |
474 | pi = proto_tree_add_uint(tree, hf_egfx_ack_frame_end, tvb, 0, 0, frame->endNum); |
475 | proto_item_set_generated(pi); |
476 | } |
477 | break; |
478 | } |
479 | |
480 | case RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE: { |
481 | uint32_t frameId; |
482 | egfx_frame_t *frame; |
483 | |
484 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Frame acknowledge QoE"); |
485 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_egfx_ackqoe, NULL((void*)0), "Frame acknowledge QoE"); |
486 | proto_tree_add_item_ret_uint(subtree, hf_egfx_ackqoe_frame_id, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000, &frameId); |
487 | offset += 4; |
488 | |
489 | proto_tree_add_item(subtree, hf_egfx_ackqoe_timestamp, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000); |
490 | offset += 4; |
491 | |
492 | proto_tree_add_item(subtree, hf_egfx_ackqoe_timediffse, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
493 | offset += 2; |
494 | |
495 | proto_tree_add_item(subtree, hf_egfx_ackqoe_timediffedr, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
496 | frame = wmem_map_lookup(conv->frames, GUINT_TO_POINTER(frameId)((gpointer) (gulong) (frameId))); |
497 | if (!frame) { |
498 | frame = wmem_alloc0(wmem_file_scope(), sizeof(*frame)); |
499 | frame->startNum = -1; |
500 | frame->endNum = -1; |
501 | frame->ackNum = frameId; |
502 | wmem_map_insert(conv->frames, GUINT_TO_POINTER(frameId)((gpointer) (gulong) (frameId)), frame); |
503 | } |
504 | |
505 | frame->ackNum = pinfo->num; |
506 | |
507 | if (PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && frame->startNum != -1) { |
508 | pi = proto_tree_add_uint(tree, hf_egfx_ackqoe_frame_start, tvb, 0, 0, frame->startNum); |
509 | proto_item_set_generated(pi); |
510 | } |
511 | |
512 | if (PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && frame->endNum != -1) { |
513 | pi = proto_tree_add_uint(tree, hf_egfx_ackqoe_frame_end, tvb, 0, 0, frame->endNum); |
514 | proto_item_set_generated(pi); |
515 | } |
516 | |
517 | break; |
518 | } |
519 | |
520 | case RDPGFX_CMDID_CREATESURFACE: |
521 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Create Surface"); |
522 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_egfx_createsurface, NULL((void*)0), "Create surface"); |
523 | proto_tree_add_item(subtree, hf_egfx_surfaceid, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
524 | offset += 2; |
Value stored to 'offset' is never read | |
525 | break; |
526 | |
527 | case RDPGFX_CMDID_MAPSURFACETOOUTPUT: |
528 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Map Surface To Output"); |
529 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_egfx_mapsurfacetooutput, NULL((void*)0), "Map surface to output"); |
530 | proto_tree_add_item(subtree, hf_egfx_surfaceid, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
531 | offset += 2; |
532 | |
533 | break; |
534 | |
535 | case RDPGFX_CMDID_WIRETOSURFACE_1: |
536 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Wire To Surface 1"); |
537 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_egfx_wiretosurface1, NULL((void*)0), "Wire to surface 1"); |
538 | proto_tree_add_item(subtree, hf_egfx_surfaceid, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
539 | offset += 2; |
540 | break; |
541 | |
542 | case RDPGFX_CMDID_WIRETOSURFACE_2: |
543 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Wire To Surface 2"); |
544 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_egfx_wiretosurface2, NULL((void*)0), "Wire to surface 2"); |
545 | proto_tree_add_item(subtree, hf_egfx_surfaceid, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
546 | offset += 2; |
547 | break; |
548 | |
549 | case RDPGFX_CMDID_DELETEENCODINGCONTEXT: |
550 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Delete Encoding Context"); |
551 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_egfx_deleteencodingcontext, NULL((void*)0), "Delete encoding context"); |
552 | proto_tree_add_item(subtree, hf_egfx_surfaceid, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
553 | offset += 2; |
554 | break; |
555 | |
556 | case RDPGFX_CMDID_SOLIDFILL: |
557 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Solid Fill"); |
558 | break; |
559 | |
560 | case RDPGFX_CMDID_SURFACETOSURFACE: |
561 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Surface To Surface"); |
562 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_egfx_surfacetosurface, NULL((void*)0), "Surface to surface"); |
563 | proto_tree_add_item(subtree, hf_egfx_surfaceid, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
564 | offset += 2; |
565 | break; |
566 | |
567 | case RDPGFX_CMDID_SURFACETOCACHE: |
568 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Surface To Cache"); |
569 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_egfx_surfacetocache, NULL((void*)0), "Surface to cache"); |
570 | proto_tree_add_item(subtree, hf_egfx_surfaceid, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
571 | offset += 2; |
572 | break; |
573 | |
574 | case RDPGFX_CMDID_CACHETOSURFACE: |
575 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Cache To Surface"); |
576 | break; |
577 | |
578 | case RDPGFX_CMDID_EVICTCACHEENTRY: |
579 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Evict Cache Entry"); |
580 | break; |
581 | |
582 | case RDPGFX_CMDID_DELETESURFACE: |
583 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Delete Surface"); |
584 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_egfx_deletesurface, NULL((void*)0), "Delete surface"); |
585 | proto_tree_add_item(subtree, hf_egfx_surfaceid, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
586 | offset += 2; |
587 | |
588 | break; |
589 | |
590 | case RDPGFX_CMDID_CACHEIMPORTOFFER: |
591 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Cache Import Offer"); |
592 | break; |
593 | |
594 | case RDPGFX_CMDID_CACHEIMPORTREPLY: |
595 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Cache Import Reply"); |
596 | break; |
597 | |
598 | case RDPGFX_CMDID_MAPSURFACETOWINDOW: |
599 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Map Surface To Window"); |
600 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_egfx_mapsurfacetowindow, NULL((void*)0), "Map surface to window"); |
601 | proto_tree_add_item(subtree, hf_egfx_surfaceid, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
602 | offset += 2; |
603 | break; |
604 | |
605 | case RDPGFX_CMDID_MAPSURFACETOSCALEDOUTPUT: |
606 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Map Surface To Scaled Output"); |
607 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_egfx_mapsurfacetoscaledoutput, NULL((void*)0), "Map surface to scaled output"); |
608 | proto_tree_add_item(subtree, hf_egfx_surfaceid, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
609 | offset += 2; |
610 | break; |
611 | |
612 | case RDPGFX_CMDID_MAPSURFACETOSCALEDWINDOW: |
613 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Map Surface To Scaled Window"); |
614 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_egfx_mapsurfacetoscaledwindow, NULL((void*)0), "Map surface to scaled window"); |
615 | proto_tree_add_item(subtree, hf_egfx_surfaceid, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
616 | offset += 2; |
617 | break; |
618 | |
619 | case RDPGFX_CMDID_PROTECT_SURFACE: { |
620 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Protect surface"); |
621 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_egfx_protectsurface, NULL((void*)0), "Protect surface"); |
622 | proto_tree_add_item(subtree, hf_egfx_surfaceid, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
623 | offset += 2; |
624 | break; |
625 | } |
626 | |
627 | case RDPGFX_CMDID_WATERMARK: { |
628 | col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Watermark surface"); |
629 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_egfx_watermark, NULL((void*)0), "Watermark"); |
630 | proto_tree_add_item(subtree, hf_egfx_surfaceid, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
631 | offset += 2; |
632 | |
633 | proto_tree_add_item(subtree, hf_egfx_watermark_width, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
634 | offset += 2; |
635 | |
636 | proto_tree_add_item(subtree, hf_egfx_watermark_height, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
637 | offset += 2; |
638 | |
639 | // XXX |
640 | proto_tree_add_item(subtree, hf_egfx_unknown_bytes, tvb, offset, 6, ENC_NA0x00000000); |
641 | offset += 6; |
642 | |
643 | proto_tree_add_item(subtree, hf_egfx_watermark_pixelformat, tvb, offset, 1, ENC_LITTLE_ENDIAN0x80000000); |
644 | offset += 1; |
645 | |
646 | // XXX |
647 | proto_tree_add_item(subtree, hf_egfx_unknown_bytes, tvb, offset, 2, ENC_NA0x00000000); |
648 | offset += 2; |
649 | |
650 | proto_tree_add_item(subtree, hf_egfx_watermark_opacity, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
651 | offset += 2; |
652 | |
653 | // XXX |
654 | proto_tree_add_item(subtree, hf_egfx_unknown_bytes, tvb, offset, 6, ENC_NA0x00000000); |
655 | offset += 6; |
656 | |
657 | proto_tree_add_item(subtree, hf_egfx_watermark_hpadding, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
658 | offset += 2; |
659 | proto_tree_add_item(subtree, hf_egfx_watermark_vpadding, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000); |
660 | offset += 2; |
661 | |
662 | // XXX |
663 | proto_tree_add_item(subtree, hf_egfx_unknown_bytes, tvb, offset, 8, ENC_NA0x00000000); |
664 | offset += 8; |
665 | |
666 | uint32_t sz; |
667 | proto_tree_add_item_ret_uint(subtree, hf_egfx_watermark_imgsize, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000, &sz); |
668 | offset += 2; |
669 | break; |
670 | } |
671 | default: |
672 | break; |
673 | } |
674 | |
675 | offset = nextOffset; |
676 | } |
677 | return offset; |
678 | } |
679 | |
680 | static int |
681 | dissect_rdp_egfx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data) |
682 | { |
683 | tvbuff_t *work_tvb = tvb; |
684 | egfx_conv_info_t *infos = egfx_get_conversation_data(pinfo); |
685 | |
686 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "EGFX"); |
687 | col_clear(pinfo->cinfo, COL_INFO); |
688 | |
689 | parent_tree = proto_tree_get_root(parent_tree); |
690 | |
691 | if (!rdp_isServerAddressTarget(pinfo)) { |
692 | uint32_t hash = crc32_ccitt_tvb(tvb, tvb_captured_length_remaining(tvb, 0)); |
693 | egfx_pdu_info_t *pdu_infos = p_get_proto_data(wmem_file_scope(), pinfo, proto_rdp_egfx, EGFX_PDU_KEY); |
694 | if (!pdu_infos) { |
695 | pdu_infos = wmem_alloc(wmem_file_scope(), sizeof(*pdu_infos)); |
696 | pdu_infos->pdus = wmem_tree_new(wmem_file_scope()); |
697 | p_set_proto_data(wmem_file_scope(), pinfo, proto_rdp_egfx, EGFX_PDU_KEY, pdu_infos); |
698 | } |
699 | |
700 | if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) { |
701 | work_tvb = rdp8_decompress(infos->zgfx, wmem_file_scope(), tvb, 0); |
702 | if (work_tvb) { |
703 | //printf("%d: zgfx sz=%d\n", pinfo->num, tvb_captured_length(work_tvb)); |
704 | wmem_tree_insert32(pdu_infos->pdus, hash, work_tvb); |
705 | } |
706 | } else { |
707 | pdu_infos = p_get_proto_data(wmem_file_scope(), pinfo, proto_rdp_egfx, EGFX_PDU_KEY); |
708 | work_tvb = wmem_tree_lookup32(pdu_infos->pdus, hash); |
709 | } |
710 | |
711 | if (work_tvb) |
712 | add_new_data_source(pinfo, work_tvb, "Uncompressed GFX"); |
713 | } |
714 | |
715 | if (work_tvb) |
716 | dissect_rdp_egfx_payload(work_tvb, pinfo, parent_tree, infos, data); |
717 | else { |
718 | if (parent_tree) |
719 | expert_add_info_format(pinfo, parent_tree->last_child, &ei_egfx_invalid_compression, "invalid compression"); |
720 | } |
721 | |
722 | return tvb_reported_length(tvb); |
723 | } |
724 | |
725 | |
726 | void proto_register_rdp_egfx(void) { |
727 | static hf_register_info hf[] = { |
728 | { &hf_egfx_cmdId, |
729 | { "CmdId", "rdp_egfx.cmdid", |
730 | FT_UINT16, BASE_HEX, VALS(rdp_egfx_cmd_vals)((0 ? (const struct _value_string*)0 : ((rdp_egfx_cmd_vals))) ), 0x0, |
731 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
732 | }, |
733 | { &hf_egfx_flags, |
734 | { "flags", "rdp_egfx.flags", |
735 | FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, |
736 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
737 | }, |
738 | { &hf_egfx_pduLength, |
739 | { "pduLength", "rdp_egfx.pdulength", |
740 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
741 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
742 | }, |
743 | { &hf_egfx_caps_capsSetCount, |
744 | { "capsSetCount", "rdp_egfx.caps.setcount", |
745 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, |
746 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
747 | }, |
748 | { &hf_egfx_cap_version, |
749 | { "Version", "rdp_egfx.cap.version", |
750 | FT_UINT32, BASE_HEX, VALS(rdp_egfx_caps_version_vals)((0 ? (const struct _value_string*)0 : ((rdp_egfx_caps_version_vals )))), 0x0, |
751 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
752 | }, |
753 | { &hf_egfx_cap_length, |
754 | { "capsDataLength", "rdp_egfx.cap.length", |
755 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
756 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
757 | }, |
758 | { &hf_egfx_ack_queue_depth, |
759 | { "queueDepth", "rdp_egfx.ack.queuedepth", |
760 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
761 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
762 | }, |
763 | { &hf_egfx_ack_frame_id, |
764 | { "frameId", "rdp_egfx.ack.frameid", |
765 | FT_UINT32, BASE_HEX, NULL((void*)0), 0x0, |
766 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
767 | }, |
768 | { &hf_egfx_ack_total_decoded, |
769 | { "Total frames decoded", "rdp_egfx.ack.totalframesdecoded", |
770 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
771 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
772 | }, |
773 | { &hf_egfx_ack_frame_start, |
774 | { "Frame starts in", "rdp_egfx.ack.framestart", |
775 | FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST)((gpointer) (glong) (FT_FRAMENUM_REQUEST)), 0x0, |
776 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
777 | }, |
778 | { &hf_egfx_ack_frame_end, |
779 | { "Frame ends in", "rdp_egfx.ack.frameend", |
780 | FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST)((gpointer) (glong) (FT_FRAMENUM_REQUEST)), 0x0, |
781 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
782 | }, |
783 | { &hf_egfx_ackqoe_frame_id, |
784 | { "frameId", "rdp_egfx.ackqoe.frameid", |
785 | FT_UINT32, BASE_HEX, NULL((void*)0), 0x0, |
786 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
787 | }, |
788 | { &hf_egfx_ackqoe_timestamp, |
789 | { "Timestamp", "rdp_egfx.ackqoe.timestamp", |
790 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
791 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
792 | }, |
793 | { &hf_egfx_ackqoe_timediffse, |
794 | { "TimeDiffSE", "rdp_egfx.ackqoe.timediffse", |
795 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, |
796 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
797 | }, |
798 | { &hf_egfx_ackqoe_timediffedr, |
799 | { "TimeDiffEDR", "rdp_egfx.ackqoe.timediffedr", |
800 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, |
801 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
802 | }, |
803 | { &hf_egfx_ackqoe_frame_start, |
804 | { "Frame starts in", "rdp_egfx.ackqoe.framestart", |
805 | FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST)((gpointer) (glong) (FT_FRAMENUM_REQUEST)), 0x0, |
806 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
807 | }, |
808 | { &hf_egfx_ackqoe_frame_end, |
809 | { "Frame ends in", "rdp_egfx.ackqoe.frameend", |
810 | FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST)((gpointer) (glong) (FT_FRAMENUM_REQUEST)), 0x0, |
811 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
812 | }, |
813 | { &hf_egfx_reset_width, |
814 | { "Width", "rdp_egfx.reset.width", |
815 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
816 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
817 | }, |
818 | { &hf_egfx_reset_height, |
819 | { "Height", "rdp_egfx.reset.height", |
820 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
821 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
822 | }, |
823 | { &hf_egfx_reset_monitorCount, |
824 | { "Monitor count", "rdp_egfx.reset.monitorcount", |
825 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
826 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
827 | }, |
828 | { &hf_egfx_reset_monitorDefLeft, |
829 | { "Left", "rdp_egfx.monitor.left", |
830 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
831 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
832 | }, |
833 | { &hf_egfx_reset_monitorDefTop, |
834 | { "Top", "rdp_egfx.monitor.top", |
835 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
836 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
837 | }, |
838 | { &hf_egfx_reset_monitorDefRight, |
839 | { "Right", "rdp_egfx.monitor.right", |
840 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
841 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
842 | }, |
843 | { &hf_egfx_reset_monitorDefBottom, |
844 | { "Bottom", "rdp_egfx.monitor.bottom", |
845 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
846 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
847 | }, |
848 | { &hf_egfx_reset_monitorDefFlags, |
849 | { "Flags", "rdp_egfx.monitor.flags", |
850 | FT_UINT32, BASE_HEX, VALS(rdp_egfx_monitor_flags_vals)((0 ? (const struct _value_string*)0 : ((rdp_egfx_monitor_flags_vals )))), 0x0, |
851 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
852 | }, |
853 | { &hf_egfx_start_timestamp, |
854 | { "Timestamp", "rdp_egfx.startframe.timestamp", |
855 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
856 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
857 | }, |
858 | { &hf_egfx_start_frameid, |
859 | { "Frame id", "rdp_egfx.startframe.frameid", |
860 | FT_UINT32, BASE_HEX, NULL((void*)0), 0x0, |
861 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
862 | }, |
863 | { &hf_egfx_start_acked_in, |
864 | { "Frame acked in", "rdp_egfx.startframe.ackedin", |
865 | FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE)((gpointer) (glong) (FT_FRAMENUM_RESPONSE)), 0x0, |
866 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
867 | }, |
868 | { &hf_egfx_end_frameid, |
869 | { "Frame id", "rdp_egfx.endframe.frameid", |
870 | FT_UINT32, BASE_HEX, NULL((void*)0), 0x0, |
871 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
872 | }, |
873 | { &hf_egfx_end_acked_in, |
874 | { "Frame acked in", "rdp_egfx.endframe.ackedin", |
875 | FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE)((gpointer) (glong) (FT_FRAMENUM_RESPONSE)), 0x0, |
876 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
877 | }, |
878 | { &hf_egfx_surfaceid, |
879 | { "Surface id", "rdp_egfx.surfaceid", |
880 | FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, |
881 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
882 | }, |
883 | { &hf_egfx_watermark_width, |
884 | { "Width", "rdp_egfx.watermark.width", |
885 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, |
886 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
887 | }, |
888 | { &hf_egfx_watermark_height, |
889 | { "Height", "rdp_egfx.watermark.height", |
890 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, |
891 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
892 | }, |
893 | { &hf_egfx_watermark_pixelformat, |
894 | { "Pixel format", "rdp_egfx.watermark.pixelformat", |
895 | FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, |
896 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
897 | }, |
898 | { &hf_egfx_watermark_opacity, |
899 | { "Opacity", "rdp_egfx.watermark.opacity", |
900 | FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, |
901 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
902 | }, |
903 | { &hf_egfx_watermark_hpadding, |
904 | { "HPadding", "rdp_egfx.watermark.hpadding", |
905 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, |
906 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
907 | }, |
908 | { &hf_egfx_watermark_vpadding, |
909 | { "VPadding", "rdp_egfx.watermark.vpadding", |
910 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, |
911 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
912 | }, |
913 | { &hf_egfx_watermark_imgsize, |
914 | { "Image size", "rdp_egfx.watermark.imgsize", |
915 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, |
916 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
917 | }, |
918 | { &hf_egfx_unknown_bytes, |
919 | { "Unknown bytes", "rdp_egfx.unknown", |
920 | FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, |
921 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } |
922 | } |
923 | }; |
924 | |
925 | static int *ett[] = { |
926 | &ett_rdp_egfx, |
927 | &ett_egfx_caps, |
928 | &ett_egfx_cap, |
929 | &ett_egfx_cap_version, |
930 | &ett_egfx_ack, |
931 | &ett_egfx_ackqoe, |
932 | &ett_egfx_reset, |
933 | &ett_egfx_capsconfirm, |
934 | &ett_egfx_monitors, |
935 | &ett_egfx_monitordef, |
936 | &ett_egfx_watermark, |
937 | &ett_egfx_createsurface, |
938 | &ett_egfx_mapsurfacetooutput, |
939 | &ett_egfx_mapsurfacetowindow, |
940 | &ett_egfx_mapsurfacetoscaledoutput, |
941 | &ett_egfx_mapsurfacetoscaledwindow, |
942 | &ett_egfx_wiretosurface1, |
943 | &ett_egfx_wiretosurface2, |
944 | &ett_egfx_protectsurface, |
945 | &ett_egfx_surfacetosurface, |
946 | &ett_egfx_surfacetocache, |
947 | &ett_egfx_deletesurface, |
948 | &ett_egfx_deleteencodingcontext |
949 | }; |
950 | |
951 | static ei_register_info ei[] = { |
952 | { &ei_egfx_pdulen_invalid, { "rdp_egfx.pdulength.invalid", PI_PROTOCOL0x09000000, PI_ERROR0x00800000, "Invalid length", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
953 | { &ei_egfx_invalid_compression, { "rdp_egfx.compression.invalid", PI_PROTOCOL0x09000000, PI_ERROR0x00800000, "Invalid compression", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
954 | }; |
955 | expert_module_t* expert_egfx; |
956 | |
957 | |
958 | proto_rdp_egfx = proto_register_protocol(PNAME"RDP Graphic pipeline channel Protocol", PSNAME"EGFX", PFNAME"rdp_egfx"); |
959 | /* Register fields and subtrees */ |
960 | proto_register_field_array(proto_rdp_egfx, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0])); |
961 | proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0])); |
962 | expert_egfx = expert_register_protocol(proto_rdp_egfx); |
963 | expert_register_field_array(expert_egfx, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0])); |
964 | |
965 | register_dissector("rdp_egfx", dissect_rdp_egfx, proto_rdp_egfx); |
966 | } |
967 | |
968 | void proto_reg_handoff_rdp_egfx(void) { |
969 | } |