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_IMruDataList),                TRUE },
209     { ID_NAME(IID_IMruPidlList),                TRUE },
210     { ID_NAME(IID_IMultiMonitorDockingSite),    TRUE },
211     { ID_NAME(IID_IMultiQI),                    TRUE },
212     { ID_NAME(IID_INameSpaceTreeControl),       TRUE },
213     { ID_NAME(IID_INamespaceProxy),             TRUE },
214     { ID_NAME(IID_INamespaceWalk)                    },
215     { ID_NAME(IID_INamespaceWalkCB)                  },
216     { ID_NAME(IID_INamespaceWalkCB2)                 },
217     { ID_NAME(IID_INetCfg),                     TRUE },
218     //{ ID_NAME(IID_INetCfgBindingInterface)           },
219     //{ ID_NAME(IID_INetCfgBindingPath)                },
220     { ID_NAME(IID_INetCfgComponent),            TRUE },
221     { ID_NAME(IID_INetCfgComponentBindings),    TRUE },
222     { ID_NAME(IID_INetCfgComponentControl),     TRUE },
223     { ID_NAME(IID_INetCfgComponentPropertyUi),  TRUE },
224     { ID_NAME(IID_INetCfgLock),                 TRUE },
225     { ID_NAME(IID_INetCfgPnpReconfigCallback),  TRUE },
226     { ID_NAME(IID_INetConnectionConnectUi),     TRUE },
227     { ID_NAME(IID_INetConnectionPropertyUi),    TRUE },
228     { ID_NAME(IID_INetConnectionPropertyUi2),   TRUE },
229     { ID_NAME(IID_INetConnectionManager)             },
230     { ID_NAME(IID_INetLanConnectionUiInfo),     TRUE },
231     { ID_NAME(IID_INewMenuClient)                    },
232     { ID_NAME(IID_INewShortcutHookA),           TRUE },
233     { ID_NAME(IID_INewShortcutHookW),           TRUE },
234     { ID_NAME(IID_INewWindowManager)                 },
235     { ID_NAME(IID_INSCTree),                    TRUE },
236     { ID_NAME(IID_INSCTree2),                   TRUE },
237     { ID_NAME(IID_IObjMgr),                     TRUE },
238     { ID_NAME(IID_IObjectSafety)                     },
239     { ID_NAME(IID_IObjectWithBackReferences)         },
240     { ID_NAME(IID_IObjectWithSite)                   },
241     { ID_NAME(IID_IOleClientSite)                    },
242     { ID_NAME(IID_IOleCommandTarget)                 },
243     { ID_NAME(IID_IOleContainer)                     },
244     { ID_NAME(IID_IOleControl)                       },
245     { ID_NAME(IID_IOleControlSite)                   },
246     { ID_NAME(IID_IOleInPlaceActiveObject)           },
247     { ID_NAME(IID_IOleInPlaceFrame)                  },
248     { ID_NAME(IID_IOleInPlaceObject)                 },
249     { ID_NAME(IID_IOleInPlaceObjectWindowless), TRUE },
250     { ID_NAME(IID_IOleInPlaceSite)                   },
251     { ID_NAME(IID_IOleInPlaceSiteEx)                 },
252     { ID_NAME(IID_IOleInPlaceSiteWindowless),   TRUE },
253     { ID_NAME(IID_IOleInPlaceUIWindow)               },
254     { ID_NAME(IID_IOleItemContainer),                },
255     { ID_NAME(IID_IOleLink),                         },
256     { ID_NAME(IID_IOleObject)                        },
257     { ID_NAME(IID_IOleWindow)                        },
258     { ID_NAME(IID_IParentAndItem)                    },
259     { ID_NAME(IID_IParseDisplayName),                },
260     { ID_NAME(IID_IPersist)                          },
261     { ID_NAME(IID_IPersistFile)                      },
262     { ID_NAME(IID_IPersistFolder)                    },
263     { ID_NAME(IID_IPersistFolder2)                   },
264     { ID_NAME(IID_IPersistFolder3)                   },
265     { ID_NAME(IID_IPersistFreeThreadedObject),  TRUE },
266     { ID_NAME(IID_IPersistHistory)                   },
267     { ID_NAME(IID_IPersistIDList)                    },
268     { ID_NAME(IID_IPersistMemory)                    },
269     { ID_NAME(IID_IPersistPropertyBag)               },
270     { ID_NAME(IID_IPersistPropertyBag2)              },
271     { ID_NAME(IID_IPersistStorage)                   },
272     { ID_NAME(IID_IPersistStream)                    },
273     { ID_NAME(IID_IPersistStreamInit)                },
274     { ID_NAME(IID_IPreviewHandler)                   },
275     { ID_NAME(IID_IPreviewHandlerFrame)              },
276     { ID_NAME(IID_IPreviewHandlerVisuals)            },
277     { ID_NAME(IID_IProgressDialog),             TRUE },
278     { ID_NAME(IID_IPropertyBag)                      },
279     { ID_NAME(IID_IPropertyBag2)                     },
280     { ID_NAME(IID_IPropertySetStorage)               },
281     { ID_NAME(IID_IPropertyStore)                    },
282     { ID_NAME(IID_IPropSheetPage),              TRUE },
283     { ID_NAME(IID_IProvideClassInfo)                 },
284     { ID_NAME(IID_IProvideClassInfo2)                },
285     { ID_NAME(IID_IQueryAssociations),          TRUE },
286     { ID_NAME(IID_IQueryCancelAutoPlay)              },
287     { ID_NAME(IID_IQueryInfo),                  TRUE },
288     { ID_NAME(IID_IQuickActivate)                    },
289     { ID_NAME(IID_IRegTreeOptions),             TRUE },
290     { ID_NAME(IID_IRemoteComputer)                   },
291     { ID_NAME(IID_IResolveShellLink)                 },
292     { ID_NAME(IID_IROTData),                         },
293     { ID_NAME(IID_IRpcOptions),                 TRUE },
294     { ID_NAME(IID_IRunnableObject)                   },
295     { ID_NAME(IID_IRunningObjectTable),              },
296     { ID_NAME(IID_ISLTracker),                  TRUE },
297     { ID_NAME(IID_IScriptErrorList)                  },
298     { ID_NAME(IID_ISearch)                           },
299     { ID_NAME(IID_ISearchAssistantOC)                },
300     { ID_NAME(IID_ISearchAssistantOC2)               },
301     { ID_NAME(IID_ISearchAssistantOC3)               },
302     { ID_NAME(IID_ISearchBar)                        },
303     { ID_NAME(IID_ISearches)                         },
304     { ID_NAME(IID_ISecMgrCacheSeedTarget)            },
305     { ID_NAME(IID_IServerSecurity),             TRUE },
306     { ID_NAME(IID_IServiceProvider)                  },
307     { ID_NAME(IID_IShellApp),                   TRUE },
308     { ID_NAME(IID_IShellBrowser)                     },
309     { ID_NAME(IID_IShellBrowserService),        TRUE },
310     { ID_NAME(IID_IShellChangeNotify),          TRUE },
311     { ID_NAME(IID_IShellCopyHookA),             TRUE },
312     { ID_NAME(IID_IShellCopyHookW),             TRUE },
313     { ID_NAME(IID_IShellDesktopTray),           TRUE },
314     { ID_NAME(IID_IShellDetails),               TRUE },
315     { ID_NAME(IID_IShellDispatch)                    },
316     { ID_NAME(IID_IShellDispatch2)                   },
317     { ID_NAME(IID_IShellDispatch3)                   },
318     { ID_NAME(IID_IShellDispatch4)                   },
319     { ID_NAME(IID_IShellDispatch5),             TRUE },
320     { ID_NAME(IID_IShellDispatch6),             TRUE },
321     { ID_NAME(IID_IShellExecuteHookA),          TRUE },
322     { ID_NAME(IID_IShellExecuteHookW),          TRUE },
323     { ID_NAME(IID_IShellExtInit),               TRUE },
324     { ID_NAME(IID_IShellFavoritesNameSpace)          },
325     { ID_NAME(IID_IShellFolder)                      },
326     { ID_NAME(IID_IShellFolder2)                     },
327     { ID_NAME(IID_IShellFolderBand),            TRUE },
328     { ID_NAME(IID_IShellFolderSearchable),      TRUE },
329     { ID_NAME(IID_IShellFolderSearchableCallback), TRUE },
330     { ID_NAME(IID_IShellFolderView),            TRUE },
331     { ID_NAME(IID_IShellFolderViewCB),          TRUE },
332     { ID_NAME(IID_IShellFolderViewDual)              },
333     { ID_NAME(IID_IShellFolderViewDual2)             },
334     { ID_NAME(IID_IShellFolderViewDual3),       TRUE },
335     { ID_NAME(IID_IShellFolderViewType),        TRUE },
336     { ID_NAME(IID_IShellIcon)                        },
337     { ID_NAME(IID_IShellIconOverlay),           TRUE },
338     { ID_NAME(IID_IShellIconOverlayIdentifier), TRUE },
339     { ID_NAME(IID_IShellImageData),             TRUE },
340     { ID_NAME(IID_IShellImageDataAbort),        TRUE },
341     { ID_NAME(IID_IShellImageDataFactory),      TRUE },
342     { ID_NAME(IID_IShellItem)                        },
343     { ID_NAME(IID_IShellItem2)                       },
344     { ID_NAME(IID_IShellItemArray)                   },
345     { ID_NAME(IID_IShellItemFilter)                  },
346     { ID_NAME(IID_IShellLinkA)                       },
347     { ID_NAME(IID_IShellLinkDataList),          TRUE },
348     { ID_NAME(IID_IShellLinkDual)                    },
349     { ID_NAME(IID_IShellLinkDual2)                   },
350     { ID_NAME(IID_IShellLinkW)                       },
351     { ID_NAME(IID_IShellMenu),                  TRUE },
352     { ID_NAME(IID_IShellMenu2),                 TRUE },
353     { ID_NAME(IID_IShellMenuAcc),               TRUE },
354     { ID_NAME(IID_IShellMenuCallback),          TRUE },
355     { ID_NAME(IID_IShellNameSpace)                   },
356     { ID_NAME(IID_IShellPropSheetExt),          TRUE },
357     { ID_NAME(IID_IShellService),               TRUE },
358     { ID_NAME(IID_IShellTaskScheduler),         TRUE },
359     { ID_NAME(IID_IShellUIHelper)                    },
360     { ID_NAME(IID_IShellUIHelper2),             TRUE },
361     { ID_NAME(IID_IShellView)                        },
362     { ID_NAME(IID_IShellView2)                       },
363     { ID_NAME(IID_IShellView3)                       },
364     { ID_NAME(IID_IShellWindows)                     },
365     { ID_NAME(IID_ISpecifyPropertyPages)             },
366     { ID_NAME(IID_IStorage)                          },
367     { ID_NAME(IID_IStream)                           },
368     { ID_NAME(IID_ISurrogate)                        },
369     { ID_NAME(IID_ISynchronize)                      },
370     { ID_NAME(IID_ISynchronizeContainer),       TRUE },
371     { ID_NAME(IID_ISynchronizeEvent),           TRUE },
372     { ID_NAME(IID_ISynchronizeHandle),          TRUE },
373     { ID_NAME(IID_ITargetEmbedding)                  },
374     { ID_NAME(IID_ITargetFrame)                      },
375     { ID_NAME(IID_ITargetFrame2)                     },
376     { ID_NAME(IID_ITargetFramePriv)                  },
377     { ID_NAME(IID_ITargetFramePriv2)                 },
378     { ID_NAME(IID_ITargetNotify)                     },
379     { ID_NAME(IID_ITaskbarList)                      },
380     { ID_NAME(IID_ITaskbarList2)                     },
381     { ID_NAME(IID_ITaskbarList3),               TRUE },
382     { ID_NAME(IID_ITaskbarList4),               TRUE },
383     { ID_NAME(IID_ITrackShellMenu),             TRUE },
384     /* This interface is completely different between PSDK and registry/shell32 */
385     { ID_NAME(IID_ITransferAdviseSink),         TRUE },
386 #define IID_ITransferAdviseSink IID_ITransferAdviseSinkPriv
387     { ID_NAME(IID_ITransferAdviseSink)               },
388 #undef IID_ITransferAdviseSink
389     { ID_NAME(IID_ITransferDestination),        TRUE },
390     { ID_NAME(IID_ITransferSource),             TRUE },
391     { ID_NAME(IID_ITranslateShellChangeNotify), TRUE },
392     { ID_NAME(IID_ITrayPriv),                   TRUE },
393     { ID_NAME(IID_ITrayPriv2),                  TRUE },
394     { ID_NAME(IID_IUnknown)                          },
395     { ID_NAME(IID_IURLSearchHook),              TRUE },
396     { ID_NAME(IID_IURLSearchHook2),             TRUE },
397     { ID_NAME(IID_IUrlHistoryNotify)                 },
398     { ID_NAME(IID_IUrlHistoryStg)                    },
399     { ID_NAME(IID_IUrlHistoryStg2)                   },
400     { ID_NAME(IID_IViewObject)                       },
401     { ID_NAME(IID_IViewObject2)                      },
402     { ID_NAME(IID_IViewObjectEx),               TRUE },
403     { ID_NAME(IID_IVisualProperties)                 },
404     { ID_NAME(IID_IWebBrowser)                       },
405     { ID_NAME(IID_IWebBrowser2)                      },
406     { ID_NAME(IID_IWebBrowserApp)                    },
407     { ID_NAME(IID_IWebBrowserPriv)                   },
408     { ID_NAME(IID_IWebBrowserPriv2)                  },
409     { ID_NAME(IID_IWinEventHandler),            TRUE },
410 
411     { ID_NAME(IID_DFConstraint),                TRUE },
412     { ID_NAME(DIID__SearchAssistantEvents)           },
413     { ID_NAME(DIID_DShellFolderViewEvents)           },
414     { ID_NAME(DIID_DShellNameSpaceEvents)            },
415     { ID_NAME(DIID_DShellWindowsEvents)              },
416     { ID_NAME(DIID_DWebBrowserEvents)                },
417     { ID_NAME(DIID_DWebBrowserEvents2)               },
418     { ID_NAME(DIID_XMLDOMDocumentEvents )            },
419 
420     { ID_NAME(IID_CDefView),                    TRUE },
421     { ID_NAME(IID_Folder)                            },
422     { ID_NAME(IID_Folder2)                           },
423     { ID_NAME(IID_Folder3)                           },
424     { ID_NAME(IID_FolderItem)                        },
425     { ID_NAME(IID_FolderItem2)                       },
426     { ID_NAME(IID_FolderItems)                       },
427     { ID_NAME(IID_FolderItems2)                      },
428     { ID_NAME(IID_FolderItems3)                      },
429     { ID_NAME(IID_FolderItemVerb)                    },
430     { ID_NAME(IID_FolderItemVerbs)                   },
431 
432     { ID_NAME(CLSID_ShellDesktop),              TRUE },
433 
434     { ID_NAME(IID_IQueryContinue)                    },
435     { ID_NAME(IID_IUserNotification)                 },
436     { ID_NAME(IID_IUserNotificationCallback)         }, // On Vista+
437     { ID_NAME(IID_IUserNotification2)                }, // On Vista+
438 
439     { ID_NAME(IID_IAggregateFilterCondition)         },
440     { ID_NAME(IID_IAliasRegistrationCallback),  TRUE },
441     { ID_NAME(IID_IAssociationArrayInitialize), TRUE },
442     { ID_NAME(IID_IAssociationList),            TRUE },
443     { ID_NAME(IID_IBackReferencedObject),       TRUE },
444     { ID_NAME(IID_IBasePropPage),               TRUE },
445     { ID_NAME(IID_ICommonLayoutDefinition),     TRUE },
446     { ID_NAME(IID_IControlPanelEnumerator),     TRUE },
447     { ID_NAME(IID_IDelegateHostItemContainer),  TRUE },
448     { ID_NAME(IID_IDrawPropertyControl),        TRUE },
449     { ID_NAME(IID_IEnumAssociationElements),    TRUE },
450     { ID_NAME(IID_IEnumerateAssociationElements),TRUE },
451     { ID_NAME(IID_IExecuteCommand),             TRUE },
452     { ID_NAME(IID_IFilterCondition)                  },
453     { ID_NAME(IID_IFolderNotify),               TRUE },
454     { ID_NAME(IID_IFolderProperties),           TRUE },
455     { ID_NAME(IID_IFolderType),                 TRUE },
456     { ID_NAME(IID_IFolderWithSearchRoot),       TRUE },
457     { ID_NAME(IID_IFrameLayoutDefinition),      TRUE },
458     { ID_NAME(IID_IItemFilter),                 TRUE },
459     { ID_NAME(IID_IItemFilterOwner),            TRUE },
460     { ID_NAME(IID_ILocalizableItemParent),      TRUE },
461     { ID_NAME(IID_INewItemAdvisor),             TRUE },
462     { ID_NAME(IID_IObjectWithAssociationElement),TRUE },
463     { ID_NAME(IID_IObjectWithAssociationList),  TRUE },
464     { ID_NAME(IID_IObjectWithQuerySource),      TRUE },
465     { ID_NAME(IID_IObjectWithSelection),        TRUE },
466     { ID_NAME(IID_IPersistString2),             TRUE },
467     { ID_NAME(IID_IPrinterFolder),              TRUE },
468     { ID_NAME(IID_IPropertyControl),            TRUE },
469     { ID_NAME(IID_IPropertyControlBase),        TRUE },
470     { ID_NAME(IID_IPropertyControlSite),        TRUE },
471     { ID_NAME(IID_IRegItemCustomAttributes),    TRUE },
472     { ID_NAME(IID_IRegItemCustomEnumerator),    TRUE },
473     { ID_NAME(IID_IRegItemFolder),              TRUE },
474     { ID_NAME(IID_IRootAndRelativeParsingFolder),TRUE },
475     { ID_NAME(IID_IScope),                      TRUE },
476     { ID_NAME(IID_IScopeItem),                  TRUE },
477     { ID_NAME(IID_IShellBrowserServce),         TRUE },
478     { ID_NAME(IID_IShellFolder3),               TRUE },
479     { ID_NAME(IID_ITaskCondition),              TRUE },
480     { ID_NAME(IID_ITaskConditionCombiner),      TRUE },
481     { ID_NAME(IID_ITaskConditionInit),          TRUE },
482     { ID_NAME(IID_ITransferProvider),           TRUE },
483     { ID_NAME(IID_IUserEventTimer)                   },
484     { ID_NAME(IID_IUserEventTimerCallback)           },
485     { ID_NAME(IID_IAssociationArrayOld),        TRUE },
486     { ID_NAME(IID_IAssociationArray),           TRUE },
487 #define IID_IDriveFolderExt IID_IDriveFolderExtOld
488     { ID_NAME(IID_IDriveFolderExt)                   },
489 #undef IID_IDriveFolderExt
490     { ID_NAME(IID_IPinnedListOld),              TRUE },
491     { ID_NAME(IID_IPinnedList),                 TRUE },
492     { ID_NAME(IID_IAttachmentExecute),          TRUE },
493 
494     // + MMC stuff
495     { ID_NAME(IID_IComponentData),              TRUE },
496     { ID_NAME(IID_IConsole),                    TRUE },
497     { ID_NAME(IID_IConsole2),                   TRUE },
498     { ID_NAME(IID_IConsoleNameSpace),           TRUE },
499     { ID_NAME(IID_IConsoleNameSpace2),          TRUE },
500     { ID_NAME(IID_IPropertySheetCallback),      TRUE },
501     { ID_NAME(IID_IPropertySheetProvider),      TRUE },
502     { ID_NAME(IID_IExtendPropertySheet),        TRUE },
503     { ID_NAME(IID_IExtendPropertySheet2),       TRUE },
504     { ID_NAME(IID_IHeaderCtrl),                 TRUE },
505     { ID_NAME(IID_IToolbar),                    TRUE },
506     { ID_NAME(IID_IImageList_mmc),              TRUE },
507     { ID_NAME(IID_IConsoleVerb),                TRUE },
508     { ID_NAME(IID_ISnapInAbout),                TRUE },
509     // - MMC stuff
510 
511     { ID_NAME(IID_ICertificateManager),         TRUE },
512 };
513 static const INT KnownInterfaceCount = RTL_NUMBER_OF(KnownInterfaces);
514 
515 static
516 PCKNOWN_INTERFACE
FindInterface(_In_ const IID * iid)517 FindInterface(
518     _In_ const IID *iid)
519 {
520     INT i;
521 
522     for (i = 0; i < KnownInterfaceCount; i++)
523         if (IsEqualIID(KnownInterfaces[i].iid, iid))
524             return &KnownInterfaces[i];
525     ASSERT(i != KnownInterfaceCount);
526     return NULL;
527 }
528 
529 static
530 BOOLEAN
IsInterfaceExpected(_In_ PCCLASS_AND_INTERFACES class,_In_ const IID * iid)531 IsInterfaceExpected(
532     _In_ PCCLASS_AND_INTERFACES class,
533     _In_ const IID *iid)
534 {
535     INT i;
536 
537     for (i = 0; class->ifaces[i].iid; i++)
538         if (IsEqualIID(class->ifaces[i].iid, iid))
539             return TRUE;
540     return FALSE;
541 }
542 
543 #define INTF_NOT_EXPOSED LONG_MAX
544 static
545 LONG
GetInterfaceOffset(_In_ PUNKNOWN pUnk,_In_ const IID * iid)546 GetInterfaceOffset(
547     _In_ PUNKNOWN pUnk,
548     _In_ const IID *iid)
549 {
550     HRESULT hr;
551     PVOID pObj;
552     PUNKNOWN pUnk2;
553     LONG offset;
554 
555     hr = IUnknown_QueryInterface(pUnk, iid, &pObj);
556     ok(hr == S_OK || hr == E_NOINTERFACE, "IUnknown::QueryInterface returned 0x%lx\n", hr);
557     if (FAILED(hr))
558         return INTF_NOT_EXPOSED;
559 
560     pUnk2 = pObj;
561     offset = (LONG_PTR)pObj - (LONG_PTR)pUnk;
562     IUnknown_Release(pUnk2);
563     return offset;
564 }
565 
566 static
567 VOID
TestModuleInterfaces(_In_ PCCLASS_AND_INTERFACES ExpectedInterfaces,_In_ INT ExpectedInterfaceCount)568 TestModuleInterfaces(
569     _In_ PCCLASS_AND_INTERFACES ExpectedInterfaces,
570     _In_ INT ExpectedInterfaceCount)
571 {
572     HRESULT hr;
573     PVOID pObj;
574     PUNKNOWN pUnk;
575     INT iClass, iIntf;
576     PCCLASS_AND_INTERFACES class;
577 
578     for (iClass = 0; iClass < ExpectedInterfaceCount; iClass++)
579     {
580         class = &ExpectedInterfaces[iClass];
581         hr = CoCreateInstance(class->clsid,
582                               NULL,
583                               CLSCTX_INPROC_SERVER,
584                               &IID_IUnknown,
585                               &pObj);
586         ok(hr == S_OK, "CoCreateInstance failed. hr=0x%lx\n", hr);
587         if (FAILED(hr))
588         {
589             skip("Failed to instantiate %s.\n", class->name);
590             continue;
591         }
592 
593         pUnk = pObj;
594 
595         /* Check that all expected interfaces are present and have the right offset */
596         for (iIntf = 0; class->ifaces[iIntf].iid; iIntf++)
597         {
598             PCKNOWN_INTERFACE iface = FindInterface(class->ifaces[iIntf].iid);
599             LONG offset = GetInterfaceOffset(pUnk, iface->iid);
600             if (offset == INTF_NOT_EXPOSED)
601                 ok(0, "%s is missing %s (offset %ld)\n", class->name, iface->name, class->ifaces[iIntf].offset);
602             else if (class->ifaces[iIntf].offset != FARAWY)
603             {
604 #ifdef FAIL_WRONG_OFFSET
605                 ok(offset == class->ifaces[iIntf].offset, "%s, %s offset is %ld, expected %ld\n", class->name, iface->name, offset, class->ifaces[iIntf].offset);
606 #else
607                 if (offset != class->ifaces[iIntf].offset)
608                     mytrace("%s, %s offset is %ld, expected %ld\n", class->name, iface->name, offset, class->ifaces[iIntf].offset);
609 #endif
610             }
611         }
612 
613         /* Check that none other than the expected interfaces are present */
614         for (iIntf = 0; iIntf < KnownInterfaceCount; iIntf++)
615         {
616             PCKNOWN_INTERFACE iface = &KnownInterfaces[iIntf];
617             LONG offset;
618             if (IsInterfaceExpected(class, iface->iid))
619                 continue;
620             offset = GetInterfaceOffset(pUnk, iface->iid);
621 #ifdef GENERATE_TABLE_ENTRIES
622             ok(offset == INTF_NOT_EXPOSED, "%s: { %s0x%lx,   &%s },\n", class->name, offset < 0 ? "-" : "", offset < 0 ? -offset : offset, iface->name);
623 #else
624             ok(offset == INTF_NOT_EXPOSED, "%s exposes %s (offset %ld), but shouldn't\n", class->name, iface->name, offset);
625 #endif
626         }
627 
628         // TODO: do some aggregation
629 
630         IUnknown_Release(pUnk);
631     }
632 }
633 
634 static
635 VOID
TestModuleRegistry(_In_ PCWSTR ModuleName,_In_ PCCLASS_AND_INTERFACES ExpectedInterfaces,_In_ INT ExpectedInterfaceCount)636 TestModuleRegistry(
637     _In_ PCWSTR ModuleName,
638     _In_ PCCLASS_AND_INTERFACES ExpectedInterfaces,
639     _In_ INT ExpectedInterfaceCount)
640 {
641     INT iClass;
642     PCCLASS_AND_INTERFACES class;
643     HKEY hKeyClasses;
644     LONG result;
645 
646     result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Classes\\CLSID", 0, KEY_ENUMERATE_SUB_KEYS, &hKeyClasses);
647     ok(result == NO_ERROR, "Failed to open classes key, error %lu\n", result);
648     if (!myskip(result == NO_ERROR, "No classes key\n"))
649     {
650         for (iClass = 0; iClass < ExpectedInterfaceCount; iClass++)
651         {
652             HKEY hKey;
653             HKEY hKeyServer;
654             NTSTATUS status;
655             UNICODE_STRING clsid;
656             DWORD type;
657             WCHAR data[100];
658             DWORD dataSize;
659             PCWSTR expectedThreadingModel;
660 
661             class = &ExpectedInterfaces[iClass];
662             status = RtlStringFromGUID(class->clsid, &clsid);
663             ok(status == STATUS_SUCCESS, "Failed to convert guid to string for %s, status %lx\n", class->name, status);
664             if (myskip(NT_SUCCESS(status), "No guid string\n"))
665                 continue;
666 
667             result = RegOpenKeyExW(hKeyClasses, clsid.Buffer, 0, KEY_ENUMERATE_SUB_KEYS, &hKey);
668             ok(result == NO_ERROR, "Failed to open key for %s, error %lu\n", class->name, result);
669             RtlFreeUnicodeString(&clsid);
670             if (myskip(result == NO_ERROR, "No key\n"))
671                 continue;
672 
673             result = RegOpenKeyExW(hKey, L"InProcServer32", 0, KEY_QUERY_VALUE, &hKeyServer);
674             ok(result == NO_ERROR, "Failed to open key for %s, error %lu\n", class->name, result);
675             RegCloseKey(hKey);
676             if (myskip(result == NO_ERROR, "No key\n"))
677                 continue;
678 
679             dataSize = sizeof(data);
680             result = RegQueryValueExW(hKeyServer, NULL, NULL, &type, (PBYTE)data, &dataSize);
681             ok(result == NO_ERROR, "Failed to query value for %s, error %lu\n", class->name, result);
682             if (!myskip(result == NO_ERROR, "No module name\n"))
683             {
684                 ok(type == REG_SZ || type == REG_EXPAND_SZ, "type %lu for %s\n", type, class->name);
685                 ok(dataSize % sizeof(WCHAR) == 0, "size %lu for %s\n", dataSize, class->name);
686                 ok(dataSize <= sizeof(data), "size %lu for %s\n", dataSize, class->name);
687                 ok(data[dataSize / sizeof(WCHAR) - 1] == UNICODE_NULL, "Not null terminated for %s\n", class->name);
688                 // TODO: Use SearchPath (or assume everything's in system32) and do a proper full path compare
689                 PathStripPathW(data);
690                 PathRemoveExtensionW(data);
691                 ok(!_wcsicmp(data, ModuleName), "Server is %ls, expected %ls for %s\n", data, ModuleName, class->name);
692             }
693 
694             dataSize = sizeof(data);
695             result = RegQueryValueExW(hKeyServer, L"ThreadingModel", NULL, &type, (PBYTE)data, &dataSize);
696             ok(result == NO_ERROR, "Failed to query value for %s, error %lu\n", class->name, result);
697             if (!myskip(result == NO_ERROR, "No ThreadingModel\n"))
698             {
699                 ok(type == REG_SZ || type == REG_EXPAND_SZ, "type %lu for %s\n", type, class->name);
700                 ok(dataSize % sizeof(WCHAR) == 0, "size %lu for %s\n", dataSize, class->name);
701                 ok(dataSize <= sizeof(data), "size %lu for %s\n", dataSize, class->name);
702                 ok(data[dataSize / sizeof(WCHAR) - 1] == UNICODE_NULL, "Not null terminated for %s\n", class->name);
703                 expectedThreadingModel = class->ThreadingModel;
704                 if (!expectedThreadingModel)
705                     expectedThreadingModel = L"Apartment";
706                 ok(!_wcsicmp(data, expectedThreadingModel), "Server is %ls, expected %ls for %s\n", data, expectedThreadingModel, class->name);
707             }
708 
709             RegCloseKey(hKeyServer);
710         }
711         RegCloseKey(hKeyClasses);
712     }
713 }
714 
715 static
716 VOID
TestManualInstantiation(_In_ PCWSTR ModuleName,_In_ PCCLASS_AND_INTERFACES ExpectedInterfaces,_In_ INT ExpectedInterfaceCount)717 TestManualInstantiation(
718     _In_ PCWSTR ModuleName,
719     _In_ PCCLASS_AND_INTERFACES ExpectedInterfaces,
720     _In_ INT ExpectedInterfaceCount)
721 {
722     INT iClass;
723     PCCLASS_AND_INTERFACES class;
724     HRESULT (__stdcall *DllGetClassObject)(REFCLSID, REFIID, PVOID *);
725 
726     DllGetClassObject = (PVOID)GetProcAddress(GetModuleHandleW(ModuleName), "DllGetClassObject");
727     ok(DllGetClassObject != NULL, "DllGetClassObject not found in %ls, error %lu\n", ModuleName, GetLastError());
728     if (myskip(DllGetClassObject != NULL, "No DllGetClassObject\n"))
729         return;
730 
731     for (iClass = 0; iClass < ExpectedInterfaceCount; iClass++)
732     {
733         PVOID pv;
734         HRESULT hr;
735         class = &ExpectedInterfaces[iClass];
736         hr = DllGetClassObject(class->clsid, &IID_IClassFactory, &pv);
737         ok(hr == S_OK, "DllGetClassObject failed for %s, hr = 0x%lx\n", class->name, hr);
738         if (!myskip(SUCCEEDED(hr), "No class factory\n"))
739         {
740             IClassFactory *pCF = pv;
741             hr = IClassFactory_CreateInstance(pCF, NULL, &IID_IUnknown, &pv);
742             ok(hr == S_OK, "IClassFactory::CreateInstance failed for %s, hr = 0x%lx\n", class->name, hr);
743             if (!myskip(SUCCEEDED(hr), "No instance\n"))
744             {
745                 IUnknown *pUnk = pv;
746                 IUnknown_Release(pUnk);
747             }
748             IClassFactory_Release(pCF);
749         }
750     }
751 }
752 
753 VOID
TestClasses(_In_ PCWSTR ModuleName,_In_ PCCLASS_AND_INTERFACES ExpectedInterfaces,_In_ INT ExpectedInterfaceCount)754 TestClasses(
755     _In_ PCWSTR ModuleName,
756     _In_ PCCLASS_AND_INTERFACES ExpectedInterfaces,
757     _In_ INT ExpectedInterfaceCount)
758 {
759     HRESULT hr;
760 
761     hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
762     ok(hr == S_OK, "CoInitializeEx failed. hr=0x%lx\n", hr);
763     if (myskip(SUCCEEDED(hr), "Failed to initialize COM. Cannot perform tests\n"))
764         return;
765 
766     TestModuleInterfaces(ExpectedInterfaces, ExpectedInterfaceCount);
767     TestModuleRegistry(ModuleName, ExpectedInterfaces, ExpectedInterfaceCount);
768     TestManualInstantiation(ModuleName, ExpectedInterfaces, ExpectedInterfaceCount);
769 
770     CoUninitialize();
771 }
772 
773 static
774 VOID
TestInterfaceRegistry(_In_ PCKNOWN_INTERFACE Interfaces,_In_ INT InterfaceCount)775 TestInterfaceRegistry(
776     _In_ PCKNOWN_INTERFACE Interfaces,
777     _In_ INT InterfaceCount)
778 {
779     INT i;
780     HKEY hKeyInterface;
781     LONG result;
782 
783     result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Classes\\Interface", 0, KEY_ENUMERATE_SUB_KEYS, &hKeyInterface);
784     ok(result == NO_ERROR, "Failed to open interface key, error %lu\n", result);
785     if (!myskip(result == NO_ERROR, "No interface key\n"))
786     {
787         for (i = 0; i < InterfaceCount; i++)
788         {
789             HKEY hKey;
790             NTSTATUS status;
791             UNICODE_STRING iid;
792             DWORD type;
793             WCHAR data[100];
794             DWORD dataSize;
795             PCKNOWN_INTERFACE iface;
796             PCWSTR expectedName;
797 
798             iface = &Interfaces[i];
799             status = RtlStringFromGUID(iface->iid, &iid);
800             ok(status == STATUS_SUCCESS, "Failed to convert guid to string for %s, status %lx\n", iface->name, status);
801             if (myskip(NT_SUCCESS(status), "No guid string\n"))
802                 continue;
803 
804             result = RegOpenKeyExW(hKeyInterface, iid.Buffer, 0, KEY_QUERY_VALUE, &hKey);
805             if (iface->noreg)
806             {
807                 ok(result == ERROR_FILE_NOT_FOUND, "RegOpenKeyEx returned %lu for %s\n", result, iface->name);
808             }
809             else
810             {
811                 ok(result == NO_ERROR, "Failed to open key for %s, error %lu\n", iface->name, result);
812                 (void)myskip(result == NO_ERROR, "No key\n");
813             }
814             RtlFreeUnicodeString(&iid);
815             if (result != NO_ERROR)
816                 continue;
817 
818             dataSize = sizeof(data);
819             result = RegQueryValueExW(hKey, NULL, NULL, &type, (PBYTE)data, &dataSize);
820             ok(result == NO_ERROR, "Failed to query value for %s, error %lu\n", iface->name, result);
821             if (!myskip(result == NO_ERROR, "No module name\n"))
822             {
823                 ok(type == REG_SZ, "type %lu for %s\n", type, iface->name);
824                 ok(dataSize % sizeof(WCHAR) == 0, "size %lu for %s\n", dataSize, iface->name);
825                 ok(dataSize <= sizeof(data), "size %lu for %s\n", dataSize, iface->name);
826                 ok(data[dataSize / sizeof(WCHAR) - 1] == UNICODE_NULL, "Not null terminated for %s\n", iface->name);
827                 expectedName = wcschr(iface->wname, L'_');
828                 if (expectedName)
829                     expectedName++;
830                 else
831                     expectedName = iface->wname;
832                 ok(!_wcsicmp(data, expectedName), "Name is %ls, expected %ls\n", data, expectedName);
833             }
834 
835             RegCloseKey(hKey);
836         }
837         RegCloseKey(hKeyInterface);
838     }
839 }
840 
START_TEST(interfaces)841 START_TEST(interfaces)
842 {
843     TestInterfaceRegistry(KnownInterfaces, KnownInterfaceCount);
844 }
845