From f2fd954313bf70edc5204b89f5f1b668925eda28 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Fri, 17 Apr 2015 14:39:17 +0200
Subject: mfplat: Implement MFTRegister. (v2)

---
 dlls/mfplat/Makefile.in |   1 +
 dlls/mfplat/main.c      | 144 ++++++++++++++++++++++++++++++++++++++++++++++++
 dlls/mfplat/mfplat.spec |   2 +-
 loader/wine.inf.in      |   4 ++
 4 files changed, 150 insertions(+), 1 deletion(-)

diff --git a/dlls/mfplat/Makefile.in b/dlls/mfplat/Makefile.in
index 2b5bd24..9679f53 100644
--- a/dlls/mfplat/Makefile.in
+++ b/dlls/mfplat/Makefile.in
@@ -1,4 +1,5 @@
 MODULE    = mfplat.dll
+IMPORTS   = user32 advapi32
 
 C_SRCS = \
 	main.c
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index 698c681..d8b0c7a 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -23,15 +23,44 @@
 
 #include "windef.h"
 #include "winbase.h"
+#include "winuser.h"
+#include "winreg.h"
 
 #include "initguid.h"
 #include "mfapi.h"
 #include "mferror.h"
 
 #include "wine/debug.h"
+#include "wine/unicode.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
 
+static WCHAR transform_keyW[] = {'S','o','f','t','w','a','r','e','\\','C','l','a','s','s','e','s',
+                                 '\\','M','e','d','i','a','F','o','u','n','d','a','t','i','o','n','\\',
+                                 'T','r','a','n','s','f','o','r','m','s',0};
+static WCHAR categories_keyW[] = {'S','o','f','t','w','a','r','e','\\','C','l','a','s','s','e','s',
+                                 '\\','M','e','d','i','a','F','o','u','n','d','a','t','i','o','n','\\',
+                                 'T','r','a','n','s','f','o','r','m','s','\\',
+                                 'C','a','t','e','g','o','r','i','e','s',0};
+static WCHAR inputtypesW[]  = {'I','n','p','u','t','T','y','p','e','s',0};
+static WCHAR outputtypesW[] = {'O','u','t','p','u','t','T','y','p','e','s',0};
+static const WCHAR szGUIDFmt[] =
+{
+    '%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0',
+    '2','x','%','0','2','x','-','%','0','2','x','%','0','2','x','%','0','2',
+    'x','%','0','2','x','%','0','2','x','%','0','2','x',0
+};
+
+static LPWSTR GUIDToString(LPWSTR lpwstr, REFGUID lpcguid)
+{
+    wsprintfW(lpwstr, szGUIDFmt, lpcguid->Data1, lpcguid->Data2,
+        lpcguid->Data3, lpcguid->Data4[0], lpcguid->Data4[1],
+        lpcguid->Data4[2], lpcguid->Data4[3], lpcguid->Data4[4],
+        lpcguid->Data4[5], lpcguid->Data4[6], lpcguid->Data4[7]);
+
+    return lpwstr;
+}
+
 BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
 {
     switch (reason)
@@ -46,6 +75,121 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
     return TRUE;
 }
 
+static HRESULT register_transform(CLSID *clsid, WCHAR *name,
+                                  UINT32 cinput, MFT_REGISTER_TYPE_INFO *input_types,
+                                  UINT32 coutput, MFT_REGISTER_TYPE_INFO *output_types)
+{
+    HKEY htransform, hclsid = 0;
+    WCHAR buffer[64];
+    GUID *types;
+    DWORD size;
+    LONG ret;
+    UINT32 i;
+
+    if (RegOpenKeyW(HKEY_LOCAL_MACHINE, transform_keyW, &htransform))
+        return E_FAIL;
+
+    GUIDToString(buffer, clsid);
+    ret = RegCreateKeyW(htransform, buffer, &hclsid);
+    RegCloseKey(htransform);
+    if (ret) return E_FAIL;
+
+    size = (strlenW(name) + 1) * sizeof(WCHAR);
+    if (RegSetValueExW(hclsid, NULL, 0, REG_SZ, (BYTE *)name, size))
+        goto err;
+
+    if (cinput)
+    {
+        size = 2 * cinput * sizeof(GUID);
+        types = HeapAlloc(GetProcessHeap(), 0, size);
+        if (!types) goto err;
+
+        for (i = 0; i < cinput; i++)
+        {
+            memcpy(&types[2 * i],     &input_types[i].guidMajorType, sizeof(GUID));
+            memcpy(&types[2 * i + 1], &input_types[i].guidSubtype,   sizeof(GUID));
+        }
+
+        ret = RegSetValueExW(hclsid, inputtypesW, 0, REG_BINARY, (BYTE *)types, size);
+        HeapFree(GetProcessHeap(), 0, types);
+        if (ret) goto err;
+    }
+
+    if (coutput)
+    {
+        size = 2 * coutput * sizeof(GUID);
+        types = HeapAlloc(GetProcessHeap(), 0, size);
+        if (!types) goto err;
+
+        for (i = 0; i < coutput; i++)
+        {
+            memcpy(&types[2 * i],     &output_types[i].guidMajorType, sizeof(GUID));
+            memcpy(&types[2 * i + 1], &output_types[i].guidSubtype,   sizeof(GUID));
+        }
+
+        ret = RegSetValueExW(hclsid, outputtypesW, 0, REG_BINARY, (BYTE *)types, size);
+        HeapFree(GetProcessHeap(), 0, types);
+        if (ret) goto err;
+    }
+
+    RegCloseKey(hclsid);
+    return S_OK;
+
+err:
+    RegCloseKey(hclsid);
+    return E_FAIL;
+}
+
+static HRESULT register_category(CLSID *clsid, GUID *category)
+{
+    HKEY hcategory, htmp1, htmp2;
+    WCHAR buffer[64];
+    DWORD ret;
+
+    if (RegOpenKeyW(HKEY_LOCAL_MACHINE, categories_keyW, &hcategory))
+        return E_FAIL;
+
+    GUIDToString(buffer, category);
+    ret = RegCreateKeyW(hcategory, buffer, &htmp1);
+    RegCloseKey(hcategory);
+    if (ret) return E_FAIL;
+
+    GUIDToString(buffer, clsid);
+    ret = RegCreateKeyW(htmp1, buffer, &htmp2);
+    RegCloseKey(htmp1);
+    if (ret) return E_FAIL;
+
+    RegCloseKey(htmp2);
+    return S_OK;
+}
+
+/***********************************************************************
+ *      MFTRegister (mfplat.@)
+ */
+HRESULT WINAPI MFTRegister(CLSID clsid, GUID category, LPWSTR name, UINT32 flags, UINT32 cinput,
+                           MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
+                           MFT_REGISTER_TYPE_INFO *output_types, void *attributes)
+{
+    HRESULT hr;
+
+    FIXME("(%s, %s, %s, %x, %u, %p, %u, %p, %p)\n", debugstr_guid(&clsid), debugstr_guid(&category),
+                                                    debugstr_w(name), flags, cinput, input_types,
+                                                    coutput, output_types, attributes);
+
+    if (attributes)
+        FIXME("attributes not yet supported.\n");
+
+    if (flags)
+        FIXME("flags not yet supported.\n");
+
+    hr = register_transform(&clsid, name, cinput, input_types, coutput, output_types);
+
+    if (SUCCEEDED(hr))
+        hr = register_category(&clsid, &category);
+
+    return hr;
+}
+
 /***********************************************************************
  *      MFStartup (mfplat.@)
  */
diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec
index 0b402b7..acde0a5 100644
--- a/dlls/mfplat/mfplat.spec
+++ b/dlls/mfplat/mfplat.spec
@@ -137,7 +137,7 @@
 @ stub MFTEnum
 @ stub MFTEnumEx
 @ stub MFTGetInfo
-@ stub MFTRegister
+@ stdcall MFTRegister(int128 int128 wstr long long ptr long ptr ptr)
 @ stub MFTRegisterLocal
 @ stub MFTRegisterLocalByCLSID
 @ stub MFTUnregister
diff --git a/loader/wine.inf.in b/loader/wine.inf.in
index f30942a..3935bae 100644
--- a/loader/wine.inf.in
+++ b/loader/wine.inf.in
@@ -623,6 +623,10 @@ HKLM,Software\Borland\Database Engine\Settings\SYSTEM\INIT,SHAREDMEMLOCATION,,90
 HKLM,Software\Clients\Mail,,2,"Native Mail Client"
 HKLM,Software\Clients\Mail\Native Mail Client,,2,"Native Mail Client"
 HKLM,Software\Clients\Mail\Native Mail Client,"DLLPath",2,"%11%\winemapi.dll"
+HKLM,Software\Classes\MediaFoundation,,16
+HKLM,Software\Classes\MediaFoundation\MediaSources,,16
+HKLM,Software\Classes\MediaFoundation\Transforms,,16
+HKLM,Software\Classes\MediaFoundation\Transforms\Categories,,16
 HKLM,Software\Microsoft\Advanced INF Setup,,16
 HKLM,Software\Microsoft\Clients,,16
 HKLM,Software\Microsoft\Cryptography\Calais\Current,,16
-- 
2.5.1

