diff --git a/rostests/apitests/CMakeLists.txt b/rostests/apitests/CMakeLists.txt index 1c0a6d8604e..a28fa473d1c 100644 --- a/rostests/apitests/CMakeLists.txt +++ b/rostests/apitests/CMakeLists.txt @@ -3,6 +3,7 @@ add_library(apitest apitest.c) add_subdirectory(advapi32) add_subdirectory(browseui) +add_subdirectory(com) add_subdirectory(crt) add_subdirectory(dciman32) add_subdirectory(gdi32) diff --git a/rostests/apitests/com/CMakeLists.txt b/rostests/apitests/com/CMakeLists.txt new file mode 100644 index 00000000000..1c9c212dacb --- /dev/null +++ b/rostests/apitests/com/CMakeLists.txt @@ -0,0 +1,17 @@ + +add_definitions(-DWINE_NO_UNICODE_MACROS) + +list(APPEND SOURCE + browseui.c + ieframe.c + shdocvw.c + shell32.c + com_apitest.c + testlist.c) + +add_executable(com_apitest ${SOURCE}) +target_link_libraries(com_apitest wine uuid) +set_module_type(com_apitest win32cui) +add_importlibs(com_apitest advapi32 ole32 shlwapi shell32 msvcrt kernel32 ntdll) + +add_cd_file(TARGET com_apitest DESTINATION reactos/bin FOR all) diff --git a/rostests/apitests/com/browseui.c b/rostests/apitests/com/browseui.c new file mode 100644 index 00000000000..5bff33e423f --- /dev/null +++ b/rostests/apitests/com/browseui.c @@ -0,0 +1,65 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: COM interface test for browseui classes + * PROGRAMMER: Thomas Faber + */ + +#include "com_apitest.h" + +#define NDEBUG +#include + +static const CLASS_AND_INTERFACES ExpectedInterfaces[] = +{ + { + ID_NAME(CLSID_RebarBandSite), + { + { 0x0, &IID_IUnknown }, + { 0xc, &IID_IBandSite }, + { 0x10, &IID_IInputObjectSite }, + { 0x14, &IID_IInputObject }, + { 0x18, &IID_IDeskBarClient }, + { 0x18, &IID_IOleWindow }, + { 0x1c, &IID_IWinEventHandler }, + { 0x20, &IID_IPersistStream }, + { 0x20, &IID_IPersist }, + { 0x24, &IID_IDropTarget }, + { 0x28, &IID_IServiceProvider }, + { 0x2c, &IID_IBandSiteHelper }, + { 0x30, &IID_IOleCommandTarget }, + } + }, + { + ID_NAME(CLSID_SH_AddressBand), + { + { 0x0, &IID_IDeskBand }, + { 0x0, &IID_IDockingWindow }, + { 0x0, &IID_IOleWindow }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IObjectWithSite }, + { 0xc, &IID_IInputObject }, + { 0x10, &IID_IPersistStream }, + { 0x10, &IID_IPersist }, + { 0x14, &IID_IOleCommandTarget }, + { 0x18, &IID_IServiceProvider }, + { 0x30, &IID_IWinEventHandler }, + { 0x34, &IID_IAddressBand }, + { 0x38, &IID_IInputObjectSite }, + } + }, + { + ID_NAME(CLSID_ShellSearchExt), + { + { 0x0, &IID_IContextMenu }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IObjectWithSite }, + } + }, +}; +static const INT ExpectedInterfaceCount = RTL_NUMBER_OF(ExpectedInterfaces); + +START_TEST(browseui) +{ + TestClasses(L"browseui", ExpectedInterfaces, ExpectedInterfaceCount); +} diff --git a/rostests/apitests/com/com_apitest.c b/rostests/apitests/com/com_apitest.c new file mode 100644 index 00000000000..3609c4bd343 --- /dev/null +++ b/rostests/apitests/com/com_apitest.c @@ -0,0 +1,459 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: COM interface test + * PROGRAMMER: Thomas Faber + */ + +#include "com_apitest.h" + +#define NDEBUG +#include + +#define myskip(c, ...) ((c) ? 0 : (skip(__VA_ARGS__), 1)) +#define mytrace(...) do { \ + int debug = winetest_debug; \ + winetest_debug = 1; \ + trace(__VA_ARGS__); \ + winetest_debug = debug; \ +} while (0) + +typedef struct _KNOWN_INTERFACE +{ + const IID *iid; + PCSTR name; +} KNOWN_INTERFACE; +typedef const KNOWN_INTERFACE *PCKNOWN_INTERFACE; + +#undef ID_NAME +#define ID_NAME(c) { &c, #c } +static KNOWN_INTERFACE KnownInterfaces[] = +{ + ID_NAME(IID_IACList), + ID_NAME(IID_IACList2), + ID_NAME(IID_IAccessible), + ID_NAME(IID_IAddressBand), + ID_NAME(IID_IAddressEditBox), + ID_NAME(IID_IBandNavigate), + ID_NAME(IID_IBandProxy), + ID_NAME(IID_IBandSite), + ID_NAME(IID_IBandSiteHelper), + ID_NAME(IID_IBanneredBar), + ID_NAME(IID_IBindCtx), + ID_NAME(IID_IBrowserService), + ID_NAME(IID_IBrowserService2), + ID_NAME(IID_IClassFactory), + ID_NAME(IID_IClassFactory2), + ID_NAME(IID_IClassFactory3), + ID_NAME(IID_IClientSecurity), + ID_NAME(IID_IComThreadingInfo), + ID_NAME(IID_IContextMenu), + ID_NAME(IID_IContextMenu2), + ID_NAME(IID_IContextMenu3), + ID_NAME(IID_IContextMenuCB), + ID_NAME(IID_IContextMenuSite), + ID_NAME(IID_IContinue), + ID_NAME(IID_IDataObject), + ID_NAME(IID_IDefViewFrame), + ID_NAME(IID_IDeskBand), + ID_NAME(IID_IDeskBar), + ID_NAME(IID_IDeskBarClient), + ID_NAME(IID_IDispatch), + ID_NAME(IID_IDockingWindow), + ID_NAME(IID_IDockingWindowFrame), + ID_NAME(IID_IDockingWindowSite), + ID_NAME(IID_IDocViewSite), + ID_NAME(IID_IDragSourceHelper), + ID_NAME(IID_IDropSource), + ID_NAME(IID_IDropTarget), + ID_NAME(IID_IDropTargetHelper), + ID_NAME(IID_IEnumExtraSearch), + ID_NAME(IID_IEnumGUID), + ID_NAME(IID_IEnumIDList), + ID_NAME(IID_IEnumShellItems), + ID_NAME(IID_IEnumString), + ID_NAME(IID_IEnumUnknown), + ID_NAME(IID_IErrorLog), + ID_NAME(IID_IExplorerToolbar), + ID_NAME(IID_IExtractIconA), + ID_NAME(IID_IExtractIconW), + ID_NAME(IID_IExtractImage), + ID_NAME(IID_IExtractImage2), + ID_NAME(IID_IFileDialog), + ID_NAME(IID_IFileDialog2), + ID_NAME(IID_IFileSearchBand), + ID_NAME(IID_IFolderBandPriv), + ID_NAME(IID_IFolderView), + ID_NAME(IID_IFolderView2), + ID_NAME(IID_IFolderViewOC), + ID_NAME(IID_IFolderViewSettings), + ID_NAME(IID_IGlobalFolderSettings), + ID_NAME(IID_IInitializeObject), + ID_NAME(IID_IInputObject), + ID_NAME(IID_IInputObjectSite), + ID_NAME(IID_IInternalUnknown), + ID_NAME(IID_IMarshal), + ID_NAME(IID_IMenuBand), + ID_NAME(IID_IMenuPopup), + ID_NAME(IID_IMoniker), + ID_NAME(IID_IMultiQI), + ID_NAME(IID_INamespaceProxy), + ID_NAME(IID_INameSpaceTreeControl), + ID_NAME(IID_INSCTree), + ID_NAME(IID_INSCTree2), + ID_NAME(IID_IObjMgr), + ID_NAME(IID_IObjectSafety), + ID_NAME(IID_IObjectWithSite), + ID_NAME(IID_IOleCommandTarget), + ID_NAME(IID_IOleInPlaceActiveObject), + ID_NAME(IID_IOleInPlaceFrame), + ID_NAME(IID_IOleInPlaceObject), + ID_NAME(IID_IOleInPlaceObjectWindowless), + ID_NAME(IID_IOleInPlaceSite), + ID_NAME(IID_IOleInPlaceSiteEx), + ID_NAME(IID_IOleInPlaceSiteWindowless), + ID_NAME(IID_IOleInPlaceUIWindow), + ID_NAME(IID_IOleObject), + ID_NAME(IID_IOleWindow), + ID_NAME(IID_IPersist), + ID_NAME(IID_IPersistFile), + ID_NAME(IID_IPersistFolder), + ID_NAME(IID_IPersistFolder2), + ID_NAME(IID_IPersistFolder3), + ID_NAME(IID_IPersistHistory), + ID_NAME(IID_IPersistIDList), + ID_NAME(IID_IPersistMemory), + ID_NAME(IID_IPersistPropertyBag), + ID_NAME(IID_IPersistPropertyBag2), + ID_NAME(IID_IPersistStorage), + ID_NAME(IID_IPersistStream), + ID_NAME(IID_IPersistStreamInit), + ID_NAME(IID_IProgressDialog), + ID_NAME(IID_IPropertyBag), + ID_NAME(IID_IPropertyBag2), + ID_NAME(IID_IQueryAssociations), + ID_NAME(IID_IQueryInfo), + ID_NAME(IID_IRegTreeOptions), + ID_NAME(IID_IRunnableObject), + ID_NAME(IID_IServerSecurity), + ID_NAME(IID_IServiceProvider), + ID_NAME(IID_IShellBrowser), + ID_NAME(IID_IShellBrowserService), + ID_NAME(IID_IShellChangeNotify), + ID_NAME(IID_IShellDesktopTray), + ID_NAME(IID_IShellDispatch), + ID_NAME(IID_IShellDispatch2), + ID_NAME(IID_IShellDispatch3), + ID_NAME(IID_IShellDispatch4), + ID_NAME(IID_IShellDispatch5), + ID_NAME(IID_IShellIconOverlayIdentifier), + ID_NAME(IID_IShellFolder), + ID_NAME(IID_IShellFolder2), + ID_NAME(IID_IShellFolderBand), + ID_NAME(IID_IShellFolderView), + ID_NAME(IID_IShellFolderViewCB), + ID_NAME(IID_IShellFolderViewDual), + ID_NAME(IID_IShellFolderViewDual2), + ID_NAME(IID_IShellIcon), + ID_NAME(IID_IShellItem), + ID_NAME(IID_IShellItem2), + ID_NAME(IID_IShellItemArray), + ID_NAME(IID_IShellItemFilter), + ID_NAME(IID_IShellLinkA), + ID_NAME(IID_IShellLinkDual), + ID_NAME(IID_IShellLinkDual2), + ID_NAME(IID_IShellLinkW), + ID_NAME(IID_IShellMenu), + ID_NAME(IID_IShellMenu2), + ID_NAME(IID_IShellMenuAcc), + ID_NAME(IID_IShellMenuCallback), + ID_NAME(IID_IShellService), + ID_NAME(IID_IShellView), + ID_NAME(IID_IShellView2), + ID_NAME(IID_IShellView3), + ID_NAME(IID_IShellWindows), + ID_NAME(IID_IStream), + ID_NAME(IID_ISurrogate), + ID_NAME(IID_ISynchronize), + ID_NAME(IID_ISynchronizeContainer), + ID_NAME(IID_ISynchronizeEvent), + ID_NAME(IID_ISynchronizeHandle), + ID_NAME(IID_ITaskbarList), + ID_NAME(IID_ITaskbarList2), + ID_NAME(IID_ITrackShellMenu), + ID_NAME(IID_ITrayPriv), + ID_NAME(IID_ITrayPriv2), + ID_NAME(IID_IUnknown), + ID_NAME(IID_IViewObject), + ID_NAME(IID_IViewObject2), + ID_NAME(IID_IWinEventHandler), + + ID_NAME(IID_DFConstraint), + ID_NAME(DIID_DShellFolderViewEvents), + + ID_NAME(IID_Folder), + ID_NAME(IID_Folder2), + ID_NAME(IID_Folder3), + ID_NAME(IID_FolderItem), + ID_NAME(IID_FolderItem2), + ID_NAME(IID_FolderItems), + ID_NAME(IID_FolderItems2), + ID_NAME(IID_FolderItems3), + ID_NAME(IID_FolderItemVerb), + ID_NAME(IID_FolderItemVerbs), +}; +static const INT KnownInterfaceCount = RTL_NUMBER_OF(KnownInterfaces); + +static +PCKNOWN_INTERFACE +FindInterface( + _In_ const IID *iid) +{ + INT i; + + for (i = 0; i < KnownInterfaceCount; i++) + if (IsEqualIID(KnownInterfaces[i].iid, iid)) + return &KnownInterfaces[i]; + ASSERT(i != KnownInterfaceCount); + return NULL; +} + +static +BOOLEAN +IsInterfaceExpected( + _In_ PCCLASS_AND_INTERFACES class, + _In_ const IID *iid) +{ + INT i; + + for (i = 0; class->ifaces[i].iid; i++) + if (IsEqualIID(class->ifaces[i].iid, iid)) + return TRUE; + return FALSE; +} + +#define INTF_NOT_EXPOSED LONG_MAX +static +LONG +GetInterfaceOffset( + _In_ PUNKNOWN pUnk, + _In_ const IID *iid) +{ + HRESULT hr; + PVOID pObj; + PUNKNOWN pUnk2; + LONG offset; + + hr = IUnknown_QueryInterface(pUnk, iid, &pObj); + ok(hr == S_OK || hr == E_NOINTERFACE, "IUnknown::QueryInterface returned 0x%lx\n", hr); + if (FAILED(hr)) + return INTF_NOT_EXPOSED; + + pUnk2 = pObj; + offset = (LONG_PTR)pObj - (LONG_PTR)pUnk; + IUnknown_Release(pUnk2); + return offset; +} + +static +VOID +TestModuleInterfaces( + _In_ PCCLASS_AND_INTERFACES ExpectedInterfaces, + _In_ INT ExpectedInterfaceCount) +{ + HRESULT hr; + PVOID pObj; + PUNKNOWN pUnk; + INT iClass, iIntf; + PCCLASS_AND_INTERFACES class; + + for (iClass = 0; iClass < ExpectedInterfaceCount; iClass++) + { + class = &ExpectedInterfaces[iClass]; + hr = CoCreateInstance(class->clsid, + NULL, + CLSCTX_INPROC_SERVER, + &IID_IUnknown, + &pObj); + ok(hr == S_OK, "CoCreateInstance failed. hr=0x%lx\n", hr); + if (FAILED(hr)) + { + skip("Failed to instantiate %s.\n", class->name); + continue; + } + + pUnk = pObj; + + /* Check that all expected interfaces are present and have the right offset */ + for (iIntf = 0; class->ifaces[iIntf].iid; iIntf++) + { + PCKNOWN_INTERFACE iface = FindInterface(class->ifaces[iIntf].iid); + LONG offset = GetInterfaceOffset(pUnk, iface->iid); + if (offset == INTF_NOT_EXPOSED) + ok(0, "%s is missing %s (offset %ld)\n", class->name, iface->name, class->ifaces[iIntf].offset); + else if (class->ifaces[iIntf].offset != FARAWY) + { +#ifdef FAIL_WRONG_OFFSET + ok(offset == class->ifaces[iIntf].offset, "%s, %s offset is %ld, expected %ld\n", class->name, iface->name, offset, class->ifaces[iIntf].offset); +#else + if (offset != class->ifaces[iIntf].offset) + mytrace("%s, %s offset is %ld, expected %ld\n", class->name, iface->name, offset, class->ifaces[iIntf].offset); +#endif + } + } + + /* Check that none other than the expected interfaces are present */ + for (iIntf = 0; iIntf < KnownInterfaceCount; iIntf++) + { + PCKNOWN_INTERFACE iface = &KnownInterfaces[iIntf]; + LONG offset; + if (IsInterfaceExpected(class, iface->iid)) + continue; + offset = GetInterfaceOffset(pUnk, iface->iid); +#ifdef GENERATE_TABLE_ENTRIES + ok(offset == INTF_NOT_EXPOSED, "%s: { %s%x, &%s },\n", class->name, offset < 0 ? "-" : "", offset < 0 ? -offset : offset, iface->name); +#else + ok(offset == INTF_NOT_EXPOSED, "%s exposes %s (offset %ld), but shouldn't\n", class->name, iface->name, offset); +#endif + } + + // TODO: do some aggregation + + IUnknown_Release(pUnk); + } +} + +static +VOID +TestModuleRegistry( + _In_ PCWSTR ModuleName, + _In_ PCCLASS_AND_INTERFACES ExpectedInterfaces, + _In_ INT ExpectedInterfaceCount) +{ + INT iClass; + PCCLASS_AND_INTERFACES class; + HKEY hKeyClasses; + LONG result; + + result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Classes\\CLSID", 0, KEY_ENUMERATE_SUB_KEYS, &hKeyClasses); + ok(result == NO_ERROR, "Failed to open classes key, error %lu\n", result); + if (!myskip(result == NO_ERROR, "No classes key\n")) + { + for (iClass = 0; iClass < ExpectedInterfaceCount; iClass++) + { + HKEY hKey; + HKEY hKeyServer; + NTSTATUS status; + UNICODE_STRING clsid; + DWORD type; + WCHAR dllName[100]; + DWORD dllNameSize; + + class = &ExpectedInterfaces[iClass]; + status = RtlStringFromGUID(class->clsid, &clsid); + ok(status == STATUS_SUCCESS, "Failed to convert guid to string for %s, status %lx\n", class->name, status); + if (myskip(NT_SUCCESS(status), "No guid string\n")) + continue; + + result = RegOpenKeyEx(hKeyClasses, clsid.Buffer, 0, KEY_ENUMERATE_SUB_KEYS, &hKey); + ok(result == NO_ERROR, "Failed to open key for %s, error %lu\n", class->name, result); + RtlFreeUnicodeString(&clsid); + if (myskip(result == NO_ERROR, "No key\n")) + continue; + + result = RegOpenKeyEx(hKey, L"InProcServer32", 0, KEY_QUERY_VALUE, &hKeyServer); + ok(result == NO_ERROR, "Failed to open key for %s, error %lu\n", class->name, result); + RegCloseKey(hKey); + if (myskip(result == NO_ERROR, "No key\n")) + continue; + + dllNameSize = sizeof(dllName); + result = RegQueryValueEx(hKeyServer, NULL, NULL, &type, (PBYTE)dllName, &dllNameSize); + ok(result == NO_ERROR, "Failed to query value for %s, error %lu\n", class->name, result); + if (!myskip(result == NO_ERROR, "No module name\n")) + { + ok(type == REG_SZ || type == REG_EXPAND_SZ, "type %lu for %s\n", type, class->name); + ok(dllNameSize % sizeof(WCHAR) == 0, "size %lu for %s\n", dllNameSize, class->name); + ok(dllNameSize <= sizeof(dllName), "size %lu for %s\n", dllNameSize, class->name); + ok(dllName[dllNameSize / sizeof(WCHAR) - 1] == UNICODE_NULL, "Not null terminated for %s\n", class->name); + // TODO: Use SearchPath (or assume everything's in system32) and do a proper full path compare + PathStripPathW(dllName); + PathRemoveExtensionW(dllName); + ok(!wcsicmp(dllName, ModuleName), "Server is %ls, expected %ls for %s\n", dllName, ModuleName, class->name); + } + + dllNameSize = sizeof(dllName); + result = RegQueryValueEx(hKeyServer, L"ThreadingModel", NULL, &type, (PBYTE)dllName, &dllNameSize); + ok(result == NO_ERROR, "Failed to query value for %s, error %lu\n", class->name, result); + if (!myskip(result == NO_ERROR, "No ThreadingModel\n")) + { + ok(type == REG_SZ || type == REG_EXPAND_SZ, "type %lu for %s\n", type, class->name); + ok(dllNameSize % sizeof(WCHAR) == 0, "size %lu for %s\n", dllNameSize, class->name); + ok(dllNameSize <= sizeof(dllName), "size %lu for %s\n", dllNameSize, class->name); + ok(dllName[dllNameSize / sizeof(WCHAR) - 1] == UNICODE_NULL, "Not null terminated for %s\n", class->name); + ok(!wcsicmp(dllName, L"Apartment"), "Server is %ls, expected %ls for %s\n", dllName, L"Apartment", class->name); + } + + RegCloseKey(hKeyServer); + } + RegCloseKey(hKeyClasses); + } +} + +static +VOID +TestManualInstantiation( + _In_ PCWSTR ModuleName, + _In_ PCCLASS_AND_INTERFACES ExpectedInterfaces, + _In_ INT ExpectedInterfaceCount) +{ + INT iClass; + PCCLASS_AND_INTERFACES class; + HRESULT (__stdcall *DllGetClassObject)(REFCLSID, REFIID, PVOID *); + + DllGetClassObject = (PVOID)GetProcAddress(GetModuleHandle(ModuleName), "DllGetClassObject"); + ok(DllGetClassObject != NULL, "DllGetClassObject not found in %ls, error %lu\n", ModuleName, GetLastError()); + if (myskip(DllGetClassObject != NULL, "No DllGetClassObject\n")) + return; + + for (iClass = 0; iClass < ExpectedInterfaceCount; iClass++) + { + PVOID pv; + HRESULT hr; + class = &ExpectedInterfaces[iClass]; + hr = DllGetClassObject(class->clsid, &IID_IClassFactory, &pv); + ok(hr == S_OK, "DllGetClassObject failed for %s, hr = 0x%lx\n", class->name, hr); + if (!myskip(SUCCEEDED(hr), "No class factory\n")) + { + IClassFactory *pCF = pv; + hr = IClassFactory_CreateInstance(pCF, NULL, &IID_IUnknown, &pv); + ok(hr == S_OK, "IClassFactory::CreateInstance failed for %s, hr = 0x%lx\n", class->name, hr); + if (SUCCEEDED(hr)) + { + IUnknown *pUnk = pv; + IUnknown_Release(pUnk); + } + IClassFactory_Release(pCF); + } + } +} + +VOID +TestClasses( + _In_ PCWSTR ModuleName, + _In_ PCCLASS_AND_INTERFACES ExpectedInterfaces, + _In_ INT ExpectedInterfaceCount) +{ + HRESULT hr; + + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + ok(hr == S_OK, "CoInitializeEx failed. hr=0x%lx\n", hr); + if (myskip(SUCCEEDED(hr), "Failed to initialize COM. Cannot perform tests\n")) + return; + + TestModuleInterfaces(ExpectedInterfaces, ExpectedInterfaceCount); + TestModuleRegistry(ModuleName, ExpectedInterfaces, ExpectedInterfaceCount); + TestManualInstantiation(ModuleName, ExpectedInterfaces, ExpectedInterfaceCount); + + CoUninitialize(); +} diff --git a/rostests/apitests/com/com_apitest.h b/rostests/apitests/com/com_apitest.h new file mode 100644 index 00000000000..bcaf19f9120 --- /dev/null +++ b/rostests/apitests/com/com_apitest.h @@ -0,0 +1,108 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: COM interface test + * PROGRAMMER: Thomas Faber + */ + +#pragma once + +/* Define this if you're adding new classes - the test will auto-generate the + * interface table entries for you ;) */ +//#define GENERATE_TABLE_ENTRIES + +/* Define this to make wrong interface offsets count as test failures... + * we usually don't want to be that strict */ +//#define FAIL_WRONG_OFFSET + +#define COBJMACROS +#define WIN32_NO_STATUS +#define UNICODE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RTL_NUMBER_OF(x) (sizeof(x) / sizeof(x[0])) +typedef IUnknown *PUNKNOWN; + +typedef struct _CLASS_AND_INTERFACES +{ + const CLSID *clsid; + PCSTR name; + struct + { + LONG offset; + const IID *iid; + } ifaces[80]; +} CLASS_AND_INTERFACES; +typedef const CLASS_AND_INTERFACES *PCCLASS_AND_INTERFACES; + +#define ID_NAME(c) &c, #c + +VOID +TestClasses( + _In_ PCWSTR ModuleName, + _In_ PCCLASS_AND_INTERFACES ExpectedInterfaces, + _In_ INT ExpectedInterfaceCount); + +/* Indicate that the interface is implemented in another (probably aggregate) object, + * so its offset varies and is "far away" */ +#define FARAWY (-65535) + +// TODO: fix our headers... we really shouldn't need these here +DEFINE_GUID(CLSID_CopyToMenu, 0xC2FBB630, 0x2971, 0x11D1, 0xA1, 0x8C, 0x00, 0xC0, 0x4F, 0xD7, 0x5D, 0x13); +DEFINE_GUID(CLSID_DeskMovr, 0x72267F6A, 0xA6F9, 0x11D0, 0xBC, 0x94, 0x00, 0xC0, 0x4F, 0xB6, 0x78, 0x63); +DEFINE_GUID(CLSID_FadeTask, 0x7EB5FBE4, 0x2100, 0x49E6, 0x85, 0x93, 0x17, 0xE1, 0x30, 0x12, 0x2F, 0x91); +DEFINE_GUID(CLSID_FileSearchBand, 0xc4ee31f3, 0x4768, 0x11d2, 0xbe, 0x5c, 0x00, 0xa0, 0xc9, 0xa8, 0x3d, 0xa1); +DEFINE_GUID(CLSID_FolderItem, 0xfef10fa2, 0x355e, 0x4e06, 0x93, 0x81, 0x9b, 0x24, 0xd7, 0xf7, 0xcc, 0x88); +DEFINE_GUID(CLSID_FolderItemsFDF, 0x53c74826, 0xab99, 0x4d33, 0xac, 0xa4, 0x31, 0x17, 0xf5, 0x1d, 0x37, 0x88); +DEFINE_GUID(CLSID_FolderViewHost, 0x20b1cb23, 0x6968, 0x4eb9, 0xb7, 0xd4, 0xa6, 0x6d, 0x00, 0xd0, 0x7c, 0xee); +DEFINE_GUID(CLSID_ISFBand, 0xD82BE2B0, 0x5764, 0x11D0, 0xA9, 0x6E, 0x00, 0xC0, 0x4F, 0xD7, 0x05, 0xA2); +DEFINE_GUID(CLSID_MenuDeskBar, 0xECD4FC4F, 0x521C, 0x11D0, 0xB7, 0x92, 0x00, 0xA0, 0xC9, 0x03, 0x12, 0xE1); +DEFINE_GUID(CLSID_MenuToolbarBase, 0x40b96610, 0xb522, 0x11d1, 0xb3, 0xb4, 0x00, 0xaa, 0x00, 0x6e, 0xfd, 0xe7); +DEFINE_GUID(CLSID_MoveToMenu, 0xC2FBB631, 0x2971, 0x11D1, 0xA1, 0x8C, 0x00, 0xC0, 0x4F, 0xD7, 0x5D, 0x13); +DEFINE_GUID(CLSID_QuickLinks, 0x0E5CBF21, 0xD15F, 0x11D0, 0x83, 0x01, 0x00, 0xAA, 0x00, 0x5B, 0x43, 0x83); +DEFINE_GUID(CLSID_SendToMenu, 0x7BA4C740, 0x9E81, 0x11CF, 0x99, 0xD3, 0x00, 0xAA, 0x00, 0x4A, 0xE8, 0x37); +DEFINE_GUID(CLSID_ShellFolderView, 0x62112aa1, 0xebe4, 0x11cf, 0xa5, 0xfb, 0x00, 0x20, 0xaf, 0xe7, 0x29, 0x2d); +DEFINE_GUID(CLSID_ShellLinkObject, 0x11219420, 0x1768, 0x11d1, 0x95, 0xbe, 0x00, 0x60, 0x97, 0x97, 0xea, 0x4f); +DEFINE_GUID(CLSID_StartMenuPin, 0xa2a9545d, 0xa0c2, 0x42b4, 0x97, 0x08, 0xa0, 0xb2, 0xba, 0xdd, 0x77, 0xc8); +DEFINE_GUID(CLSID_TrackShellMenu, 0x8278F931, 0x2A3E, 0x11d2, 0x83, 0x8F, 0x00, 0xC0, 0x4F, 0xD9, 0x18, 0xD0); + +DEFINE_GUID(IID_IDefViewFrame, 0x710EB7A0, 0x45ED, 0x11D0, 0x92, 0x4A, 0x00, 0x20, 0xAF, 0xC7, 0xAC, 0x4D); +DEFINE_GUID(IID_IDocViewSite, 0x87D605E0, 0xC511, 0x11CF, 0x89, 0xA9, 0x00, 0xA0, 0xC9, 0x05, 0x41, 0x29); +DEFINE_GUID(IID_IExtractImage, 0xbb2e617c, 0x0920, 0x11d1, 0x9a, 0x0b, 0x00, 0xc0, 0x4f, 0xc2, 0xd6, 0xc1); +DEFINE_GUID(IID_IExtractImage2, 0x953bb1ee, 0x93b4, 0x11d1, 0x98, 0xa3, 0x00, 0xc0, 0x4f, 0xb6, 0x87, 0xda); +DEFINE_GUID(IID_IFileSearchBand, 0x2d91eea1, 0x9932, 0x11d2, 0xbe, 0x86, 0x00, 0xa0, 0xc9, 0xa8, 0x3d, 0xa1); +DEFINE_GUID(IID_IFolderBandPriv, 0x47c01f95, 0xe185, 0x412c, 0xb5, 0xc5, 0x4f, 0x27, 0xdf, 0x96, 0x5a, 0xea); +DEFINE_GUID(IID_IFolderView2, 0x1af3a467, 0x214f, 0x4298, 0x90, 0x8e, 0x06, 0xb0, 0x3e, 0x0b, 0x39, 0xf9); +DEFINE_GUID(IID_IFolderViewSettings, 0xae8c987d, 0x8797, 0x4ed3, 0xbe, 0x72, 0x2a, 0x47, 0xdd, 0x93, 0x8d, 0xb0); +DEFINE_GUID(IID_IShellDispatch3, 0x177160ca, 0xbb5a, 0x411c, 0x84, 0x1d, 0xbd, 0x38, 0xfa, 0xcd, 0xea, 0xa0); +DEFINE_GUID(IID_IShellDispatch4, 0xefd84b2d, 0x4bcf, 0x4298, 0xbe, 0x25, 0xeb, 0x54, 0x2a, 0x59, 0xfb, 0xda); +DEFINE_GUID(IID_IShellDispatch5, 0x866738b9, 0x6cf2, 0x4de8, 0x87, 0x67, 0xf7, 0x94, 0xeb, 0xe7, 0x4f, 0x4e); +DEFINE_GUID(IID_IContextMenuSite, 0x0811aebe, 0x0b87, 0x4c54, 0x9e, 0x72, 0x54, 0x8c, 0xf6, 0x49, 0x01, 0x6b); +DEFINE_GUID(IID_IShellDesktopTray, 0x213e2df9, 0x9a14, 0x4328, 0x99, 0xb1, 0x69, 0x61, 0xf9, 0x14, 0x3c, 0xe9); +DEFINE_GUID(IID_IShellFolderBand, 0x7fe80cc8, 0xc247, 0x11d0, 0xb9, 0x3a, 0x00, 0xa0, 0xc9, 0x03, 0x12, 0xe1); +DEFINE_GUID(IID_IShellFolderViewDual, 0xe7a1af80, 0x4d96, 0x11cf, 0x96, 0x0c, 0x00, 0x80, 0xc7, 0xf4, 0xee, 0x85); +DEFINE_GUID(IID_IShellFolderViewDual2, 0x31c147b6, 0x0ade, 0x4a3c, 0xb5, 0x14, 0xdd, 0xf9, 0x32, 0xef, 0x6d, 0x17); +DEFINE_GUID(IID_IShellLinkDual, 0x88a05c00, 0xf000, 0x11ce, 0x83, 0x50, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00); +DEFINE_GUID(IID_IShellLinkDual2, 0x317ee249, 0xf12e, 0x11d2, 0xb1, 0xe4, 0x00, 0xc0, 0x4f, 0x8e, 0xeb, 0x3e); +DEFINE_GUID(IID_IShellView3, 0xec39fa88, 0xf8af, 0x41c5, 0x84, 0x21, 0x38, 0xbe, 0xd2, 0x8f, 0x46, 0x73); + +DEFINE_GUID(IID_DFConstraint, 0x403df050, 0x23bd, 0x11d2, 0x93, 0x9f, 0x00, 0xa0, 0xc9, 0x1e, 0xed, 0xba); + +DEFINE_GUID(IID_FolderItems2, 0xc94f0ad0, 0xf363, 0x11d2, 0xa3, 0x27, 0x00, 0xc0, 0x4f, 0x8e, 0xec, 0x7f); +DEFINE_GUID(IID_FolderItems3, 0xeaa7c309, 0xbbec, 0x49d5, 0x82, 0x1d, 0x64, 0xd9, 0x66, 0xcb, 0x66, 0x7f); diff --git a/rostests/apitests/com/ieframe.c b/rostests/apitests/com/ieframe.c new file mode 100644 index 00000000000..f8aacbaceb5 --- /dev/null +++ b/rostests/apitests/com/ieframe.c @@ -0,0 +1,32 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: COM interface test for ieframe classes + * PROGRAMMER: Thomas Faber + */ + +#include "com_apitest.h" + +#define NDEBUG +#include + +static const CLASS_AND_INTERFACES ExpectedInterfaces[] = +{ + { + ID_NAME(CLSID_ShellWindows), + { + { -0xa0, &IID_IMarshal }, + { -0x20, &IID_IClientSecurity }, + { 0x0, &IID_IMultiQI }, + { 0x0, &IID_IUnknown }, + { FARAWY, &IID_IShellWindows }, + { FARAWY, &IID_IDispatch }, + } + }, +}; +static const INT ExpectedInterfaceCount = RTL_NUMBER_OF(ExpectedInterfaces); + +START_TEST(ieframe) +{ + TestClasses(L"ieframe", ExpectedInterfaces, ExpectedInterfaceCount); +} diff --git a/rostests/apitests/com/shdocvw.c b/rostests/apitests/com/shdocvw.c new file mode 100644 index 00000000000..62dfe324e17 --- /dev/null +++ b/rostests/apitests/com/shdocvw.c @@ -0,0 +1,57 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: COM interface test for shdocvw classes + * PROGRAMMER: Thomas Faber + */ + +#include "com_apitest.h" + +#define NDEBUG +#include + +static const CLASS_AND_INTERFACES ExpectedInterfaces[] = +{ + { + ID_NAME(CLSID_FontsFolderShortcut), + { + { 0x0, &IID_IShellFolder2 }, + { 0x0, &IID_IShellFolder }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IPersistFolder3 }, + { 0x4, &IID_IPersistFolder2 }, + { 0x4, &IID_IPersistFolder }, + { 0x4, &IID_IPersist }, + { 0x8, &IID_IShellLinkA }, + { 0xc, &IID_IShellLinkW }, + { 0x10, &IID_IPersistFile }, + { 0x14, &IID_IExtractIconW }, + { 0x18, &IID_IQueryInfo }, + { 0x20, &IID_IPersistStream }, + { 0x20, &IID_IPersistStreamInit }, + { 0x24, &IID_IPersistPropertyBag }, + } + }, +#if 0 // E_OUTOFMEMORY? + { + ID_NAME(CLSID_ShellDispatchInproc), + { + { 0x0, &IID_IUnknown }, + } + }, +#endif + { + ID_NAME(CLSID_TaskbarList), + { + { 0x0, &IID_ITaskbarList2 }, + { 0x0, &IID_ITaskbarList }, + { 0x0, &IID_IUnknown }, + } + }, +}; +static const INT ExpectedInterfaceCount = RTL_NUMBER_OF(ExpectedInterfaces); + +START_TEST(shdocvw) +{ + TestClasses(L"shdocvw", ExpectedInterfaces, ExpectedInterfaceCount); +} diff --git a/rostests/apitests/com/shell32.c b/rostests/apitests/com/shell32.c new file mode 100644 index 00000000000..c943a06dad7 --- /dev/null +++ b/rostests/apitests/com/shell32.c @@ -0,0 +1,437 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: COM interface test for shell32 classes + * PROGRAMMER: Thomas Faber + */ + +#include "com_apitest.h" + +#define NDEBUG +#include + +static const CLASS_AND_INTERFACES ExpectedInterfaces[] = +{ + { + ID_NAME(CLSID_CopyToMenu), + { + { 0x0, &IID_IContextMenu3 }, + { 0x0, &IID_IContextMenu2 }, + { 0x0, &IID_IContextMenu }, + { 0x0, &IID_IUnknown }, + { 0x8, &IID_IObjectWithSite }, + } + }, + { + ID_NAME(CLSID_DeskMovr), + { + { 0x0, &IID_IUnknown }, + { 0x74, &IID_IOleObject }, + { 0x78, &IID_IPersistPropertyBag }, + { 0x80, &IID_IOleInPlaceActiveObject }, + { 0x84, &IID_IViewObject2 }, + { 0x84, &IID_IViewObject }, + { 0x88, &IID_IOleWindow }, + { 0x88, &IID_IOleInPlaceObject }, + { 0x88, &IID_IOleInPlaceObjectWindowless }, + } + }, + { + ID_NAME(CLSID_DragDropHelper), + { + { 0x0, &IID_IDragSourceHelper }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IDropTargetHelper }, + } + }, + { + ID_NAME(CLSID_FadeTask), + { + { 0x0, &IID_IUnknown }, + } + }, + { + ID_NAME(CLSID_FileSearchBand), + { + { 0x0, &IID_IFileSearchBand }, + { 0x0, &IID_IDispatch }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IObjectWithSite }, + { 0x8, &IID_IPersistStream }, + { 0x8, &IID_IPersist }, + { 0xc, &IID_IDeskBand }, + { 0xc, &IID_IDockingWindow }, + { 0xc, &IID_IOleWindow }, + { 0x10, &IID_IInputObject }, + { 0x18, &IID_IOleInPlaceSite }, + } + }, + { + ID_NAME(CLSID_FolderItem), + { + //{ 0x0, &CLSID_ShellFolderItem }, // broken QueryInterface that doesn't add a reference + { 0x0, &IID_FolderItem2 }, + { 0x0, &IID_FolderItem }, + { 0x0, &IID_IDispatch }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IPersistFolder2 }, + { 0x4, &IID_IPersistFolder }, + { 0x4, &IID_IPersist }, + { 0x8, &IID_IObjectSafety }, + } + }, + { + ID_NAME(CLSID_FolderItemsFDF), + { + { 0x0, &IID_FolderItems3 }, + //{ 0x0, &IID_FolderItems2 }, ???? + { 0x0, &IID_FolderItems }, + { 0x0, &IID_IDispatch }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IPersistFolder }, + { 0x8, &IID_IObjectSafety }, + } + }, + { + ID_NAME(CLSID_FolderShortcut), + { + { 0x0, &IID_IShellFolder2 }, + { 0x0, &IID_IShellFolder }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IPersistFolder3 }, + { 0x4, &IID_IPersistFolder2 }, + { 0x4, &IID_IPersistFolder }, + { 0x4, &IID_IPersist }, + { 0x8, &IID_IShellLinkA }, + { 0xc, &IID_IShellLinkW }, + { 0x10, &IID_IPersistFile }, + { 0x14, &IID_IExtractIconW }, + { 0x18, &IID_IQueryInfo }, + { 0x20, &IID_IPersistStream }, + { 0x20, &IID_IPersistStreamInit }, + { 0x24, &IID_IPersistPropertyBag }, + } + }, + { + ID_NAME(CLSID_FolderViewHost), + { + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IServiceProvider }, + { 0x8, &IID_IOleWindow }, + { 0xc, &IID_IFolderView }, + { 0x10, &IID_IObjectWithSite }, + } + }, + { + ID_NAME(CLSID_ISFBand), + { + { -0xac, &IID_IDeskBand }, + { -0xac, &IID_IDockingWindow }, + { -0xac, &IID_IOleWindow }, + { -0xa8, &IID_IObjectWithSite }, + { -0xa0, &IID_IInputObject }, + { -0x9c, &IID_IPersistStream }, + { -0x9c, &IID_IPersist }, + { -0x98, &IID_IOleCommandTarget }, + { -0x94, &IID_IServiceProvider }, + { -0x78, &IID_IWinEventHandler }, + { -0x74, &IID_IShellChangeNotify }, + { -0x70, &IID_IDropTarget }, + { -0x4, &IID_IContextMenu }, + { 0x0, &IID_IShellFolderBand }, + { 0x0, &IID_IUnknown }, + { 0x94, &IID_IFolderBandPriv }, + } + }, + { + ID_NAME(CLSID_MenuBand), + { + { -0x30, &IID_IDeskBand }, + { -0x30, &IID_IDockingWindow }, + { -0x30, &IID_IOleWindow }, + { -0x2c, &IID_IObjectWithSite }, + { -0x24, &IID_IInputObject }, + { -0x20, &IID_IPersistStream }, + { -0x20, &IID_IPersist }, + { -0x1c, &IID_IOleCommandTarget }, + { -0x18, &IID_IServiceProvider }, + { 0x0, &IID_IMenuPopup }, + { 0x0, &IID_IDeskBar }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IMenuBand }, + { 0x8, &IID_IShellMenu2 }, + { 0x8, &IID_IShellMenu }, + { 0xc, &IID_IWinEventHandler }, + { 0x10, &IID_IShellMenuAcc }, + } + }, + { + ID_NAME(CLSID_MenuBandSite), + { + { 0x0, &IID_IBandSite }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IDeskBarClient }, + { 0x4, &IID_IOleWindow }, + { 0x8, &IID_IOleCommandTarget }, + { 0xc, &IID_IInputObject }, + { 0x10, &IID_IInputObjectSite }, + { 0x14, &IID_IWinEventHandler }, + { 0x18, &IID_IServiceProvider }, + } + }, + { + ID_NAME(CLSID_MenuDeskBar), + { + { -0x48, &IID_IOleCommandTarget }, + { -0x44, &IID_IServiceProvider }, + { -0x40, &IID_IDeskBar }, + { -0x40, &IID_IOleWindow }, + { -0x3c, &IID_IInputObjectSite }, + { -0x38, &IID_IInputObject }, + { 0x0, &IID_IMenuPopup }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IObjectWithSite }, + { 0x8, &IID_IBanneredBar }, + { 0xc, &IID_IInitializeObject }, + } + }, +#if 0 // This is registered to shell32, but can't be instanciated + { + ID_NAME(CLSID_MenuToolbarBase), + { + { 0x0, &IID_IUnknown }, + } + }, +#endif + { + ID_NAME(CLSID_MoveToMenu), + { + { 0x0, &IID_IContextMenu3 }, + { 0x0, &IID_IContextMenu2 }, + { 0x0, &IID_IContextMenu }, + { 0x0, &IID_IUnknown }, + { 0x8, &IID_IObjectWithSite }, + } + }, + { + ID_NAME(CLSID_NewMenu), + { + { -0xc, &IID_IObjectWithSite }, + { -0x4, &IID_IContextMenu3 }, + { -0x4, &IID_IContextMenu2 }, + { -0x4, &IID_IContextMenu }, + { 0x0, &IID_IUnknown }, + } + }, + { + ID_NAME(CLSID_PersonalStartMenu), + { + { -0x30, &IID_IDeskBand }, + { -0x30, &IID_IDockingWindow }, + { -0x30, &IID_IOleWindow }, + { -0x2c, &IID_IObjectWithSite }, + { -0x24, &IID_IInputObject }, + { -0x20, &IID_IPersistStream }, + { -0x20, &IID_IPersist }, + { -0x1c, &IID_IOleCommandTarget }, + { -0x18, &IID_IServiceProvider }, + { 0x0, &IID_IMenuPopup }, + { 0x0, &IID_IDeskBar }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IMenuBand }, + { 0x8, &IID_IShellMenu2 }, + { 0x8, &IID_IShellMenu }, + { 0xc, &IID_IWinEventHandler }, + { 0x10, &IID_IShellMenuAcc }, + } + }, + { + ID_NAME(CLSID_QuickLinks), + { + { -0xac, &IID_IDeskBand }, + { -0xac, &IID_IDockingWindow }, + { -0xac, &IID_IOleWindow }, + { -0xa8, &IID_IObjectWithSite }, + { -0xa0, &IID_IInputObject }, + { -0x9c, &IID_IPersistStream }, + { -0x9c, &IID_IPersist }, + { -0x98, &IID_IOleCommandTarget }, + { -0x94, &IID_IServiceProvider }, + { -0x78, &IID_IWinEventHandler }, + { -0x74, &IID_IShellChangeNotify }, + { -0x70, &IID_IDropTarget }, + { -0x4, &IID_IContextMenu }, + { 0x0, &IID_IShellFolderBand }, + { 0x0, &IID_IUnknown }, + { 0x94, &IID_IFolderBandPriv }, + } + }, + { + ID_NAME(CLSID_SendToMenu), + { + { -0x4, &IID_IContextMenu3 }, + { -0x4, &IID_IContextMenu2 }, + { -0x4, &IID_IContextMenu }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IOleWindow }, + } + }, + { + ID_NAME(CLSID_Shell), + { + { 0x0, &IID_IShellDispatch4 }, + { 0x0, &IID_IShellDispatch3 }, + { 0x0, &IID_IShellDispatch2 }, + { 0x0, &IID_IShellDispatch }, + { 0x0, &IID_IDispatch }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IObjectSafety }, + { 0x20, &IID_IObjectWithSite }, + } + }, + { + ID_NAME(CLSID_ShellDesktop), + { + { -0x8, &IID_IObjectWithSite }, + { 0x0, &IID_IUnknown }, + { 0x8, &IID_IPersistFolder2 }, + { 0x8, &IID_IPersistFolder }, + { 0x8, &IID_IPersist }, + { 0xc, &IID_IShellIcon }, + { 0x14, &IID_IContextMenuCB }, + { 0x20, &IID_IOleCommandTarget }, + { FARAWY, &IID_IShellFolder2 }, + { FARAWY, &IID_IShellFolder }, + } + }, + { + ID_NAME(CLSID_ShellFSFolder), + { + { 0x0, &IID_IUnknown }, + { 0xc, &IID_IShellFolder2 }, + { 0xc, &IID_IShellFolder }, + { 0x10, &IID_IShellIcon }, + { 0x18, &IID_IPersistFolder3 }, + { 0x18, &IID_IPersistFolder2 }, + { 0x18, &IID_IPersistFolder }, + { 0x18, &IID_IPersist }, + { 0x2c, &IID_IContextMenuCB }, + { 0x34, &IID_IOleCommandTarget }, + } + }, + { + ID_NAME(CLSID_ShellFldSetExt), + { + { 0x0, &IID_IUnknown }, + { 0x8, &IID_IObjectWithSite }, + } + }, + { + ID_NAME(CLSID_ShellFolderView), + { + { 0x0, &IID_IShellFolderViewDual2 }, + { 0x0, &IID_IShellFolderViewDual }, + { 0x0, &IID_IDispatch }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IShellService }, + { 0x8, &IID_IServiceProvider }, + { 0xc, &IID_IObjectSafety }, + { 0x14, &IID_IObjectWithSite }, + } + }, + { + ID_NAME(CLSID_ShellFolderViewOC), + { + { 0x0, &IID_IFolderViewOC }, + { 0x0, &IID_IDispatch }, + { 0x0, &IID_IUnknown }, + { 0x8, &IID_IObjectSafety }, + { 0x88, &IID_IPersistStreamInit }, + { 0x88, &IID_IPersist }, + { 0x90, &IID_IOleObject }, + { 0x94, &IID_IOleInPlaceActiveObject }, + { 0x98, &IID_IOleInPlaceObjectWindowless }, + { 0x98, &IID_IOleInPlaceObject }, + { 0x98, &IID_IOleWindow }, + } + }, + { + ID_NAME(CLSID_ShellItem), + { + { 0x0, &IID_IShellItem }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IPersistIDList }, + } + }, + { + ID_NAME(CLSID_ShellLink), + { + { 0x0, &IID_IShellLinkA }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IShellLinkW }, + { 0x8, &IID_IPersistStream }, + { 0xc, &IID_IPersistFile }, + { 0x14, &IID_IContextMenu3 }, + { 0x14, &IID_IContextMenu2 }, + { 0x14, &IID_IContextMenu }, + { 0x18, &IID_IDropTarget }, + { 0x1c, &IID_IQueryInfo }, + { 0x24, &IID_IExtractIconA }, + { 0x28, &IID_IExtractIconW }, + { 0x2c, &IID_IExtractImage2 }, + { 0x2c, &IID_IExtractImage }, + { 0x30, &IID_IPersistPropertyBag }, + { 0x34, &IID_IServiceProvider }, + { 0x3c, &IID_IObjectWithSite }, + } + }, +#if 0 // Apparently we can only get this through Folder.Items().GetLink + { + ID_NAME(CLSID_ShellLinkObject), + { + { 0x0, &IID_IUnknown }, + } + }, +#endif + { + ID_NAME(CLSID_StartMenu), + { + { -0x48, &IID_IOleCommandTarget }, + { -0x44, &IID_IServiceProvider }, + { -0x40, &IID_IDeskBar }, + { -0x40, &IID_IOleWindow }, + { -0x3c, &IID_IInputObjectSite }, + { -0x38, &IID_IInputObject }, + { 0x0, &IID_IMenuPopup }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IObjectWithSite }, + { 0x8, &IID_IBanneredBar }, + { 0xc, &IID_IInitializeObject }, + } + }, + { + ID_NAME(CLSID_StartMenuPin), + { + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IContextMenu }, + { 0xc, &IID_IObjectWithSite }, + } + }, + { + ID_NAME(CLSID_TrackShellMenu), + { + { 0x0, &IID_ITrackShellMenu }, + { 0x0, &IID_IShellMenu }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IShellMenu2 }, + { 0x8, &IID_IObjectWithSite }, + { 0xc, &IID_IServiceProvider }, + } + }, +}; +static const INT ExpectedInterfaceCount = RTL_NUMBER_OF(ExpectedInterfaces); + +START_TEST(shell32) +{ + TestClasses(L"shell32", ExpectedInterfaces, ExpectedInterfaceCount); +} diff --git a/rostests/apitests/com/testlist.c b/rostests/apitests/com/testlist.c new file mode 100644 index 00000000000..941a9916e69 --- /dev/null +++ b/rostests/apitests/com/testlist.c @@ -0,0 +1,21 @@ +#define WIN32_LEAN_AND_MEAN +#define __ROS_LONG64__ +#include + +#define STANDALONE +#include "wine/test.h" + +extern void func_browseui(void); +extern void func_ieframe(void); +extern void func_shdocvw(void); +extern void func_shell32(void); + +const struct test winetest_testlist[] = +{ + { "browseui", func_browseui }, + { "ieframe", func_ieframe }, + { "shdocvw", func_shdocvw }, + { "shell32", func_shell32 }, + + { 0, 0 } +};