1 /**
2 * FreeRDP: A Remote Desktop Protocol Implementation
3 * Graphics Pipeline Extension
4 *
5 * Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6 * Copyright 2015 Thincast Technologies GmbH
7 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <winpr/crt.h>
27 #include <winpr/stream.h>
28 #include <freerdp/channels/log.h>
29
30 #define TAG CHANNELS_TAG("rdpgfx.common")
31
32 #include "rdpgfx_common.h"
33
34 static const char* RDPGFX_CMDID_STRINGS[] = { "RDPGFX_CMDID_UNUSED_0000",
35 "RDPGFX_CMDID_WIRETOSURFACE_1",
36 "RDPGFX_CMDID_WIRETOSURFACE_2",
37 "RDPGFX_CMDID_DELETEENCODINGCONTEXT",
38 "RDPGFX_CMDID_SOLIDFILL",
39 "RDPGFX_CMDID_SURFACETOSURFACE",
40 "RDPGFX_CMDID_SURFACETOCACHE",
41 "RDPGFX_CMDID_CACHETOSURFACE",
42 "RDPGFX_CMDID_EVICTCACHEENTRY",
43 "RDPGFX_CMDID_CREATESURFACE",
44 "RDPGFX_CMDID_DELETESURFACE",
45 "RDPGFX_CMDID_STARTFRAME",
46 "RDPGFX_CMDID_ENDFRAME",
47 "RDPGFX_CMDID_FRAMEACKNOWLEDGE",
48 "RDPGFX_CMDID_RESETGRAPHICS",
49 "RDPGFX_CMDID_MAPSURFACETOOUTPUT",
50 "RDPGFX_CMDID_CACHEIMPORTOFFER",
51 "RDPGFX_CMDID_CACHEIMPORTREPLY",
52 "RDPGFX_CMDID_CAPSADVERTISE",
53 "RDPGFX_CMDID_CAPSCONFIRM",
54 "RDPGFX_CMDID_UNUSED_0014",
55 "RDPGFX_CMDID_MAPSURFACETOWINDOW",
56 "RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE",
57 "RDPGFX_CMDID_MAPSURFACETOSCALEDOUTPUT",
58 "RDPGFX_CMDID_MAPSURFACETOSCALEDWINDOW" };
59
rdpgfx_get_cmd_id_string(UINT16 cmdId)60 const char* rdpgfx_get_cmd_id_string(UINT16 cmdId)
61 {
62 if (cmdId <= RDPGFX_CMDID_MAPSURFACETOSCALEDWINDOW)
63 return RDPGFX_CMDID_STRINGS[cmdId];
64 else
65 return "RDPGFX_CMDID_UNKNOWN";
66 }
67
rdpgfx_get_codec_id_string(UINT16 codecId)68 const char* rdpgfx_get_codec_id_string(UINT16 codecId)
69 {
70 switch (codecId)
71 {
72 case RDPGFX_CODECID_UNCOMPRESSED:
73 return "RDPGFX_CODECID_UNCOMPRESSED";
74
75 case RDPGFX_CODECID_CAVIDEO:
76 return "RDPGFX_CODECID_CAVIDEO";
77
78 case RDPGFX_CODECID_CLEARCODEC:
79 return "RDPGFX_CODECID_CLEARCODEC";
80
81 case RDPGFX_CODECID_PLANAR:
82 return "RDPGFX_CODECID_PLANAR";
83
84 case RDPGFX_CODECID_AVC420:
85 return "RDPGFX_CODECID_AVC420";
86
87 case RDPGFX_CODECID_AVC444:
88 return "RDPGFX_CODECID_AVC444";
89
90 case RDPGFX_CODECID_AVC444v2:
91 return "RDPGFX_CODECID_AVC444v2";
92
93 case RDPGFX_CODECID_ALPHA:
94 return "RDPGFX_CODECID_ALPHA";
95
96 case RDPGFX_CODECID_CAPROGRESSIVE:
97 return "RDPGFX_CODECID_CAPROGRESSIVE";
98
99 case RDPGFX_CODECID_CAPROGRESSIVE_V2:
100 return "RDPGFX_CODECID_CAPROGRESSIVE_V2";
101 }
102
103 return "RDPGFX_CODECID_UNKNOWN";
104 }
105
106 /**
107 * Function description
108 *
109 * @return 0 on success, otherwise a Win32 error code
110 */
rdpgfx_read_header(wStream * s,RDPGFX_HEADER * header)111 UINT rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header)
112 {
113 if (Stream_GetRemainingLength(s) < 8)
114 {
115 WLog_ERR(TAG, "calloc failed!");
116 return CHANNEL_RC_NO_MEMORY;
117 }
118
119 Stream_Read_UINT16(s, header->cmdId); /* cmdId (2 bytes) */
120 Stream_Read_UINT16(s, header->flags); /* flags (2 bytes) */
121 Stream_Read_UINT32(s, header->pduLength); /* pduLength (4 bytes) */
122 return CHANNEL_RC_OK;
123 }
124
125 /**
126 * Function description
127 *
128 * @return 0 on success, otherwise a Win32 error code
129 */
rdpgfx_write_header(wStream * s,const RDPGFX_HEADER * header)130 UINT rdpgfx_write_header(wStream* s, const RDPGFX_HEADER* header)
131 {
132 if (!Stream_EnsureRemainingCapacity(s, 8))
133 return ERROR_INTERNAL_ERROR;
134 Stream_Write_UINT16(s, header->cmdId); /* cmdId (2 bytes) */
135 Stream_Write_UINT16(s, header->flags); /* flags (2 bytes) */
136 Stream_Write_UINT32(s, header->pduLength); /* pduLength (4 bytes) */
137 return CHANNEL_RC_OK;
138 }
139
140 /**
141 * Function description
142 *
143 * @return 0 on success, otherwise a Win32 error code
144 */
rdpgfx_read_point16(wStream * s,RDPGFX_POINT16 * pt16)145 UINT rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* pt16)
146 {
147 if (Stream_GetRemainingLength(s) < 4)
148 {
149 WLog_ERR(TAG, "not enough data!");
150 return ERROR_INVALID_DATA;
151 }
152
153 Stream_Read_UINT16(s, pt16->x); /* x (2 bytes) */
154 Stream_Read_UINT16(s, pt16->y); /* y (2 bytes) */
155 return CHANNEL_RC_OK;
156 }
157
158 /**
159 * Function description
160 *
161 * @return 0 on success, otherwise a Win32 error code
162 */
rdpgfx_write_point16(wStream * s,const RDPGFX_POINT16 * point16)163 UINT rdpgfx_write_point16(wStream* s, const RDPGFX_POINT16* point16)
164 {
165 Stream_Write_UINT16(s, point16->x); /* x (2 bytes) */
166 Stream_Write_UINT16(s, point16->y); /* y (2 bytes) */
167 return CHANNEL_RC_OK;
168 }
169
170 /**
171 * Function description
172 *
173 * @return 0 on success, otherwise a Win32 error code
174 */
rdpgfx_read_rect16(wStream * s,RECTANGLE_16 * rect16)175 UINT rdpgfx_read_rect16(wStream* s, RECTANGLE_16* rect16)
176 {
177 if (Stream_GetRemainingLength(s) < 8)
178 {
179 WLog_ERR(TAG, "not enough data!");
180 return ERROR_INVALID_DATA;
181 }
182
183 Stream_Read_UINT16(s, rect16->left); /* left (2 bytes) */
184 Stream_Read_UINT16(s, rect16->top); /* top (2 bytes) */
185 Stream_Read_UINT16(s, rect16->right); /* right (2 bytes) */
186 Stream_Read_UINT16(s, rect16->bottom); /* bottom (2 bytes) */
187 if (rect16->left >= rect16->right)
188 return ERROR_INVALID_DATA;
189 if (rect16->top >= rect16->bottom)
190 return ERROR_INVALID_DATA;
191 return CHANNEL_RC_OK;
192 }
193
194 /**
195 * Function description
196 *
197 * @return 0 on success, otherwise a Win32 error code
198 */
rdpgfx_write_rect16(wStream * s,const RECTANGLE_16 * rect16)199 UINT rdpgfx_write_rect16(wStream* s, const RECTANGLE_16* rect16)
200 {
201 Stream_Write_UINT16(s, rect16->left); /* left (2 bytes) */
202 Stream_Write_UINT16(s, rect16->top); /* top (2 bytes) */
203 Stream_Write_UINT16(s, rect16->right); /* right (2 bytes) */
204 Stream_Write_UINT16(s, rect16->bottom); /* bottom (2 bytes) */
205 return CHANNEL_RC_OK;
206 }
207
208 /**
209 * Function description
210 *
211 * @return 0 on success, otherwise a Win32 error code
212 */
rdpgfx_read_color32(wStream * s,RDPGFX_COLOR32 * color32)213 UINT rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32)
214 {
215 if (Stream_GetRemainingLength(s) < 4)
216 {
217 WLog_ERR(TAG, "not enough data!");
218 return ERROR_INVALID_DATA;
219 }
220
221 Stream_Read_UINT8(s, color32->B); /* B (1 byte) */
222 Stream_Read_UINT8(s, color32->G); /* G (1 byte) */
223 Stream_Read_UINT8(s, color32->R); /* R (1 byte) */
224 Stream_Read_UINT8(s, color32->XA); /* XA (1 byte) */
225 return CHANNEL_RC_OK;
226 }
227
228 /**
229 * Function description
230 *
231 * @return 0 on success, otherwise a Win32 error code
232 */
rdpgfx_write_color32(wStream * s,const RDPGFX_COLOR32 * color32)233 UINT rdpgfx_write_color32(wStream* s, const RDPGFX_COLOR32* color32)
234 {
235 Stream_Write_UINT8(s, color32->B); /* B (1 byte) */
236 Stream_Write_UINT8(s, color32->G); /* G (1 byte) */
237 Stream_Write_UINT8(s, color32->R); /* R (1 byte) */
238 Stream_Write_UINT8(s, color32->XA); /* XA (1 byte) */
239 return CHANNEL_RC_OK;
240 }
241