summaryrefslogtreecommitdiffstats
path: root/libfreerdp/cache/persistent.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 01:24:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 01:24:41 +0000
commita9bcc81f821d7c66f623779fa5147e728eb3c388 (patch)
tree98676963bcdd537ae5908a067a8eb110b93486a6 /libfreerdp/cache/persistent.c
parentInitial commit. (diff)
downloadfreerdp3-a9bcc81f821d7c66f623779fa5147e728eb3c388.tar.xz
freerdp3-a9bcc81f821d7c66f623779fa5147e728eb3c388.zip
Adding upstream version 3.3.0+dfsg1.upstream/3.3.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'libfreerdp/cache/persistent.c')
-rw-r--r--libfreerdp/cache/persistent.c374
1 files changed, 374 insertions, 0 deletions
diff --git a/libfreerdp/cache/persistent.c b/libfreerdp/cache/persistent.c
new file mode 100644
index 0000000..8499c7e
--- /dev/null
+++ b/libfreerdp/cache/persistent.c
@@ -0,0 +1,374 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Persistent Bitmap Cache
+ *
+ * Copyright 2016 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <freerdp/config.h>
+
+#include <winpr/crt.h>
+#include <winpr/stream.h>
+#include <winpr/assert.h>
+
+#include <freerdp/freerdp.h>
+#include <freerdp/constants.h>
+
+#include <freerdp/log.h>
+#include <freerdp/cache/persistent.h>
+
+#define TAG FREERDP_TAG("cache.persistent")
+
+struct rdp_persistent_cache
+{
+ FILE* fp;
+ BOOL write;
+ UINT32 version;
+ int count;
+ char* filename;
+ BYTE* bmpData;
+ UINT32 bmpSize;
+};
+
+int persistent_cache_get_version(rdpPersistentCache* persistent)
+{
+ WINPR_ASSERT(persistent);
+ return persistent->version;
+}
+
+int persistent_cache_get_count(rdpPersistentCache* persistent)
+{
+ WINPR_ASSERT(persistent);
+ return persistent->count;
+}
+
+static int persistent_cache_read_entry_v2(rdpPersistentCache* persistent,
+ PERSISTENT_CACHE_ENTRY* entry)
+{
+ PERSISTENT_CACHE_ENTRY_V2 entry2 = { 0 };
+
+ WINPR_ASSERT(persistent);
+ WINPR_ASSERT(entry);
+
+ if (fread((void*)&entry2, sizeof(entry2), 1, persistent->fp) != 1)
+ return -1;
+
+ entry->key64 = entry2.key64;
+ entry->width = entry2.width;
+ entry->height = entry2.height;
+ entry->size = entry2.width * entry2.height * 4;
+ entry->flags = entry2.flags;
+
+ entry->data = persistent->bmpData;
+
+ if (fread((void*)entry->data, 0x4000, 1, persistent->fp) != 1)
+ return -1;
+
+ return 1;
+}
+
+static int persistent_cache_write_entry_v2(rdpPersistentCache* persistent,
+ const PERSISTENT_CACHE_ENTRY* entry)
+{
+ int padding = 0;
+ PERSISTENT_CACHE_ENTRY_V2 entry2 = { 0 };
+
+ WINPR_ASSERT(persistent);
+ WINPR_ASSERT(entry);
+ entry2.key64 = entry->key64;
+ entry2.width = entry->width;
+ entry2.height = entry->height;
+ entry2.size = entry->size;
+ entry2.flags = entry->flags;
+
+ if (!entry2.flags)
+ entry2.flags = 0x00000011;
+
+ if (fwrite((void*)&entry2, sizeof(entry2), 1, persistent->fp) != 1)
+ return -1;
+
+ if (fwrite((void*)entry->data, entry->size, 1, persistent->fp) != 1)
+ return -1;
+
+ if (0x4000 > entry->size)
+ {
+ padding = 0x4000 - entry->size;
+
+ if (fwrite((void*)persistent->bmpData, padding, 1, persistent->fp) != 1)
+ return -1;
+ }
+
+ persistent->count++;
+
+ return 1;
+}
+
+static int persistent_cache_read_v2(rdpPersistentCache* persistent)
+{
+ WINPR_ASSERT(persistent);
+ while (1)
+ {
+ PERSISTENT_CACHE_ENTRY_V2 entry = { 0 };
+
+ if (fread((void*)&entry, sizeof(entry), 1, persistent->fp) != 1)
+ break;
+
+ if (fseek(persistent->fp, 0x4000, SEEK_CUR) != 0)
+ break;
+
+ persistent->count++;
+ }
+
+ return 1;
+}
+
+static int persistent_cache_read_entry_v3(rdpPersistentCache* persistent,
+ PERSISTENT_CACHE_ENTRY* entry)
+{
+ PERSISTENT_CACHE_ENTRY_V3 entry3 = { 0 };
+
+ WINPR_ASSERT(persistent);
+ WINPR_ASSERT(entry);
+
+ if (fread((void*)&entry3, sizeof(entry3), 1, persistent->fp) != 1)
+ return -1;
+
+ entry->key64 = entry3.key64;
+ entry->width = entry3.width;
+ entry->height = entry3.height;
+ entry->size = entry3.width * entry3.height * 4;
+ entry->flags = 0;
+
+ if (entry->size > persistent->bmpSize)
+ {
+ persistent->bmpSize = entry->size;
+ BYTE* bmpData = (BYTE*)winpr_aligned_recalloc(persistent->bmpData, persistent->bmpSize,
+ sizeof(BYTE), 32);
+
+ if (!bmpData)
+ return -1;
+
+ persistent->bmpData = bmpData;
+ }
+
+ entry->data = persistent->bmpData;
+
+ if (fread((void*)entry->data, entry->size, 1, persistent->fp) != 1)
+ return -1;
+
+ return 1;
+}
+
+static int persistent_cache_write_entry_v3(rdpPersistentCache* persistent,
+ const PERSISTENT_CACHE_ENTRY* entry)
+{
+ PERSISTENT_CACHE_ENTRY_V3 entry3 = { 0 };
+
+ WINPR_ASSERT(persistent);
+ WINPR_ASSERT(entry);
+
+ entry3.key64 = entry->key64;
+ entry3.width = entry->width;
+ entry3.height = entry->height;
+
+ if (fwrite((void*)&entry3, sizeof(entry3), 1, persistent->fp) != 1)
+ return -1;
+
+ if (fwrite((void*)entry->data, entry->size, 1, persistent->fp) != 1)
+ return -1;
+
+ persistent->count++;
+
+ return 1;
+}
+
+static int persistent_cache_read_v3(rdpPersistentCache* persistent)
+{
+ WINPR_ASSERT(persistent);
+ while (1)
+ {
+ PERSISTENT_CACHE_ENTRY_V3 entry = { 0 };
+
+ if (fread((void*)&entry, sizeof(entry), 1, persistent->fp) != 1)
+ break;
+
+ if (fseek(persistent->fp, (entry.width * entry.height * 4), SEEK_CUR) != 0)
+ break;
+
+ persistent->count++;
+ }
+
+ return 1;
+}
+
+int persistent_cache_read_entry(rdpPersistentCache* persistent, PERSISTENT_CACHE_ENTRY* entry)
+{
+ WINPR_ASSERT(persistent);
+ WINPR_ASSERT(entry);
+
+ if (persistent->version == 3)
+ return persistent_cache_read_entry_v3(persistent, entry);
+ else if (persistent->version == 2)
+ return persistent_cache_read_entry_v2(persistent, entry);
+
+ return -1;
+}
+
+int persistent_cache_write_entry(rdpPersistentCache* persistent,
+ const PERSISTENT_CACHE_ENTRY* entry)
+{
+ WINPR_ASSERT(persistent);
+ WINPR_ASSERT(entry);
+
+ if (persistent->version == 3)
+ return persistent_cache_write_entry_v3(persistent, entry);
+ else if (persistent->version == 2)
+ return persistent_cache_write_entry_v2(persistent, entry);
+
+ return -1;
+}
+
+static int persistent_cache_open_read(rdpPersistentCache* persistent)
+{
+ BYTE sig[8] = { 0 };
+ int status = 1;
+ long offset = 0;
+
+ WINPR_ASSERT(persistent);
+ persistent->fp = winpr_fopen(persistent->filename, "rb");
+
+ if (!persistent->fp)
+ return -1;
+
+ if (fread(sig, 8, 1, persistent->fp) != 1)
+ return -1;
+
+ if (!strncmp((const char*)sig, "RDP8bmp", 8))
+ persistent->version = 3;
+ else
+ persistent->version = 2;
+
+ fseek(persistent->fp, 0, SEEK_SET);
+
+ if (persistent->version == 3)
+ {
+ PERSISTENT_CACHE_HEADER_V3 header;
+
+ if (fread(&header, sizeof(header), 1, persistent->fp) != 1)
+ return -1;
+
+ status = persistent_cache_read_v3(persistent);
+ offset = sizeof(header);
+ }
+ else
+ {
+ status = persistent_cache_read_v2(persistent);
+ offset = 0;
+ }
+
+ fseek(persistent->fp, offset, SEEK_SET);
+
+ return status;
+}
+
+static int persistent_cache_open_write(rdpPersistentCache* persistent)
+{
+ WINPR_ASSERT(persistent);
+
+ persistent->fp = winpr_fopen(persistent->filename, "w+b");
+
+ if (!persistent->fp)
+ return -1;
+
+ if (persistent->version == 3)
+ {
+ PERSISTENT_CACHE_HEADER_V3 header = { 0 };
+ strncpy((char*)header.sig, "RDP8bmp", 8);
+ header.flags = 0x00000006;
+
+ if (fwrite(&header, sizeof(header), 1, persistent->fp) != 1)
+ return -1;
+ }
+
+ ZeroMemory(persistent->bmpData, persistent->bmpSize);
+
+ return 1;
+}
+
+int persistent_cache_open(rdpPersistentCache* persistent, const char* filename, BOOL write,
+ UINT32 version)
+{
+ WINPR_ASSERT(persistent);
+ WINPR_ASSERT(filename);
+ persistent->write = write;
+
+ persistent->filename = _strdup(filename);
+
+ if (!persistent->filename)
+ return -1;
+
+ if (persistent->write)
+ {
+ persistent->version = version;
+ return persistent_cache_open_write(persistent);
+ }
+
+ return persistent_cache_open_read(persistent);
+}
+
+int persistent_cache_close(rdpPersistentCache* persistent)
+{
+ WINPR_ASSERT(persistent);
+ if (persistent->fp)
+ {
+ fclose(persistent->fp);
+ persistent->fp = NULL;
+ }
+
+ return 1;
+}
+
+rdpPersistentCache* persistent_cache_new(void)
+{
+ rdpPersistentCache* persistent = calloc(1, sizeof(rdpPersistentCache));
+
+ if (!persistent)
+ return NULL;
+
+ persistent->bmpSize = 0x4000;
+ persistent->bmpData = calloc(1, persistent->bmpSize);
+
+ if (!persistent->bmpData)
+ {
+ free(persistent);
+ return NULL;
+ }
+
+ return persistent;
+}
+
+void persistent_cache_free(rdpPersistentCache* persistent)
+{
+ if (!persistent)
+ return;
+
+ persistent_cache_close(persistent);
+
+ free(persistent->filename);
+
+ winpr_aligned_free(persistent->bmpData);
+
+ free(persistent);
+}