1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         GPLv2+ - See COPYING in the top level directory
4  * PURPOSE:         COM interface test
5  * PROGRAMMER:      Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #include "com_apitest.h"
9 
10 #include <winreg.h>
11 #include <mshtmhst.h>
12 #include <shlwapi.h>
13 #include <commoncontrols.h>
14 #include <activscp.h>
15 #include <ndk/rtlfuncs.h>
16 
17 #define NDEBUG
18 #include <debug.h>
19 
20 #define myskip(c, ...) ((c) ? 0 : (skip(__VA_ARGS__), 1))
21 #define mytrace(...) do {       \
22     int debug = winetest_debug; \
23     winetest_debug = 1;         \
24     trace(__VA_ARGS__);         \
25     winetest_debug = debug;     \
26 } while (0)
27 
28 typedef struct _KNOWN_INTERFACE
29 {
30     const IID *iid;
31     PCSTR name;
32     PCWSTR wname;
33     BOOLEAN noreg;
34 } KNOWN_INTERFACE;
35 typedef const KNOWN_INTERFACE *PCKNOWN_INTERFACE;
36 
37 #undef ID_NAME
38 #define ID_NAME(c) &c, #c, L ## #c
39 static KNOWN_INTERFACE KnownInterfaces[] =
40 {
41     { ID_NAME(IID_IACList),                     TRUE },
42     { ID_NAME(IID_IACList2),                    TRUE },
43     { ID_NAME(IID_IADesktopP2),                 TRUE },
44     { ID_NAME(IID_IAccIdentity)                      },
45     { ID_NAME(IID_IAccPropServer)                    },
46     { ID_NAME(IID_IAccPropServices)                  },
47     { ID_NAME(IID_IAccessible)                       },
48     { ID_NAME(IID_IAccessibleHandler)                },
49     { ID_NAME(IID_IAccessControl),              TRUE },
50     { ID_NAME(IID_IAccessor)                         },
51     { ID_NAME(IID_IACLCustomMRU),               TRUE },
52     { ID_NAME(IID_IActiveDesktop),              TRUE },
53     { ID_NAME(IID_IActiveDesktopP),             TRUE },
54     { ID_NAME(IID_IActionProgress)                   },
55     { ID_NAME(IID_IActionProgressDialog)             },
56     { ID_NAME(IID_IAddressBarParser),           TRUE },
57     { ID_NAME(IID_IAddressBand),                TRUE },
58     { ID_NAME(IID_IAddressEditBox),             TRUE },
59     { ID_NAME(IID_IAsyncMoniker),               TRUE },
60     { ID_NAME(IID_IAugmentedShellFolder),       TRUE },
61     { ID_NAME(IID_IAugmentedShellFolder2),      TRUE },
62     { ID_NAME(IID_IAutoComplete),               TRUE },
63     { ID_NAME(IID_IAutoComplete2),              TRUE },
64     { ID_NAME(IID_IAutoCompleteDropDown)             },
65     { ID_NAME(IID_IBandHost)                         },
66     { ID_NAME(IID_IBandNavigate),                    },
67     { ID_NAME(IID_IBandProxy),                  TRUE },
68     { ID_NAME(IID_IBandSite)                         },
69     { ID_NAME(IID_IBandSiteHelper),             TRUE },
70     { ID_NAME(IID_IBanneredBar),                TRUE },
71     { ID_NAME(IID_IBindCtx)                          },
72     { ID_NAME(IID_IBindEventHandler)                 },
73     { ID_NAME(IID_IBindHost)                         },
74     { ID_NAME(IID_IBinding)                          },
75     { ID_NAME(IID_IBindProtocol),               TRUE },
76     { ID_NAME(IID_IBindResource)                     },
77     { ID_NAME(IID_IBindStatusCallback)               },
78     { ID_NAME(IID_IBlockingLock)                     },
79     { ID_NAME(IID_IBrowserFrameOptions),        TRUE },
80     { ID_NAME(IID_IBrowserService)                   },
81     { ID_NAME(IID_IBrowserService2),            TRUE },
82     { ID_NAME(IID_IBrowserService3),            TRUE },
83     { ID_NAME(IID_IBrowserService4),            TRUE },
84     { ID_NAME(IID_ICDBurn)                           },
85     { ID_NAME(IID_ICDBurnExt)                        },
86     { ID_NAME(IID_ICDBurnPriv)                       },
87     { ID_NAME(IID_ICallFactory),                TRUE },
88     { ID_NAME(IID_ICancelMethodCalls),          TRUE },
89     { ID_NAME(IID_ICatInformation)                   },
90     { ID_NAME(IID_ICatRegister)                      },
91     { ID_NAME(IID_IClassActivator),                  },
92     { ID_NAME(IID_IClassFactory)                     },
93     { ID_NAME(IID_IClassFactory2)                    },
94     { ID_NAME(IID_IClassFactory3),              TRUE },
95     { ID_NAME(IID_IClientSecurity),             TRUE },
96     { ID_NAME(IID_ICommDlgBrowser)                   },
97     { ID_NAME(IID_ICommDlgBrowser2)                  },
98     { ID_NAME(IID_ICommDlgBrowser3)                  },
99     { ID_NAME(IID_ICompositeFolder)                  },
100     { ID_NAME(IID_IComputerInfoChangeNotify),        },
101     { ID_NAME(IID_IComThreadingInfo),           TRUE },
102     { ID_NAME(IID_IConnectionPoint)                  },
103     { ID_NAME(IID_IConnectionPointContainer)         },
104     { ID_NAME(IID_IContext),                    TRUE },
105     { ID_NAME(IID_IContextMenu),                TRUE },
106     { ID_NAME(IID_IContextMenu2),               TRUE },
107     { ID_NAME(IID_IContextMenu3),               TRUE },
108     { ID_NAME(IID_IContextMenuCB),              TRUE },
109     { ID_NAME(IID_IContextMenuSite)                  },
110     { ID_NAME(IID_IContinue)                         },
111     { ID_NAME(IID_IContinueCallback)                 },
112     { ID_NAME(IID_ICopyHookA),                  TRUE },
113     { ID_NAME(IID_ICopyHookW),                  TRUE },
114     { ID_NAME(IID_ICurrentWorkingDirectory),    TRUE },
115     { ID_NAME(IID_ICustomizeInfoTip)                 },
116     { ID_NAME(IID_IDVGetEnum),                  TRUE },
117     { ID_NAME(IID_IDataObject)                       },
118     //{ ID_NAME(IID_IDefViewID)                        }, == DefViewFrame3
119     { ID_NAME(IID_IDefViewFrame),               TRUE },
120     { ID_NAME(IID_IDefViewFrame3)                    },
121     { ID_NAME(IID_IDefViewFrameGroup)                },
122     { ID_NAME(IID_IDefViewSafety),                   },
123     { ID_NAME(IID_IDefViewScript),              TRUE },
124     { ID_NAME(IID_IDelayedRelease),             TRUE },
125     { ID_NAME(IID_IDeskBand)                         },
126     { ID_NAME(IID_IDeskBandEx)                       },
127     { ID_NAME(IID_IDeskBar),                    TRUE },
128     { ID_NAME(IID_IDeskBarClient),              TRUE },
129     { ID_NAME(IID_IDeskMovr),                   TRUE },
130     { ID_NAME(IID_IDiscMasterProgressEvents)         },
131     { ID_NAME(IID_IDispatch)                         },
132     { ID_NAME(IID_IDispatchEx)                       },
133     { ID_NAME(IID_IDockingWindow)                    },
134     { ID_NAME(IID_IDockingWindowFrame),         TRUE },
135     { ID_NAME(IID_IDockingWindowSite),          TRUE },
136     { ID_NAME(IID_IDocViewSite),                TRUE },
137     { ID_NAME(IID_IDragSourceHelper),           TRUE },
138     { ID_NAME(IID_IDriveFolderExt),             TRUE },
139     { ID_NAME(IID_IDropSource)                       },
140     { ID_NAME(IID_IDropTarget)                       },
141     { ID_NAME(IID_IDropTargetHelper),           TRUE },
142     { ID_NAME(IID_IEFrameAuto)                       },
143     //{ ID_NAME(IID_IEnumCATID)                        }, == EnumGUID
144     //{ ID_NAME(IID_IEnumCLSID)                        }, == EnumGUID
145     { ID_NAME(IID_IEnumCATEGORYINFO)                 },
146     { ID_NAME(IID_IEnumConnectionPoints)             },
147     { ID_NAME(IID_IEnumConnections)                  },
148     { ID_NAME(IID_IEnumExtraSearch)                  },
149     { ID_NAME(IID_IEnumGUID)                         },
150     { ID_NAME(IID_IEnumIDList)                       },
151     { ID_NAME(IID_IEnumMoniker)                      },
152     //{ ID_NAME(IID_IEnumNetCfgBindingInterface)       },
153     //{ ID_NAME(IID_IEnumNetCfgBindingPath)            },
154     { ID_NAME(IID_IEnumNetCfgComponent),        TRUE },
155     { ID_NAME(IID_IEnumNetConnection)                },
156     { ID_NAME(IID_IEnumShellItems)                   },
157     { ID_NAME(IID_IEnumSTATSTG)                       },
158     { ID_NAME(IID_IEnumString)                       },
159     { ID_NAME(IID_IEnumUnknown)                      },
160     { ID_NAME(IID_IEnumVARIANT)                      },
161     { ID_NAME(IID_IErrorLog)                         },
162     { ID_NAME(IID_IExplorerBrowser)                  },
163     { ID_NAME(IID_IExplorerToolbar),            TRUE },
164     { ID_NAME(IID_IExtractIconA),               TRUE },
165     { ID_NAME(IID_IExtractIconW),               TRUE },
166     { ID_NAME(IID_IExtractImage)                     },
167     { ID_NAME(IID_IExtractImage2)                    },
168     { ID_NAME(IID_IFileDialog)                       },
169     { ID_NAME(IID_IFileDialog2),                TRUE },
170     { ID_NAME(IID_IFileOpenDialog)                   },
171     { ID_NAME(IID_IFileSaveDialog)                   },
172     { ID_NAME(IID_IFileSearchBand)                   },
173     { ID_NAME(IID_IFileViewerA),                TRUE },
174     { ID_NAME(IID_IFileViewerSite),             TRUE },
175     { ID_NAME(IID_IFileViewerW),                TRUE },
176     { ID_NAME(IID_IFilter)                           },
177     { ID_NAME(IID_IFolderBandPriv)                   },
178     { ID_NAME(IID_IFolderFilter)                     },
179     { ID_NAME(IID_IFolderFilterSite)                 },
180     { ID_NAME(IID_IFolderView)                       },
181     { ID_NAME(IID_IFolderView2)                      },
182     { ID_NAME(IID_IFolderViewHost),             TRUE },
183     { ID_NAME(IID_IFolderViewOC)                     },
184     { ID_NAME(IID_IFolderViewSettings)               },
185     { ID_NAME(IID_IForegroundTransfer),         TRUE },
186     { ID_NAME(IID_IGetNameSpaceExtensionPointer),TRUE},
187     { ID_NAME(IID_IGlobalFolderSettings),       TRUE },
188     { ID_NAME(IID_IHWEventHandler)                   },
189     { ID_NAME(IID_IHWEventHandler2)                  },
190     { ID_NAME(IID_IHlinkFrame)                       },
191     { ID_NAME(IID_IImageList),                  TRUE },
192     { ID_NAME(IID_IImageList2),                 TRUE },
193     { ID_NAME(IID_IInitializeObject),           TRUE },
194     { ID_NAME(IID_IInitializeWithBindCtx)            },
195     { ID_NAME(IID_IInitializeWithFile)               },
196     { ID_NAME(IID_IInputObject)                      },
197     { ID_NAME(IID_IInputObjectSite)                  },
198     { ID_NAME(IID_IInternalUnknown),            TRUE },
199     { ID_NAME(IID_IInternetSecurityManager)          },
200     { ID_NAME(IID_IInternetZoneManager),        TRUE },
201     { ID_NAME(IID_IItemNameLimits)                   },
202     { ID_NAME(IID_IMarshal)                          },
203     { ID_NAME(IID_IMarshal2),                   TRUE },
204     { ID_NAME(IID_IMenuBand),                   TRUE },
205     { ID_NAME(IID_IMenuPopup),                  TRUE },
206     { ID_NAME(IID_IModalWindow)                      },
207     { ID_NAME(IID_IMoniker)                          },
208     { ID_NAME(IID_IMultiMonitorDockingSite),    TRUE },
209     { ID_NAME(IID_IMultiQI),                    TRUE },
210     { ID_NAME(IID_INameSpaceTreeControl),       TRUE },
211     { ID_NAME(IID_INamespaceProxy),             TRUE },
212     { ID_NAME(IID_INamespaceWalk)                    },
213     { ID_NAME(IID_INamespaceWalkCB)                  },
214     { ID_NAME(IID_INamespaceWalkCB2)                 },
215     { ID_NAME(IID_INetCfg),                     TRUE },
216     //{ ID_NAME(IID_INetCfgBindingInterface)           },
217     //{ ID_NAME(IID_INetCfgBindingPath)                },
218     { ID_NAME(IID_INetCfgComponent),            TRUE },
219     { ID_NAME(IID_INetCfgComponentBindings),    TRUE },
220     { ID_NAME(IID_INetCfgComponentControl),     TRUE },
221     { ID_NAME(IID_INetCfgComponentPropertyUi),  TRUE },
222     { ID_NAME(IID_INetCfgLock),                 TRUE },
223     { ID_NAME(IID_INetCfgPnpReconfigCallback),  TRUE },
224     { ID_NAME(IID_INetConnectionConnectUi),     TRUE },
225     { ID_NAME(IID_INetConnectionPropertyUi),    TRUE },
226     { ID_NAME(IID_INetConnectionPropertyUi2),   TRUE },
227     { ID_NAME(IID_INetConnectionManager)             },
228     { ID_NAME(IID_INetLanConnectionUiInfo),     TRUE },
229     { ID_NAME(IID_INewMenuClient)                    },
230     { ID_NAME(IID_INewShortcutHookA),           TRUE },
231     { ID_NAME(IID_INewShortcutHookW),           TRUE },
232     { ID_NAME(IID_INewWindowManager)                 },
233     { ID_NAME(IID_INSCTree),                    TRUE },
234     { ID_NAME(IID_INSCTree2),                   TRUE },
235     { ID_NAME(IID_IObjMgr),                     TRUE },
236     { ID_NAME(IID_IObjectSafety)                     },
237     { ID_NAME(IID_IObjectWithBackReferences)         },
238     { ID_NAME(IID_IObjectWithSite)                   },
239     { ID_NAME(IID_IOleClientSite)                    },
240     { ID_NAME(IID_IOleCommandTarget)                 },
241     { ID_NAME(IID_IOleContainer)                     },
242     { ID_NAME(IID_IOleControl)                       },
243     { ID_NAME(IID_IOleControlSite)                   },
244     { ID_NAME(IID_IOleInPlaceActiveObject)           },
245     { ID_NAME(IID_IOleInPlaceFrame)                  },
246     { ID_NAME(IID_IOleInPlaceObject)                 },
247     { ID_NAME(IID_IOleInPlaceObjectWindowless), TRUE },
248     { ID_NAME(IID_IOleInPlaceSite)                   },
249     { ID_NAME(IID_IOleInPlaceSiteEx)                 },
250     { ID_NAME(IID_IOleInPlaceSiteWindowless),   TRUE },
251     { ID_NAME(IID_IOleInPlaceUIWindow)               },
252     { ID_NAME(IID_IOleItemContainer),                },
253     { ID_NAME(IID_IOleLink),                         },
254     { ID_NAME(IID_IOleObject)                        },
255     { ID_NAME(IID_IOleWindow)                        },
256     { ID_NAME(IID_IParentAndItem)                    },
257     { ID_NAME(IID_IParseDisplayName),                },
258     { ID_NAME(IID_IPersist)                          },
259     { ID_NAME(IID_IPersistFile)                      },
260     { ID_NAME(IID_IPersistFolder)                    },
261     { ID_NAME(IID_IPersistFolder2)                   },
262     { ID_NAME(IID_IPersistFolder3)                   },
263     { ID_NAME(IID_IPersistFreeThreadedObject),  TRUE },
264     { ID_NAME(IID_IPersistHistory)                   },
265     { ID_NAME(IID_IPersistIDList)                    },
266     { ID_NAME(IID_IPersistMemory)                    },
267     { ID_NAME(IID_IPersistPropertyBag)               },
268     { ID_NAME(IID_IPersistPropertyBag2)              },
269     { ID_NAME(IID_IPersistStorage)                   },
270     { ID_NAME(IID_IPersistStream)                    },
271     { ID_NAME(IID_IPersistStreamInit)                },
272     { ID_NAME(IID_IPreviewHandler)                   },
273     { ID_NAME(IID_IPreviewHandlerFrame)              },
274     { ID_NAME(IID_IPreviewHandlerVisuals)            },
275     { ID_NAME(IID_IProgressDialog),             TRUE },
276     { ID_NAME(IID_IPropertyBag)                      },
277     { ID_NAME(IID_IPropertyBag2)                     },
278     { ID_NAME(IID_IPropertySetStorage)               },
279     { ID_NAME(IID_IPropertyStore)                    },
280     { ID_NAME(IID_IPropSheetPage),              TRUE },
281     { ID_NAME(IID_IProvideClassInfo)                 },
282     { ID_NAME(IID_IProvideClassInfo2)                },
283     { ID_NAME(IID_IQueryAssociations),          TRUE },
284     { ID_NAME(IID_IQueryCancelAutoPlay)              },
285     { ID_NAME(IID_IQueryInfo),                  TRUE },
286     { ID_NAME(IID_IQuickActivate)                    },
287     { ID_NAME(IID_IRegTreeOptions),             TRUE },
288     { ID_NAME(IID_IRemoteComputer)                   },
289     { ID_NAME(IID_IResolveShellLink)                 },
290     { ID_NAME(IID_IROTData),                         },
291     { ID_NAME(IID_IRpcOptions),                 TRUE },
292     { ID_NAME(IID_IRunnableObject)                   },
293     { ID_NAME(IID_IRunningObjectTable),              },
294     { ID_NAME(IID_ISLTracker),                  TRUE },
295     { ID_NAME(IID_IScriptErrorList)                  },
296     { ID_NAME(IID_ISearch)                           },
297     { ID_NAME(IID_ISearchAssistantOC)                },
298     { ID_NAME(IID_ISearchAssistantOC2)               },
299     { ID_NAME(IID_ISearchAssistantOC3)               },
300     { ID_NAME(IID_ISearchBar)                        },
301     { ID_NAME(IID_ISearches)                         },
302     { ID_NAME(IID_ISecMgrCacheSeedTarget)            },
303     { ID_NAME(IID_IServerSecurity),             TRUE },
304     { ID_NAME(IID_IServiceProvider)                  },
305     { ID_NAME(IID_IShellApp),                   TRUE },
306     { ID_NAME(IID_IShellBrowser)                     },
307     { ID_NAME(IID_IShellBrowserService),        TRUE },
308     { ID_NAME(IID_IShellChangeNotify),          TRUE },
309     { ID_NAME(IID_IShellCopyHookA),             TRUE },
310     { ID_NAME(IID_IShellCopyHookW),             TRUE },
311     { ID_NAME(IID_IShellDesktopTray),           TRUE },
312     { ID_NAME(IID_IShellDetails),               TRUE },
313     { ID_NAME(IID_IShellDispatch)                    },
314     { ID_NAME(IID_IShellDispatch2)                   },
315     { ID_NAME(IID_IShellDispatch3)                   },
316     { ID_NAME(IID_IShellDispatch4)                   },
317     { ID_NAME(IID_IShellDispatch5),             TRUE },
318     { ID_NAME(IID_IShellDispatch6),             TRUE },
319     { ID_NAME(IID_IShellExecuteHookA),          TRUE },
320     { ID_NAME(IID_IShellExecuteHookW),          TRUE },
321     { ID_NAME(IID_IShellExtInit),               TRUE },
322     { ID_NAME(IID_IShellFavoritesNameSpace)          },
323     { ID_NAME(IID_IShellFolder)                      },
324     { ID_NAME(IID_IShellFolder2)                     },
325     { ID_NAME(IID_IShellFolderBand),            TRUE },
326     { ID_NAME(IID_IShellFolderSearchable),      TRUE },
327     { ID_NAME(IID_IShellFolderSearchableCallback), TRUE },
328     { ID_NAME(IID_IShellFolderView),            TRUE },
329     { ID_NAME(IID_IShellFolderViewCB),          TRUE },
330     { ID_NAME(IID_IShellFolderViewDual)              },
331     { ID_NAME(IID_IShellFolderViewDual2)             },
332     { ID_NAME(IID_IShellFolderViewDual3),       TRUE },
333     { ID_NAME(IID_IShellFolderViewType),        TRUE },
334     { ID_NAME(IID_IShellIcon)                        },
335     { ID_NAME(IID_IShellIconOverlay),           TRUE },
336     { ID_NAME(IID_IShellIconOverlayIdentifier), TRUE },
337     { ID_NAME(IID_IShellImageData),             TRUE },
338     { ID_NAME(IID_IShellImageDataAbort),        TRUE },
339     { ID_NAME(IID_IShellImageDataFactory),      TRUE },
340     { ID_NAME(IID_IShellItem)                        },
341     { ID_NAME(IID_IShellItem2)                       },
342     { ID_NAME(IID_IShellItemArray)                   },
343     { ID_NAME(IID_IShellItemFilter)                  },
344     { ID_NAME(IID_IShellLinkA)                       },
345     { ID_NAME(IID_IShellLinkDataList),          TRUE },
346     { ID_NAME(IID_IShellLinkDual)                    },
347     { ID_NAME(IID_IShellLinkDual2)                   },
348     { ID_NAME(IID_IShellLinkW)                       },
349     { ID_NAME(IID_IShellMenu),                  TRUE },
350     { ID_NAME(IID_IShellMenu2),                 TRUE },
351     { ID_NAME(IID_IShellMenuAcc),               TRUE },
352     { ID_NAME(IID_IShellMenuCallback),          TRUE },
353     { ID_NAME(IID_IShellNameSpace)                   },
354     { ID_NAME(IID_IShellPropSheetExt),          TRUE },
355     { ID_NAME(IID_IShellService),               TRUE },
356     { ID_NAME(IID_IShellTaskScheduler),         TRUE },
357     { ID_NAME(IID_IShellUIHelper)                    },
358     { ID_NAME(IID_IShellUIHelper2),             TRUE },
359     { ID_NAME(IID_IShellView)                        },
360     { ID_NAME(IID_IShellView2)                       },
361     { ID_NAME(IID_IShellView3)                       },
362     { ID_NAME(IID_IShellWindows)                     },
363     { ID_NAME(IID_ISpecifyPropertyPages)             },
364     { ID_NAME(IID_IStorage)                          },
365     { ID_NAME(IID_IStream)                           },
366     { ID_NAME(IID_ISurrogate)                        },
367     { ID_NAME(IID_ISynchronize)                      },
368     { ID_NAME(IID_ISynchronizeContainer),       TRUE },
369     { ID_NAME(IID_ISynchronizeEvent),           TRUE },
370     { ID_NAME(IID_ISynchronizeHandle),          TRUE },
371     { ID_NAME(IID_ITargetEmbedding)                  },
372     { ID_NAME(IID_ITargetFrame)                      },
373     { ID_NAME(IID_ITargetFrame2)                     },
374     { ID_NAME(IID_ITargetFramePriv)                  },
375     { ID_NAME(IID_ITargetFramePriv2)                 },
376     { ID_NAME(IID_ITargetNotify)                     },
377     { ID_NAME(IID_ITaskbarList)                      },
378     { ID_NAME(IID_ITaskbarList2)                     },
379     { ID_NAME(IID_ITaskbarList3),               TRUE },
380     { ID_NAME(IID_ITaskbarList4),               TRUE },
381     { ID_NAME(IID_ITrackShellMenu),             TRUE },
382     /* This interface is completely different between PSDK and registry/shell32 */
383     { ID_NAME(IID_ITransferAdviseSink),         TRUE },
384 #define IID_ITransferAdviseSink IID_ITransferAdviseSinkPriv
385     { ID_NAME(IID_ITransferAdviseSink)               },
386 #undef IID_ITransferAdviseSink
387     { ID_NAME(IID_ITransferDestination),        TRUE },
388     { ID_NAME(IID_ITransferSource),             TRUE },
389     { ID_NAME(IID_ITranslateShellChangeNotify), TRUE },
390     { ID_NAME(IID_ITrayPriv),                   TRUE },
391     { ID_NAME(IID_ITrayPriv2),                  TRUE },
392     { ID_NAME(IID_IUnknown)                          },
393     { ID_NAME(IID_IURLSearchHook),              TRUE },
394     { ID_NAME(IID_IURLSearchHook2),             TRUE },
395     { ID_NAME(IID_IUrlHistoryNotify)                 },
396     { ID_NAME(IID_IUrlHistoryStg)                    },
397     { ID_NAME(IID_IUrlHistoryStg2)                   },
398     { ID_NAME(IID_IViewObject)                       },
399     { ID_NAME(IID_IViewObject2)                      },
400     { ID_NAME(IID_IViewObjectEx),               TRUE },
401     { ID_NAME(IID_IVisualProperties)                 },
402     { ID_NAME(IID_IWebBrowser)                       },
403     { ID_NAME(IID_IWebBrowser2)                      },
404     { ID_NAME(IID_IWebBrowserApp)                    },
405     { ID_NAME(IID_IWebBrowserPriv)                   },
406     { ID_NAME(IID_IWebBrowserPriv2)                  },
407     { ID_NAME(IID_IWinEventHandler),            TRUE },
408 
409     { ID_NAME(IID_DFConstraint),                TRUE },
410     { ID_NAME(DIID__SearchAssistantEvents)           },
411     { ID_NAME(DIID_DShellFolderViewEvents)           },
412     { ID_NAME(DIID_DShellNameSpaceEvents)            },
413     { ID_NAME(DIID_DShellWindowsEvents)              },
414     { ID_NAME(DIID_DWebBrowserEvents)                },
415     { ID_NAME(DIID_DWebBrowserEvents2)               },
416     { ID_NAME(DIID_XMLDOMDocumentEvents )            },
417 
418     { ID_NAME(IID_CDefView),                    TRUE },
419     { ID_NAME(IID_Folder)                            },
420     { ID_NAME(IID_Folder2)                           },
421     { ID_NAME(IID_Folder3)                           },
422     { ID_NAME(IID_FolderItem)                        },
423     { ID_NAME(IID_FolderItem2)                       },
424     { ID_NAME(IID_FolderItems)                       },
425     { ID_NAME(IID_FolderItems2)                      },
426     { ID_NAME(IID_FolderItems3)                      },
427     { ID_NAME(IID_FolderItemVerb)                    },
428     { ID_NAME(IID_FolderItemVerbs)                   },
429 
430     { ID_NAME(CLSID_ShellDesktop),              TRUE },
431 
432     { ID_NAME(IID_IQueryContinue)                    },
433     { ID_NAME(IID_IUserNotification)                 },
434     { ID_NAME(IID_IUserNotificationCallback)         }, // On Vista+
435     { ID_NAME(IID_IUserNotification2)                }, // On Vista+
436 
437     { ID_NAME(IID_IAggregateFilterCondition)         },
438     { ID_NAME(IID_IAliasRegistrationCallback),  TRUE },
439     { ID_NAME(IID_IAssociationArrayInitialize), TRUE },
440     { ID_NAME(IID_IAssociationList),            TRUE },
441     { ID_NAME(IID_IBackReferencedObject),       TRUE },
442     { ID_NAME(IID_IBasePropPage),               TRUE },
443     { ID_NAME(IID_ICommonLayoutDefinition),     TRUE },
444     { ID_NAME(IID_IControlPanelEnumerator),     TRUE },
445     { ID_NAME(IID_IDelegateHostItemContainer),  TRUE },
446     { ID_NAME(IID_IDrawPropertyControl),        TRUE },
447     { ID_NAME(IID_IEnumAssociationElements),    TRUE },
448     { ID_NAME(IID_IEnumerateAssociationElements),TRUE },
449     { ID_NAME(IID_IExecuteCommand),             TRUE },
450     { ID_NAME(IID_IFilterCondition)                  },
451     { ID_NAME(IID_IFolderNotify),               TRUE },
452     { ID_NAME(IID_IFolderProperties),           TRUE },
453     { ID_NAME(IID_IFolderType),                 TRUE },
454     { ID_NAME(IID_IFolderWithSearchRoot),       TRUE },
455     { ID_NAME(IID_IFrameLayoutDefinition),      TRUE },
456     { ID_NAME(IID_IItemFilter),                 TRUE },
457     { ID_NAME(IID_IItemFilterOwner),            TRUE },
458     { ID_NAME(IID_ILocalizableItemParent),      TRUE },
459     { ID_NAME(IID_INewItemAdvisor),             TRUE },
460     { ID_NAME(IID_IObjectWithAssociationElement),TRUE },
461     { ID_NAME(IID_IObjectWithAssociationList),  TRUE },
462     { ID_NAME(IID_IObjectWithQuerySource),      TRUE },
463     { ID_NAME(IID_IObjectWithSelection),        TRUE },
464     { ID_NAME(IID_IPersistString2),             TRUE },
465     { ID_NAME(IID_IPrinterFolder),              TRUE },
466     { ID_NAME(IID_IPropertyControl),            TRUE },
467     { ID_NAME(IID_IPropertyControlBase),        TRUE },
468     { ID_NAME(IID_IPropertyControlSite),        TRUE },
469     { ID_NAME(IID_IRegItemCustomAttributes),    TRUE },
470     { ID_NAME(IID_IRegItemCustomEnumerator),    TRUE },
471     { ID_NAME(IID_IRegItemFolder),              TRUE },
472     { ID_NAME(IID_IRootAndRelativeParsingFolder),TRUE },
473     { ID_NAME(IID_IScope),                      TRUE },
474     { ID_NAME(IID_IScopeItem),                  TRUE },
475     { ID_NAME(IID_IShellBrowserServce),         TRUE },
476     { ID_NAME(IID_IShellFolder3),               TRUE },
477     { ID_NAME(IID_ITaskCondition),              TRUE },
478     { ID_NAME(IID_ITaskConditionCombiner),      TRUE },
479     { ID_NAME(IID_ITaskConditionInit),          TRUE },
480     { ID_NAME(IID_ITransferProvider),           TRUE },
481     { ID_NAME(IID_IUserEventTimer)                   },
482     { ID_NAME(IID_IUserEventTimerCallback)           },
483     { ID_NAME(IID_IAssociationArrayOld),        TRUE },
484     { ID_NAME(IID_IAssociationArray),           TRUE },
485 #define IID_IDriveFolderExt IID_IDriveFolderExtOld
486     { ID_NAME(IID_IDriveFolderExt)                   },
487 #undef IID_IDriveFolderExt
488     { ID_NAME(IID_IPinnedListOld),              TRUE },
489     { ID_NAME(IID_IPinnedList),                 TRUE },
490     { ID_NAME(IID_IAttachmentExecute),          TRUE },
491 };
492 static const INT KnownInterfaceCount = RTL_NUMBER_OF(KnownInterfaces);
493 
494 static
495 PCKNOWN_INTERFACE
496 FindInterface(
497     _In_ const IID *iid)
498 {
499     INT i;
500 
501     for (i = 0; i < KnownInterfaceCount; i++)
502         if (IsEqualIID(KnownInterfaces[i].iid, iid))
503             return &KnownInterfaces[i];
504     ASSERT(i != KnownInterfaceCount);
505     return NULL;
506 }
507 
508 static
509 BOOLEAN
510 IsInterfaceExpected(
511     _In_ PCCLASS_AND_INTERFACES class,
512     _In_ const IID *iid)
513 {
514     INT i;
515 
516     for (i = 0; class->ifaces[i].iid; i++)
517         if (IsEqualIID(class->ifaces[i].iid, iid))
518             return TRUE;
519     return FALSE;
520 }
521 
522 #define INTF_NOT_EXPOSED LONG_MAX
523 static
524 LONG
525 GetInterfaceOffset(
526     _In_ PUNKNOWN pUnk,
527     _In_ const IID *iid)
528 {
529     HRESULT hr;
530     PVOID pObj;
531     PUNKNOWN pUnk2;
532     LONG offset;
533 
534     hr = IUnknown_QueryInterface(pUnk, iid, &pObj);
535     ok(hr == S_OK || hr == E_NOINTERFACE, "IUnknown::QueryInterface returned 0x%lx\n", hr);
536     if (FAILED(hr))
537         return INTF_NOT_EXPOSED;
538 
539     pUnk2 = pObj;
540     offset = (LONG_PTR)pObj - (LONG_PTR)pUnk;
541     IUnknown_Release(pUnk2);
542     return offset;
543 }
544 
545 static
546 VOID
547 TestModuleInterfaces(
548     _In_ PCCLASS_AND_INTERFACES ExpectedInterfaces,
549     _In_ INT ExpectedInterfaceCount)
550 {
551     HRESULT hr;
552     PVOID pObj;
553     PUNKNOWN pUnk;
554     INT iClass, iIntf;
555     PCCLASS_AND_INTERFACES class;
556 
557     for (iClass = 0; iClass < ExpectedInterfaceCount; iClass++)
558     {
559         class = &ExpectedInterfaces[iClass];
560         hr = CoCreateInstance(class->clsid,
561                               NULL,
562                               CLSCTX_INPROC_SERVER,
563                               &IID_IUnknown,
564                               &pObj);
565         ok(hr == S_OK, "CoCreateInstance failed. hr=0x%lx\n", hr);
566         if (FAILED(hr))
567         {
568             skip("Failed to instantiate %s.\n", class->name);
569             continue;
570         }
571 
572         pUnk = pObj;
573 
574         /* Check that all expected interfaces are present and have the right offset */
575         for (iIntf = 0; class->ifaces[iIntf].iid; iIntf++)
576         {
577             PCKNOWN_INTERFACE iface = FindInterface(class->ifaces[iIntf].iid);
578             LONG offset = GetInterfaceOffset(pUnk, iface->iid);
579             if (offset == INTF_NOT_EXPOSED)
580                 ok(0, "%s is missing %s (offset %ld)\n", class->name, iface->name, class->ifaces[iIntf].offset);
581             else if (class->ifaces[iIntf].offset != FARAWY)
582             {
583 #ifdef FAIL_WRONG_OFFSET
584                 ok(offset == class->ifaces[iIntf].offset, "%s, %s offset is %ld, expected %ld\n", class->name, iface->name, offset, class->ifaces[iIntf].offset);
585 #else
586                 if (offset != class->ifaces[iIntf].offset)
587                     mytrace("%s, %s offset is %ld, expected %ld\n", class->name, iface->name, offset, class->ifaces[iIntf].offset);
588 #endif
589             }
590         }
591 
592         /* Check that none other than the expected interfaces are present */
593         for (iIntf = 0; iIntf < KnownInterfaceCount; iIntf++)
594         {
595             PCKNOWN_INTERFACE iface = &KnownInterfaces[iIntf];
596             LONG offset;
597             if (IsInterfaceExpected(class, iface->iid))
598                 continue;
599             offset = GetInterfaceOffset(pUnk, iface->iid);
600 #ifdef GENERATE_TABLE_ENTRIES
601             ok(offset == INTF_NOT_EXPOSED, "%s: { %s0x%lx,   &%s },\n", class->name, offset < 0 ? "-" : "", offset < 0 ? -offset : offset, iface->name);
602 #else
603             ok(offset == INTF_NOT_EXPOSED, "%s exposes %s (offset %ld), but shouldn't\n", class->name, iface->name, offset);
604 #endif
605         }
606 
607         // TODO: do some aggregation
608 
609         IUnknown_Release(pUnk);
610     }
611 }
612 
613 static
614 VOID
615 TestModuleRegistry(
616     _In_ PCWSTR ModuleName,
617     _In_ PCCLASS_AND_INTERFACES ExpectedInterfaces,
618     _In_ INT ExpectedInterfaceCount)
619 {
620     INT iClass;
621     PCCLASS_AND_INTERFACES class;
622     HKEY hKeyClasses;
623     LONG result;
624 
625     result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Classes\\CLSID", 0, KEY_ENUMERATE_SUB_KEYS, &hKeyClasses);
626     ok(result == NO_ERROR, "Failed to open classes key, error %lu\n", result);
627     if (!myskip(result == NO_ERROR, "No classes key\n"))
628     {
629         for (iClass = 0; iClass < ExpectedInterfaceCount; iClass++)
630         {
631             HKEY hKey;
632             HKEY hKeyServer;
633             NTSTATUS status;
634             UNICODE_STRING clsid;
635             DWORD type;
636             WCHAR data[100];
637             DWORD dataSize;
638             PCWSTR expectedThreadingModel;
639 
640             class = &ExpectedInterfaces[iClass];
641             status = RtlStringFromGUID(class->clsid, &clsid);
642             ok(status == STATUS_SUCCESS, "Failed to convert guid to string for %s, status %lx\n", class->name, status);
643             if (myskip(NT_SUCCESS(status), "No guid string\n"))
644                 continue;
645 
646             result = RegOpenKeyExW(hKeyClasses, clsid.Buffer, 0, KEY_ENUMERATE_SUB_KEYS, &hKey);
647             ok(result == NO_ERROR, "Failed to open key for %s, error %lu\n", class->name, result);
648             RtlFreeUnicodeString(&clsid);
649             if (myskip(result == NO_ERROR, "No key\n"))
650                 continue;
651 
652             result = RegOpenKeyExW(hKey, L"InProcServer32", 0, KEY_QUERY_VALUE, &hKeyServer);
653             ok(result == NO_ERROR, "Failed to open key for %s, error %lu\n", class->name, result);
654             RegCloseKey(hKey);
655             if (myskip(result == NO_ERROR, "No key\n"))
656                 continue;
657 
658             dataSize = sizeof(data);
659             result = RegQueryValueExW(hKeyServer, NULL, NULL, &type, (PBYTE)data, &dataSize);
660             ok(result == NO_ERROR, "Failed to query value for %s, error %lu\n", class->name, result);
661             if (!myskip(result == NO_ERROR, "No module name\n"))
662             {
663                 ok(type == REG_SZ || type == REG_EXPAND_SZ, "type %lu for %s\n", type, class->name);
664                 ok(dataSize % sizeof(WCHAR) == 0, "size %lu for %s\n", dataSize, class->name);
665                 ok(dataSize <= sizeof(data), "size %lu for %s\n", dataSize, class->name);
666                 ok(data[dataSize / sizeof(WCHAR) - 1] == UNICODE_NULL, "Not null terminated for %s\n", class->name);
667                 // TODO: Use SearchPath (or assume everything's in system32) and do a proper full path compare
668                 PathStripPathW(data);
669                 PathRemoveExtensionW(data);
670                 ok(!wcsicmp(data, ModuleName), "Server is %ls, expected %ls for %s\n", data, ModuleName, class->name);
671             }
672 
673             dataSize = sizeof(data);
674             result = RegQueryValueExW(hKeyServer, L"ThreadingModel", NULL, &type, (PBYTE)data, &dataSize);
675             ok(result == NO_ERROR, "Failed to query value for %s, error %lu\n", class->name, result);
676             if (!myskip(result == NO_ERROR, "No ThreadingModel\n"))
677             {
678                 ok(type == REG_SZ || type == REG_EXPAND_SZ, "type %lu for %s\n", type, class->name);
679                 ok(dataSize % sizeof(WCHAR) == 0, "size %lu for %s\n", dataSize, class->name);
680                 ok(dataSize <= sizeof(data), "size %lu for %s\n", dataSize, class->name);
681                 ok(data[dataSize / sizeof(WCHAR) - 1] == UNICODE_NULL, "Not null terminated for %s\n", class->name);
682                 expectedThreadingModel = class->ThreadingModel;
683                 if (!expectedThreadingModel)
684                     expectedThreadingModel = L"Apartment";
685                 ok(!wcsicmp(data, expectedThreadingModel), "Server is %ls, expected %ls for %s\n", data, expectedThreadingModel, class->name);
686             }
687 
688             RegCloseKey(hKeyServer);
689         }
690         RegCloseKey(hKeyClasses);
691     }
692 }
693 
694 static
695 VOID
696 TestManualInstantiation(
697     _In_ PCWSTR ModuleName,
698     _In_ PCCLASS_AND_INTERFACES ExpectedInterfaces,
699     _In_ INT ExpectedInterfaceCount)
700 {
701     INT iClass;
702     PCCLASS_AND_INTERFACES class;
703     HRESULT (__stdcall *DllGetClassObject)(REFCLSID, REFIID, PVOID *);
704 
705     DllGetClassObject = (PVOID)GetProcAddress(GetModuleHandleW(ModuleName), "DllGetClassObject");
706     ok(DllGetClassObject != NULL, "DllGetClassObject not found in %ls, error %lu\n", ModuleName, GetLastError());
707     if (myskip(DllGetClassObject != NULL, "No DllGetClassObject\n"))
708         return;
709 
710     for (iClass = 0; iClass < ExpectedInterfaceCount; iClass++)
711     {
712         PVOID pv;
713         HRESULT hr;
714         class = &ExpectedInterfaces[iClass];
715         hr = DllGetClassObject(class->clsid, &IID_IClassFactory, &pv);
716         ok(hr == S_OK, "DllGetClassObject failed for %s, hr = 0x%lx\n", class->name, hr);
717         if (!myskip(SUCCEEDED(hr), "No class factory\n"))
718         {
719             IClassFactory *pCF = pv;
720             hr = IClassFactory_CreateInstance(pCF, NULL, &IID_IUnknown, &pv);
721             ok(hr == S_OK, "IClassFactory::CreateInstance failed for %s, hr = 0x%lx\n", class->name, hr);
722             if (!myskip(SUCCEEDED(hr), "No instance\n"))
723             {
724                 IUnknown *pUnk = pv;
725                 IUnknown_Release(pUnk);
726             }
727             IClassFactory_Release(pCF);
728         }
729     }
730 }
731 
732 VOID
733 TestClasses(
734     _In_ PCWSTR ModuleName,
735     _In_ PCCLASS_AND_INTERFACES ExpectedInterfaces,
736     _In_ INT ExpectedInterfaceCount)
737 {
738     HRESULT hr;
739 
740     hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
741     ok(hr == S_OK, "CoInitializeEx failed. hr=0x%lx\n", hr);
742     if (myskip(SUCCEEDED(hr), "Failed to initialize COM. Cannot perform tests\n"))
743         return;
744 
745     TestModuleInterfaces(ExpectedInterfaces, ExpectedInterfaceCount);
746     TestModuleRegistry(ModuleName, ExpectedInterfaces, ExpectedInterfaceCount);
747     TestManualInstantiation(ModuleName, ExpectedInterfaces, ExpectedInterfaceCount);
748 
749     CoUninitialize();
750 }
751 
752 static
753 VOID
754 TestInterfaceRegistry(
755     _In_ PCKNOWN_INTERFACE Interfaces,
756     _In_ INT InterfaceCount)
757 {
758     INT i;
759     HKEY hKeyInterface;
760     LONG result;
761 
762     result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Classes\\Interface", 0, KEY_ENUMERATE_SUB_KEYS, &hKeyInterface);
763     ok(result == NO_ERROR, "Failed to open interface key, error %lu\n", result);
764     if (!myskip(result == NO_ERROR, "No interface key\n"))
765     {
766         for (i = 0; i < InterfaceCount; i++)
767         {
768             HKEY hKey;
769             NTSTATUS status;
770             UNICODE_STRING iid;
771             DWORD type;
772             WCHAR data[100];
773             DWORD dataSize;
774             PCKNOWN_INTERFACE iface;
775             PCWSTR expectedName;
776 
777             iface = &Interfaces[i];
778             status = RtlStringFromGUID(iface->iid, &iid);
779             ok(status == STATUS_SUCCESS, "Failed to convert guid to string for %s, status %lx\n", iface->name, status);
780             if (myskip(NT_SUCCESS(status), "No guid string\n"))
781                 continue;
782 
783             result = RegOpenKeyExW(hKeyInterface, iid.Buffer, 0, KEY_QUERY_VALUE, &hKey);
784             if (iface->noreg)
785             {
786                 ok(result == ERROR_FILE_NOT_FOUND, "RegOpenKeyEx returned %lu for %s\n", result, iface->name);
787             }
788             else
789             {
790                 ok(result == NO_ERROR, "Failed to open key for %s, error %lu\n", iface->name, result);
791                 (void)myskip(result == NO_ERROR, "No key\n");
792             }
793             RtlFreeUnicodeString(&iid);
794             if (result != NO_ERROR)
795                 continue;
796 
797             dataSize = sizeof(data);
798             result = RegQueryValueExW(hKey, NULL, NULL, &type, (PBYTE)data, &dataSize);
799             ok(result == NO_ERROR, "Failed to query value for %s, error %lu\n", iface->name, result);
800             if (!myskip(result == NO_ERROR, "No module name\n"))
801             {
802                 ok(type == REG_SZ, "type %lu for %s\n", type, iface->name);
803                 ok(dataSize % sizeof(WCHAR) == 0, "size %lu for %s\n", dataSize, iface->name);
804                 ok(dataSize <= sizeof(data), "size %lu for %s\n", dataSize, iface->name);
805                 ok(data[dataSize / sizeof(WCHAR) - 1] == UNICODE_NULL, "Not null terminated for %s\n", iface->name);
806                 expectedName = wcschr(iface->wname, L'_');
807                 if (expectedName)
808                     expectedName++;
809                 else
810                     expectedName = iface->wname;
811                 ok(!wcsicmp(data, expectedName), "Name is %ls, expected %ls\n", data, expectedName);
812             }
813 
814             RegCloseKey(hKey);
815         }
816         RegCloseKey(hKeyInterface);
817     }
818 }
819 
820 START_TEST(interfaces)
821 {
822     TestInterfaceRegistry(KnownInterfaces, KnownInterfaceCount);
823 }
824