1100 lines
39 KiB
C
1100 lines
39 KiB
C
/*
|
|
* Copyright 2012 Jacek Caban for CodeWeavers
|
|
*
|
|
* 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 <stdarg.h>
|
|
#include <stdio.h>
|
|
|
|
#define COBJMACROS
|
|
#define CONST_VTABLE
|
|
|
|
#include <windef.h>
|
|
#include <winbase.h>
|
|
#include <winuser.h>
|
|
#include <exdisp.h>
|
|
|
|
#include <atlbase.h>
|
|
#include <mshtml.h>
|
|
|
|
#include <wine/test.h>
|
|
|
|
static const GUID CLSID_Test =
|
|
{0x178fc163,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
|
|
#define CLSID_TEST_STR "178fc163-0000-0000-0000-000000000046"
|
|
|
|
static const GUID CATID_CatTest1 =
|
|
{0x178fc163,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x46}};
|
|
#define CATID_CATTEST1_STR "178fc163-0000-0000-0000-000000000146"
|
|
|
|
static const GUID CATID_CatTest2 =
|
|
{0x178fc163,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x46}};
|
|
#define CATID_CATTEST2_STR "178fc163-0000-0000-0000-000000000246"
|
|
|
|
static const WCHAR emptyW[] = {'\0'};
|
|
static const WCHAR randomW[] = {'r','a','n','d','o','m','\0'};
|
|
static const WCHAR progid1W[] = {'S','h','e','l','l','.','E','x','p','l','o','r','e','r','.','2','\0'};
|
|
static const WCHAR clsid1W[] = {'{','8','8','5','6','f','9','6','1','-','3','4','0','a','-',
|
|
'1','1','d','0','-','a','9','6','b','-',
|
|
'0','0','c','0','4','f','d','7','0','5','a','2','}','\0'};
|
|
static const WCHAR url1W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q',
|
|
'.','o','r','g','/','t','e','s','t','s','/','w','i','n','e','h','q','_',
|
|
's','n','a','p','s','h','o','t','/','\0'};
|
|
static const WCHAR mshtml1W[] = {'m','s','h','t','m','l',':','<','h','t','m','l','>','<','b','o','d','y','>',
|
|
't','e','s','t','<','/','b','o','d','y','>','<','/','h','t','m','l','>','\0'};
|
|
static const WCHAR mshtml2W[] = {'M','S','H','T','M','L',':','<','h','t','m','l','>','<','b','o','d','y','>',
|
|
't','e','s','t','<','/','b','o','d','y','>','<','/','h','t','m','l','>','\0'};
|
|
static const WCHAR mshtml3W[] = {'<','h','t','m','l','>','<','b','o','d','y','>', 't','e','s','t',
|
|
'<','/','b','o','d','y','>','<','/','h','t','m','l','>','\0'};
|
|
static const WCHAR fileW[] = {'f','i','l','e',':','/','/','/','\0'};
|
|
static const WCHAR html_fileW[] = {'t','e','s','t','.','h','t','m','l','\0'};
|
|
static const char html_str[] = "<html><body>test</body><html>";
|
|
|
|
static BOOL is_token_admin(HANDLE token)
|
|
{
|
|
PSID administrators = NULL;
|
|
SID_IDENTIFIER_AUTHORITY nt_authority = { SECURITY_NT_AUTHORITY };
|
|
DWORD groups_size;
|
|
PTOKEN_GROUPS groups;
|
|
DWORD group_index;
|
|
|
|
/* Create a well-known SID for the Administrators group. */
|
|
if (! AllocateAndInitializeSid(&nt_authority, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
|
|
&administrators))
|
|
return FALSE;
|
|
|
|
/* Get the group info from the token */
|
|
groups_size = 0;
|
|
GetTokenInformation(token, TokenGroups, NULL, 0, &groups_size);
|
|
groups = HeapAlloc(GetProcessHeap(), 0, groups_size);
|
|
if (groups == NULL)
|
|
{
|
|
FreeSid(administrators);
|
|
return FALSE;
|
|
}
|
|
if (! GetTokenInformation(token, TokenGroups, groups, groups_size, &groups_size))
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, groups);
|
|
FreeSid(administrators);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Now check if the token groups include the Administrators group */
|
|
for (group_index = 0; group_index < groups->GroupCount; group_index++)
|
|
{
|
|
if (EqualSid(groups->Groups[group_index].Sid, administrators))
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, groups);
|
|
FreeSid(administrators);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
/* If we end up here we didn't find the Administrators group */
|
|
HeapFree(GetProcessHeap(), 0, groups);
|
|
FreeSid(administrators);
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL is_process_limited(void)
|
|
{
|
|
static BOOL (WINAPI *pOpenProcessToken)(HANDLE, DWORD, PHANDLE) = NULL;
|
|
HANDLE token;
|
|
BOOL result=FALSE;
|
|
|
|
if (!pOpenProcessToken)
|
|
{
|
|
HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
|
|
pOpenProcessToken = (void*)GetProcAddress(hadvapi32, "OpenProcessToken");
|
|
if (!pOpenProcessToken)
|
|
return FALSE;
|
|
}
|
|
|
|
if (pOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
|
|
{
|
|
BOOL ret;
|
|
TOKEN_ELEVATION_TYPE type = TokenElevationTypeDefault;
|
|
DWORD size;
|
|
|
|
ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size);
|
|
if (ret)
|
|
{
|
|
if (type == TokenElevationTypeDefault)
|
|
/* UAC is disabled, check for administrators group */
|
|
result = !is_token_admin(token);
|
|
else if (type == TokenElevationTypeFull)
|
|
result = FALSE;
|
|
else if (type == TokenElevationTypeLimited)
|
|
result = TRUE;
|
|
}
|
|
CloseHandle(token);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static void test_winmodule(void)
|
|
{
|
|
_AtlCreateWndData create_data[3];
|
|
_ATL_WIN_MODULE winmod;
|
|
void *p;
|
|
HRESULT hres;
|
|
|
|
winmod.cbSize = 0xdeadbeef;
|
|
hres = AtlWinModuleInit(&winmod);
|
|
ok(hres == E_INVALIDARG, "AtlWinModuleInit failed: %08x\n", hres);
|
|
|
|
winmod.cbSize = sizeof(winmod);
|
|
winmod.m_pCreateWndList = (void*)0xdeadbeef;
|
|
winmod.m_csWindowCreate.LockCount = 0xdeadbeef;
|
|
winmod.m_rgWindowClassAtoms.m_aT = (void*)0xdeadbeef;
|
|
winmod.m_rgWindowClassAtoms.m_nSize = 0xdeadbeef;
|
|
winmod.m_rgWindowClassAtoms.m_nAllocSize = 0xdeadbeef;
|
|
hres = AtlWinModuleInit(&winmod);
|
|
ok(hres == S_OK, "AtlWinModuleInit failed: %08x\n", hres);
|
|
ok(!winmod.m_pCreateWndList, "winmod.m_pCreateWndList = %p\n", winmod.m_pCreateWndList);
|
|
ok(winmod.m_csWindowCreate.LockCount == -1, "winmod.m_csWindowCreate.LockCount = %d\n",
|
|
winmod.m_csWindowCreate.LockCount);
|
|
ok(winmod.m_rgWindowClassAtoms.m_aT == (void*)0xdeadbeef, "winmod.m_rgWindowClassAtoms.m_aT = %p\n",
|
|
winmod.m_rgWindowClassAtoms.m_aT);
|
|
ok(winmod.m_rgWindowClassAtoms.m_nSize == 0xdeadbeef, "winmod.m_rgWindowClassAtoms.m_nSize = %d\n",
|
|
winmod.m_rgWindowClassAtoms.m_nSize);
|
|
ok(winmod.m_rgWindowClassAtoms.m_nAllocSize == 0xdeadbeef, "winmod.m_rgWindowClassAtoms.m_nAllocSize = %d\n",
|
|
winmod.m_rgWindowClassAtoms.m_nAllocSize);
|
|
|
|
InitializeCriticalSection(&winmod.m_csWindowCreate);
|
|
|
|
AtlWinModuleAddCreateWndData(&winmod, create_data, (void*)0xdead0001);
|
|
ok(winmod.m_pCreateWndList == create_data, "winmod.m_pCreateWndList != create_data\n");
|
|
ok(create_data[0].m_pThis == (void*)0xdead0001, "unexpected create_data[0].m_pThis %p\n", create_data[0].m_pThis);
|
|
ok(create_data[0].m_dwThreadID == GetCurrentThreadId(), "unexpected create_data[0].m_dwThreadID %x\n",
|
|
create_data[0].m_dwThreadID);
|
|
ok(!create_data[0].m_pNext, "unexpected create_data[0].m_pNext %p\n", create_data[0].m_pNext);
|
|
|
|
AtlWinModuleAddCreateWndData(&winmod, create_data+1, (void*)0xdead0002);
|
|
ok(winmod.m_pCreateWndList == create_data+1, "winmod.m_pCreateWndList != create_data\n");
|
|
ok(create_data[1].m_pThis == (void*)0xdead0002, "unexpected create_data[1].m_pThis %p\n", create_data[1].m_pThis);
|
|
ok(create_data[1].m_dwThreadID == GetCurrentThreadId(), "unexpected create_data[1].m_dwThreadID %x\n",
|
|
create_data[1].m_dwThreadID);
|
|
ok(create_data[1].m_pNext == create_data, "unexpected create_data[1].m_pNext %p\n", create_data[1].m_pNext);
|
|
|
|
AtlWinModuleAddCreateWndData(&winmod, create_data+2, (void*)0xdead0003);
|
|
ok(winmod.m_pCreateWndList == create_data+2, "winmod.m_pCreateWndList != create_data\n");
|
|
ok(create_data[2].m_pThis == (void*)0xdead0003, "unexpected create_data[2].m_pThis %p\n", create_data[2].m_pThis);
|
|
ok(create_data[2].m_dwThreadID == GetCurrentThreadId(), "unexpected create_data[2].m_dwThreadID %x\n",
|
|
create_data[2].m_dwThreadID);
|
|
ok(create_data[2].m_pNext == create_data+1, "unexpected create_data[2].m_pNext %p\n", create_data[2].m_pNext);
|
|
|
|
p = AtlWinModuleExtractCreateWndData(&winmod);
|
|
ok(p == (void*)0xdead0003, "unexpected AtlWinModuleExtractCreateWndData result %p\n", p);
|
|
ok(winmod.m_pCreateWndList == create_data+1, "winmod.m_pCreateWndList != create_data\n");
|
|
ok(create_data[2].m_pNext == create_data+1, "unexpected create_data[2].m_pNext %p\n", create_data[2].m_pNext);
|
|
|
|
create_data[1].m_dwThreadID = 0xdeadbeef;
|
|
|
|
p = AtlWinModuleExtractCreateWndData(&winmod);
|
|
ok(p == (void*)0xdead0001, "unexpected AtlWinModuleExtractCreateWndData result %p\n", p);
|
|
ok(winmod.m_pCreateWndList == create_data+1, "winmod.m_pCreateWndList != create_data\n");
|
|
ok(!create_data[0].m_pNext, "unexpected create_data[0].m_pNext %p\n", create_data[0].m_pNext);
|
|
ok(!create_data[1].m_pNext, "unexpected create_data[1].m_pNext %p\n", create_data[1].m_pNext);
|
|
|
|
p = AtlWinModuleExtractCreateWndData(&winmod);
|
|
ok(!p, "unexpected AtlWinModuleExtractCreateWndData result %p\n", p);
|
|
ok(winmod.m_pCreateWndList == create_data+1, "winmod.m_pCreateWndList != create_data\n");
|
|
}
|
|
|
|
#define test_key_exists(a,b) _test_key_exists(__LINE__,a,b)
|
|
static void _test_key_exists(unsigned line, HKEY root, const char *key_name)
|
|
{
|
|
HKEY key;
|
|
DWORD res;
|
|
|
|
res = RegOpenKeyA(root, key_name, &key);
|
|
ok_(__FILE__,line)(res == ERROR_SUCCESS, "Could not open key %s\n", key_name);
|
|
if(res == ERROR_SUCCESS)
|
|
RegCloseKey(key);
|
|
}
|
|
|
|
#define test_key_not_exists(a,b) _test_key_not_exists(__LINE__,a,b)
|
|
static void _test_key_not_exists(unsigned line, HKEY root, const char *key_name)
|
|
{
|
|
HKEY key;
|
|
DWORD res;
|
|
|
|
res = RegOpenKeyA(root, key_name, &key);
|
|
ok_(__FILE__,line)(res == ERROR_FILE_NOT_FOUND, "Attempting to open %s returned %u\n", key_name, res);
|
|
if(res == ERROR_SUCCESS)
|
|
RegCloseKey(key);
|
|
}
|
|
|
|
static void test_regcat(void)
|
|
{
|
|
unsigned char b;
|
|
HRESULT hres;
|
|
|
|
const struct _ATL_CATMAP_ENTRY catmap[] = {
|
|
{_ATL_CATMAP_ENTRY_IMPLEMENTED, &CATID_CatTest1},
|
|
{_ATL_CATMAP_ENTRY_REQUIRED, &CATID_CatTest2},
|
|
{_ATL_CATMAP_ENTRY_END}
|
|
};
|
|
|
|
if (is_process_limited())
|
|
{
|
|
skip("process is limited\n");
|
|
return;
|
|
}
|
|
|
|
hres = AtlRegisterClassCategoriesHelper(&CLSID_Test, catmap, TRUE);
|
|
ok(hres == S_OK, "AtlRegisterClassCategoriesHelper failed: %08x\n", hres);
|
|
|
|
test_key_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}");
|
|
test_key_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}\\Implemented Categories\\{" CATID_CATTEST1_STR "}");
|
|
test_key_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}\\Required Categories\\{" CATID_CATTEST2_STR "}");
|
|
|
|
hres = AtlRegisterClassCategoriesHelper(&CLSID_Test, catmap, FALSE);
|
|
ok(hres == S_OK, "AtlRegisterClassCategoriesHelper failed: %08x\n", hres);
|
|
|
|
test_key_not_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}\\Implemented Categories");
|
|
test_key_not_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}\\Required Categories");
|
|
test_key_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}");
|
|
|
|
ok(RegDeleteKeyA(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}") == ERROR_SUCCESS, "Could not delete key\n");
|
|
|
|
hres = AtlRegisterClassCategoriesHelper(&CLSID_Test, NULL, TRUE);
|
|
ok(hres == S_OK, "AtlRegisterClassCategoriesHelper failed: %08x\n", hres);
|
|
|
|
test_key_not_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}");
|
|
|
|
b = 10;
|
|
hres = AtlGetPerUserRegistration(&b);
|
|
ok(hres == S_OK, "AtlGetPerUserRegistration failed: %08x\n", hres);
|
|
ok(!b, "AtlGetPerUserRegistration returned %x\n", b);
|
|
}
|
|
|
|
static void test_typelib(void)
|
|
{
|
|
ITypeLib *typelib;
|
|
HINSTANCE inst;
|
|
size_t len;
|
|
BSTR path;
|
|
HRESULT hres;
|
|
|
|
static const WCHAR scrrun_dll_suffixW[] = {'\\','s','c','r','r','u','n','.','d','l','l',0};
|
|
static const WCHAR mshtml_tlb_suffixW[] = {'\\','m','s','h','t','m','l','.','t','l','b',0};
|
|
|
|
inst = LoadLibraryA("scrrun.dll");
|
|
ok(inst != NULL, "Could not load scrrun.dll\n");
|
|
|
|
typelib = NULL;
|
|
hres = AtlLoadTypeLib(inst, NULL, &path, &typelib);
|
|
ok(hres == S_OK, "AtlLoadTypeLib failed: %08x\n", hres);
|
|
FreeLibrary(inst);
|
|
|
|
len = SysStringLen(path);
|
|
ok(len > ARRAY_SIZE(scrrun_dll_suffixW)
|
|
&& lstrcmpiW(path+len-ARRAY_SIZE(scrrun_dll_suffixW), scrrun_dll_suffixW),
|
|
"unexpected path %s\n", wine_dbgstr_w(path));
|
|
SysFreeString(path);
|
|
ok(typelib != NULL, "typelib == NULL\n");
|
|
ITypeLib_Release(typelib);
|
|
|
|
inst = LoadLibraryA("mshtml.dll");
|
|
ok(inst != NULL, "Could not load mshtml.dll\n");
|
|
|
|
typelib = NULL;
|
|
hres = AtlLoadTypeLib(inst, NULL, &path, &typelib);
|
|
ok(hres == S_OK, "AtlLoadTypeLib failed: %08x\n", hres);
|
|
FreeLibrary(inst);
|
|
|
|
len = SysStringLen(path);
|
|
ok(len > ARRAY_SIZE(mshtml_tlb_suffixW)
|
|
&& lstrcmpiW(path+len-ARRAY_SIZE(mshtml_tlb_suffixW), mshtml_tlb_suffixW),
|
|
"unexpected path %s\n", wine_dbgstr_w(path));
|
|
SysFreeString(path);
|
|
ok(typelib != NULL, "typelib == NULL\n");
|
|
ITypeLib_Release(typelib);
|
|
}
|
|
|
|
static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface, REFIID riid, void **ppv)
|
|
{
|
|
if(IsEqualGUID(&IID_IConnectionPoint, riid)) {
|
|
*ppv = iface;
|
|
return S_OK;
|
|
}
|
|
|
|
ok(0, "unexpected call\n");
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *pIID)
|
|
{
|
|
ok(0, "unexpected call\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
|
|
IConnectionPointContainer **ppCPC)
|
|
{
|
|
ok(0, "unexpected call\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static int advise_cnt;
|
|
|
|
static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
|
|
DWORD *pdwCookie)
|
|
{
|
|
ok(pUnkSink == (IUnknown*)0xdead0000, "pUnkSink = %p\n", pUnkSink);
|
|
*pdwCookie = 0xdeadbeef;
|
|
advise_cnt++;
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD dwCookie)
|
|
{
|
|
ok(dwCookie == 0xdeadbeef, "dwCookie = %x\n", dwCookie);
|
|
advise_cnt--;
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
|
|
IEnumConnections **ppEnum)
|
|
{
|
|
ok(0, "unexpected call\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static const IConnectionPointVtbl ConnectionPointVtbl =
|
|
{
|
|
ConnectionPoint_QueryInterface,
|
|
ConnectionPoint_AddRef,
|
|
ConnectionPoint_Release,
|
|
ConnectionPoint_GetConnectionInterface,
|
|
ConnectionPoint_GetConnectionPointContainer,
|
|
ConnectionPoint_Advise,
|
|
ConnectionPoint_Unadvise,
|
|
ConnectionPoint_EnumConnections
|
|
};
|
|
|
|
static IConnectionPoint ConnectionPoint = { &ConnectionPointVtbl };
|
|
|
|
static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
|
|
REFIID riid, void **ppv)
|
|
{
|
|
if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) {
|
|
*ppv = iface;
|
|
return S_OK;
|
|
}
|
|
|
|
ok(0, "unexpected call\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
|
|
IEnumConnectionPoints **ppEnum)
|
|
{
|
|
ok(0, "unexpected call\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
|
|
REFIID riid, IConnectionPoint **ppCP)
|
|
{
|
|
ok(IsEqualGUID(riid, &CLSID_Test), "unexpected riid\n");
|
|
*ppCP = &ConnectionPoint;
|
|
return S_OK;
|
|
}
|
|
|
|
static const IConnectionPointContainerVtbl ConnectionPointContainerVtbl = {
|
|
ConnectionPointContainer_QueryInterface,
|
|
ConnectionPointContainer_AddRef,
|
|
ConnectionPointContainer_Release,
|
|
ConnectionPointContainer_EnumConnectionPoints,
|
|
ConnectionPointContainer_FindConnectionPoint
|
|
};
|
|
|
|
static IConnectionPointContainer ConnectionPointContainer = { &ConnectionPointContainerVtbl };
|
|
|
|
static void test_cp(void)
|
|
{
|
|
DWORD cookie = 0;
|
|
HRESULT hres;
|
|
|
|
hres = AtlAdvise(NULL, (IUnknown*)0xdeed0000, &CLSID_Test, &cookie);
|
|
ok(hres == E_INVALIDARG, "expect E_INVALIDARG, returned %08x\n", hres);
|
|
|
|
hres = AtlUnadvise(NULL, &CLSID_Test, 0xdeadbeef);
|
|
ok(hres == E_INVALIDARG, "expect E_INVALIDARG, returned %08x\n", hres);
|
|
|
|
hres = AtlAdvise((IUnknown*)&ConnectionPointContainer, (IUnknown*)0xdead0000, &CLSID_Test, &cookie);
|
|
ok(hres == S_OK, "AtlAdvise failed: %08x\n", hres);
|
|
ok(cookie == 0xdeadbeef, "cookie = %x\n", cookie);
|
|
ok(advise_cnt == 1, "advise_cnt = %d\n", advise_cnt);
|
|
|
|
hres = AtlUnadvise((IUnknown*)&ConnectionPointContainer, &CLSID_Test, 0xdeadbeef);
|
|
ok(hres == S_OK, "AtlUnadvise failed: %08x\n", hres);
|
|
ok(!advise_cnt, "advise_cnt = %d\n", advise_cnt);
|
|
}
|
|
|
|
static CLSID persist_clsid;
|
|
|
|
static HRESULT WINAPI Persist_QueryInterface(IPersist *iface, REFIID riid, void **ppv)
|
|
{
|
|
ok(0, "unexpected call\n");
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static ULONG WINAPI Persist_AddRef(IPersist *iface)
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
static ULONG WINAPI Persist_Release(IPersist *iface)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static HRESULT WINAPI Persist_GetClassID(IPersist *iface, CLSID *pClassID)
|
|
{
|
|
*pClassID = persist_clsid;
|
|
return S_OK;
|
|
}
|
|
|
|
static const IPersistVtbl PersistVtbl = {
|
|
Persist_QueryInterface,
|
|
Persist_AddRef,
|
|
Persist_Release,
|
|
Persist_GetClassID
|
|
};
|
|
|
|
static IPersist Persist = { &PersistVtbl };
|
|
|
|
static HRESULT WINAPI ProvideClassInfo2_QueryInterface(IProvideClassInfo2 *iface, REFIID riid, void **ppv)
|
|
{
|
|
ok(0, "unexpected call\n");
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static ULONG WINAPI ProvideClassInfo2_AddRef(IProvideClassInfo2 *iface)
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
static ULONG WINAPI ProvideClassInfo2_Release(IProvideClassInfo2 *iface)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static HRESULT WINAPI ProvideClassInfo2_GetClassInfo(IProvideClassInfo2 *iface, ITypeInfo **ppTI)
|
|
{
|
|
ok(0, "unexpected call\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI ProvideClassInfo2_GetGUID(IProvideClassInfo2 *iface, DWORD dwGuidKind, GUID *pGUID)
|
|
{
|
|
ok(dwGuidKind == GUIDKIND_DEFAULT_SOURCE_DISP_IID, "unexpected dwGuidKind %x\n", dwGuidKind);
|
|
*pGUID = DIID_DispHTMLBody;
|
|
return S_OK;
|
|
}
|
|
|
|
static const IProvideClassInfo2Vtbl ProvideClassInfo2Vtbl = {
|
|
ProvideClassInfo2_QueryInterface,
|
|
ProvideClassInfo2_AddRef,
|
|
ProvideClassInfo2_Release,
|
|
ProvideClassInfo2_GetClassInfo,
|
|
ProvideClassInfo2_GetGUID
|
|
};
|
|
|
|
static IProvideClassInfo2 ProvideClassInfo2 = { &ProvideClassInfo2Vtbl };
|
|
static BOOL support_classinfo2;
|
|
|
|
static HRESULT WINAPI Dispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
|
|
{
|
|
*ppv = NULL;
|
|
|
|
if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IDispatch, riid)) {
|
|
*ppv = iface;
|
|
return S_OK;
|
|
}
|
|
|
|
if(IsEqualGUID(&IID_IProvideClassInfo2, riid)) {
|
|
if(!support_classinfo2)
|
|
return E_NOINTERFACE;
|
|
*ppv = &ProvideClassInfo2;
|
|
return S_OK;
|
|
}
|
|
|
|
if(IsEqualGUID(&IID_IPersist, riid)) {
|
|
*ppv = &Persist;
|
|
return S_OK;
|
|
}
|
|
|
|
ok(0, "unexpected riid: %s\n", wine_dbgstr_guid(riid));
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static ULONG WINAPI Dispatch_AddRef(IDispatch *iface)
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
static ULONG WINAPI Dispatch_Release(IDispatch *iface)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static HRESULT WINAPI Dispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
|
|
{
|
|
ok(0, "unexpected call\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI Dispatch_GetTypeInfo(IDispatch *iface, UINT iTInfo, LCID lcid,
|
|
ITypeInfo **ppTInfo)
|
|
{
|
|
ITypeLib *typelib;
|
|
HRESULT hres;
|
|
|
|
static const WCHAR mshtml_tlbW[] = {'m','s','h','t','m','l','.','t','l','b',0};
|
|
|
|
ok(!iTInfo, "iTInfo = %d\n", iTInfo);
|
|
ok(!lcid, "lcid = %x\n", lcid);
|
|
|
|
hres = LoadTypeLib(mshtml_tlbW, &typelib);
|
|
ok(hres == S_OK, "LoadTypeLib failed: %08x\n", hres);
|
|
|
|
hres = ITypeLib_GetTypeInfoOfGuid(typelib, &IID_IHTMLElement, ppTInfo);
|
|
ok(hres == S_OK, "GetTypeInfoOfGuid failed: %08x\n", hres);
|
|
|
|
ITypeLib_Release(typelib);
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI Dispatch_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *rgszNames,
|
|
UINT cNames, LCID lcid, DISPID *rgDispId)
|
|
{
|
|
ok(0, "unexpected call\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI Dispatch_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid,
|
|
LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
|
|
EXCEPINFO *pExcepInfo, UINT *puArgErr)
|
|
{
|
|
ok(0, "unexpected call\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static const IDispatchVtbl DispatchVtbl = {
|
|
Dispatch_QueryInterface,
|
|
Dispatch_AddRef,
|
|
Dispatch_Release,
|
|
Dispatch_GetTypeInfoCount,
|
|
Dispatch_GetTypeInfo,
|
|
Dispatch_GetIDsOfNames,
|
|
Dispatch_Invoke
|
|
};
|
|
|
|
static IDispatch Dispatch = { &DispatchVtbl };
|
|
|
|
static void test_source_iface(void)
|
|
{
|
|
unsigned short maj_ver, min_ver;
|
|
IID libid, iid;
|
|
HRESULT hres;
|
|
|
|
support_classinfo2 = TRUE;
|
|
|
|
maj_ver = min_ver = 0xdead;
|
|
hres = AtlGetObjectSourceInterface((IUnknown*)&Dispatch, &libid, &iid, &maj_ver, &min_ver);
|
|
ok(hres == S_OK, "AtlGetObjectSourceInterface failed: %08x\n", hres);
|
|
ok(IsEqualGUID(&libid, &LIBID_MSHTML), "libid = %s\n", wine_dbgstr_guid(&libid));
|
|
ok(IsEqualGUID(&iid, &DIID_DispHTMLBody), "iid = %s\n", wine_dbgstr_guid(&iid));
|
|
ok(maj_ver == 4 && min_ver == 0, "ver = %d.%d\n", maj_ver, min_ver);
|
|
|
|
support_classinfo2 = FALSE;
|
|
persist_clsid = CLSID_HTMLDocument;
|
|
|
|
maj_ver = min_ver = 0xdead;
|
|
hres = AtlGetObjectSourceInterface((IUnknown*)&Dispatch, &libid, &iid, &maj_ver, &min_ver);
|
|
ok(hres == S_OK, "AtlGetObjectSourceInterface failed: %08x\n", hres);
|
|
ok(IsEqualGUID(&libid, &LIBID_MSHTML), "libid = %s\n", wine_dbgstr_guid(&libid));
|
|
ok(IsEqualGUID(&iid, &DIID_HTMLDocumentEvents), "iid = %s\n", wine_dbgstr_guid(&iid));
|
|
ok(maj_ver == 4 && min_ver == 0, "ver = %d.%d\n", maj_ver, min_ver);
|
|
|
|
persist_clsid = CLSID_HTMLStyle;
|
|
|
|
maj_ver = min_ver = 0xdead;
|
|
hres = AtlGetObjectSourceInterface((IUnknown*)&Dispatch, &libid, &iid, &maj_ver, &min_ver);
|
|
ok(hres == S_OK, "AtlGetObjectSourceInterface failed: %08x\n", hres);
|
|
ok(IsEqualGUID(&libid, &LIBID_MSHTML), "libid = %s\n", wine_dbgstr_guid(&libid));
|
|
ok(IsEqualGUID(&iid, &IID_NULL), "iid = %s\n", wine_dbgstr_guid(&iid));
|
|
ok(maj_ver == 4 && min_ver == 0, "ver = %d.%d\n", maj_ver, min_ver);
|
|
}
|
|
|
|
static void test_ax_win(void)
|
|
{
|
|
DWORD ret, ret_size, i;
|
|
HRESULT res;
|
|
HWND hwnd;
|
|
HANDLE hfile;
|
|
IUnknown *control;
|
|
WNDPROC wndproc[2] = {NULL, NULL};
|
|
WCHAR file_uri1W[MAX_PATH], pathW[MAX_PATH];
|
|
WNDCLASSEXW wcex;
|
|
static HMODULE hinstance = 0;
|
|
static const WCHAR cls_names[][16] =
|
|
{
|
|
{'A','t','l','A','x','W','i','n','1','0','0',0},
|
|
{'A','t','l','A','x','W','i','n','L','i','c','1','0','0',0}
|
|
};
|
|
|
|
ret = AtlAxWinInit();
|
|
ok(ret, "AtlAxWinInit failed\n");
|
|
|
|
hinstance = GetModuleHandleA(NULL);
|
|
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
memset(&wcex, 0, sizeof(wcex));
|
|
wcex.cbSize = sizeof(wcex);
|
|
ret = GetClassInfoExW(hinstance, cls_names[i], &wcex);
|
|
ok(ret, "%s has not registered\n", wine_dbgstr_w(cls_names[i]));
|
|
ok(wcex.style == (CS_GLOBALCLASS | CS_DBLCLKS), "wcex.style %08x\n", wcex.style);
|
|
wndproc[i] = wcex.lpfnWndProc;
|
|
|
|
hwnd = CreateWindowW(cls_names[i], NULL, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
|
|
ok(hwnd != NULL, "CreateWindow failed!\n");
|
|
control = (IUnknown *)0xdeadbeef;
|
|
res = AtlAxGetControl(hwnd, &control);
|
|
ok(res == E_FAIL, "Expected E_FAIL, returned %08x\n", res);
|
|
ok(!control, "returned %p\n", control);
|
|
if (control) IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
|
|
hwnd = CreateWindowW(cls_names[i], emptyW, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
|
|
ok(hwnd != NULL, "CreateWindow failed!\n");
|
|
control = (IUnknown *)0xdeadbeef;
|
|
res = AtlAxGetControl(hwnd, &control);
|
|
ok(res == E_FAIL, "Expected E_FAIL, returned %08x\n", res);
|
|
ok(!control, "returned %p\n", control);
|
|
if (control) IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
|
|
hwnd = CreateWindowW(cls_names[i], randomW, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
|
|
todo_wine ok(!hwnd, "returned %p\n", hwnd);
|
|
if(hwnd) DestroyWindow(hwnd);
|
|
|
|
hwnd = CreateWindowW(cls_names[i], progid1W, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
|
|
ok(hwnd != NULL, "CreateWindow failed!\n");
|
|
control = NULL;
|
|
res = AtlAxGetControl(hwnd, &control);
|
|
ok(res == S_OK, "AtlAxGetControl failed with res %08x\n", res);
|
|
ok(control != NULL, "AtlAxGetControl failed!\n");
|
|
IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
|
|
hwnd = CreateWindowW(cls_names[i], clsid1W, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
|
|
ok(hwnd != NULL, "CreateWindow failed!\n");
|
|
control = NULL;
|
|
res = AtlAxGetControl(hwnd, &control);
|
|
ok(res == S_OK, "AtlAxGetControl failed with res %08x\n", res);
|
|
ok(control != NULL, "AtlAxGetControl failed!\n");
|
|
IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
|
|
hwnd = CreateWindowW(cls_names[i], url1W, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
|
|
ok(hwnd != NULL, "CreateWindow failed!\n");
|
|
control = NULL;
|
|
res = AtlAxGetControl(hwnd, &control);
|
|
ok(res == S_OK, "AtlAxGetControl failed with res %08x\n", res);
|
|
ok(control != NULL, "AtlAxGetControl failed!\n");
|
|
IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
|
|
/* test html stream with "MSHTML:" prefix */
|
|
hwnd = CreateWindowW(cls_names[i], mshtml1W, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
|
|
ok(hwnd != NULL, "CreateWindow failed!\n");
|
|
control = NULL;
|
|
res = AtlAxGetControl(hwnd, &control);
|
|
ok(res == S_OK, "AtlAxGetControl failed with res %08x\n", res);
|
|
ok(control != NULL, "AtlAxGetControl failed!\n");
|
|
IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
|
|
hwnd = CreateWindowW(cls_names[i], mshtml2W, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
|
|
ok(hwnd != NULL, "CreateWindow failed!\n");
|
|
control = NULL;
|
|
res = AtlAxGetControl(hwnd, &control);
|
|
ok(res == S_OK, "AtlAxGetControl failed with res %08x\n", res);
|
|
ok(control != NULL, "AtlAxGetControl failed!\n");
|
|
IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
|
|
/* test html stream without "MSHTML:" prefix */
|
|
hwnd = CreateWindowW(cls_names[i], mshtml3W, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
|
|
todo_wine ok(!hwnd, "returned %p\n", hwnd);
|
|
if(hwnd) DestroyWindow(hwnd);
|
|
|
|
ret = GetTempPathW(MAX_PATH, pathW);
|
|
ok(ret, "GetTempPath failed!\n");
|
|
lstrcatW(pathW, html_fileW);
|
|
hfile = CreateFileW(pathW, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, 0);
|
|
ok(hfile != INVALID_HANDLE_VALUE, "failed to create file\n");
|
|
ret = WriteFile(hfile, html_str, sizeof(html_str), &ret_size, NULL);
|
|
ok(ret, "WriteFile failed\n");
|
|
CloseHandle(hfile);
|
|
|
|
/* test C:// scheme */
|
|
hwnd = CreateWindowW(cls_names[i], pathW, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
|
|
ok(hwnd != NULL, "CreateWindow failed!\n");
|
|
control = NULL;
|
|
res = AtlAxGetControl(hwnd, &control);
|
|
ok(res == S_OK, "AtlAxGetControl failed with res %08x\n", res);
|
|
ok(control != NULL, "AtlAxGetControl failed!\n");
|
|
IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
|
|
/* test file:// scheme */
|
|
lstrcpyW(file_uri1W, fileW);
|
|
lstrcatW(file_uri1W, pathW);
|
|
hwnd = CreateWindowW(cls_names[i], file_uri1W, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
|
|
ok(hwnd != NULL, "CreateWindow failed!\n");
|
|
control = NULL;
|
|
res = AtlAxGetControl(hwnd, &control);
|
|
ok(res == S_OK, "AtlAxGetControl failed with res %08x\n", res);
|
|
ok(control != NULL, "AtlAxGetControl failed!\n");
|
|
IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
|
|
/* test file:// scheme on non-existent file */
|
|
ret = DeleteFileW(pathW);
|
|
ok(ret, "DeleteFile failed!\n");
|
|
hwnd = CreateWindowW(cls_names[i], file_uri1W, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
|
|
ok(hwnd != NULL, "CreateWindow failed!\n");
|
|
control = NULL;
|
|
res = AtlAxGetControl(hwnd, &control);
|
|
ok(res == S_OK, "AtlAxGetControl failed with res %08x\n", res);
|
|
ok(control != NULL, "AtlAxGetControl failed!\n");
|
|
IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
}
|
|
todo_wine ok(wndproc[0] != wndproc[1], "expected different proc!\n");
|
|
}
|
|
|
|
static ATOM register_class(void)
|
|
{
|
|
WNDCLASSA wndclassA;
|
|
|
|
wndclassA.style = 0;
|
|
wndclassA.lpfnWndProc = DefWindowProcA;
|
|
wndclassA.cbClsExtra = 0;
|
|
wndclassA.cbWndExtra = 0;
|
|
wndclassA.hInstance = GetModuleHandleA(NULL);
|
|
wndclassA.hIcon = NULL;
|
|
wndclassA.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
|
|
wndclassA.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
|
|
wndclassA.lpszMenuName = NULL;
|
|
wndclassA.lpszClassName = "WineAtlTestClass";
|
|
|
|
return RegisterClassA(&wndclassA);
|
|
}
|
|
|
|
static HWND create_container_window(void)
|
|
{
|
|
return CreateWindowA("WineAtlTestClass", "Wine ATL Test Window", 0,
|
|
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
CW_USEDEFAULT, NULL, NULL, NULL, NULL);
|
|
}
|
|
|
|
static void test_AtlAxAttachControl(void)
|
|
{
|
|
HWND hwnd;
|
|
HRESULT hr;
|
|
IUnknown *control, *container;
|
|
LONG val;
|
|
|
|
hr = AtlAxAttachControl(NULL, NULL, NULL);
|
|
ok(hr == E_INVALIDARG, "Expected AtlAxAttachControl to return E_INVALIDARG, got 0x%08x\n", hr);
|
|
|
|
container = (IUnknown *)0xdeadbeef;
|
|
hr = AtlAxAttachControl(NULL, NULL, &container);
|
|
ok(hr == E_INVALIDARG, "Expected AtlAxAttachControl to return E_INVALIDARG, got 0x%08x\n", hr);
|
|
ok(container == (IUnknown *)0xdeadbeef,
|
|
"Expected the output container pointer to be untouched, got %p\n", container);
|
|
|
|
hwnd = create_container_window();
|
|
hr = AtlAxAttachControl(NULL, hwnd, NULL);
|
|
ok(hr == E_INVALIDARG, "Expected AtlAxAttachControl to return E_INVALIDARG, got 0x%08x\n", hr);
|
|
DestroyWindow(hwnd);
|
|
|
|
hwnd = create_container_window();
|
|
container = (IUnknown *)0xdeadbeef;
|
|
hr = AtlAxAttachControl(NULL, hwnd, &container);
|
|
ok(hr == E_INVALIDARG, "Expected AtlAxAttachControl to return E_INVALIDARG, got 0x%08x\n", hr);
|
|
ok(container == (IUnknown *)0xdeadbeef, "returned %p\n", container);
|
|
DestroyWindow(hwnd);
|
|
|
|
hr = CoCreateInstance(&CLSID_WebBrowser, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER,
|
|
&IID_IOleObject, (void **)&control);
|
|
ok(hr == S_OK, "Expected CoCreateInstance to return S_OK, got 0x%08x\n", hr);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
skip("Couldn't obtain a test IOleObject instance\n");
|
|
return;
|
|
}
|
|
|
|
hr = AtlAxAttachControl(control, NULL, NULL);
|
|
ok(hr == S_FALSE, "Expected AtlAxAttachControl to return S_FALSE, got 0x%08x\n", hr);
|
|
|
|
container = NULL;
|
|
hr = AtlAxAttachControl(control, NULL, &container);
|
|
ok(hr == S_FALSE, "Expected AtlAxAttachControl to return S_FALSE, got 0x%08x\n", hr);
|
|
ok(container != NULL, "got %p\n", container);
|
|
IUnknown_Release(container);
|
|
|
|
hwnd = create_container_window();
|
|
SetWindowLongW(hwnd, GWLP_USERDATA, 0xdeadbeef);
|
|
hr = AtlAxAttachControl(control, hwnd, NULL);
|
|
ok(hr == S_OK, "Expected AtlAxAttachControl to return S_OK, got 0x%08x\n", hr);
|
|
val = GetWindowLongW(hwnd, GWLP_USERDATA);
|
|
ok(val == 0xdeadbeef, "returned %08x\n", val);
|
|
DestroyWindow(hwnd);
|
|
|
|
hwnd = create_container_window();
|
|
SetWindowLongW(hwnd, GWLP_USERDATA, 0xdeadbeef);
|
|
container = NULL;
|
|
hr = AtlAxAttachControl(control, hwnd, &container);
|
|
ok(hr == S_OK, "Expected AtlAxAttachControl to return S_OK, got 0x%08x\n", hr);
|
|
ok(container != NULL, "Expected not NULL!\n");
|
|
IUnknown_Release(container);
|
|
val = GetWindowLongW(hwnd, GWLP_USERDATA);
|
|
ok(val == 0xdeadbeef, "Expected unchanged, returned %08x\n", val);
|
|
DestroyWindow(hwnd);
|
|
|
|
IUnknown_Release(control);
|
|
}
|
|
|
|
static void test_AtlAxCreateControl(void)
|
|
{
|
|
HWND hwnd;
|
|
IUnknown *control, *container;
|
|
HRESULT hr;
|
|
DWORD ret, ret_size;
|
|
HANDLE hfile;
|
|
WCHAR file_uri1W[MAX_PATH], pathW[MAX_PATH];
|
|
|
|
container = NULL;
|
|
control = (IUnknown *)0xdeadbeef;
|
|
hr = AtlAxCreateControlEx(NULL, NULL, NULL, &container, &control, NULL, NULL);
|
|
todo_wine ok(hr == S_FALSE, "got 0x%08x\n", hr);
|
|
todo_wine ok(container != NULL, "returned %p\n", container);
|
|
ok(!control, "returned %p\n", control);
|
|
|
|
container = NULL;
|
|
control = (IUnknown *)0xdeadbeef;
|
|
hwnd = create_container_window();
|
|
ok(hwnd != NULL, "create window failed!\n");
|
|
hr = AtlAxCreateControlEx(NULL, hwnd, NULL, &container, &control, &IID_NULL, NULL);
|
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
|
todo_wine ok(container != NULL, "returned %p!\n", container);
|
|
ok(!control, "returned %p\n", control);
|
|
DestroyWindow(hwnd);
|
|
|
|
container = NULL;
|
|
control = (IUnknown *)0xdeadbeef;
|
|
hwnd = create_container_window();
|
|
ok(hwnd != NULL, "create window failed!\n");
|
|
hr = AtlAxCreateControlEx(emptyW, hwnd, NULL, &container, &control, &IID_NULL, NULL);
|
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
|
todo_wine ok(container != NULL, "returned %p!\n", container);
|
|
ok(!control, "returned %p\n", control);
|
|
DestroyWindow(hwnd);
|
|
|
|
container = (IUnknown *)0xdeadbeef;
|
|
control = (IUnknown *)0xdeadbeef;
|
|
hwnd = create_container_window();
|
|
ok(hwnd != NULL, "create window failed!\n");
|
|
hr = AtlAxCreateControlEx(randomW, hwnd, NULL, &container, &control, &IID_NULL, NULL);
|
|
ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
|
|
ok(!container, "returned %p!\n", container);
|
|
ok(!control, "returned %p\n", control);
|
|
DestroyWindow(hwnd);
|
|
|
|
container = NULL;
|
|
control = NULL;
|
|
hwnd = create_container_window();
|
|
ok(hwnd != NULL, "create window failed!\n");
|
|
hr = AtlAxCreateControlEx(progid1W, hwnd, NULL, &container, &control, &IID_NULL, NULL);
|
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
|
ok(container != NULL, "returned %p!\n", container);
|
|
ok(control != NULL, "returned %p\n", control);
|
|
IUnknown_Release(container);
|
|
IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
|
|
container = NULL;
|
|
control = NULL;
|
|
hwnd = create_container_window();
|
|
ok(hwnd != NULL, "create window failed!\n");
|
|
hr = AtlAxCreateControlEx(clsid1W, hwnd, NULL, &container, &control, &IID_NULL, NULL);
|
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
|
ok(container != NULL, "returned %p!\n", container);
|
|
ok(control != NULL, "returned %p\n", control);
|
|
IUnknown_Release(container);
|
|
IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
|
|
container = NULL;
|
|
control = NULL;
|
|
hwnd = create_container_window();
|
|
ok(hwnd != NULL, "create window failed!\n");
|
|
hr = AtlAxCreateControlEx(url1W, hwnd, NULL, &container, &control, &IID_NULL, NULL);
|
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
|
ok(container != NULL, "returned %p!\n", container);
|
|
ok(control != NULL, "returned %p\n", control);
|
|
IUnknown_Release(container);
|
|
IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
|
|
container = NULL;
|
|
control = NULL;
|
|
hwnd = create_container_window();
|
|
ok(hwnd != NULL, "create window failed!\n");
|
|
hr = AtlAxCreateControlEx(mshtml1W, hwnd, NULL, &container, &control, &IID_NULL, NULL);
|
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
|
ok(container != NULL, "returned %p!\n", container);
|
|
ok(control != NULL, "returned %p\n", control);
|
|
IUnknown_Release(container);
|
|
IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
|
|
container = NULL;
|
|
control = NULL;
|
|
hwnd = create_container_window();
|
|
ok(hwnd != NULL, "create window failed!\n");
|
|
hr = AtlAxCreateControlEx(mshtml2W, hwnd, NULL, &container, &control, &IID_NULL, NULL);
|
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
|
ok(container != NULL, "returned %p!\n", container);
|
|
ok(control != NULL, "returned %p\n", control);
|
|
IUnknown_Release(container);
|
|
IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
|
|
container = (IUnknown *)0xdeadbeef;
|
|
control = (IUnknown *)0xdeadbeef;
|
|
hwnd = create_container_window();
|
|
ok(hwnd != NULL, "create window failed!\n");
|
|
hr = AtlAxCreateControlEx(mshtml3W, hwnd, NULL, &container, &control, &IID_NULL, NULL);
|
|
ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
|
|
ok(!container, "returned %p!\n", container);
|
|
ok(!control, "returned %p\n", control);
|
|
DestroyWindow(hwnd);
|
|
|
|
ret = GetTempPathW(MAX_PATH, pathW);
|
|
ok(ret, "GetTempPath failed!\n");
|
|
lstrcatW(pathW, html_fileW);
|
|
hfile = CreateFileW(pathW, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, 0);
|
|
ok(hfile != INVALID_HANDLE_VALUE, "failed to create file\n");
|
|
ret = WriteFile(hfile, html_str, sizeof(html_str), &ret_size, NULL);
|
|
ok(ret, "WriteFile failed\n");
|
|
CloseHandle(hfile);
|
|
|
|
/* test C:// scheme */
|
|
container = NULL;
|
|
control = NULL;
|
|
hwnd = create_container_window();
|
|
ok(hwnd != NULL, "create window failed!\n");
|
|
hr = AtlAxCreateControlEx(pathW, hwnd, NULL, &container, &control, &IID_NULL, NULL);
|
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
|
ok(container != NULL, "returned %p!\n", container);
|
|
ok(control != NULL, "returned %p\n", control);
|
|
IUnknown_Release(container);
|
|
IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
|
|
/* test file:// scheme */
|
|
lstrcpyW(file_uri1W, fileW);
|
|
lstrcatW(file_uri1W, pathW);
|
|
container = NULL;
|
|
control = NULL;
|
|
hwnd = create_container_window();
|
|
ok(hwnd != NULL, "create window failed!\n");
|
|
hr = AtlAxCreateControlEx(file_uri1W, hwnd, NULL, &container, &control, &IID_NULL, NULL);
|
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
|
ok(container != NULL, "returned %p!\n", container);
|
|
ok(control != NULL, "returned %p\n", control);
|
|
IUnknown_Release(container);
|
|
IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
|
|
/* test file:// scheme on non-existent file. */
|
|
ret = DeleteFileW(pathW);
|
|
ok(ret, "DeleteFile failed!\n");
|
|
container = NULL;
|
|
control = NULL;
|
|
hwnd = create_container_window();
|
|
ok(hwnd != NULL, "create window failed!\n");
|
|
hr = AtlAxCreateControlEx(file_uri1W, hwnd, NULL, &container, &control, &IID_NULL, NULL);
|
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
|
ok(container != NULL, "returned %p!\n", container);
|
|
ok(control != NULL, "returned %p\n", control);
|
|
IUnknown_Release(container);
|
|
IUnknown_Release(control);
|
|
DestroyWindow(hwnd);
|
|
}
|
|
|
|
START_TEST(atl)
|
|
{
|
|
if (!register_class())
|
|
return;
|
|
|
|
CoInitialize(NULL);
|
|
|
|
test_winmodule();
|
|
test_regcat();
|
|
test_typelib();
|
|
test_cp();
|
|
test_source_iface();
|
|
test_ax_win();
|
|
test_AtlAxAttachControl();
|
|
test_AtlAxCreateControl();
|
|
|
|
CoUninitialize();
|
|
}
|