From e68b9f65a4f9c7f9c10b11152cac04bcdf6facf9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Mon, 8 Feb 2016 04:44:24 +0100
Subject: avifile.dll16: Correctly convert result of AVIStreamGetFrame to a segptr.

---
 dlls/avifile.dll16/Makefile.in        |   3 +
 dlls/avifile.dll16/avifile.dll16.spec |   6 +-
 dlls/avifile.dll16/main.c             | 137 ++++++++++++++++++++++++++++++++++
 3 files changed, 143 insertions(+), 3 deletions(-)
 create mode 100644 dlls/avifile.dll16/main.c

diff --git a/dlls/avifile.dll16/Makefile.in b/dlls/avifile.dll16/Makefile.in
index 6050c6c..4152c2f 100644
--- a/dlls/avifile.dll16/Makefile.in
+++ b/dlls/avifile.dll16/Makefile.in
@@ -1,3 +1,6 @@
 MODULE    = avifile.dll16
 IMPORTS   = avifil32
 EXTRADLLFLAGS = -m16 -Wb,--main-module,avifil32.dll
+
+C_SRCS = \
+	main.c
diff --git a/dlls/avifile.dll16/avifile.dll16.spec b/dlls/avifile.dll16/avifile.dll16.spec
index 71a6c74..0e19413 100644
--- a/dlls/avifile.dll16/avifile.dll16.spec
+++ b/dlls/avifile.dll16/avifile.dll16.spec
@@ -20,9 +20,9 @@
 105 stub     AVIMAKECOMPRESSEDSTREAM
 106 stub     AVIMAKEFILEFROMSTREAMS
 107 stub     AVIMAKESTREAMFROMCLIPBOARD
-110 pascal   AVIStreamGetFrame(long long) AVIStreamGetFrame
-111 pascal   AVIStreamGetFrameClose(long) AVIStreamGetFrameClose
-112 pascal   AVIStreamGetFrameOpen(long ptr) AVIStreamGetFrameOpen
+110 pascal   AVIStreamGetFrame(long long) AVIStreamGetFrame16
+111 pascal   AVIStreamGetFrameClose(long) AVIStreamGetFrameClose16
+112 pascal   AVIStreamGetFrameOpen(long ptr) AVIStreamGetFrameOpen16
 120 stub     _AVISAVE
 121 stub     AVISAVEV
 122 stub     AVISAVEOPTIONS
diff --git a/dlls/avifile.dll16/main.c b/dlls/avifile.dll16/main.c
new file mode 100644
index 0000000..f780c43
--- /dev/null
+++ b/dlls/avifile.dll16/main.c
@@ -0,0 +1,137 @@
+/*
+ * Wrapper for 16 bit avifile functions
+ *
+ * Copyright 2016 Michael Müller
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "wine/winbase16.h"
+#include "winternl.h"
+#include "wingdi.h"
+#include "vfw.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(avifile16);
+
+struct frame_wrapper16
+{
+    PGETFRAME pg;
+    PVOID ptr;
+    DWORD size;
+    WORD sel;
+    WORD count;
+};
+
+static void free_segptr_frame(struct frame_wrapper16 *wrapper)
+{
+    int i;
+
+    if (!wrapper->sel)
+        return;
+
+    for (i = 0; i < wrapper->count; i++)
+        FreeSelector16(wrapper->sel + (i << __AHSHIFT));
+
+    wrapper->sel = 0;
+}
+
+static SEGPTR alloc_segptr_frame(struct frame_wrapper16 *wrapper, void *ptr, DWORD size)
+{
+    int i;
+
+    if (wrapper->sel)
+    {
+        if (wrapper->ptr == ptr && wrapper->size == size)
+            return MAKESEGPTR(wrapper->sel, 0);
+        free_segptr_frame(wrapper);
+    }
+
+    wrapper->ptr    = ptr;
+    wrapper->size   = size;
+    wrapper->count  = (size + 0xffff) / 0x10000;
+    wrapper->sel    = AllocSelectorArray16(wrapper->count);
+    if (!wrapper->sel)
+        return 0;
+
+    for (i = 0; i < wrapper->count; i++)
+    {
+        SetSelectorBase(wrapper->sel + (i << __AHSHIFT), (DWORD)ptr + i * 0x10000);
+        SetSelectorLimit16(wrapper->sel + (i << __AHSHIFT), size - 1);
+        size -= 0x10000;
+    }
+
+    return MAKESEGPTR(wrapper->sel, 0);
+}
+
+/***********************************************************************
+ *      AVIStreamGetFrameOpen   (AVIFILE.112)
+ */
+PGETFRAME WINAPI AVIStreamGetFrameOpen16(PAVISTREAM pstream, LPBITMAPINFOHEADER lpbiWanted)
+{
+    struct frame_wrapper16 *wrapper;
+    PGETFRAME pg;
+
+    pg = AVIStreamGetFrameOpen(pstream, lpbiWanted);
+    if (!pg) return NULL;
+
+    wrapper = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wrapper));
+    if (!wrapper)
+    {
+        AVIStreamGetFrameClose(pg);
+        return NULL;
+    }
+
+    wrapper->pg = pg;
+    return (PGETFRAME)wrapper;
+}
+
+/***********************************************************************
+ *      AVIStreamGetFrame	(AVIFILE.110)
+ */
+SEGPTR WINAPI AVIStreamGetFrame16(PGETFRAME pg, LONG pos)
+{
+    struct frame_wrapper16 *wrapper = (void *)pg;
+    BITMAPINFOHEADER *bih;
+
+    if (!pg) return 0;
+
+    bih = AVIStreamGetFrame(wrapper->pg, pos);
+    if (bih)
+    {
+        DWORD size = bih->biSize + bih->biSizeImage;
+        return alloc_segptr_frame(wrapper, bih, size);
+    }
+
+    return 0;
+}
+
+
+/***********************************************************************
+ *      AVIStreamGetFrameClose  (AVIFILE.111)
+ */
+HRESULT WINAPI AVIStreamGetFrameClose16(PGETFRAME pg)
+{
+    struct frame_wrapper16 *wrapper = (void *)pg;
+    HRESULT hr;
+
+    if (!pg) return S_OK;
+
+    hr = AVIStreamGetFrameClose(wrapper->pg);
+    free_segptr_frame(wrapper);
+    HeapFree(GetProcessHeap(), 0, wrapper);
+    return hr;
+}
-- 
2.7.0

