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