Files
reactos/modules/rostests/apitests/com/com_apitest.c
Carl J. Bialorucki 5f243e66b6 [COM_APITEST][INCLUDE/REACTOS][PSDK] Fix com tests for WS03, Vista+ (#8343)
[COM_APITEST]
- Add NTDDI version gating to classes and interfaces in tests
- Remove rigid offset tests. Instead, offsets to known interfaces can be logged by defining LOG_COM_INTERFACE_OFFSETS.
- Replace the noreg member of the known interfaces array with a function pointer that can be used to determine if a com test should be globally registered depending on the current NTDDI version. I could probably replace this with a min and max registered NTDDI value, but I thought this was confusing for interfaces that are never globally registered.

[INCLUDE/REACTOS]
- Rename the existing interface definition for IShellBrowserService to IShellBrowserService_XP at {1307EE17-EA83-49EB-96B2-3A28E2D7048A}. This only exists on XP and Server 2003, no earlier or later versions.
- Rename IID_IShellBrowserServce to IID_IShellBrowserService since this definition is correct for Windows 7+ at {DFBC7E30-F9E5-455F-88F8-FA98C1E494CA}
- Add an interface definition for IShellBrowserService4 at {F5A24314-5B8B-44FA-BC2E-31285544B520}. This definition for IShellBrowserService exists for Vista only and no other version.

[PSDK]
- Add a define for NTDDI_WIN7SP1. While this isn't defined in the public Windows headers, it clearly exists in private headers because it is referenced in the public WinBase.h header.
2025-09-29 08:33:38 -05:00

898 lines
48 KiB
C

/*
* PROJECT: ReactOS api tests
* LICENSE: GPLv2+ - See COPYING in the top level directory
* PURPOSE: COM interface test
* PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
*/
#include "com_apitest.h"
#include <winreg.h>
#include <mshtmhst.h>
#include <shlwapi.h>
#include <commoncontrols.h>
#include <activscp.h>
#include <ndk/rtlfuncs.h>
#define NDEBUG
#include <debug.h>
#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;
PCWSTR wname;
BOOLEAN (*IsRegistered)(ULONG version);
} KNOWN_INTERFACE;
typedef const KNOWN_INTERFACE *PCKNOWN_INTERFACE;
#undef ID_NAME
#define ID_NAME(c) &c, #c, L ## #c
#define ID_NAME_EX(c, d) &c, #d, L ## #d
BOOLEAN RegisteredAlways(ULONG version) { return TRUE; }
BOOLEAN RegisteredNever(ULONG version) { return FALSE; }
BOOLEAN RegisteredOnWS03AndVista(ULONG version) { return version >= NTDDI_WS03 && version < NTDDI_WIN7; }
BOOLEAN RegisteredOnVistaOrNewer(ULONG version) { return version >= NTDDI_VISTA; }
BOOLEAN RegisteredOnVistaOnly(ULONG version) { return version >= NTDDI_VISTA && version < NTDDI_WIN7; }
BOOLEAN RegisteredOnVistaAndWin7(ULONG version) { return version >= NTDDI_VISTA && version < NTDDI_WIN8; }
BOOLEAN RegisteredOnVistaToWin8Dot1(ULONG version) { return version >= NTDDI_VISTA && version < NTDDI_WIN10; }
BOOLEAN RegisteredOnWin7OrNewer(ULONG version) { return version >= NTDDI_WIN7; }
BOOLEAN RegisteredOnWin8OrNewer(ULONG version) { return version >= NTDDI_WIN8; }
BOOLEAN RegisteredOnWS03OrOlder(ULONG version) { return version <= NTDDI_WS03SP4; }
static KNOWN_INTERFACE KnownInterfaces[] =
{
{ ID_NAME(DIID__SearchAssistantEvents), RegisteredOnWS03OrOlder },
{ ID_NAME(IID_IMarshal), RegisteredOnWS03OrOlder },
{ ID_NAME(IID_ICDBurnPriv), RegisteredOnWS03OrOlder },
{ ID_NAME(IID_ICompositeFolder), RegisteredOnWS03OrOlder },
{ ID_NAME(IID_IDefViewSafety), RegisteredOnWS03OrOlder },
{ ID_NAME(IID_IDropSource), RegisteredOnWS03OrOlder },
{ ID_NAME(IID_ISearch), RegisteredOnWS03OrOlder },
{ ID_NAME(IID_ISearchAssistantOC), RegisteredOnWS03OrOlder },
{ ID_NAME(IID_ISearchAssistantOC2), RegisteredOnWS03OrOlder },
{ ID_NAME(IID_ISearchAssistantOC3), RegisteredOnWS03OrOlder },
{ ID_NAME(IID_ISearchBar), RegisteredOnWS03OrOlder },
{ ID_NAME(IID_ISearches), RegisteredOnWS03OrOlder },
{ ID_NAME(IID_IEFrameAuto), RegisteredOnWS03OrOlder },
{ ID_NAME(IID_IWebBrowserPriv2), RegisteredOnWS03OrOlder },
/* These interfaces are different between PSDK and registry/shell32 */
{ ID_NAME_EX(IID_ITransferAdviseSinkPriv,
IID_ITransferAdviseSink), RegisteredOnWS03OrOlder },
{ ID_NAME_EX(IID_IDriveFolderExtOld,
IID_IDriveFolderExt), RegisteredOnWS03OrOlder },
{ ID_NAME(IID_IAggregateFilterCondition), RegisteredOnWS03AndVista },
{ ID_NAME(IID_IBandNavigate), RegisteredOnWS03AndVista },
{ ID_NAME(IID_IAccIdentity), RegisteredAlways },
{ ID_NAME(IID_IAccPropServer), RegisteredAlways },
{ ID_NAME(IID_IAccPropServices), RegisteredAlways },
{ ID_NAME(IID_IAccessible), RegisteredAlways },
{ ID_NAME(IID_IAccessibleHandler), RegisteredAlways },
{ ID_NAME(IID_IAccessor), RegisteredAlways },
{ ID_NAME(IID_IActionProgress), RegisteredAlways },
{ ID_NAME(IID_IActionProgressDialog), RegisteredAlways },
{ ID_NAME(IID_IAutoCompleteDropDown), RegisteredAlways },
{ ID_NAME(IID_IBandHost), RegisteredAlways },
{ ID_NAME(IID_IBandSite), RegisteredAlways },
{ ID_NAME(IID_IBindCtx), RegisteredAlways },
{ ID_NAME(IID_IBindEventHandler), RegisteredAlways },
{ ID_NAME(IID_IBindHost), RegisteredAlways },
{ ID_NAME(IID_IBinding), RegisteredAlways },
{ ID_NAME(IID_IBindResource), RegisteredAlways },
{ ID_NAME(IID_IBindStatusCallback), RegisteredAlways },
{ ID_NAME(IID_IBlockingLock), RegisteredAlways },
{ ID_NAME(IID_IBrowserService), RegisteredAlways },
{ ID_NAME(IID_ICDBurn), RegisteredAlways },
{ ID_NAME(IID_ICDBurnExt), RegisteredAlways },
{ ID_NAME(IID_ICatInformation), RegisteredAlways },
{ ID_NAME(IID_ICatRegister), RegisteredAlways },
{ ID_NAME(IID_IClassActivator), RegisteredAlways },
{ ID_NAME(IID_IClassFactory), RegisteredAlways },
{ ID_NAME(IID_IClassFactory2), RegisteredAlways },
{ ID_NAME(IID_ICommDlgBrowser), RegisteredAlways },
{ ID_NAME(IID_ICommDlgBrowser2), RegisteredAlways },
{ ID_NAME(IID_ICommDlgBrowser3), RegisteredAlways },
{ ID_NAME(IID_IComputerInfoChangeNotify), RegisteredAlways },
{ ID_NAME(IID_IConnectionPoint), RegisteredAlways },
{ ID_NAME(IID_IConnectionPointContainer), RegisteredAlways },
{ ID_NAME(IID_IContextMenuSite), RegisteredAlways },
{ ID_NAME(IID_IContinue), RegisteredAlways },
{ ID_NAME(IID_IContinueCallback), RegisteredAlways },
{ ID_NAME(IID_ICustomizeInfoTip), RegisteredAlways },
{ ID_NAME(IID_IDataObject), RegisteredAlways },
{ ID_NAME(IID_IDefViewFrame3), RegisteredAlways },
{ ID_NAME(IID_IDefViewFrameGroup), RegisteredAlways },
{ ID_NAME(IID_IDeskBand), RegisteredAlways },
{ ID_NAME(IID_IDeskBandEx), RegisteredAlways },
// { ID_NAME(IID_IDefViewID), RegisteredAlways }, == DefViewFrame3
{ ID_NAME(IID_IDiscMasterProgressEvents), RegisteredAlways },
{ ID_NAME(IID_IDispatch), RegisteredAlways },
{ ID_NAME(IID_IDispatchEx), RegisteredAlways },
{ ID_NAME(IID_IDockingWindow), RegisteredAlways },
{ ID_NAME(IID_IDropTarget), RegisteredAlways },
// { ID_NAME(IID_IEnumCATID), RegisteredAlways }, == EnumGUID
// { ID_NAME(IID_IEnumCLSID), RegisteredAlways }, == EnumGUID
{ ID_NAME(IID_IEnumCATEGORYINFO), RegisteredAlways },
{ ID_NAME(IID_IEnumConnectionPoints), RegisteredAlways },
{ ID_NAME(IID_IEnumConnections), RegisteredAlways },
{ ID_NAME(IID_IEnumExtraSearch), RegisteredAlways },
{ ID_NAME(IID_IEnumGUID), RegisteredAlways },
{ ID_NAME(IID_IEnumIDList), RegisteredAlways },
{ ID_NAME(IID_IEnumMoniker), RegisteredAlways },
{ ID_NAME(IID_IEnumNetConnection), RegisteredAlways },
{ ID_NAME(IID_IEnumShellItems), RegisteredAlways },
{ ID_NAME(IID_IEnumSTATSTG), RegisteredAlways },
{ ID_NAME(IID_IEnumString), RegisteredAlways },
{ ID_NAME(IID_IEnumUnknown), RegisteredAlways },
{ ID_NAME(IID_IEnumVARIANT), RegisteredAlways },
{ ID_NAME(IID_IErrorLog), RegisteredAlways },
{ ID_NAME(IID_IExplorerBrowser), RegisteredAlways },
{ ID_NAME(IID_IExtractImage), RegisteredAlways },
{ ID_NAME(IID_IExtractImage2), RegisteredAlways },
{ ID_NAME(IID_IFileDialog), RegisteredAlways },
{ ID_NAME(IID_IFileOpenDialog), RegisteredAlways },
{ ID_NAME(IID_IFileSaveDialog), RegisteredAlways },
{ ID_NAME(IID_IFileSearchBand), RegisteredAlways },
{ ID_NAME(IID_IFilter), RegisteredAlways },
{ ID_NAME(IID_IFilterCondition), RegisteredAlways },
{ ID_NAME(IID_IFolderBandPriv), RegisteredAlways },
{ ID_NAME(IID_IFolderFilter), RegisteredAlways },
{ ID_NAME(IID_IFolderFilterSite), RegisteredAlways },
{ ID_NAME(IID_IFolderView), RegisteredAlways },
{ ID_NAME(IID_IFolderView2), RegisteredAlways },
{ ID_NAME(IID_IFolderViewOC), RegisteredAlways },
{ ID_NAME(IID_IFolderViewSettings), RegisteredAlways },
{ ID_NAME(IID_IHWEventHandler), RegisteredAlways },
{ ID_NAME(IID_IHWEventHandler2), RegisteredAlways },
{ ID_NAME(IID_IHlinkFrame), RegisteredAlways },
{ ID_NAME(IID_IInitializeWithBindCtx), RegisteredAlways },
{ ID_NAME(IID_IInitializeWithFile), RegisteredAlways },
{ ID_NAME(IID_IInputObject), RegisteredAlways },
{ ID_NAME(IID_IInputObjectSite), RegisteredAlways },
{ ID_NAME(IID_IInternetSecurityManager), RegisteredAlways },
{ ID_NAME(IID_IItemNameLimits), RegisteredAlways },
{ ID_NAME(IID_IModalWindow), RegisteredAlways },
{ ID_NAME(IID_IMoniker), RegisteredAlways },
{ ID_NAME(IID_INamespaceWalk), RegisteredAlways },
{ ID_NAME(IID_INamespaceWalkCB), RegisteredAlways },
{ ID_NAME(IID_INamespaceWalkCB2), RegisteredAlways },
{ ID_NAME(IID_INetConnectionManager), RegisteredAlways },
{ ID_NAME(IID_INewMenuClient), RegisteredAlways },
{ ID_NAME(IID_INewWindowManager), RegisteredAlways },
{ ID_NAME(IID_IObjectSafety), RegisteredAlways },
{ ID_NAME(IID_IObjectWithBackReferences), RegisteredAlways },
{ ID_NAME(IID_IObjectWithSite), RegisteredAlways },
{ ID_NAME(IID_IOleClientSite), RegisteredAlways },
{ ID_NAME(IID_IOleCommandTarget), RegisteredAlways },
{ ID_NAME(IID_IOleContainer), RegisteredAlways },
{ ID_NAME(IID_IOleControl), RegisteredAlways },
{ ID_NAME(IID_IOleControlSite), RegisteredAlways },
{ ID_NAME(IID_IOleInPlaceActiveObject), RegisteredAlways },
{ ID_NAME(IID_IOleInPlaceFrame), RegisteredAlways },
{ ID_NAME(IID_IOleInPlaceObject), RegisteredAlways },
{ ID_NAME(IID_IOleInPlaceSite), RegisteredAlways },
{ ID_NAME(IID_IOleInPlaceSiteEx), RegisteredAlways },
{ ID_NAME(IID_IOleInPlaceUIWindow), RegisteredAlways },
{ ID_NAME(IID_IOleItemContainer), RegisteredAlways },
{ ID_NAME(IID_IOleLink), RegisteredAlways },
{ ID_NAME(IID_IOleObject), RegisteredAlways },
{ ID_NAME(IID_IOleWindow), RegisteredAlways },
{ ID_NAME(IID_IParentAndItem), RegisteredAlways },
{ ID_NAME(IID_IParseDisplayName), RegisteredAlways },
{ ID_NAME(IID_IPersist), RegisteredAlways },
{ ID_NAME(IID_IPersistFile), RegisteredAlways },
{ ID_NAME(IID_IPersistFolder), RegisteredAlways },
{ ID_NAME(IID_IPersistFolder2), RegisteredAlways },
{ ID_NAME(IID_IPersistFolder3), RegisteredAlways },
{ ID_NAME(IID_IPersistHistory), RegisteredAlways },
{ ID_NAME(IID_IPersistIDList), RegisteredAlways },
{ ID_NAME(IID_IPersistMemory), RegisteredAlways },
{ ID_NAME(IID_IPersistPropertyBag), RegisteredAlways },
{ ID_NAME(IID_IPersistPropertyBag2), RegisteredAlways },
{ ID_NAME(IID_IPersistStorage), RegisteredAlways },
{ ID_NAME(IID_IPersistStream), RegisteredAlways },
{ ID_NAME(IID_IPersistStreamInit), RegisteredAlways },
{ ID_NAME(IID_IPreviewHandler), RegisteredAlways },
{ ID_NAME(IID_IPreviewHandlerFrame), RegisteredAlways },
{ ID_NAME(IID_IPreviewHandlerVisuals), RegisteredAlways },
{ ID_NAME(IID_IPropertyBag), RegisteredAlways },
{ ID_NAME(IID_IPropertyBag2), RegisteredAlways },
{ ID_NAME(IID_IPropertySetStorage), RegisteredAlways },
{ ID_NAME(IID_IPropertyStore), RegisteredAlways },
{ ID_NAME(IID_IProvideClassInfo), RegisteredAlways },
{ ID_NAME(IID_IProvideClassInfo2), RegisteredAlways },
{ ID_NAME(IID_IQueryCancelAutoPlay), RegisteredAlways },
{ ID_NAME(IID_IQuickActivate), RegisteredAlways },
{ ID_NAME(IID_IRemoteComputer), RegisteredAlways },
{ ID_NAME(IID_IResolveShellLink), RegisteredAlways },
{ ID_NAME(IID_IROTData), RegisteredAlways },
{ ID_NAME(IID_IRunnableObject), RegisteredAlways },
{ ID_NAME(IID_IRunningObjectTable), RegisteredAlways },
{ ID_NAME(IID_IScriptErrorList), RegisteredAlways },
{ ID_NAME(IID_ISecMgrCacheSeedTarget), RegisteredAlways },
{ ID_NAME(IID_IServiceProvider), RegisteredAlways },
{ ID_NAME(IID_IShellBrowser), RegisteredAlways },
{ ID_NAME(IID_IShellDispatch), RegisteredAlways },
{ ID_NAME(IID_IShellDispatch2), RegisteredAlways },
{ ID_NAME(IID_IShellDispatch3), RegisteredAlways },
{ ID_NAME(IID_IShellDispatch4), RegisteredAlways },
{ ID_NAME(IID_IShellFavoritesNameSpace), RegisteredAlways },
{ ID_NAME(IID_IShellFolder), RegisteredAlways },
{ ID_NAME(IID_IShellFolder2), RegisteredAlways },
{ ID_NAME(IID_IShellFolderViewDual), RegisteredAlways },
{ ID_NAME(IID_IShellFolderViewDual2), RegisteredAlways },
{ ID_NAME(IID_IShellIcon), RegisteredAlways },
{ ID_NAME(IID_IShellItem), RegisteredAlways },
{ ID_NAME(IID_IShellItem2), RegisteredAlways },
{ ID_NAME(IID_IShellItemArray), RegisteredAlways },
{ ID_NAME(IID_IShellItemFilter), RegisteredAlways },
{ ID_NAME(IID_IShellLinkA), RegisteredAlways },
{ ID_NAME(IID_IShellLinkDual), RegisteredAlways },
{ ID_NAME(IID_IShellLinkDual2), RegisteredAlways },
{ ID_NAME(IID_IShellLinkW), RegisteredAlways },
{ ID_NAME(IID_IShellNameSpace), RegisteredAlways },
{ ID_NAME(IID_IShellUIHelper), RegisteredAlways },
{ ID_NAME(IID_IShellView), RegisteredAlways },
{ ID_NAME(IID_IShellView2), RegisteredAlways },
{ ID_NAME(IID_IShellView3), RegisteredAlways },
{ ID_NAME(IID_IShellWindows), RegisteredAlways },
{ ID_NAME(IID_ISpecifyPropertyPages), RegisteredAlways },
{ ID_NAME(IID_IStorage), RegisteredAlways },
{ ID_NAME(IID_IStream), RegisteredAlways },
{ ID_NAME(IID_ISurrogate), RegisteredAlways },
{ ID_NAME(IID_ISynchronize), RegisteredAlways },
{ ID_NAME(IID_ITargetEmbedding), RegisteredAlways },
{ ID_NAME(IID_ITargetFrame), RegisteredAlways },
{ ID_NAME(IID_ITargetFrame2), RegisteredAlways },
{ ID_NAME(IID_ITargetFramePriv), RegisteredAlways },
{ ID_NAME(IID_ITargetFramePriv2), RegisteredAlways },
{ ID_NAME(IID_ITargetNotify), RegisteredAlways },
{ ID_NAME(IID_ITaskbarList), RegisteredAlways },
{ ID_NAME(IID_ITaskbarList2), RegisteredAlways },
{ ID_NAME(IID_IUnknown), RegisteredAlways },
{ ID_NAME(IID_IUrlHistoryNotify), RegisteredAlways },
{ ID_NAME(IID_IUrlHistoryStg), RegisteredAlways },
{ ID_NAME(IID_IUrlHistoryStg2), RegisteredAlways },
{ ID_NAME(IID_IViewObject), RegisteredAlways },
{ ID_NAME(IID_IViewObject2), RegisteredAlways },
{ ID_NAME(IID_IVisualProperties), RegisteredAlways },
{ ID_NAME(IID_IWebBrowser), RegisteredAlways },
{ ID_NAME(IID_IWebBrowser2), RegisteredAlways },
{ ID_NAME(IID_IWebBrowserApp), RegisteredAlways },
{ ID_NAME(IID_IWebBrowserPriv), RegisteredAlways },
{ ID_NAME(DIID_DShellFolderViewEvents), RegisteredAlways },
{ ID_NAME(DIID_DShellNameSpaceEvents), RegisteredAlways },
{ ID_NAME(DIID_DShellWindowsEvents), RegisteredAlways },
{ ID_NAME(DIID_DWebBrowserEvents), RegisteredAlways },
{ ID_NAME(DIID_DWebBrowserEvents2), RegisteredAlways },
{ ID_NAME(DIID_XMLDOMDocumentEvents), RegisteredAlways },
{ ID_NAME(IID_Folder), RegisteredAlways },
{ ID_NAME(IID_Folder2), RegisteredAlways },
{ ID_NAME(IID_Folder3), RegisteredAlways },
{ ID_NAME(IID_FolderItem), RegisteredAlways },
{ ID_NAME(IID_FolderItem2), RegisteredAlways },
{ ID_NAME(IID_FolderItems), RegisteredAlways },
{ ID_NAME(IID_FolderItems2), RegisteredAlways },
{ ID_NAME(IID_FolderItems3), RegisteredAlways },
{ ID_NAME(IID_FolderItemVerb), RegisteredAlways },
{ ID_NAME(IID_FolderItemVerbs), RegisteredAlways },
{ ID_NAME(IID_IQueryContinue), RegisteredAlways },
{ ID_NAME(IID_IUserNotification), RegisteredAlways },
{ ID_NAME(IID_IUserNotificationCallback), RegisteredAlways },
{ ID_NAME(IID_IUserNotification2), RegisteredAlways },
{ ID_NAME(IID_IUserEventTimer), RegisteredAlways },
{ ID_NAME(IID_IUserEventTimerCallback), RegisteredAlways },
{ ID_NAME(IID_IControlPanelEnumerator), RegisteredOnVistaOnly },
{ ID_NAME(IID_IShellFolder3), RegisteredOnVistaOnly },
{ ID_NAME_EX(IID_IShellBrowserService4,
IID_IShellBrowserService), RegisteredOnVistaOnly },
{ ID_NAME(IID_IDriveFolderExt), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_INetConnectionConnectUi), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_INetConnectionCommonUi2), RegisteredOnVistaOrNewer }, // This also covers IID_INetLanConnectionUiInfo.
{ ID_NAME(IID_ISLTracker), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_IShellDispatch5), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_IShellFolderViewDual3), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_IShellLinkDataList), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_IShellUIHelper2), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_IBackReferencedObject), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_ICommonLayoutDefinition), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_IDelegateHostItemContainer), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_IExecuteCommand), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_IFolderType), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_IFrameLayoutDefinition), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_IItemFilter), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_IItemFilterOwner), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_INewItemAdvisor), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_IObjectWithAssociationElement), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_IObjectWithQuerySource), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_IObjectWithSelection), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_IPersistString2), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_IRootAndRelativeParsingFolder), RegisteredOnVistaOrNewer },
{ ID_NAME(IID_IAssociationArray), RegisteredOnVistaAndWin7 },
{ ID_NAME(IID_IObjectWithAssociationList), RegisteredOnVistaAndWin7 },
{ ID_NAME(IID_IRegItemFolder), RegisteredOnVistaToWin8Dot1 },
{ ID_NAME(IID_IFileDialog2), RegisteredOnWin7OrNewer },
{ ID_NAME(IID_INameSpaceTreeControl), RegisteredOnWin7OrNewer },
{ ID_NAME(IID_ITaskbarList3), RegisteredOnWin7OrNewer },
{ ID_NAME(IID_ITaskbarList4), RegisteredOnWin7OrNewer },
{ ID_NAME(IID_IShellBrowserService), RegisteredOnWin7OrNewer },
{ ID_NAME(IID_ITransferAdviseSink), RegisteredOnWin8OrNewer },
{ ID_NAME(IID_IACList), RegisteredNever },
{ ID_NAME(IID_IACList2), RegisteredNever },
{ ID_NAME(IID_IADesktopP2), RegisteredNever },
{ ID_NAME(IID_IAccessControl), RegisteredNever },
{ ID_NAME(IID_IACLCustomMRU), RegisteredNever },
{ ID_NAME(IID_IActiveDesktop), RegisteredNever },
{ ID_NAME(IID_IActiveDesktopP), RegisteredNever },
{ ID_NAME(IID_IAddressBarParser), RegisteredNever },
{ ID_NAME(IID_IAddressBand), RegisteredNever },
{ ID_NAME(IID_IAddressEditBox), RegisteredNever },
{ ID_NAME(IID_IAsyncMoniker), RegisteredNever },
{ ID_NAME(IID_IAugmentedShellFolder), RegisteredNever },
{ ID_NAME(IID_IAugmentedShellFolder2), RegisteredNever },
{ ID_NAME(IID_IAutoComplete), RegisteredNever },
{ ID_NAME(IID_IAutoComplete2), RegisteredNever },
{ ID_NAME(IID_IBandProxy), RegisteredNever },
{ ID_NAME(IID_IBandSiteHelper), RegisteredNever },
{ ID_NAME(IID_IBanneredBar), RegisteredNever },
{ ID_NAME(IID_IBindProtocol), RegisteredNever },
{ ID_NAME(IID_IBrowserFrameOptions), RegisteredNever },
{ ID_NAME(IID_IBrowserService2), RegisteredNever },
{ ID_NAME(IID_IBrowserService3), RegisteredNever },
{ ID_NAME(IID_IBrowserService4), RegisteredNever },
{ ID_NAME(IID_ICallFactory), RegisteredNever },
{ ID_NAME(IID_ICancelMethodCalls), RegisteredNever },
{ ID_NAME(IID_IClassFactory3), RegisteredNever },
{ ID_NAME(IID_IClientSecurity), RegisteredNever },
{ ID_NAME(IID_IComThreadingInfo), RegisteredNever },
{ ID_NAME(IID_IContext), RegisteredNever },
{ ID_NAME(IID_IContextMenu), RegisteredNever },
{ ID_NAME(IID_IContextMenu2), RegisteredNever },
{ ID_NAME(IID_IContextMenu3), RegisteredNever },
{ ID_NAME(IID_IContextMenuCB), RegisteredNever },
{ ID_NAME(IID_ICopyHookA), RegisteredNever },
{ ID_NAME(IID_ICopyHookW), RegisteredNever },
{ ID_NAME(IID_ICurrentWorkingDirectory), RegisteredNever },
{ ID_NAME(IID_IDVGetEnum), RegisteredNever },
{ ID_NAME(IID_IDefViewFrame), RegisteredNever },
{ ID_NAME(IID_IDefViewScript), RegisteredNever },
{ ID_NAME(IID_IDelayedRelease), RegisteredNever },
{ ID_NAME(IID_IDeskBar), RegisteredNever },
{ ID_NAME(IID_IDeskBarClient), RegisteredNever },
{ ID_NAME(IID_IDeskMovr), RegisteredNever },
{ ID_NAME(IID_IDockingWindowFrame), RegisteredNever },
{ ID_NAME(IID_IDockingWindowSite), RegisteredNever },
{ ID_NAME(IID_IDocViewSite), RegisteredNever },
{ ID_NAME(IID_IDragSourceHelper), RegisteredNever },
{ ID_NAME(IID_IDropTargetHelper), RegisteredNever },
{ ID_NAME(IID_IEnumNetCfgComponent), RegisteredNever },
{ ID_NAME(IID_IExplorerToolbar), RegisteredNever },
{ ID_NAME(IID_IExtractIconA), RegisteredNever },
{ ID_NAME(IID_IExtractIconW), RegisteredNever },
{ ID_NAME(IID_IFileViewerA), RegisteredNever },
{ ID_NAME(IID_IFileViewerSite), RegisteredNever },
{ ID_NAME(IID_IFileViewerW), RegisteredNever },
{ ID_NAME(IID_IFolderViewHost), RegisteredNever },
{ ID_NAME(IID_IForegroundTransfer), RegisteredNever },
{ ID_NAME(IID_IGetNameSpaceExtensionPointer), RegisteredNever },
{ ID_NAME(IID_IGlobalFolderSettings), RegisteredNever },
{ ID_NAME(IID_IImageList), RegisteredNever },
{ ID_NAME(IID_IImageList2), RegisteredNever },
{ ID_NAME(IID_IInitializeObject), RegisteredNever },
{ ID_NAME(IID_IInternalUnknown), RegisteredNever },
{ ID_NAME(IID_IInternetZoneManager), RegisteredNever },
{ ID_NAME(IID_IMarshal2), RegisteredNever },
{ ID_NAME(IID_IMenuBand), RegisteredNever },
{ ID_NAME(IID_IMenuPopup), RegisteredNever },
{ ID_NAME(IID_IMruDataList), RegisteredNever },
{ ID_NAME(IID_IMruPidlList), RegisteredNever },
{ ID_NAME(IID_IMultiMonitorDockingSite), RegisteredNever },
{ ID_NAME(IID_IMultiQI), RegisteredNever },
{ ID_NAME(IID_INamespaceProxy), RegisteredNever },
{ ID_NAME(IID_INetCfg), RegisteredNever },
{ ID_NAME(IID_INetCfgComponent), RegisteredNever },
{ ID_NAME(IID_INetCfgComponentBindings), RegisteredNever },
{ ID_NAME(IID_INetCfgComponentControl), RegisteredNever },
{ ID_NAME(IID_INetCfgComponentPropertyUi), RegisteredNever },
{ ID_NAME(IID_INetCfgLock), RegisteredNever },
{ ID_NAME(IID_INetCfgPnpReconfigCallback), RegisteredNever },
{ ID_NAME(IID_INetConnectionPropertyUi), RegisteredNever },
{ ID_NAME(IID_INetConnectionPropertyUi2), RegisteredNever },
{ ID_NAME(IID_INewShortcutHookA), RegisteredNever },
{ ID_NAME(IID_INewShortcutHookW), RegisteredNever },
{ ID_NAME(IID_INSCTree), RegisteredNever },
{ ID_NAME(IID_INSCTree2), RegisteredNever },
{ ID_NAME(IID_IObjMgr), RegisteredNever },
{ ID_NAME(IID_IOleInPlaceObjectWindowless), RegisteredNever },
{ ID_NAME(IID_IOleInPlaceSiteWindowless), RegisteredNever },
{ ID_NAME(IID_IPersistFreeThreadedObject), RegisteredNever },
{ ID_NAME(IID_IProgressDialog), RegisteredNever },
{ ID_NAME(IID_IPropSheetPage), RegisteredNever },
{ ID_NAME(IID_IQueryAssociations), RegisteredNever },
{ ID_NAME(IID_IQueryInfo), RegisteredNever },
{ ID_NAME(IID_IRegTreeOptions), RegisteredNever },
{ ID_NAME(IID_IRpcOptions), RegisteredNever },
{ ID_NAME(IID_IServerSecurity), RegisteredNever },
{ ID_NAME(IID_IShellApp), RegisteredNever },
{ ID_NAME(IID_IShellChangeNotify), RegisteredNever },
{ ID_NAME(IID_IShellCopyHookA), RegisteredNever },
{ ID_NAME(IID_IShellCopyHookW), RegisteredNever },
{ ID_NAME(IID_IShellDesktopTray), RegisteredNever },
{ ID_NAME(IID_IShellDetails), RegisteredNever },
{ ID_NAME(IID_IShellDispatch6), RegisteredNever },
{ ID_NAME(IID_IShellExecuteHookA), RegisteredNever },
{ ID_NAME(IID_IShellExecuteHookW), RegisteredNever },
{ ID_NAME(IID_IShellExtInit), RegisteredNever },
{ ID_NAME(IID_IShellFolderBand), RegisteredNever },
{ ID_NAME(IID_IShellFolderSearchable), RegisteredNever },
{ ID_NAME(IID_IShellFolderSearchableCallback), RegisteredNever },
{ ID_NAME(IID_IShellFolderView), RegisteredNever },
{ ID_NAME(IID_IShellFolderViewCB), RegisteredNever },
{ ID_NAME(IID_IShellFolderViewType), RegisteredNever },
{ ID_NAME(IID_IShellIconOverlay), RegisteredNever },
{ ID_NAME(IID_IShellIconOverlayIdentifier), RegisteredNever },
{ ID_NAME(IID_IShellImageData), RegisteredNever },
{ ID_NAME(IID_IShellImageDataAbort), RegisteredNever },
{ ID_NAME(IID_IShellImageDataFactory), RegisteredNever },
{ ID_NAME(IID_IShellMenu), RegisteredNever },
{ ID_NAME(IID_IShellMenu2), RegisteredNever },
{ ID_NAME(IID_IShellMenuAcc), RegisteredNever },
{ ID_NAME(IID_IShellMenuCallback), RegisteredNever },
{ ID_NAME(IID_IShellPropSheetExt), RegisteredNever },
{ ID_NAME(IID_IShellService), RegisteredNever },
{ ID_NAME(IID_IShellTaskScheduler), RegisteredNever },
{ ID_NAME(IID_ISynchronizeContainer), RegisteredNever },
{ ID_NAME(IID_ISynchronizeEvent), RegisteredNever },
{ ID_NAME(IID_ISynchronizeHandle), RegisteredNever },
{ ID_NAME(IID_ITrackShellMenu), RegisteredNever },
{ ID_NAME(IID_ITransferDestination), RegisteredNever },
{ ID_NAME(IID_ITransferSource), RegisteredNever },
{ ID_NAME(IID_ITranslateShellChangeNotify), RegisteredNever },
{ ID_NAME(IID_ITrayPriv), RegisteredNever },
{ ID_NAME(IID_ITrayPriv2), RegisteredNever },
{ ID_NAME(IID_IURLSearchHook), RegisteredNever },
{ ID_NAME(IID_IURLSearchHook2), RegisteredNever },
{ ID_NAME(IID_IViewObjectEx), RegisteredNever },
{ ID_NAME(IID_IWinEventHandler), RegisteredNever },
{ ID_NAME(IID_DFConstraint), RegisteredNever },
{ ID_NAME(IID_CDefView), RegisteredNever },
{ ID_NAME(CLSID_ShellDesktop), RegisteredNever },
{ ID_NAME(IID_IAliasRegistrationCallback), RegisteredNever },
{ ID_NAME(IID_IAssociationArrayInitialize), RegisteredNever },
{ ID_NAME(IID_IAssociationList), RegisteredNever },
{ ID_NAME(IID_IBasePropPage), RegisteredNever },
{ ID_NAME(IID_IDrawPropertyControl), RegisteredNever },
{ ID_NAME(IID_IEnumAssociationElements), RegisteredNever },
{ ID_NAME(IID_IEnumerateAssociationElements), RegisteredNever },
{ ID_NAME(IID_IFolderNotify), RegisteredNever },
{ ID_NAME(IID_IFolderProperties), RegisteredNever },
{ ID_NAME(IID_IFolderWithSearchRoot), RegisteredNever },
{ ID_NAME(IID_ILocalizableItemParent), RegisteredNever },
{ ID_NAME(IID_IPrinterFolder), RegisteredNever },
{ ID_NAME(IID_IPropertyControl), RegisteredNever },
{ ID_NAME(IID_IPropertyControlBase), RegisteredNever },
{ ID_NAME(IID_IPropertyControlSite), RegisteredNever },
{ ID_NAME(IID_IRegItemCustomAttributes), RegisteredNever },
{ ID_NAME(IID_IRegItemCustomEnumerator), RegisteredNever },
{ ID_NAME(IID_IScope), RegisteredNever },
{ ID_NAME(IID_IScopeItem), RegisteredNever },
{ ID_NAME(IID_ITaskCondition), RegisteredNever },
{ ID_NAME(IID_ITaskConditionCombiner), RegisteredNever },
{ ID_NAME(IID_ITaskConditionInit), RegisteredNever },
{ ID_NAME(IID_ITransferProvider), RegisteredNever },
{ ID_NAME(IID_IAssociationArrayOld), RegisteredNever },
{ ID_NAME(IID_IPinnedListOld), RegisteredNever },
{ ID_NAME(IID_IPinnedList), RegisteredNever },
{ ID_NAME(IID_IAttachmentExecute), RegisteredNever },
{ ID_NAME(IID_IComponentData), RegisteredNever },
{ ID_NAME(IID_IConsole), RegisteredNever },
{ ID_NAME(IID_IConsole2), RegisteredNever },
{ ID_NAME(IID_IConsoleNameSpace), RegisteredNever },
{ ID_NAME(IID_IConsoleNameSpace2), RegisteredNever },
{ ID_NAME(IID_IPropertySheetCallback), RegisteredNever },
{ ID_NAME(IID_IPropertySheetProvider), RegisteredNever },
{ ID_NAME(IID_IExtendPropertySheet), RegisteredNever },
{ ID_NAME(IID_IExtendPropertySheet2), RegisteredNever },
{ ID_NAME(IID_IHeaderCtrl), RegisteredNever },
{ ID_NAME(IID_IToolbar), RegisteredNever },
{ ID_NAME(IID_IImageList_mmc), RegisteredNever },
{ ID_NAME(IID_IConsoleVerb), RegisteredNever },
{ ID_NAME(IID_ISnapInAbout), RegisteredNever },
{ ID_NAME(IID_ICertificateManager), RegisteredNever },
{ ID_NAME(IID_IEnumNetCfgBindingInterface), RegisteredNever },
{ ID_NAME(IID_IEnumNetCfgBindingPath), RegisteredNever },
{ ID_NAME(IID_INetCfgBindingInterface), RegisteredNever },
{ ID_NAME(IID_INetCfgBindingPath), RegisteredNever },
};
static const INT KnownInterfaceCount = RTL_NUMBER_OF(KnownInterfaces);
#define ValidClassForVersion(pClass, version) \
((pClass)->MinClassNTDDIVersion <= (version) && (pClass)->MaxClassNTDDIVersion >= (version))
#define ValidInterfaceForVersion(interface, version) \
((interface).MinInterfaceNTDDIVersion <= (version) && (interface).MaxInterfaceNTDDIVersion >= (version))
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,
_In_ ULONG NTDDIVersion)
{
INT i;
for (i = 0; class->ifaces[i].iid; i++)
{
if (ValidInterfaceForVersion(class->ifaces[i], NTDDIVersion) &&
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,
_In_ ULONG NTDDIVersion)
{
HRESULT hr;
PVOID pObj;
PUNKNOWN pUnk;
INT iClass, iIntf;
PCCLASS_AND_INTERFACES class;
for (iClass = 0; iClass < ExpectedInterfaceCount; iClass++)
{
class = &ExpectedInterfaces[iClass];
if (!ValidClassForVersion(class, NTDDIVersion))
continue;
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 */
for (iIntf = 0; class->ifaces[iIntf].iid; iIntf++)
{
if (!ValidInterfaceForVersion(class->ifaces[iIntf], NTDDIVersion))
continue;
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\n", class->name, iface->name);
#ifdef LOG_COM_INTERFACE_OFFSETS
else
mytrace("%s0x%lx, %s, %s\n", offset < 0 ? "-" : "", offset < 0 ? -offset : offset, class->name, iface->name);
#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, NTDDIVersion))
continue;
offset = GetInterfaceOffset(pUnk, iface->iid);
ok(offset == INTF_NOT_EXPOSED, "%s exposes %s (offset %s0x%lx), but shouldn't\n", class->name, iface->name, offset < 0 ? "-" : "", offset < 0 ? -offset : offset);
}
// TODO: do some aggregation
IUnknown_Release(pUnk);
}
}
static
VOID
TestModuleRegistry(
_In_ PCWSTR ModuleName,
_In_ PCCLASS_AND_INTERFACES ExpectedInterfaces,
_In_ INT ExpectedInterfaceCount,
_In_ ULONG NTDDIVersion)
{
INT iClass;
PCCLASS_AND_INTERFACES class;
HKEY hKeyClasses;
LONG result;
result = RegOpenKeyExW(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 data[100];
DWORD dataSize;
PCWSTR expectedThreadingModel;
class = &ExpectedInterfaces[iClass];
if (!ValidClassForVersion(class, NTDDIVersion))
continue;
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 = RegOpenKeyExW(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 = RegOpenKeyExW(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;
dataSize = sizeof(data);
result = RegQueryValueExW(hKeyServer, NULL, NULL, &type, (PBYTE)data, &dataSize);
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(dataSize % sizeof(WCHAR) == 0, "size %lu for %s\n", dataSize, class->name);
ok(dataSize <= sizeof(data), "size %lu for %s\n", dataSize, class->name);
ok(data[dataSize / 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(data);
PathRemoveExtensionW(data);
ok(!_wcsicmp(data, ModuleName), "Server is %ls, expected %ls for %s\n", data, ModuleName, class->name);
}
dataSize = sizeof(data);
result = RegQueryValueExW(hKeyServer, L"ThreadingModel", NULL, &type, (PBYTE)data, &dataSize);
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(dataSize % sizeof(WCHAR) == 0, "size %lu for %s\n", dataSize, class->name);
ok(dataSize <= sizeof(data), "size %lu for %s\n", dataSize, class->name);
ok(data[dataSize / sizeof(WCHAR) - 1] == UNICODE_NULL, "Not null terminated for %s\n", class->name);
expectedThreadingModel = class->ThreadingModel;
if (!expectedThreadingModel)
expectedThreadingModel = L"Apartment";
ok(!_wcsicmp(data, expectedThreadingModel), "Server is %ls, expected %ls for %s\n", data, expectedThreadingModel, class->name);
}
RegCloseKey(hKeyServer);
}
RegCloseKey(hKeyClasses);
}
}
static
VOID
TestManualInstantiation(
_In_ PCWSTR ModuleName,
_In_ PCCLASS_AND_INTERFACES ExpectedInterfaces,
_In_ INT ExpectedInterfaceCount,
_In_ ULONG NTDDIVersion)
{
INT iClass;
PCCLASS_AND_INTERFACES class;
HRESULT (__stdcall *DllGetClassObject)(REFCLSID, REFIID, PVOID *);
DllGetClassObject = (PVOID)GetProcAddress(GetModuleHandleW(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];
if (!ValidClassForVersion(class, NTDDIVersion))
continue;
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 (!myskip(SUCCEEDED(hr), "No instance\n"))
{
IUnknown *pUnk = pv;
IUnknown_Release(pUnk);
}
IClassFactory_Release(pCF);
}
}
}
VOID
TestClassesEx(
_In_ PCWSTR ModuleName,
_In_ PCCLASS_AND_INTERFACES ExpectedInterfaces,
_In_ INT ExpectedInterfaceCount,
_In_ ULONG MinimumNTDDIVersion,
_In_ ULONG MaximumNTDDIVersion,
_In_ BOOLEAN IsWinRT)
{
HRESULT hr;
ULONG NTDDIVersion;
NTDDIVersion = GetNTDDIVersion();
if (NTDDIVersion < MinimumNTDDIVersion || NTDDIVersion > MaximumNTDDIVersion)
{
skip("Skipping all tests for module %S, NTDDI version (0x%08lx) is outside of the supported range (0x%08lx-0x%08lx).\n",
ModuleName, NTDDIVersion, MinimumNTDDIVersion, MaximumNTDDIVersion);
return;
}
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, NTDDIVersion);
TestModuleRegistry(ModuleName, ExpectedInterfaces, ExpectedInterfaceCount, NTDDIVersion);
if (IsWinRT)
skip("%S is a WinRT module, skipping manual instantiation tests.\n", ModuleName);
else
TestManualInstantiation(ModuleName, ExpectedInterfaces, ExpectedInterfaceCount, NTDDIVersion);
CoUninitialize();
}
VOID
TestClasses(
_In_ PCWSTR ModuleName,
_In_ PCCLASS_AND_INTERFACES ExpectedInterfaces,
_In_ INT ExpectedInterfaceCount)
{
TestClassesEx(ModuleName, ExpectedInterfaces, ExpectedInterfaceCount, NTDDI_MIN, NTDDI_MAX, FALSE);
}
static
VOID
TestInterfaceRegistry(
_In_ PCKNOWN_INTERFACE Interfaces,
_In_ INT InterfaceCount)
{
INT i;
HKEY hKeyInterface;
LONG result;
ULONG CurrentNTDDI;
result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Classes\\Interface", 0, KEY_ENUMERATE_SUB_KEYS, &hKeyInterface);
ok(result == NO_ERROR, "Failed to open interface key, error %lu\n", result);
if (!myskip(result == NO_ERROR, "No interface key\n"))
{
CurrentNTDDI = GetNTDDIVersion();
for (i = 0; i < InterfaceCount; i++)
{
HKEY hKey;
NTSTATUS status;
UNICODE_STRING iid;
DWORD type;
WCHAR data[100];
DWORD dataSize;
PCKNOWN_INTERFACE iface;
PCWSTR expectedName;
iface = &Interfaces[i];
status = RtlStringFromGUID(iface->iid, &iid);
ok(status == STATUS_SUCCESS, "Failed to convert guid to string for %s, status %lx\n", iface->name, status);
if (myskip(NT_SUCCESS(status), "No guid string\n"))
continue;
result = RegOpenKeyExW(hKeyInterface, iid.Buffer, 0, KEY_QUERY_VALUE, &hKey);
if (iface->IsRegistered(CurrentNTDDI))
{
ok(result == NO_ERROR, "%s should be registered. (Error %lu)\n", iface->name, result);
// (void)myskip(result == NO_ERROR, "No key\n");
}
else
{
ok(result == ERROR_FILE_NOT_FOUND, "%s should not be registered. (Error %lu)\n", iface->name, result);
}
RtlFreeUnicodeString(&iid);
if (result != NO_ERROR)
continue;
dataSize = sizeof(data);
result = RegQueryValueExW(hKey, NULL, NULL, &type, (PBYTE)data, &dataSize);
ok(result == NO_ERROR, "Failed to query value for %s, error %lu\n", iface->name, result);
if (!myskip(result == NO_ERROR, "No module name\n"))
{
ok(type == REG_SZ, "type %lu for %s\n", type, iface->name);
ok(dataSize % sizeof(WCHAR) == 0, "size %lu for %s\n", dataSize, iface->name);
ok(dataSize <= sizeof(data), "size %lu for %s\n", dataSize, iface->name);
ok(data[dataSize / sizeof(WCHAR) - 1] == UNICODE_NULL, "Not null terminated for %s\n", iface->name);
expectedName = wcschr(iface->wname, L'_');
if (expectedName)
expectedName++;
else
expectedName = iface->wname;
ok(!_wcsicmp(data, expectedName), "Name is %ls, expected %ls\n", data, expectedName);
}
RegCloseKey(hKey);
}
RegCloseKey(hKeyInterface);
}
}
START_TEST(interfaces)
{
TestInterfaceRegistry(KnownInterfaces, KnownInterfaceCount);
}