[OLE32_WINETEST]
[reactos.git] / rostests / winetests / ole32 / compobj.c
index 755d15a..c1ff25a 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#define WIN32_NO_STATUS
+#define _INC_WINDOWS
+#define COM_NO_WINDOWS_H
+
 #define COBJMACROS
 #define CONST_VTABLE
 
 #include <stdarg.h>
+#include <stdio.h>
 
-#include "windef.h"
-#include "winbase.h"
+#include <windef.h>
+#include <winbase.h>
+#include <winnls.h>
+#include <winreg.h>
 #define USE_COM_CONTEXT_DEF
-#include "initguid.h"
-#include "objbase.h"
-#include "shlguid.h"
-#include "urlmon.h" /* for CLSID_FileProtocol */
+#include <initguid.h>
+//#include "objbase.h"
+//#include "shlguid.h"
+#include <ole2.h>
+#include <urlmon.h> /* for CLSID_FileProtocol */
 
-#include "ctxtcall.h"
+#include <ctxtcall.h>
 
-#include "wine/test.h"
+#include <wine/test.h>
 
 extern const IID GUID_NULL;
 
 /* functions that are not present on all versions of Windows */
-HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
-HRESULT (WINAPI * pCoGetObjectContext)(REFIID riid, LPVOID *ppv);
-HRESULT (WINAPI * pCoSwitchCallContext)(IUnknown *pObject, IUnknown **ppOldObject);
-HRESULT (WINAPI * pCoGetTreatAsClass)(REFCLSID clsidOld, LPCLSID pClsidNew);
-HRESULT (WINAPI * pCoGetContextToken)(ULONG_PTR *token);
+static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
+static HRESULT (WINAPI * pCoGetObjectContext)(REFIID riid, LPVOID *ppv);
+static HRESULT (WINAPI * pCoSwitchCallContext)(IUnknown *pObject, IUnknown **ppOldObject);
+static HRESULT (WINAPI * pCoGetTreatAsClass)(REFCLSID clsidOld, LPCLSID pClsidNew);
+static HRESULT (WINAPI * pCoTreatAsClass)(REFCLSID clsidOld, REFCLSID pClsidNew);
+static HRESULT (WINAPI * pCoGetContextToken)(ULONG_PTR *token);
+static LONG (WINAPI * pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
+static LONG (WINAPI * pRegOverridePredefKey)(HKEY key, HKEY override);
+
+static BOOL   (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
+static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
+static BOOL   (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
+static BOOL   (WINAPI *pIsWow64Process)(HANDLE, LPBOOL);
+static void   (WINAPI *pReleaseActCtx)(HANDLE);
 
 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
@@ -50,27 +67,29 @@ HRESULT (WINAPI * pCoGetContextToken)(ULONG_PTR *token);
 
 static const CLSID CLSID_non_existent =   { 0x12345678, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
 static const CLSID CLSID_StdFont = { 0x0be35203, 0x8f91, 0x11ce, { 0x9d, 0xe3, 0x00, 0xaa, 0x00, 0x4b, 0xb8, 0x51 } };
-static WCHAR stdfont[] = {'S','t','d','F','o','n','t',0};
+static const GUID IID_Testiface = { 0x22222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
+static const GUID IID_Testiface2 = { 0x32222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
+static const GUID IID_Testiface3 = { 0x42222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
+static const GUID IID_Testiface4 = { 0x52222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
+static const GUID IID_Testiface5 = { 0x62222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
+static const GUID IID_Testiface6 = { 0x72222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
+static const GUID IID_TestPS = { 0x66666666, 0x8888, 0x7777, { 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 } };
+
+DEFINE_GUID(CLSID_InProcFreeMarshaler, 0x0000033a,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
+
+static const WCHAR stdfont[] = {'S','t','d','F','o','n','t',0};
 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
-static WCHAR wszCLSID_StdFont[] =
+static const WCHAR wszCLSID_StdFont[] =
 {
     '{','0','b','e','3','5','2','0','3','-','8','f','9','1','-','1','1','c','e','-',
     '9','d','e','3','-','0','0','a','a','0','0','4','b','b','8','5','1','}',0
 };
+static const WCHAR progidW[] = {'P','r','o','g','I','d','.','P','r','o','g','I','d',0};
+static const WCHAR cf_brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
+                                    'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}','a',0};
 
-static const IID IID_IWineTest =
-{
-    0x5201163f,
-    0x8164,
-    0x4fd0,
-    {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
-}; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
-static const CLSID CLSID_WineOOPTest = {
-    0x5201163f,
-    0x8164,
-    0x4fd0,
-    {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
-}; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
+DEFINE_GUID(IID_IWineTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
+DEFINE_GUID(CLSID_WineOOPTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
 
 static LONG cLocks;
 
@@ -117,7 +136,7 @@ static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
 
 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
     LPCLASSFACTORY iface,
-    LPUNKNOWN pUnkOuter,
+    IUnknown *pUnkOuter,
     REFIID riid,
     LPVOID *ppvObj)
 {
@@ -144,10 +163,143 @@ static const IClassFactoryVtbl TestClassFactory_Vtbl =
 
 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
 
+static WCHAR manifest_path[MAX_PATH];
+
+static BOOL create_manifest_file(const char *filename, const char *manifest)
+{
+    int manifest_len;
+    DWORD size;
+    HANDLE file;
+    WCHAR path[MAX_PATH];
+
+    MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
+    GetFullPathNameW(path, sizeof(manifest_path)/sizeof(WCHAR), manifest_path, NULL);
+
+    manifest_len = strlen(manifest);
+    file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+                       FILE_ATTRIBUTE_NORMAL, NULL);
+    ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
+    if(file == INVALID_HANDLE_VALUE)
+        return FALSE;
+    WriteFile(file, manifest, manifest_len, &size, NULL);
+    CloseHandle(file);
+
+    return TRUE;
+}
+
+static HANDLE activate_context(const char *manifest, ULONG_PTR *cookie)
+{
+    WCHAR path[MAX_PATH];
+    ACTCTXW actctx;
+    HANDLE handle;
+    BOOL ret;
+
+    if (!pCreateActCtxW) return NULL;
+
+    create_manifest_file("file.manifest", manifest);
+
+    MultiByteToWideChar( CP_ACP, 0, "file.manifest", -1, path, MAX_PATH );
+    memset(&actctx, 0, sizeof(ACTCTXW));
+    actctx.cbSize = sizeof(ACTCTXW);
+    actctx.lpSource = path;
+
+    handle = pCreateActCtxW(&actctx);
+    ok(handle != INVALID_HANDLE_VALUE || broken(handle == INVALID_HANDLE_VALUE) /* some old XP/2k3 versions */,
+        "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
+    if (handle == INVALID_HANDLE_VALUE)
+    {
+        win_skip("activation context generation failed, some tests will be skipped\n");
+        handle = NULL;
+    }
+
+    ok(actctx.cbSize == sizeof(ACTCTXW), "actctx.cbSize=%d\n", actctx.cbSize);
+    ok(actctx.dwFlags == 0, "actctx.dwFlags=%d\n", actctx.dwFlags);
+    ok(actctx.lpSource == path, "actctx.lpSource=%p\n", actctx.lpSource);
+    ok(actctx.wProcessorArchitecture == 0, "actctx.wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
+    ok(actctx.wLangId == 0, "actctx.wLangId=%d\n", actctx.wLangId);
+    ok(actctx.lpAssemblyDirectory == NULL, "actctx.lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
+    ok(actctx.lpResourceName == NULL, "actctx.lpResourceName=%p\n", actctx.lpResourceName);
+    ok(actctx.lpApplicationName == NULL, "actctx.lpApplicationName=%p\n", actctx.lpApplicationName);
+    ok(actctx.hModule == NULL, "actctx.hModule=%p\n", actctx.hModule);
+
+    DeleteFileA("file.manifest");
+
+    if (handle)
+    {
+        ret = pActivateActCtx(handle, cookie);
+        ok(ret, "ActivateActCtx failed: %u\n", GetLastError());
+    }
+
+    return handle;
+}
+
+static const char actctx_manifest[] =
+"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
+"<assemblyIdentity version=\"1.2.3.4\"  name=\"Wine.Test\" type=\"win32\""
+" publicKeyToken=\"6595b6414666f1df\" />"
+"<file name=\"testlib.dll\">"
+"    <comClass"
+"              clsid=\"{0000033a-0000-0000-c000-000000000046}\""
+"              progid=\"FTMarshal\""
+"    />"
+"    <comClass"
+"              clsid=\"{5201163f-8164-4fd0-a1a2-5d5a3654d3bd}\""
+"              progid=\"WineOOPTest\""
+"    />"
+"    <comClass description=\"Test com class\""
+"              clsid=\"{12345678-1234-1234-1234-56789abcdef0}\""
+"              progid=\"ProgId.ProgId\""
+"              miscStatusIcon=\"recomposeonresize\""
+"    />"
+"    <comClass clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb851}\""
+"              progid=\"CustomFont\""
+"              miscStatusIcon=\"recomposeonresize\""
+"              miscStatusContent=\"insideout\""
+"    />"
+"    <comClass clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb852}\""
+"              progid=\"StdFont\""
+"    />"
+"    <comClass clsid=\"{62222222-1234-1234-1234-56789abcdef0}\" >"
+"        <progid>ProgId.ProgId.1</progid>"
+"    </comClass>"
+"    <comInterfaceProxyStub "
+"        name=\"Iifaceps\""
+"        iid=\"{22222222-1234-1234-1234-56789abcdef0}\""
+"        proxyStubClsid32=\"{66666666-8888-7777-6666-555555555555}\""
+"    />"
+"</file>"
+"    <comInterfaceExternalProxyStub "
+"        name=\"Iifaceps2\""
+"        iid=\"{32222222-1234-1234-1234-56789abcdef0}\""
+"    />"
+"    <comInterfaceExternalProxyStub "
+"        name=\"Iifaceps3\""
+"        iid=\"{42222222-1234-1234-1234-56789abcdef0}\""
+"        proxyStubClsid32=\"{66666666-8888-7777-6666-555555555555}\""
+"    />"
+"    <comInterfaceExternalProxyStub "
+"        name=\"Iifaceps4\""
+"        iid=\"{52222222-1234-1234-1234-56789abcdef0}\""
+"        proxyStubClsid32=\"{00000000-0000-0000-0000-000000000000}\""
+"    />"
+"    <clrClass "
+"        clsid=\"{72222222-1234-1234-1234-56789abcdef0}\""
+"        name=\"clrclass\""
+"    >"
+"        <progid>clrprogid.1</progid>"
+"    </clrClass>"
+"</assembly>";
+
+DEFINE_GUID(CLSID_Testclass, 0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0);
+
 static void test_ProgIDFromCLSID(void)
 {
+    ULONG_PTR cookie = 0;
     LPWSTR progid;
-    HRESULT hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
+    HANDLE handle;
+    HRESULT hr;
+
+    hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
     ok(hr == S_OK, "ProgIDFromCLSID failed with error 0x%08x\n", hr);
     if (hr == S_OK)
     {
@@ -162,10 +314,39 @@ static void test_ProgIDFromCLSID(void)
 
     hr = ProgIDFromCLSID(&CLSID_StdFont, NULL);
     ok(hr == E_INVALIDARG, "ProgIDFromCLSID should return E_INVALIDARG instead of 0x%08x\n", hr);
+
+    if ((handle = activate_context(actctx_manifest, &cookie)))
+    {
+        static const WCHAR customfontW[] = {'C','u','s','t','o','m','F','o','n','t',0};
+
+        hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(!lstrcmpiW(progid, progidW), "got %s\n", wine_dbgstr_w(progid));
+        CoTaskMemFree(progid);
+
+        /* try something registered and redirected */
+        progid = NULL;
+        hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(!lstrcmpiW(progid, customfontW), "got wrong progid %s\n", wine_dbgstr_w(progid));
+        CoTaskMemFree(progid);
+
+        /* classes without default progid, progid list is not used */
+        hr = ProgIDFromCLSID(&IID_Testiface5, &progid);
+        ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
+
+        hr = ProgIDFromCLSID(&IID_Testiface6, &progid);
+        ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
+
+        pDeactivateActCtx(0, cookie);
+        pReleaseActCtx(handle);
+    }
 }
 
 static void test_CLSIDFromProgID(void)
 {
+    ULONG_PTR cookie = 0;
+    HANDLE handle;
     CLSID clsid;
     HRESULT hr = CLSIDFromProgID(stdfont, &clsid);
     ok(hr == S_OK, "CLSIDFromProgID failed with error 0x%08x\n", hr);
@@ -187,18 +368,183 @@ static void test_CLSIDFromProgID(void)
     hr = CLSIDFromProgID(wszNonExistent, &clsid);
     ok(hr == CO_E_CLASSSTRING, "CLSIDFromProgID on nonexistent ProgID should have returned CO_E_CLASSSTRING instead of 0x%08x\n", hr);
     ok(IsEqualCLSID(&clsid, &CLSID_NULL), "CLSIDFromProgID should have set clsid to all-zeros on failure\n");
+
+    /* fails without proper context */
+    memset(&clsid, 0xcc, sizeof(clsid));
+    hr = CLSIDFromProgID(progidW, &clsid);
+    ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
+    ok(IsEqualCLSID(&clsid, &CLSID_NULL), "wrong clsid\n");
+
+    if ((handle = activate_context(actctx_manifest, &cookie)))
+    {
+        GUID clsid1;
+
+        memset(&clsid, 0xcc, sizeof(clsid));
+        hr = CLSIDFromProgID(wszNonExistent, &clsid);
+        ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
+        ok(IsEqualCLSID(&clsid, &CLSID_NULL), "should have zero CLSID on failure\n");
+
+        /* CLSIDFromString() doesn't check activation context */
+        hr = CLSIDFromString(progidW, &clsid);
+        ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
+
+        clsid = CLSID_NULL;
+        hr = CLSIDFromProgID(progidW, &clsid);
+        /* it returns generated CLSID here */
+        ok(!IsEqualCLSID(&clsid, &CLSID_non_existent) && !IsEqualCLSID(&clsid, &CLSID_NULL),
+                 "got wrong clsid %s\n", wine_dbgstr_guid(&clsid));
+
+        /* duplicate progid present in context - returns generated guid here too */
+        clsid = CLSID_NULL;
+        hr = CLSIDFromProgID(stdfont, &clsid);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        clsid1 = CLSID_StdFont;
+        /* that's where it differs from StdFont */
+        clsid1.Data4[7] = 0x52;
+        ok(!IsEqualCLSID(&clsid, &CLSID_StdFont) && !IsEqualCLSID(&clsid, &CLSID_NULL) && !IsEqualCLSID(&clsid, &clsid1),
+            "got %s\n", wine_dbgstr_guid(&clsid));
+
+        pDeactivateActCtx(0, cookie);
+        pReleaseActCtx(handle);
+    }
 }
 
 static void test_CLSIDFromString(void)
 {
     CLSID clsid;
+    WCHAR wszCLSID_Broken[50];
+    UINT i;
+
     HRESULT hr = CLSIDFromString(wszCLSID_StdFont, &clsid);
     ok_ole_success(hr, "CLSIDFromString");
     ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
 
+    memset(&clsid, 0xab, sizeof(clsid));
     hr = CLSIDFromString(NULL, &clsid);
-    ok_ole_success(hr, "CLSIDFromString");
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
+
+    /* string is longer, but starts with a valid CLSID */
+    memset(&clsid, 0, sizeof(clsid));
+    hr = CLSIDFromString(cf_brokenW, &clsid);
+    ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
+    ok(IsEqualCLSID(&clsid, &IID_IClassFactory), "got %s\n", wine_dbgstr_guid(&clsid));
+
+    lstrcpyW(wszCLSID_Broken, wszCLSID_StdFont);
+    for(i = lstrlenW(wszCLSID_StdFont); i < 49; i++)
+        wszCLSID_Broken[i] = 'A';
+    wszCLSID_Broken[i] = '\0';
+
+    memset(&clsid, 0, sizeof(CLSID));
+    hr = CLSIDFromString(wszCLSID_Broken, &clsid);
+    ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
+    ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
+
+    wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = 'A';
+    memset(&clsid, 0, sizeof(CLSID));
+    hr = CLSIDFromString(wszCLSID_Broken, &clsid);
+    ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
+    ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
+
+    wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)] = '\0';
+    memset(&clsid, 0, sizeof(CLSID));
+    hr = CLSIDFromString(wszCLSID_Broken, &clsid);
+    ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
+    ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
+
+    wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = '\0';
+    memset(&clsid, 0, sizeof(CLSID));
+    hr = CLSIDFromString(wszCLSID_Broken, &clsid);
+    ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
+    ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
+
+    memset(&clsid, 0xcc, sizeof(CLSID));
+    hr = CLSIDFromString(wszCLSID_Broken+1, &clsid);
+    ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
     ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
+
+    wszCLSID_Broken[9] = '*';
+    memset(&clsid, 0xcc, sizeof(CLSID));
+    hr = CLSIDFromString(wszCLSID_Broken, &clsid);
+    ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
+    ok(clsid.Data1 == CLSID_StdFont.Data1, "Got %08x\n", clsid.Data1);
+    ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
+
+    wszCLSID_Broken[3] = '*';
+    memset(&clsid, 0xcc, sizeof(CLSID));
+    hr = CLSIDFromString(wszCLSID_Broken, &clsid);
+    ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
+    ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
+    ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
+
+    wszCLSID_Broken[3] = '\0';
+    memset(&clsid, 0xcc, sizeof(CLSID));
+    hr = CLSIDFromString(wszCLSID_Broken, &clsid);
+    ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
+    ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
+    ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
+}
+
+static void test_IIDFromString(void)
+{
+    static const WCHAR cfW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
+                                    'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
+    static const WCHAR brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
+                                        'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
+    static const WCHAR broken2W[] = {'{','0','0','0','0','0','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
+                                        'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
+    static const WCHAR broken3W[] = {'b','r','o','k','e','n','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
+                                        'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
+    HRESULT hr;
+    IID iid;
+
+    hr = IIDFromString(wszCLSID_StdFont, &iid);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(IsEqualIID(&iid, &CLSID_StdFont), "got iid %s\n", wine_dbgstr_guid(&iid));
+
+    memset(&iid, 0xab, sizeof(iid));
+    hr = IIDFromString(NULL, &iid);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(IsEqualIID(&iid, &CLSID_NULL), "got iid %s\n", wine_dbgstr_guid(&iid));
+
+    hr = IIDFromString(cfW, &iid);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(IsEqualIID(&iid, &IID_IClassFactory), "got iid %s\n", wine_dbgstr_guid(&iid));
+
+    /* string starts with a valid IID but is longer */
+    memset(&iid, 0xab, sizeof(iid));
+    hr = IIDFromString(cf_brokenW, &iid);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+    ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
+
+    /* invalid IID in a valid format */
+    memset(&iid, 0xab, sizeof(iid));
+    hr = IIDFromString(brokenW, &iid);
+    ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
+    ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1);
+
+    memset(&iid, 0xab, sizeof(iid));
+    hr = IIDFromString(broken2W, &iid);
+    ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
+    ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1);
+
+    /* format is broken, but string length is okay */
+    memset(&iid, 0xab, sizeof(iid));
+    hr = IIDFromString(broken3W, &iid);
+    ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
+    ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
+
+    /* invalid string */
+    memset(&iid, 0xab, sizeof(iid));
+    hr = IIDFromString(wszNonExistent, &iid);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+    ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
+
+    /* valid ProgID */
+    memset(&iid, 0xab, sizeof(iid));
+    hr = IIDFromString(stdfont, &iid);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+    ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
 }
 
 static void test_StringFromGUID2(void)
@@ -292,10 +638,10 @@ static void test_CoCreateInstance(void)
     /* show that COM doesn't have to be initialized for multi-threaded apartments if another
        thread has already done so */
 
-    info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
+    info.wait = CreateEventA(NULL, TRUE, FALSE, NULL);
     ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
 
-    info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
+    info.stop = CreateEventA(NULL, TRUE, FALSE, NULL);
     ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
 
     thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
@@ -323,11 +669,14 @@ static void test_CoCreateInstance(void)
 static void test_CoGetClassObject(void)
 {
     HRESULT hr;
-    HANDLE thread;
+    HANDLE thread, handle;
     DWORD tid, exitcode;
+    ULONG_PTR cookie;
     IUnknown *pUnk;
     struct info info;
     REFCLSID rclsid = &CLSID_InternetZoneManager;
+    HKEY hkey;
+    LONG res;
 
     hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
     ok(hr == CO_E_NOTINITIALIZED, "CoGetClassObject should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
@@ -341,10 +690,10 @@ static void test_CoGetClassObject(void)
     /* show that COM doesn't have to be initialized for multi-threaded apartments if another
        thread has already done so */
 
-    info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
+    info.wait = CreateEventA(NULL, TRUE, FALSE, NULL);
     ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
 
-    info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
+    info.stop = CreateEventA(NULL, TRUE, FALSE, NULL);
     ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
 
     thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
@@ -372,25 +721,72 @@ static void test_CoGetClassObject(void)
     CloseHandle(thread);
     CloseHandle(info.wait);
     CloseHandle(info.stop);
+
+    if (!pRegOverridePredefKey)
+    {
+        win_skip("RegOverridePredefKey not available\n");
+        return;
+    }
+
+    pCoInitializeEx(NULL, COINIT_MULTITHREADED);
+
+    hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
+    if (hr == S_OK)
+    {
+        IUnknown_Release(pUnk);
+
+        res = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
+                             KEY_ALL_ACCESS, NULL, &hkey, NULL);
+        ok(!res, "RegCreateKeyEx returned %d\n", res);
+
+        res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
+        ok(!res, "RegOverridePredefKey returned %d\n", res);
+
+        hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
+        ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
+
+        res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
+        ok(!res, "RegOverridePredefKey returned %d\n", res);
+
+        if (hr == S_OK) IUnknown_Release(pUnk);
+        RegCloseKey(hkey);
+    }
+
+    hr = CoGetClassObject(&CLSID_InProcFreeMarshaler, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    IUnknown_Release(pUnk);
+
+    /* context redefines FreeMarshaler CLSID */
+    if ((handle = activate_context(actctx_manifest, &cookie)))
+    {
+        hr = CoGetClassObject(&CLSID_InProcFreeMarshaler, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        IUnknown_Release(pUnk);
+
+        pDeactivateActCtx(0, cookie);
+        pReleaseActCtx(handle);
+    }
+
+    CoUninitialize();
 }
 
 static ATOM register_dummy_class(void)
 {
-    WNDCLASS wc =
+    WNDCLASSA wc =
     {
         0,
-        DefWindowProc,
+        DefWindowProcA,
         0,
         0,
-        GetModuleHandle(NULL),
+        GetModuleHandleA(NULL),
         NULL,
-        LoadCursor(NULL, IDC_ARROW),
+        LoadCursorA(NULL, (LPSTR)IDC_ARROW),
         (HBRUSH)(COLOR_BTNFACE+1),
         NULL,
-        TEXT("WineOleTestClass"),
+        "WineOleTestClass",
     };
 
-    return RegisterClass(&wc);
+    return RegisterClassA(&wc);
 }
 
 static void test_ole_menu(void)
@@ -398,7 +794,7 @@ static void test_ole_menu(void)
        HWND hwndFrame;
        HRESULT hr;
 
-       hwndFrame = CreateWindow(MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
+       hwndFrame = CreateWindowA((LPCSTR)MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
        hr = OleSetMenuDescriptor(NULL, hwndFrame, NULL, NULL, NULL);
        todo_wine ok_ole_success(hr, "OleSetMenuDescriptor");
 
@@ -515,7 +911,7 @@ static void test_CoRegisterMessageFilter(void)
 }
 
 static HRESULT WINAPI Test_IUnknown_QueryInterface(
-    LPUNKNOWN iface,
+    IUnknown *iface,
     REFIID riid,
     LPVOID *ppvObj)
 {
@@ -533,12 +929,12 @@ static HRESULT WINAPI Test_IUnknown_QueryInterface(
     return E_NOINTERFACE;
 }
 
-static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
+static ULONG WINAPI Test_IUnknown_AddRef(IUnknown *iface)
 {
     return 2; /* non-heap-based object */
 }
 
-static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
+static ULONG WINAPI Test_IUnknown_Release(IUnknown *iface)
 {
     return 1; /* non-heap-based object */
 }
@@ -625,7 +1021,7 @@ static void test_CoRegisterPSClsid(void)
     CLSID clsid;
 
     hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
-    ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returened CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
+    ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
 
     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
 
@@ -658,8 +1054,14 @@ static void test_CoRegisterPSClsid(void)
 
 static void test_CoGetPSClsid(void)
 {
+    ULONG_PTR cookie;
+    HANDLE handle;
     HRESULT hr;
     CLSID clsid;
+    HKEY hkey;
+    LONG res;
+    const BOOL is_win64 = (sizeof(void*) != sizeof(int));
+    BOOL is_wow64 = FALSE;
 
     hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
     ok(hr == CO_E_NOTINITIALIZED,
@@ -681,6 +1083,105 @@ static void test_CoGetPSClsid(void)
        "CoGetPSClsid for null clsid returned 0x%08x instead of E_INVALIDARG\n",
        hr);
 
+    if (!pRegOverridePredefKey)
+    {
+        win_skip("RegOverridePredefKey not available\n");
+        CoUninitialize();
+        return;
+    }
+    hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
+    ok_ole_success(hr, "CoGetPSClsid");
+
+    res = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
+                          KEY_ALL_ACCESS, NULL, &hkey, NULL);
+    ok(!res, "RegCreateKeyEx returned %d\n", res);
+
+    res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
+    ok(!res, "RegOverridePredefKey returned %d\n", res);
+
+    hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
+    ok_ole_success(hr, "CoGetPSClsid");
+
+    res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
+    ok(!res, "RegOverridePredefKey returned %d\n", res);
+
+    RegCloseKey(hkey);
+
+    /* not registered CLSID */
+    hr = CoGetPSClsid(&IID_Testiface, &clsid);
+    ok(hr == REGDB_E_IIDNOTREG, "got 0x%08x\n", hr);
+
+    if ((handle = activate_context(actctx_manifest, &cookie)))
+    {
+        memset(&clsid, 0, sizeof(clsid));
+        hr = CoGetPSClsid(&IID_Testiface, &clsid);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(IsEqualGUID(&clsid, &IID_Testiface), "got clsid %s\n", wine_dbgstr_guid(&clsid));
+
+        memset(&clsid, 0, sizeof(clsid));
+        hr = CoGetPSClsid(&IID_Testiface2, &clsid);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(IsEqualGUID(&clsid, &IID_Testiface2), "got clsid %s\n", wine_dbgstr_guid(&clsid));
+
+        memset(&clsid, 0, sizeof(clsid));
+        hr = CoGetPSClsid(&IID_Testiface3, &clsid);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", wine_dbgstr_guid(&clsid));
+
+        memset(&clsid, 0xaa, sizeof(clsid));
+        hr = CoGetPSClsid(&IID_Testiface4, &clsid);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(IsEqualGUID(&clsid, &GUID_NULL), "got clsid %s\n", wine_dbgstr_guid(&clsid));
+
+        /* register same interface and try to get CLSID back */
+        hr = CoRegisterPSClsid(&IID_Testiface, &IID_Testiface4);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        memset(&clsid, 0, sizeof(clsid));
+        hr = CoGetPSClsid(&IID_Testiface, &clsid);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(IsEqualGUID(&clsid, &IID_Testiface4), "got clsid %s\n", wine_dbgstr_guid(&clsid));
+
+        pDeactivateActCtx(0, cookie);
+        pReleaseActCtx(handle);
+    }
+
+    if (pRegDeleteKeyExA &&
+        (is_win64 ||
+         (pIsWow64Process && pIsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)))
+    {
+        static GUID IID_DeadBeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
+        static const char clsidDeadBeef[] = "{deadbeef-dead-beef-dead-beefdeadbeef}";
+        static const char clsidA[] = "{66666666-8888-7777-6666-555555555555}";
+        HKEY hkey_iface, hkey_psclsid;
+        REGSAM opposite = is_win64 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY;
+
+        hr = CoGetPSClsid(&IID_DeadBeef, &clsid);
+        ok(hr == REGDB_E_IIDNOTREG, "got 0x%08x\n", hr);
+
+        res = RegCreateKeyExA(HKEY_CLASSES_ROOT, "Interface",
+                              0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey_iface, NULL);
+        ok(!res, "RegCreateKeyEx returned %d\n", res);
+        res = RegCreateKeyExA(hkey_iface, clsidDeadBeef,
+                              0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey, NULL);
+        ok(!res, "RegCreateKeyEx returned %d\n", res);
+        res = RegCreateKeyExA(hkey, "ProxyStubClsid32",
+                              0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey_psclsid, NULL);
+        res = RegSetValueExA(hkey_psclsid, NULL, 0, REG_SZ, (const BYTE *)clsidA, strlen(clsidA)+1);
+        ok(!res, "RegSetValueEx returned %d\n", res);
+        RegCloseKey(hkey_psclsid);
+
+        hr = CoGetPSClsid(&IID_DeadBeef, &clsid);
+        ok_ole_success(hr, "CoGetPSClsid");
+        ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", wine_dbgstr_guid(&clsid));
+
+        res = pRegDeleteKeyExA(hkey, "ProxyStubClsid32", opposite, 0);
+        ok(!res, "RegDeleteKeyEx returned %d\n", res);
+        RegCloseKey(hkey);
+        res = pRegDeleteKeyExA(hkey_iface, clsidDeadBeef, opposite, 0);
+        ok(!res, "RegDeleteKeyEx returned %d\n", res);
+        RegCloseKey(hkey_iface);
+    }
+
     CoUninitialize();
 }
 
@@ -799,6 +1300,8 @@ static void test_CoMarshalInterThreadInterfaceInStream(void)
 
 static void test_CoRegisterClassObject(void)
 {
+    ULONG_PTR ctxcookie;
+    HANDLE handle;
     DWORD cookie;
     HRESULT hr;
     IClassFactory *pcf;
@@ -872,7 +1375,34 @@ static void test_CoRegisterClassObject(void)
 
     /* crashes with at least win9x DCOM! */
     if (0)
-        hr = CoRevokeClassObject(cookie);
+        CoRevokeClassObject(cookie);
+
+    /* test that object is accessible */
+    hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, CLSCTX_INPROC_SERVER,
+        REGCLS_MULTIPLEUSE, &cookie);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    IClassFactory_Release(pcf);
+
+    /* context now contains CLSID_WineOOPTest, test if registered one could still be used */
+    if ((handle = activate_context(actctx_manifest, &ctxcookie)))
+    {
+        hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
+todo_wine
+        ok(hr == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND), "got 0x%08x\n", hr);
+
+        pDeactivateActCtx(0, ctxcookie);
+        pReleaseActCtx(handle);
+    }
+
+    hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    IClassFactory_Release(pcf);
+
+    hr = CoRevokeClassObject(cookie);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
 
     CoUninitialize();
 }
@@ -1055,7 +1585,7 @@ static DWORD CALLBACK free_libraries_thread(LPVOID p)
 
 static inline BOOL is_module_loaded(const char *module)
 {
-    return GetModuleHandle(module) ? TRUE : FALSE;
+    return GetModuleHandleA(module) != 0;
 }
 
 static void test_CoFreeUnusedLibraries(void)
@@ -1127,10 +1657,10 @@ static void test_CoGetObjectContext(void)
     /* show that COM doesn't have to be initialized for multi-threaded apartments if another
        thread has already done so */
 
-    info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
+    info.wait = CreateEventA(NULL, TRUE, FALSE, NULL);
     ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
 
-    info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
+    info.stop = CreateEventA(NULL, TRUE, FALSE, NULL);
     ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
 
     thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
@@ -1216,10 +1746,15 @@ static void test_CoGetObjectContext(void)
 }
 
 typedef struct {
-    const IUnknownVtbl *lpVtbl;
+    IUnknown IUnknown_iface;
     LONG refs;
 } Test_CallContext;
 
+static inline Test_CallContext *impl_from_IUnknown(IUnknown *iface)
+{
+    return CONTAINING_RECORD(iface, Test_CallContext, IUnknown_iface);
+}
+
 static HRESULT WINAPI Test_CallContext_QueryInterface(
     IUnknown *iface,
     REFIID riid,
@@ -1240,13 +1775,13 @@ static HRESULT WINAPI Test_CallContext_QueryInterface(
 
 static ULONG WINAPI Test_CallContext_AddRef(IUnknown *iface)
 {
-    Test_CallContext *This = (Test_CallContext*)iface;
+    Test_CallContext *This = impl_from_IUnknown(iface);
     return InterlockedIncrement(&This->refs);
 }
 
 static ULONG WINAPI Test_CallContext_Release(IUnknown *iface)
 {
-    Test_CallContext *This = (Test_CallContext*)iface;
+    Test_CallContext *This = impl_from_IUnknown(iface);
     ULONG refs = InterlockedDecrement(&This->refs);
     if (!refs)
         HeapFree(GetProcessHeap(), 0, This);
@@ -1265,7 +1800,7 @@ static void test_CoGetCallContext(void)
     HRESULT hr;
     ULONG refs;
     IUnknown *pUnk;
-    IUnknown *test_object;
+    Test_CallContext *test_object;
 
     if (!pCoSwitchCallContext)
     {
@@ -1276,41 +1811,43 @@ static void test_CoGetCallContext(void)
     CoInitialize(NULL);
 
     test_object = HeapAlloc(GetProcessHeap(), 0, sizeof(Test_CallContext));
-    ((Test_CallContext*)test_object)->lpVtbl = &TestCallContext_Vtbl;
-    ((Test_CallContext*)test_object)->refs = 1;
+    test_object->IUnknown_iface.lpVtbl = &TestCallContext_Vtbl;
+    test_object->refs = 1;
 
     hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
     ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
 
     pUnk = (IUnknown*)0xdeadbeef;
-    hr = pCoSwitchCallContext(test_object, &pUnk);
+    hr = pCoSwitchCallContext(&test_object->IUnknown_iface, &pUnk);
     ok_ole_success(hr, "CoSwitchCallContext");
     ok(pUnk == NULL, "expected NULL, got %p\n", pUnk);
-    refs = IUnknown_AddRef(test_object);
+    refs = IUnknown_AddRef(&test_object->IUnknown_iface);
     ok(refs == 2, "Expected refcount 2, got %d\n", refs);
-    IUnknown_Release(test_object);
+    IUnknown_Release(&test_object->IUnknown_iface);
 
     pUnk = (IUnknown*)0xdeadbeef;
     hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
     ok_ole_success(hr, "CoGetCallContext");
-    ok(pUnk == test_object, "expected %p, got %p\n", test_object, pUnk);
-    refs = IUnknown_AddRef(test_object);
+    ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
+       &test_object->IUnknown_iface, pUnk);
+    refs = IUnknown_AddRef(&test_object->IUnknown_iface);
     ok(refs == 3, "Expected refcount 3, got %d\n", refs);
-    IUnknown_Release(test_object);
+    IUnknown_Release(&test_object->IUnknown_iface);
     IUnknown_Release(pUnk);
 
     pUnk = (IUnknown*)0xdeadbeef;
     hr = pCoSwitchCallContext(NULL, &pUnk);
     ok_ole_success(hr, "CoSwitchCallContext");
-    ok(pUnk == test_object, "expected %p, got %p\n", test_object, pUnk);
-    refs = IUnknown_AddRef(test_object);
+    ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
+       &test_object->IUnknown_iface, pUnk);
+    refs = IUnknown_AddRef(&test_object->IUnknown_iface);
     ok(refs == 2, "Expected refcount 2, got %d\n", refs);
-    IUnknown_Release(test_object);
+    IUnknown_Release(&test_object->IUnknown_iface);
 
     hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
     ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
 
-    IUnknown_Release(test_object);
+    IUnknown_Release(&test_object->IUnknown_iface);
 
     CoUninitialize();
 }
@@ -1339,10 +1876,10 @@ static void test_CoGetContextToken(void)
     /* show that COM doesn't have to be initialized for multi-threaded apartments if another
        thread has already done so */
 
-    info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
+    info.wait = CreateEventA(NULL, TRUE, FALSE, NULL);
     ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
 
-    info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
+    info.stop = CreateEventA(NULL, TRUE, FALSE, NULL);
     ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
 
     thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
@@ -1410,11 +1947,15 @@ static void test_CoGetContextToken(void)
     CoUninitialize();
 }
 
-static void test_CoGetTreatAsClass(void)
+static void test_TreatAsClass(void)
 {
     HRESULT hr;
     CLSID out;
     static GUID deadbeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
+    static const char deadbeefA[] = "{DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF}";
+    IInternetProtocol *pIP = NULL;
+    HKEY clsidkey, deadbeefkey;
+    LONG lr;
 
     if (!pCoGetTreatAsClass)
     {
@@ -1424,6 +1965,63 @@ static void test_CoGetTreatAsClass(void)
     hr = pCoGetTreatAsClass(&deadbeef,&out);
     ok (hr == S_FALSE, "expected S_FALSE got %x\n",hr);
     ok (IsEqualGUID(&out,&deadbeef), "expected to get same clsid back\n");
+
+    lr = RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_READ, &clsidkey);
+    ok(lr == ERROR_SUCCESS, "Couldn't open CLSID key\n");
+
+    lr = RegCreateKeyExA(clsidkey, deadbeefA, 0, NULL, 0, KEY_WRITE, NULL, &deadbeefkey, NULL);
+    ok(lr == ERROR_SUCCESS, "Couldn't create class key\n");
+
+    hr = pCoTreatAsClass(&deadbeef, &deadbeef);
+    ok(hr == REGDB_E_WRITEREGDB, "CoTreatAsClass gave wrong error: %08x\n", hr);
+
+    hr = pCoTreatAsClass(&deadbeef, &CLSID_FileProtocol);
+    if(hr == REGDB_E_WRITEREGDB){
+        win_skip("Insufficient privileges to use CoTreatAsClass\n");
+        goto exit;
+    }
+    ok(hr == S_OK, "CoTreatAsClass failed: %08x\n", hr);
+
+    hr = pCoGetTreatAsClass(&deadbeef, &out);
+    ok(hr == S_OK, "CoGetTreatAsClass failed: %08x\n",hr);
+    ok(IsEqualGUID(&out, &CLSID_FileProtocol), "expected to get substituted clsid\n");
+
+    OleInitialize(NULL);
+
+    hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pIP);
+    if(hr == REGDB_E_CLASSNOTREG)
+    {
+        win_skip("IE not installed so can't test CoCreateInstance\n");
+        goto exit;
+    }
+
+    ok(hr == S_OK, "CoCreateInstance failed: %08x\n", hr);
+    if(pIP){
+        IInternetProtocol_Release(pIP);
+        pIP = NULL;
+    }
+
+    hr = pCoTreatAsClass(&deadbeef, &CLSID_NULL);
+    ok(hr == S_OK, "CoTreatAsClass failed: %08x\n", hr);
+
+    hr = pCoGetTreatAsClass(&deadbeef, &out);
+    ok(hr == S_FALSE, "expected S_FALSE got %08x\n", hr);
+    ok(IsEqualGUID(&out, &deadbeef), "expected to get same clsid back\n");
+
+    /* bizarrely, native's CoTreatAsClass takes some time to take effect in CoCreateInstance */
+    Sleep(200);
+
+    hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pIP);
+    ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance gave wrong error: %08x\n", hr);
+
+    if(pIP)
+        IInternetProtocol_Release(pIP);
+
+exit:
+    OleUninitialize();
+    RegCloseKey(deadbeefkey);
+    RegDeleteKeyA(clsidkey, deadbeefA);
+    RegCloseKey(clsidkey);
 }
 
 static void test_CoInitializeEx(void)
@@ -1447,22 +2045,97 @@ static void test_CoInitializeEx(void)
     OleUninitialize();
 }
 
-START_TEST(compobj)
+static void test_OleRegGetMiscStatus(void)
 {
-    HMODULE hOle32 = GetModuleHandle("ole32");
+    ULONG_PTR cookie;
+    HANDLE handle;
+    DWORD status;
+    HRESULT hr;
+
+    hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, NULL);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+
+    status = 0xdeadbeef;
+    hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status);
+    ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
+    ok(status == 0, "got 0x%08x\n", status);
+
+    status = -1;
+    hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(status == 0, "got 0x%08x\n", status);
+
+    if ((handle = activate_context(actctx_manifest, &cookie)))
+    {
+        status = 0;
+        hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status);
+
+        /* context data takes precedence over registration info */
+        status = 0;
+        hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status);
+
+        /* there's no such attribute in context */
+        status = -1;
+        hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_DOCPRINT, &status);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(status == 0, "got 0x%08x\n", status);
+
+        pDeactivateActCtx(0, cookie);
+        pReleaseActCtx(handle);
+    }
+}
+
+static void test_CoCreateGuid(void)
+{
+    HRESULT hr;
+
+    hr = CoCreateGuid(NULL);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+}
+
+static void init_funcs(void)
+{
+    HMODULE hOle32 = GetModuleHandleA("ole32");
+    HMODULE hAdvapi32 = GetModuleHandleA("advapi32");
+    HMODULE hkernel32 = GetModuleHandleA("kernel32");
+
     pCoGetObjectContext = (void*)GetProcAddress(hOle32, "CoGetObjectContext");
     pCoSwitchCallContext = (void*)GetProcAddress(hOle32, "CoSwitchCallContext");
     pCoGetTreatAsClass = (void*)GetProcAddress(hOle32,"CoGetTreatAsClass");
+    pCoTreatAsClass = (void*)GetProcAddress(hOle32,"CoTreatAsClass");
     pCoGetContextToken = (void*)GetProcAddress(hOle32, "CoGetContextToken");
-    if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx")))
+    pRegDeleteKeyExA = (void*)GetProcAddress(hAdvapi32, "RegDeleteKeyExA");
+    pRegOverridePredefKey = (void*)GetProcAddress(hAdvapi32, "RegOverridePredefKey");
+    pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx");
+
+    pActivateActCtx = (void*)GetProcAddress(hkernel32, "ActivateActCtx");
+    pCreateActCtxW = (void*)GetProcAddress(hkernel32, "CreateActCtxW");
+    pDeactivateActCtx = (void*)GetProcAddress(hkernel32, "DeactivateActCtx");
+    pIsWow64Process = (void*)GetProcAddress(hkernel32, "IsWow64Process");
+    pReleaseActCtx = (void*)GetProcAddress(hkernel32, "ReleaseActCtx");
+}
+
+START_TEST(compobj)
+{
+    init_funcs();
+
+    if (!pCoInitializeEx)
     {
         trace("You need DCOM95 installed to run this test\n");
         return;
     }
 
+    if (!pCreateActCtxW)
+        win_skip("Activation contexts are not supported, some tests will be skipped.\n");
+
     test_ProgIDFromCLSID();
     test_CLSIDFromProgID();
     test_CLSIDFromString();
+    test_IIDFromString();
     test_StringFromGUID2();
     test_CoCreateInstance();
     test_ole_menu();
@@ -1480,6 +2153,8 @@ START_TEST(compobj)
     test_CoGetObjectContext();
     test_CoGetCallContext();
     test_CoGetContextToken();
-    test_CoGetTreatAsClass();
+    test_TreatAsClass();
     test_CoInitializeEx();
+    test_OleRegGetMiscStatus();
+    test_CoCreateGuid();
 }