FreeRDP
Loading...
Searching...
No Matches
persistent.c
1
20#include <freerdp/config.h>
21
22#include <winpr/crt.h>
23#include <winpr/stream.h>
24#include <winpr/assert.h>
25
26#include <freerdp/freerdp.h>
27#include <freerdp/constants.h>
28
29#include <freerdp/cache/persistent.h>
30
31struct rdp_persistent_cache
32{
33 FILE* fp;
34 BOOL write;
35 int version;
36 int count;
37 char* filename;
38 BYTE* bmpData;
39 UINT32 bmpSize;
40};
41
42static const char sig_str[] = "RDP8bmp";
43
44int persistent_cache_get_version(rdpPersistentCache* persistent)
45{
46 WINPR_ASSERT(persistent);
47 return persistent->version;
48}
49
50int persistent_cache_get_count(rdpPersistentCache* persistent)
51{
52 WINPR_ASSERT(persistent);
53 return persistent->count;
54}
55
56static int persistent_cache_read_entry_v2(rdpPersistentCache* persistent,
58{
59 PERSISTENT_CACHE_ENTRY_V2 entry2 = { 0 };
60
61 WINPR_ASSERT(persistent);
62 WINPR_ASSERT(entry);
63
64 if (fread((void*)&entry2, sizeof(entry2), 1, persistent->fp) != 1)
65 return -1;
66
67 entry->key64 = entry2.key64;
68 entry->width = entry2.width;
69 entry->height = entry2.height;
70 entry->size = entry2.width * entry2.height * 4;
71 entry->flags = entry2.flags;
72
73 entry->data = persistent->bmpData;
74
75 if (fread((void*)entry->data, 0x4000, 1, persistent->fp) != 1)
76 return -1;
77
78 return 1;
79}
80
81static int persistent_cache_write_entry_v2(rdpPersistentCache* persistent,
82 const PERSISTENT_CACHE_ENTRY* entry)
83{
84 PERSISTENT_CACHE_ENTRY_V2 entry2 = { 0 };
85
86 WINPR_ASSERT(persistent);
87 WINPR_ASSERT(entry);
88 entry2.key64 = entry->key64;
89 entry2.width = entry->width;
90 entry2.height = entry->height;
91 entry2.size = entry->size;
92 entry2.flags = entry->flags;
93
94 if (!entry2.flags)
95 entry2.flags = 0x00000011;
96
97 if (fwrite(&entry2, sizeof(entry2), 1, persistent->fp) != 1)
98 return -1;
99
100 if (fwrite(entry->data, entry->size, 1, persistent->fp) != 1)
101 return -1;
102
103 if (0x4000 > entry->size)
104 {
105 const size_t padding = 0x4000 - entry->size;
106
107 if (fwrite(persistent->bmpData, padding, 1, persistent->fp) != 1)
108 return -1;
109 }
110
111 persistent->count++;
112
113 return 1;
114}
115
116static int persistent_cache_read_v2(rdpPersistentCache* persistent)
117{
118 WINPR_ASSERT(persistent);
119 while (1)
120 {
121 PERSISTENT_CACHE_ENTRY_V2 entry = { 0 };
122
123 if (fread((void*)&entry, sizeof(entry), 1, persistent->fp) != 1)
124 break;
125
126 if (fseek(persistent->fp, 0x4000, SEEK_CUR) != 0)
127 break;
128
129 persistent->count++;
130 }
131
132 return 1;
133}
134
135static int persistent_cache_read_entry_v3(rdpPersistentCache* persistent,
137{
138 PERSISTENT_CACHE_ENTRY_V3 entry3 = { 0 };
139
140 WINPR_ASSERT(persistent);
141 WINPR_ASSERT(entry);
142
143 if (fread(&entry3, sizeof(entry3), 1, persistent->fp) != 1)
144 return -1;
145
146 entry->key64 = entry3.key64;
147 entry->width = entry3.width;
148 entry->height = entry3.height;
149 const UINT64 size = 4ull * entry3.width * entry3.height;
150 if (size > UINT32_MAX)
151 return -1;
152 entry->size = (UINT32)size;
153 entry->flags = 0;
154
155 if (entry->size > persistent->bmpSize)
156 {
157 persistent->bmpSize = entry->size;
158 BYTE* bmpData = (BYTE*)winpr_aligned_recalloc(persistent->bmpData, persistent->bmpSize,
159 sizeof(BYTE), 32);
160
161 if (!bmpData)
162 return -1;
163
164 persistent->bmpData = bmpData;
165 }
166
167 entry->data = persistent->bmpData;
168
169 if (fread((void*)entry->data, entry->size, 1, persistent->fp) != 1)
170 return -1;
171
172 return 1;
173}
174
175static int persistent_cache_write_entry_v3(rdpPersistentCache* persistent,
176 const PERSISTENT_CACHE_ENTRY* entry)
177{
178 PERSISTENT_CACHE_ENTRY_V3 entry3 = { 0 };
179
180 WINPR_ASSERT(persistent);
181 WINPR_ASSERT(entry);
182
183 entry3.key64 = entry->key64;
184 entry3.width = entry->width;
185 entry3.height = entry->height;
186
187 if (fwrite((void*)&entry3, sizeof(entry3), 1, persistent->fp) != 1)
188 return -1;
189
190 if (fwrite((void*)entry->data, entry->size, 1, persistent->fp) != 1)
191 return -1;
192
193 persistent->count++;
194
195 return 1;
196}
197
198static int persistent_cache_read_v3(rdpPersistentCache* persistent)
199{
200 WINPR_ASSERT(persistent);
201 while (1)
202 {
203 PERSISTENT_CACHE_ENTRY_V3 entry = { 0 };
204
205 if (fread((void*)&entry, sizeof(entry), 1, persistent->fp) != 1)
206 break;
207
208 if (_fseeki64(persistent->fp, (4LL * entry.width * entry.height), SEEK_CUR) != 0)
209 break;
210
211 persistent->count++;
212 }
213
214 return 1;
215}
216
217int persistent_cache_read_entry(rdpPersistentCache* persistent, PERSISTENT_CACHE_ENTRY* entry)
218{
219 WINPR_ASSERT(persistent);
220 WINPR_ASSERT(entry);
221
222 if (persistent->version == 3)
223 return persistent_cache_read_entry_v3(persistent, entry);
224 else if (persistent->version == 2)
225 return persistent_cache_read_entry_v2(persistent, entry);
226
227 return -1;
228}
229
230int persistent_cache_write_entry(rdpPersistentCache* persistent,
231 const PERSISTENT_CACHE_ENTRY* entry)
232{
233 WINPR_ASSERT(persistent);
234 WINPR_ASSERT(entry);
235
236 if (persistent->version == 3)
237 return persistent_cache_write_entry_v3(persistent, entry);
238 else if (persistent->version == 2)
239 return persistent_cache_write_entry_v2(persistent, entry);
240
241 return -1;
242}
243
244static int persistent_cache_open_read(rdpPersistentCache* persistent)
245{
246 BYTE sig[8] = { 0 };
247 int status = 1;
248 long offset = 0;
249
250 WINPR_ASSERT(persistent);
251 persistent->fp = winpr_fopen(persistent->filename, "rb");
252
253 if (!persistent->fp)
254 return -1;
255
256 if (fread(sig, 8, 1, persistent->fp) != 1)
257 return -1;
258
259 if (memcmp(sig, sig_str, sizeof(sig_str)) == 0)
260 persistent->version = 3;
261 else
262 persistent->version = 2;
263
264 (void)fseek(persistent->fp, 0, SEEK_SET);
265
266 if (persistent->version == 3)
267 {
269
270 if (fread(&header, sizeof(header), 1, persistent->fp) != 1)
271 return -1;
272
273 status = persistent_cache_read_v3(persistent);
274 offset = sizeof(header);
275 }
276 else
277 {
278 status = persistent_cache_read_v2(persistent);
279 offset = 0;
280 }
281
282 (void)fseek(persistent->fp, offset, SEEK_SET);
283
284 return status;
285}
286
287static int persistent_cache_open_write(rdpPersistentCache* persistent)
288{
289 WINPR_ASSERT(persistent);
290
291 persistent->fp = winpr_fopen(persistent->filename, "w+b");
292
293 if (!persistent->fp)
294 return -1;
295
296 if (persistent->version == 3)
297 {
298 PERSISTENT_CACHE_HEADER_V3 header = { 0 };
299 memcpy(header.sig, sig_str, MIN(sizeof(header.sig), sizeof(sig_str)));
300 header.flags = 0x00000006;
301
302 if (fwrite(&header, sizeof(header), 1, persistent->fp) != 1)
303 return -1;
304 }
305
306 ZeroMemory(persistent->bmpData, persistent->bmpSize);
307
308 return 1;
309}
310
311int persistent_cache_open(rdpPersistentCache* persistent, const char* filename, BOOL write,
312 UINT32 version)
313{
314 WINPR_ASSERT(persistent);
315 WINPR_ASSERT(filename);
316 persistent->write = write;
317
318 persistent->filename = _strdup(filename);
319
320 if (!persistent->filename)
321 return -1;
322
323 if (persistent->write)
324 {
325 WINPR_ASSERT(version <= INT32_MAX);
326 persistent->version = (int)version;
327 return persistent_cache_open_write(persistent);
328 }
329
330 return persistent_cache_open_read(persistent);
331}
332
333int persistent_cache_close(rdpPersistentCache* persistent)
334{
335 WINPR_ASSERT(persistent);
336 if (persistent->fp)
337 {
338 (void)fclose(persistent->fp);
339 persistent->fp = NULL;
340 }
341
342 return 1;
343}
344
345rdpPersistentCache* persistent_cache_new(void)
346{
347 rdpPersistentCache* persistent = calloc(1, sizeof(rdpPersistentCache));
348
349 if (!persistent)
350 return NULL;
351
352 persistent->bmpSize = 0x4000;
353 persistent->bmpData = calloc(1, persistent->bmpSize);
354
355 if (!persistent->bmpData)
356 {
357 free(persistent);
358 return NULL;
359 }
360
361 return persistent;
362}
363
364void persistent_cache_free(rdpPersistentCache* persistent)
365{
366 if (!persistent)
367 return;
368
369 persistent_cache_close(persistent);
370
371 free(persistent->filename);
372
373 winpr_aligned_free(persistent->bmpData);
374
375 free(persistent);
376}
Definition persistent.h:59
Definition persistent.h:50
Definition persistent.h:70