From a33160eef805e950e8b3c36c74f0688ca9e2328e Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Sun, 7 Feb 2016 12:52:26 +0800
Subject: avifil32: Add support for AVIFile interface proxies. [v2]

---
 dlls/avifil32/Makefile.in        |   4 +-
 dlls/avifil32/avifil32.idl       |  25 ++++++----
 dlls/avifil32/avifile_ifaces.idl | 105 +++++++++++++++++++++++++++++++++++++++
 dlls/avifil32/avifile_private.h  |   1 +
 dlls/avifil32/factory.c          |   8 ++-
 5 files changed, 130 insertions(+), 13 deletions(-)
 create mode 100644 dlls/avifil32/avifile_ifaces.idl

diff --git a/dlls/avifil32/Makefile.in b/dlls/avifil32/Makefile.in
index 81d2ff8..4030514 100644
--- a/dlls/avifil32/Makefile.in
+++ b/dlls/avifil32/Makefile.in
@@ -1,6 +1,6 @@
 MODULE    = avifil32.dll
 IMPORTLIB = avifil32
-IMPORTS   = uuid msacm32 msvfw32 winmm ole32 user32 advapi32
+IMPORTS   = uuid msacm32 msvfw32 winmm ole32 user32 advapi32 rpcrt4
 
 C_SRCS = \
 	acmstream.c \
@@ -17,3 +17,5 @@ C_SRCS = \
 IDL_SRCS = avifil32.idl
 
 RC_SRCS = avifil32.rc
+
+dlldata_EXTRADEFS = -DENTRY_PREFIX=avifil32_
diff --git a/dlls/avifil32/avifil32.idl b/dlls/avifil32/avifil32.idl
index 1f50f15..e23c176 100644
--- a/dlls/avifil32/avifil32.idl
+++ b/dlls/avifil32/avifil32.idl
@@ -18,39 +18,42 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#pragma makedep proxy
 #pragma makedep register
 
+#include "avifile_ifaces.idl"
+
+[
+    helpstring("IAVIStream & IAVIFile Proxy"),
+    threading(both),
+    uuid(0002000d-0000-0000-c000-000000000046)
+]
+coclass PSFactoryBuffer { interface IFactoryBuffer; }
+
 [
     helpstring("Microsoft AVI Files"),
-    threading(apartment),
+    threading(both),
     uuid(00020000-0000-0000-C000-000000000046)
 ]
 coclass AVIFile { interface IAVIFile; }
 
 [
     helpstring("AVI Compressed Stream"),
-    threading(apartment),
+    threading(both),
     uuid(00020001-0000-0000-c000-000000000046)
 ]
 coclass ICMStream { interface IAVIStream; }
 
 [
     helpstring("Microsoft Wave File"),
-    threading(apartment),
+    threading(both),
     uuid(00020003-0000-0000-c000-000000000046)
 ]
 coclass WAVFile { interface IAVIFile; }
 
 [
-    helpstring("IAVIStream & IAVIFile Proxy"),
-    threading(apartment),
-    uuid(0002000d-0000-0000-c000-000000000046)
-]
-coclass AVIProxy { }
-
-[
     helpstring("ACM Compressed Audio Stream"),
-    threading(apartment),
+    threading(both),
     uuid(0002000f-0000-0000-c000-000000000046)
 ]
 coclass ACMStream { interface IAVIStream; }
diff --git a/dlls/avifil32/avifile_ifaces.idl b/dlls/avifil32/avifile_ifaces.idl
new file mode 100644
index 0000000..f9280e5
--- /dev/null
+++ b/dlls/avifil32/avifile_ifaces.idl
@@ -0,0 +1,105 @@
+/*
+ * Proxy support for avifil32
+ *
+ * Copyright 2016 Dmitry Timoshkov
+ *
+ * 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
+ */
+
+/*
+ * These interface descriptions are supposed to be used for automatic proxy
+ * generation by an IDL compiler.
+ *
+ * While it's possible to convert include/vfw.h to an .idl, that's proved to
+ * be a major waste of an effort because the resulting interface descriptions
+ * can't be used for automatic proxy generation since they are not compatible
+ * with IDL compiler restrictions for proxies, and fixing them up would make
+ * generated vfw.h source incompatible with PSDK's equivalent.
+ */
+
+import "wtypes.idl";
+import "unknwn.idl";
+
+typedef struct _AVISTREAMINFOW
+{
+    DWORD fccType;
+    DWORD fccHandler;
+    DWORD dwFlags;
+    DWORD dwCaps;
+    WORD  wPriority;
+    WORD  wLanguage;
+    DWORD dwScale;
+    DWORD dwRate;
+    DWORD dwStart;
+    DWORD dwLength;
+    DWORD dwInitialFrames;
+    DWORD dwSuggestedBufferSize;
+    DWORD dwQuality;
+    DWORD dwSampleSize;
+    RECT  rcFrame;
+    DWORD dwEditCount;
+    DWORD dwFormatChangeCount;
+    WCHAR szName[64];
+} AVISTREAMINFOW;
+
+[
+    object,
+    uuid(00020021-0000-0000-c000-000000000046)
+]
+interface IAVIStream : IUnknown
+{
+    HRESULT Create(LPARAM lParam1, LPARAM lParam2);
+    HRESULT Info(AVISTREAMINFOW *psi, LONG lSize);
+    LONG FindSample(LONG lPos, LONG lFlags);
+    HRESULT ReadFormat(LONG lPos, [out,size_is(*lpcbFormat)] char *lpFormat, [in,out] LONG *lpcbFormat);
+    HRESULT SetFormat(LONG lPos, [in,size_is(cbFormat)] char *lpFormat, LONG cbFormat);
+    HRESULT Read(LONG lStart, LONG lSamples, [out,size_is(cbBuffer)] char *lpBuffer, LONG cbBuffer, LONG *plBytes, LONG *plSamples);
+    HRESULT Write(LONG lStart, LONG lSamples, [in,size_is(cbBuffer)] char *lpBuffer, LONG cbBuffer, DWORD dwFlags, LONG *plSampWritten, LONG *plBytesWritten);
+    HRESULT Delete(LONG lStart, LONG lSamples);
+    HRESULT ReadData(DWORD fcc, [out,size_is(*lpcbBuffer)] char *lpBuffer, [in,out] LONG *lpcbBuffer);
+    HRESULT WriteData(DWORD fcc, [in,size_is(cbBuffer)] char *lpBuffer, LONG cbBuffer);
+    HRESULT SetInfo(AVISTREAMINFOW *plInfo, LONG cbInfo);
+};
+
+typedef struct _AVIFILEINFOW
+{
+    DWORD dwMaxBytesPerSec;
+    DWORD dwFlags;
+    DWORD dwCaps;
+    DWORD dwStreams;
+    DWORD dwSuggestedBufferSize;
+    DWORD dwWidth;
+    DWORD dwHeight;
+    DWORD dwScale;
+    DWORD dwRate;
+    DWORD dwLength;
+    DWORD dwEditCount;
+    WCHAR szFileType[64];
+} AVIFILEINFOW;
+
+[
+    object,
+    uuid(00020020-0000-0000-c000-000000000046)
+]
+interface IAVIFile : IUnknown
+{
+    HRESULT Info(AVIFILEINFOW *pfi, LONG lSize);
+    HRESULT GetStream(IAVIStream **ppStream, DWORD fccType, LONG lParam);
+    HRESULT CreateStream(IAVIStream **ppStream, AVISTREAMINFOW *psi);
+    HRESULT WriteData(DWORD fcc, [in,size_is(cbBuffer)] char *lpBuffer, LONG cbBuffer);
+    HRESULT ReadData(DWORD fcc, [out,size_is(*lpcbBuffer)] char *lpBuffer, [in,out] LONG *lpcbBuffer);
+    HRESULT EndRecord(void);
+    HRESULT DeleteStream(DWORD fccType, LONG lParam);
+};
diff --git a/dlls/avifil32/avifile_private.h b/dlls/avifil32/avifile_private.h
index 0fd74c4..9cce2d3 100644
--- a/dlls/avifil32/avifile_private.h
+++ b/dlls/avifil32/avifile_private.h
@@ -67,5 +67,6 @@ extern PGETFRAME AVIFILE_CreateGetFrame(PAVISTREAM pstream) DECLSPEC_HIDDEN;
 extern PAVIFILE  AVIFILE_CreateAVITempFile(int nStreams, const PAVISTREAM *ppStreams) DECLSPEC_HIDDEN;
 
 extern LPCWSTR  AVIFILE_BasenameW(LPCWSTR szFileName) DECLSPEC_HIDDEN;
+extern HRESULT WINAPI avifil32_DllGetClassObject(REFCLSID pclsid, REFIID piid, LPVOID *ppv) DECLSPEC_HIDDEN;
 
 #endif
diff --git a/dlls/avifil32/factory.c b/dlls/avifil32/factory.c
index c74a716..1b8988d 100644
--- a/dlls/avifil32/factory.c
+++ b/dlls/avifil32/factory.c
@@ -195,12 +195,18 @@ LPCWSTR AVIFILE_BasenameW(LPCWSTR szPath)
  */
 HRESULT WINAPI DllGetClassObject(REFCLSID pclsid, REFIID piid, LPVOID *ppv)
 {
+  HRESULT hr;
+
   TRACE("(%s,%s,%p)\n", debugstr_guid(pclsid), debugstr_guid(piid), ppv);
 
   if (pclsid == NULL || piid == NULL || ppv == NULL)
     return E_FAIL;
 
-  return AVIFILE_CreateClassFactory(pclsid,piid,ppv);
+  hr = AVIFILE_CreateClassFactory(pclsid,piid,ppv);
+  if (SUCCEEDED(hr))
+    return hr;
+
+  return avifil32_DllGetClassObject(pclsid,piid,ppv);
 }
 
 /*****************************************************************************
-- 
2.7.0

