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