#define CONST_VTABLE
#include <stdarg.h>
+#include <stdio.h>
#include <windef.h>
#include <winbase.h>
+#include <winnls.h>
#include <winreg.h>
#define USE_COM_CONTEXT_DEF
-//#include "initguid.h"
+#include <initguid.h>
//#include "objbase.h"
//#include "shlguid.h"
#include <ole2.h>
-//#include "urlmon.h" /* for CLSID_FileProtocol */
+#include <urlmon.h> /* for CLSID_FileProtocol */
#include <ctxtcall.h>
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)
#define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
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;
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)
{
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);
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)
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';
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)
{
WCHAR str[50];
/* 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);
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;
/* 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);
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);
{
IUnknown_Release(pUnk);
- res = RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, KEY_ALL_ACCESS, &hkey);
- ok(!res, "RegOpenKeyExA returned %d\n", res);
+ 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);
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)
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");
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,
hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
ok_ole_success(hr, "CoGetPSClsid");
- res = RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, KEY_ALL_ACCESS, &hkey);
- ok(!res, "RegOpenKeyExA returned %d\n", res);
+ 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);
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();
}
static void test_CoRegisterClassObject(void)
{
+ ULONG_PTR ctxcookie;
+ HANDLE handle;
DWORD cookie;
HRESULT hr;
IClassFactory *pcf;
if (0)
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();
}
static inline BOOL is_module_loaded(const char *module)
{
- return GetModuleHandle(module) != 0;
+ return GetModuleHandleA(module) != 0;
}
static void test_CoFreeUnusedLibraries(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);
/* 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);
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)
{
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)
OleUninitialize();
}
-START_TEST(compobj)
+static void test_OleRegGetMiscStatus(void)
{
- HMODULE hOle32 = GetModuleHandle("ole32");
- HMODULE hAdvapi32 = GetModuleHandle("advapi32");
+ 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");
+ pRegDeleteKeyExA = (void*)GetProcAddress(hAdvapi32, "RegDeleteKeyExA");
pRegOverridePredefKey = (void*)GetProcAddress(hAdvapi32, "RegOverridePredefKey");
- if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx")))
+ 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();
test_CoGetObjectContext();
test_CoGetCallContext();
test_CoGetContextToken();
- test_CoGetTreatAsClass();
+ test_TreatAsClass();
test_CoInitializeEx();
+ test_OleRegGetMiscStatus();
+ test_CoCreateGuid();
}