Index: browseui/CMakeLists.txt =================================================================== --- modules/rostests/apitests/browseui/CMakeLists.txt (revision 0) +++ modules/rostests/apitests/browseui/CMakeLists.txt (working copy) @@ -0,0 +1,10 @@ + +list(APPEND SOURCE + SHExplorerParseCmdLine.c + testlist.c) + +add_executable(browseui_apitest ${SOURCE}) +target_link_libraries(browseui_apitest wine) +set_module_type(browseui_apitest win32cui) +add_importlibs(browseui_apitest browseui shell32 msvcrt kernel32 ntdll) +add_cd_file(TARGET browseui_apitest DESTINATION reactos/bin FOR all) Index: browseui/SHExplorerParseCmdLine.c =================================================================== --- modules/rostests/apitests/browseui/SHExplorerParseCmdLine.c (revision 0) +++ modules/rostests/apitests/browseui/SHExplorerParseCmdLine.c (working copy) @@ -0,0 +1,144 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Test for SHExplorerParseCmdLine + * PROGRAMMER: Thomas Faber + */ + +#define UNICODE +#include +#include +#include + +#define UNKNOWN_SIZE 0x100 + +typedef struct _EXPLORER_INFO +{ + PWSTR SomeValue; + PIDLIST_ABSOLUTE pidl; + DWORD dwFlags; + ULONG Unknown[UNKNOWN_SIZE]; +} EXPLORER_INFO, *PEXPLORER_INFO; + +PVOID +WINAPI +SHExplorerParseCmdLine( + PEXPLORER_INFO Info); + +#define PIDL_IS_UNTOUCHED -1 +#define PIDL_IS_NULL -2 +#define PIDL_IS_PATH -3 + +static +VOID +TestCommandLine( + _In_ INT ExpectedRet, + _In_ INT ExpectedCsidl, + _In_ DWORD ExpectedFlags, + _In_ PCWSTR ExpectedFileName, + _In_ PCWSTR PidlPath) +{ + EXPLORER_INFO Info; + PVOID Ret; + ULONG i; + + FillMemory(&Info, sizeof(Info), 0x55); + Info.dwFlags = 0x00000000; + Ret = SHExplorerParseCmdLine(&Info); + + if (ExpectedRet == -1) + ok(Ret == Info.pidl, "Ret = %p, expected %p\n", Ret, Info.pidl); + else + ok(Ret == (PVOID)ExpectedRet, "Ret = %p, expected %p\n", Ret, (PVOID)ExpectedRet); + + if (ExpectedFileName == NULL) + ok(Info.SomeValue == (PVOID)0x5555555555555555ULL, "SomeValue = %p\n", Info.SomeValue); + else + { + ok(Info.SomeValue != NULL && Info.SomeValue != (PVOID)0x5555555555555555ULL, "SomeValue = %p\n", Info.SomeValue); + if (Info.SomeValue != NULL && Info.SomeValue != (PVOID)0x5555555555555555ULL) + { + ok(!wcscmp(Info.SomeValue, ExpectedFileName), "FileName = %ls, expected %ls\n", Info.SomeValue, ExpectedFileName); + LocalFree(Info.SomeValue); + } + } + + if (ExpectedCsidl == PIDL_IS_UNTOUCHED) + ok(Info.pidl == (PVOID)0x5555555555555555ULL, "pidl = %p\n", Info.pidl); + else if (ExpectedCsidl == PIDL_IS_NULL) + ok(Info.pidl == NULL, "pidl = %p\n", Info.pidl); + else + { + PIDLIST_ABSOLUTE ExpectedPidl; + HRESULT hr; + + ok(Info.pidl != NULL, "pidl = %p\n", Info.pidl); + if (Info.pidl != NULL && Info.pidl != (PVOID)0x5555555555555555ULL) + { + if (ExpectedCsidl == PIDL_IS_PATH) + { + ExpectedPidl = SHSimpleIDListFromPath(PidlPath); + hr = ExpectedPidl == NULL ? E_FAIL : S_OK; + ok(ExpectedPidl != NULL, "SHSimpleIDListFromPath failed\n"); + } + else + { + hr = SHGetFolderLocation(NULL, ExpectedCsidl, NULL, 0, &ExpectedPidl); + ok(hr == S_OK, "SHGetFolderLocation returned %08lx\n", hr); + } + if (SUCCEEDED(hr)) + { + ok(ILIsEqual(Info.pidl, ExpectedPidl), "Unexpected pidl value\n"); + ILFree(ExpectedPidl); + } + ILFree(Info.pidl); + } + } + + ok(Info.dwFlags == ExpectedFlags, "dwFlags = %08lx, expected %08lx\n", Info.dwFlags, ExpectedFlags); + for (i = 0; i < sizeof(Info.Unknown) / sizeof(Info.Unknown[0]); i++) + ok(Info.Unknown[i] == 0x55555555, "Unknown[%lu] = %08lx\n", i, Info.Unknown[i]); +} + +START_TEST(SHExplorerParseCmdLine) +{ + struct + { + PCWSTR CommandLine; + INT ExpectedRet; + INT ExpectedCsidl; + DWORD ExpectedFlags; + PCWSTR ExpectedFileName; + PCWSTR PidlPath; + } Tests[] = + { + { L"", -1, CSIDL_MYDOCUMENTS, 0x00000009 }, + { L"/e", TRUE, PIDL_IS_UNTOUCHED, 0x00000008 }, + { L"/n", TRUE, PIDL_IS_UNTOUCHED, 0x00004001 }, + { L"/x", TRUE, PIDL_IS_NULL, 0x02000000, L"/x" }, + { L"-e", TRUE, PIDL_IS_NULL, 0x02000000, L"-e" }, + { L"C:\\", TRUE, PIDL_IS_PATH, 0x00000200, NULL, L"C:\\" }, + { L"/e,C:\\", TRUE, PIDL_IS_PATH, 0x00000208, NULL, L"C:\\" }, + }; + int TestCount = sizeof(Tests) / sizeof(Tests[0]); + PWSTR CommandLine; + WCHAR OriginalCommandLine[1024]; + int i; + + CommandLine = GetCommandLine(); + (VOID)StringCbCopy(OriginalCommandLine, sizeof(OriginalCommandLine), CommandLine); + + for (i = 0; i < TestCount; i++) + { + wcscpy(CommandLine, L"browseui_apitest.exe "); + wcscat(CommandLine, Tests[i].CommandLine); + trace("Command line: %ls\n", CommandLine); + TestCommandLine(Tests[i].ExpectedRet, + Tests[i].ExpectedCsidl, + Tests[i].ExpectedFlags, + Tests[i].ExpectedFileName, + Tests[i].PidlPath); + } + + wcscpy(CommandLine, OriginalCommandLine); +} Index: browseui/testlist.c =================================================================== --- modules/rostests/apitests/browseui/testlist.c (revision 0) +++ modules/rostests/apitests/browseui/testlist.c (working copy) @@ -0,0 +1,16 @@ +#define WIN32_LEAN_AND_MEAN +#define __ROS_LONG64__ +#include + +#define STANDALONE +#include "wine/test.h" + +extern void func_SHExplorerParseCmdLine(void); + +const struct test winetest_testlist[] = +{ + { "SHExplorerParseCmdLine", func_SHExplorerParseCmdLine }, + + { 0, 0 } +}; + Index: CMakeLists.txt =================================================================== --- modules/rostests/apitests/CMakeLists.txt (revision 58178) +++ modules/rostests/apitests/CMakeLists.txt (working copy) @@ -2,13 +2,16 @@ add_library(apitest apitest.c) add_subdirectory(advapi32) +add_subdirectory(browseui) add_subdirectory(crt) add_subdirectory(dciman32) +#add_subdirectory(explorer) add_subdirectory(gdi32) add_subdirectory(kernel32) add_subdirectory(msvcrt) add_subdirectory(ntdll) add_subdirectory(powrprof) +add_subdirectory(shell32) add_subdirectory(user32) if((NOT MSVC) AND (ARCH STREQUAL "i386")) add_subdirectory(w32kdll) Index: shell32/CMakeLists.txt =================================================================== --- modules/rostests/apitests/shell32/CMakeLists.txt (revision 0) +++ modules/rostests/apitests/shell32/CMakeLists.txt (working copy) @@ -0,0 +1,11 @@ + +list(APPEND SOURCE + interfaces.c + testlist.c) + +add_executable(shell32_apitest ${SOURCE}) +target_link_libraries(shell32_apitest wine uuid) +set_module_type(shell32_apitest win32cui) +add_importlibs(shell32_apitest shell32 ole32 msvcrt kernel32 ntdll) + +add_cd_file(TARGET shell32_apitest DESTINATION reactos/bin FOR all) Index: shell32/interfaces.c =================================================================== --- modules/rostests/apitests/shell32/interfaces.c (revision 0) +++ modules/rostests/apitests/shell32/interfaces.c (working copy) @@ -0,0 +1,530 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Test for LdrEnumResources + * PROGRAMMER: Thomas Faber + */ + +#define COBJMACROS +#define WIN32_NO_STATUS +#define UNICODE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define NDEBUG +#include + +#define RTL_NUMBER_OF(x) (sizeof(x) / sizeof(x[0])) +typedef IUnknown *PUNKNOWN; + +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_MenuBand, 0x5B4DAE26, 0xB807, 0x11D0, 0x98, 0x15, 0x00, 0xC0, 0x4F, 0xD9, 0x19, 0x72); +//DEFINE_GUID(CLSID_MenuBandSite, 0xE13EF4E4, 0xD2F2, 0x11D0, 0x98, 0x16, 0x00, 0xC0, 0x4F, 0xD9, 0x19, 0x72); +DEFINE_GUID(CLSID_MenuDeskBar, 0xECD4FC4F, 0x521C, 0x11D0, 0xB7, 0x92, 0x00, 0xA0, 0xC9, 0x03, 0x12, 0xE1); +DEFINE_GUID(CLSID_MoveToMenu, 0xC2FBB631, 0x2971, 0x11D1, 0xA1, 0x8C, 0x00, 0xC0, 0x4F, 0xD7, 0x5D, 0x13); +//DEFINE_GUID(CLSID_PersonalStartMenu, 0x3F6953F0, 0x5359, 0x47FC, 0xBD, 0x99, 0x9F, 0x2C, 0xB9, 0x5A, 0x62, 0xFD); +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_ShellFSFolder, 0xF3364BA0, 0x65B9, 0x11CE, 0xA9, 0xBA, 0x00, 0xAA, 0x00, 0x4A, 0xE8, 0x37); +//DEFINE_GUID(CLSID_StartMenu, 0x4622AD11, 0xFF23, 0x11D0, 0x8D, 0x34, 0x00, 0xA0, 0xC9, 0x0F, 0x27, 0x19); +DEFINE_GUID(CLSID_TrackShellMenu, 0x8278F931, 0x2A3E, 0x11d2, 0x83, 0x8F, 0x00, 0xC0, 0x4F, 0xD9, 0x18, 0xD0); + +#ifdef __REACTOS__ +// FIXME: get guids... and also get them into the right headers +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_MenuToolbarBase, 0x40b96610, 0xb522, 0x11d1, 0xb3, 0xb4, 0x00, 0xaa, 0x00, 0x6e, 0xfd, 0xe7); +DEFINE_GUID(CLSID_StartMenuPin, 0xa2a9545d, 0xa0c2, 0x42b4, 0x97, 0x08, 0xa0, 0xb2, 0xba, 0xdd, 0x77, 0xc8); + +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_IFolderBandPriv, 0x47c01f95, 0xe185, 0x412c, 0xb5, 0xc5, 0x4f, 0x27, 0xdf, 0x96, 0x5a, 0xea); +#endif + +DEFINE_GUID(IID_IShellFolderBand, 0x7fe80cc8, 0xc247, 0x11d0, 0xb9, 0x3a, 0x00, 0xa0, 0xc9, 0x03, 0x12, 0xe1); +DEFINE_GUID(IID_IShellFolderView, 0x37a378c0, 0xf82d, 0x11ce, 0xae, 0x65, 0x08, 0x00, 0x2b, 0x2e, 0x12, 0x62); // FIXME: undefined reference? WTF! +//DEFINE_GUID(IID_IShellMenu2, 0x6F51C646, 0x0EFE, 0x4370, 0x88, 0x2A, 0xC1, 0xF6, 0x1C, 0xB2, 0x7C, 0x3B); +//DEFINE_GUID(IID_IShellMenuAcc, 0xFAF6FE96, 0xCE5E, 0x11D1, 0x83, 0x71, 0x00, 0xC0, 0x4F, 0xD9, 0x18, 0xD0); +//DEFINE_GUID(IID_IWinEventHandler, 0xEA5F2D61, 0xE008, 0x11CF, 0x99, 0xCB, 0x00, 0xC0, 0x4F, 0xD6, 0x44, 0x97); + +typedef struct _KNOWN_INTERFACE +{ + const IID *iid; + PCSTR name; +} KNOWN_INTERFACE; +typedef const KNOWN_INTERFACE *PCKNOWN_INTERFACE; + +#define ID_NAME(c) { &c, #c } +static KNOWN_INTERFACE KnownInterfaces[] = +{ + //ID_NAME(IID_IAccessibilityDockingService), + //ID_NAME(IID_IAccessibilityDockingServiceCallback), + //ID_NAME(IID_IAccessControl), + //ID_NAME(IID_IAgileObject), + ID_NAME(IID_IBandSite), + ID_NAME(IID_IBandSiteHelper), + ID_NAME(IID_IBanneredBar), + ID_NAME(IID_IComThreadingInfo), + //ID_NAME(IID_IContext), + ID_NAME(IID_IContextMenu), + 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_IDropTarget), + //ID_NAME(IID_IEnumGuid), + ID_NAME(IID_IEnumString), + ID_NAME(IID_IEnumUnknown), + //ID_NAME(IID_IEnumProperty), + ID_NAME(IID_IFolderBandPriv), + ID_NAME(IID_IInitializeObject), + ID_NAME(IID_IInputObject), + ID_NAME(IID_IInputObjectSite), + ID_NAME(IID_IMenuBand), + ID_NAME(IID_IMenuPopup), + ID_NAME(IID_IObjectWithSite), + ID_NAME(IID_IOleCommandTarget), + ID_NAME(IID_IOleWindow), + ID_NAME(IID_IPersist), + ID_NAME(IID_IPersistFile), + ID_NAME(IID_IPersistStorage), + ID_NAME(IID_IPersistStream), + ID_NAME(IID_IPersistStreamInit), + ID_NAME(IID_IQueryInfo), + ID_NAME(IID_IRunnableObject), + ID_NAME(IID_IServerSecurity), + ID_NAME(IID_IServiceProvider), + ID_NAME(IID_IShellChangeNotify), + ID_NAME(IID_IShellFolderBand), + ID_NAME(IID_IShellFolderView), + ID_NAME(IID_IShellFolderViewCB), + ID_NAME(IID_IShellMenu), + ID_NAME(IID_IShellMenu2), + ID_NAME(IID_IShellMenuAcc), + ID_NAME(IID_IShellMenuCallback), + ID_NAME(IID_IShellService), + ID_NAME(IID_IStream), + ID_NAME(IID_ISurrogate), + //ID_NAME(IID_ISurrogateService), + ID_NAME(IID_ISynchronize), + ID_NAME(IID_ISynchronizeContainer), + ID_NAME(IID_ISynchronizeEvent), + ID_NAME(IID_ISynchronizeHandle), + ID_NAME(IID_ITrackShellMenu), + ID_NAME(IID_IUnknown), + ID_NAME(IID_IWinEventHandler), +}; +const INT KnownInterfaceCount = RTL_NUMBER_OF(KnownInterfaces); + +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; + +#undef ID_NAME +#define ID_NAME(c) &c, #c +const CLASS_AND_INTERFACES ExpectedInterfaces[] = +{ + { + ID_NAME(CLSID_CopyToMenu), + { + { 0x0, &IID_IContextMenu }, + { 0x0, &IID_IUnknown }, + { 0x8, &IID_IObjectWithSite }, + } + }, + { + ID_NAME(CLSID_DeskMovr), + { + { 0x0, &IID_IUnknown }, + { 0x88, &IID_IOleWindow }, + } + }, + { + ID_NAME(CLSID_DragDropHelper), + { + { 0x0, &IID_IUnknown }, + } + }, + { + ID_NAME(CLSID_FadeTask), + { + { 0x0, &IID_IUnknown }, + } + }, + { + ID_NAME(CLSID_FolderViewHost), + { + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IServiceProvider }, + { 0x8, &IID_IOleWindow }, + { 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 // Windows can't create this. Dunno why it even exists. + { + ID_NAME(CLSID_MenuToolbarBase), + { + { 0x0, &IID_IUnknown }, + } + }, +#endif + { + ID_NAME(CLSID_MoveToMenu), + { + { 0x0, &IID_IContextMenu }, + { 0x0, &IID_IUnknown }, + { 0x8, &IID_IObjectWithSite }, + } + }, + { + ID_NAME(CLSID_NewMenu), + { + { -0xc, &IID_IObjectWithSite }, + { -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_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_SendToMenu), + { + { -0x4, &IID_IContextMenu }, + { 0x0, &IID_IUnknown }, + { 0x4, &IID_IOleWindow }, + } + }, + { + ID_NAME(CLSID_ShellDesktop), + { + { -0x8, &IID_IObjectWithSite }, + { 0x0, &IID_IUnknown }, + { 0x8, &IID_IPersist }, + { 0x20, &IID_IOleCommandTarget }, + } + }, + { + ID_NAME(CLSID_ShellFldSetExt), + { + { 0x0, &IID_IUnknown }, + { 0x8, &IID_IObjectWithSite }, + } + }, + { + ID_NAME(CLSID_ShellFSFolder), + { + { 0x0, &IID_IUnknown }, + { 0x18, &IID_IPersist }, + { 0x34, &IID_IOleCommandTarget }, + } + }, + { + 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 }, + } + }, +}; +const INT ExpectedInterfaceCount = RTL_NUMBER_OF(ExpectedInterfaces); + +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; +} + +START_TEST(interfaces) +{ + HRESULT hr; + PVOID pObj; + PUNKNOWN pUnk; + INT iClass, iIntf; + PCCLASS_AND_INTERFACES class; + + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + ok(hr == S_OK, "CoInitializeEx failed. hr=0x%lx\n", hr); + if (FAILED(hr)) + { + skip("Failed to initialize COM. Cannot perform tests\n"); + return; + } + + 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 + ok(offset == class->ifaces[iIntf].offset, "%s, %s offset is %ld, expected %ld\n", class->name, iface->name, offset, class->ifaces[iIntf].offset); + } + + /* 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); + ok(offset == INTF_NOT_EXPOSED, "%s exposes %s (offset %ld), but shouldn't\n", class->name, iface->name, offset); + //ok(offset == INTF_NOT_EXPOSED, "%s: { %s%x, &%s },\n", class->name, offset < 0 ? "-" : "", offset < 0 ? -offset : offset, iface->name); + } + + // TODO: do some aggregation + + IUnknown_Release(pUnk); + } + + CoUninitialize(); +} Index: shell32/testlist.c =================================================================== --- modules/rostests/apitests/shell32/testlist.c (revision 0) +++ modules/rostests/apitests/shell32/testlist.c (working copy) @@ -0,0 +1,16 @@ +#define WIN32_LEAN_AND_MEAN +#define __ROS_LONG64__ +#include + +#define STANDALONE +#include "wine/test.h" + +extern void func_interfaces(void); + +const struct test winetest_testlist[] = +{ + { "interfaces", func_interfaces }, + + { 0, 0 } +}; +