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>
8 #include "com_apitest.h"
13 #define myskip(c, ...) ((c) ? 0 : (skip(__VA_ARGS__), 1))
14 #define mytrace(...) do { \
15 int debug = winetest_debug; \
18 winetest_debug = debug; \
21 typedef struct _KNOWN_INTERFACE
28 typedef const KNOWN_INTERFACE
*PCKNOWN_INTERFACE
;
31 #define ID_NAME(c) &c, #c, L ## #c
32 static KNOWN_INTERFACE KnownInterfaces
[] =
34 { ID_NAME(IID_IACList
), TRUE
},
35 { ID_NAME(IID_IACList2
), TRUE
},
36 { ID_NAME(IID_IADesktopP2
), TRUE
},
37 { ID_NAME(IID_IAccessible
) },
38 { ID_NAME(IID_IAccessControl
), TRUE
},
39 { ID_NAME(IID_IAccessor
) },
40 { ID_NAME(IID_IActiveDesktop
), TRUE
},
41 { ID_NAME(IID_IActiveDesktopP
), TRUE
},
42 { ID_NAME(IID_IAddressBarParser
), TRUE
},
43 { ID_NAME(IID_IAddressBand
), TRUE
},
44 { ID_NAME(IID_IAddressEditBox
), TRUE
},
45 { ID_NAME(IID_IAugmentedShellFolder
), TRUE
},
46 { ID_NAME(IID_IAugmentedShellFolder2
), TRUE
},
47 { ID_NAME(IID_IAutoComplete
), TRUE
},
48 { ID_NAME(IID_IAutoComplete2
), TRUE
},
49 { ID_NAME(IID_IBandNavigate
), TRUE
},
50 { ID_NAME(IID_IBandProxy
), TRUE
},
51 { ID_NAME(IID_IBandSite
) },
52 { ID_NAME(IID_IBandSiteHelper
), TRUE
},
53 { ID_NAME(IID_IBanneredBar
), TRUE
},
54 { ID_NAME(IID_IBindCtx
) },
55 { ID_NAME(IID_IBrowserFrameOptions
), TRUE
},
56 { ID_NAME(IID_IBrowserService
) },
57 { ID_NAME(IID_IBrowserService2
), TRUE
},
58 { ID_NAME(IID_IBrowserService3
), TRUE
},
59 { ID_NAME(IID_IClassFactory
) },
60 { ID_NAME(IID_IClassFactory2
) },
61 { ID_NAME(IID_IClassFactory3
), TRUE
},
62 { ID_NAME(IID_IClientSecurity
), TRUE
},
63 { ID_NAME(IID_IComThreadingInfo
), TRUE
},
64 { ID_NAME(IID_IContext
), TRUE
},
65 { ID_NAME(IID_IContextMenu
), TRUE
},
66 { ID_NAME(IID_IContextMenu2
), TRUE
},
67 { ID_NAME(IID_IContextMenu3
), TRUE
},
68 { ID_NAME(IID_IContextMenuCB
), TRUE
},
69 { ID_NAME(IID_IContextMenuSite
) },
70 { ID_NAME(IID_IContinue
) },
71 { ID_NAME(IID_IDVGetEnum
), TRUE
},
72 { ID_NAME(IID_IDataObject
) },
73 //{ ID_NAME(IID_IDefViewID) }, == DefViewFrame3
74 { ID_NAME(IID_IDefViewFrame
), TRUE
},
75 { ID_NAME(IID_IDefViewFrame3
) },
76 { ID_NAME(IID_IDefViewFrameGroup
) },
77 { ID_NAME(IID_IDefViewSafety
), },
78 { ID_NAME(IID_IDefViewScript
), TRUE
},
79 { ID_NAME(IID_IDeskBand
) },
80 { ID_NAME(IID_IDeskBandEx
) },
81 { ID_NAME(IID_IDeskBar
), TRUE
},
82 { ID_NAME(IID_IDeskBarClient
), TRUE
},
83 { ID_NAME(IID_IDeskMovr
), TRUE
},
84 { ID_NAME(IID_IDispatch
) },
85 { ID_NAME(IID_IDockingWindow
) },
86 { ID_NAME(IID_IDockingWindowFrame
), TRUE
},
87 { ID_NAME(IID_IDockingWindowSite
), TRUE
},
88 { ID_NAME(IID_IDocViewSite
), TRUE
},
89 { ID_NAME(IID_IDragSourceHelper
), TRUE
},
90 { ID_NAME(IID_IDropSource
) },
91 { ID_NAME(IID_IDropTarget
) },
92 { ID_NAME(IID_IDropTargetHelper
), TRUE
},
93 { ID_NAME(IID_IEnumExtraSearch
) },
94 { ID_NAME(IID_IEnumGUID
) },
95 { ID_NAME(IID_IEnumIDList
) },
96 { ID_NAME(IID_IEnumShellItems
) },
97 { ID_NAME(IID_IEnumString
) },
98 { ID_NAME(IID_IEnumUnknown
) },
99 { ID_NAME(IID_IEnumVARIANT
) },
100 { ID_NAME(IID_IErrorLog
) },
101 { ID_NAME(IID_IExplorerToolbar
), TRUE
},
102 { ID_NAME(IID_IExtractIconA
), TRUE
},
103 { ID_NAME(IID_IExtractIconW
), TRUE
},
104 { ID_NAME(IID_IExtractImage
) },
105 { ID_NAME(IID_IExtractImage2
) },
106 { ID_NAME(IID_IFileDialog
) },
107 { ID_NAME(IID_IFileDialog2
), TRUE
},
108 { ID_NAME(IID_IFileSearchBand
) },
109 { ID_NAME(IID_IFolderBandPriv
) },
110 { ID_NAME(IID_IFolderFilter
) },
111 { ID_NAME(IID_IFolderFilterSite
) },
112 { ID_NAME(IID_IFolderView
) },
113 { ID_NAME(IID_IFolderView2
) },
114 { ID_NAME(IID_IFolderViewOC
) },
115 { ID_NAME(IID_IFolderViewSettings
) },
116 { ID_NAME(IID_IGlobalFolderSettings
), TRUE
},
117 { ID_NAME(IID_IInitializeObject
), TRUE
},
118 { ID_NAME(IID_IInputObject
) },
119 { ID_NAME(IID_IInputObjectSite
) },
120 { ID_NAME(IID_IInternalUnknown
), TRUE
},
121 { ID_NAME(IID_IMarshal
) },
122 { ID_NAME(IID_IMenuBand
), TRUE
},
123 { ID_NAME(IID_IMenuPopup
), TRUE
},
124 { ID_NAME(IID_IMoniker
) },
125 { ID_NAME(IID_IMultiMonitorDockingSite
), TRUE
},
126 { ID_NAME(IID_IMultiQI
), TRUE
},
127 { ID_NAME(IID_INamespaceProxy
), TRUE
},
128 { ID_NAME(IID_INameSpaceTreeControl
), TRUE
},
129 { ID_NAME(IID_INSCTree
), TRUE
},
130 { ID_NAME(IID_INSCTree2
), TRUE
},
131 { ID_NAME(IID_IObjMgr
), TRUE
},
132 { ID_NAME(IID_IObjectSafety
) },
133 { ID_NAME(IID_IObjectWithSite
) },
134 { ID_NAME(IID_IOleCommandTarget
) },
135 { ID_NAME(IID_IOleInPlaceActiveObject
) },
136 { ID_NAME(IID_IOleInPlaceFrame
) },
137 { ID_NAME(IID_IOleInPlaceObject
) },
138 { ID_NAME(IID_IOleInPlaceObjectWindowless
), TRUE
},
139 { ID_NAME(IID_IOleInPlaceSite
) },
140 { ID_NAME(IID_IOleInPlaceSiteEx
) },
141 { ID_NAME(IID_IOleInPlaceSiteWindowless
), TRUE
},
142 { ID_NAME(IID_IOleInPlaceUIWindow
) },
143 { ID_NAME(IID_IOleObject
) },
144 { ID_NAME(IID_IOleWindow
) },
145 { ID_NAME(IID_IPersist
) },
146 { ID_NAME(IID_IPersistFile
) },
147 { ID_NAME(IID_IPersistFolder
) },
148 { ID_NAME(IID_IPersistFolder2
) },
149 { ID_NAME(IID_IPersistFolder3
) },
150 { ID_NAME(IID_IPersistHistory
) },
151 { ID_NAME(IID_IPersistIDList
) },
152 { ID_NAME(IID_IPersistMemory
) },
153 { ID_NAME(IID_IPersistPropertyBag
) },
154 { ID_NAME(IID_IPersistPropertyBag2
) },
155 { ID_NAME(IID_IPersistStorage
) },
156 { ID_NAME(IID_IPersistStream
) },
157 { ID_NAME(IID_IPersistStreamInit
) },
158 { ID_NAME(IID_IProgressDialog
), TRUE
},
159 { ID_NAME(IID_IPropertyBag
) },
160 { ID_NAME(IID_IPropertyBag2
) },
161 { ID_NAME(IID_IQueryAssociations
), TRUE
},
162 { ID_NAME(IID_IQueryInfo
), TRUE
},
163 { ID_NAME(IID_IRegTreeOptions
), TRUE
},
164 { ID_NAME(IID_IRunnableObject
) },
165 { ID_NAME(IID_IServerSecurity
), TRUE
},
166 { ID_NAME(IID_IServiceProvider
) },
167 { ID_NAME(IID_ISFHelper
), TRUE
},
168 { ID_NAME(IID_IShellBrowser
) },
169 { ID_NAME(IID_IShellBrowserService
), TRUE
},
170 { ID_NAME(IID_IShellChangeNotify
), TRUE
},
171 { ID_NAME(IID_IShellDesktopTray
), TRUE
},
172 { ID_NAME(IID_IShellDispatch
) },
173 { ID_NAME(IID_IShellDispatch2
) },
174 { ID_NAME(IID_IShellDispatch3
) },
175 { ID_NAME(IID_IShellDispatch4
) },
176 { ID_NAME(IID_IShellDispatch5
), TRUE
},
177 { ID_NAME(IID_IShellExtInit
), TRUE
},
178 { ID_NAME(IID_IShellPropSheetExt
), TRUE
},
179 { ID_NAME(IID_IShellIconOverlayIdentifier
), TRUE
},
180 { ID_NAME(IID_IShellFolder
) },
181 { ID_NAME(IID_IShellFolder2
) },
182 { ID_NAME(IID_IShellFolderBand
), TRUE
},
183 { ID_NAME(IID_IShellFolderView
), TRUE
},
184 { ID_NAME(IID_IShellFolderViewCB
), TRUE
},
185 { ID_NAME(IID_IShellFolderViewDual
) },
186 { ID_NAME(IID_IShellFolderViewDual2
) },
187 { ID_NAME(IID_IShellIcon
) },
188 { ID_NAME(IID_IShellItem
) },
189 { ID_NAME(IID_IShellItem2
) },
190 { ID_NAME(IID_IShellItemArray
) },
191 { ID_NAME(IID_IShellItemFilter
) },
192 { ID_NAME(IID_IShellLinkA
) },
193 { ID_NAME(IID_IShellLinkDual
) },
194 { ID_NAME(IID_IShellLinkDual2
) },
195 { ID_NAME(IID_IShellLinkW
) },
196 { ID_NAME(IID_IShellMenu
), TRUE
},
197 { ID_NAME(IID_IShellMenu2
), TRUE
},
198 { ID_NAME(IID_IShellMenuAcc
), TRUE
},
199 { ID_NAME(IID_IShellMenuCallback
), TRUE
},
200 { ID_NAME(IID_IShellNameSpace
) },
201 { ID_NAME(IID_IShellService
), TRUE
},
202 { ID_NAME(IID_IShellView
) },
203 { ID_NAME(IID_IShellView2
) },
204 { ID_NAME(IID_IShellView3
) },
205 { ID_NAME(IID_IShellWindows
) },
206 { ID_NAME(IID_IStorage
) },
207 { ID_NAME(IID_IStream
) },
208 { ID_NAME(IID_ISurrogate
) },
209 { ID_NAME(IID_ISynchronize
) },
210 { ID_NAME(IID_ISynchronizeContainer
), TRUE
},
211 { ID_NAME(IID_ISynchronizeEvent
), TRUE
},
212 { ID_NAME(IID_ISynchronizeHandle
), TRUE
},
213 { ID_NAME(IID_ITaskbarList
) },
214 { ID_NAME(IID_ITaskbarList2
) },
215 { ID_NAME(IID_ITrackShellMenu
), TRUE
},
216 { ID_NAME(IID_ITrayPriv
), TRUE
},
217 { ID_NAME(IID_ITrayPriv2
), TRUE
},
218 { ID_NAME(IID_IUnknown
) },
219 { ID_NAME(IID_IViewObject
) },
220 { ID_NAME(IID_IViewObject2
) },
221 { ID_NAME(IID_IViewObjectEx
), TRUE
},
222 { ID_NAME(IID_IWinEventHandler
), TRUE
},
224 { ID_NAME(IID_DFConstraint
), TRUE
},
225 { ID_NAME(DIID_DShellFolderViewEvents
) },
227 { ID_NAME(IID_CDefView
), TRUE
},
228 { ID_NAME(IID_Folder
) },
229 { ID_NAME(IID_Folder2
) },
230 { ID_NAME(IID_Folder3
) },
231 { ID_NAME(IID_FolderItem
) },
232 { ID_NAME(IID_FolderItem2
) },
233 { ID_NAME(IID_FolderItems
) },
234 { ID_NAME(IID_FolderItems2
) },
235 { ID_NAME(IID_FolderItems3
) },
236 { ID_NAME(IID_FolderItemVerb
) },
237 { ID_NAME(IID_FolderItemVerbs
) },
238 { ID_NAME(IID_IShellTaskScheduler
) },
240 { ID_NAME(CLSID_ShellDesktop
), TRUE
}
242 static const INT KnownInterfaceCount
= RTL_NUMBER_OF(KnownInterfaces
);
251 for (i
= 0; i
< KnownInterfaceCount
; i
++)
252 if (IsEqualIID(KnownInterfaces
[i
].iid
, iid
))
253 return &KnownInterfaces
[i
];
254 ASSERT(i
!= KnownInterfaceCount
);
261 _In_ PCCLASS_AND_INTERFACES
class,
266 for (i
= 0; class->ifaces
[i
].iid
; i
++)
267 if (IsEqualIID(class->ifaces
[i
].iid
, iid
))
272 #define INTF_NOT_EXPOSED LONG_MAX
284 hr
= IUnknown_QueryInterface(pUnk
, iid
, &pObj
);
285 ok(hr
== S_OK
|| hr
== E_NOINTERFACE
, "IUnknown::QueryInterface returned 0x%lx\n", hr
);
287 return INTF_NOT_EXPOSED
;
290 offset
= (LONG_PTR
)pObj
- (LONG_PTR
)pUnk
;
291 IUnknown_Release(pUnk2
);
297 TestModuleInterfaces(
298 _In_ PCCLASS_AND_INTERFACES ExpectedInterfaces
,
299 _In_ INT ExpectedInterfaceCount
)
305 PCCLASS_AND_INTERFACES
class;
307 for (iClass
= 0; iClass
< ExpectedInterfaceCount
; iClass
++)
309 class = &ExpectedInterfaces
[iClass
];
310 hr
= CoCreateInstance(class->clsid
,
312 CLSCTX_INPROC_SERVER
,
315 ok(hr
== S_OK
, "CoCreateInstance failed. hr=0x%lx\n", hr
);
318 skip("Failed to instantiate %s.\n", class->name
);
324 /* Check that all expected interfaces are present and have the right offset */
325 for (iIntf
= 0; class->ifaces
[iIntf
].iid
; iIntf
++)
327 PCKNOWN_INTERFACE iface
= FindInterface(class->ifaces
[iIntf
].iid
);
328 LONG offset
= GetInterfaceOffset(pUnk
, iface
->iid
);
329 if (offset
== INTF_NOT_EXPOSED
)
330 ok(0, "%s is missing %s (offset %ld)\n", class->name
, iface
->name
, class->ifaces
[iIntf
].offset
);
331 else if (class->ifaces
[iIntf
].offset
!= FARAWY
)
333 #ifdef FAIL_WRONG_OFFSET
334 ok(offset
== class->ifaces
[iIntf
].offset
, "%s, %s offset is %ld, expected %ld\n", class->name
, iface
->name
, offset
, class->ifaces
[iIntf
].offset
);
336 if (offset
!= class->ifaces
[iIntf
].offset
)
337 mytrace("%s, %s offset is %ld, expected %ld\n", class->name
, iface
->name
, offset
, class->ifaces
[iIntf
].offset
);
342 /* Check that none other than the expected interfaces are present */
343 for (iIntf
= 0; iIntf
< KnownInterfaceCount
; iIntf
++)
345 PCKNOWN_INTERFACE iface
= &KnownInterfaces
[iIntf
];
347 if (IsInterfaceExpected(class, iface
->iid
))
349 offset
= GetInterfaceOffset(pUnk
, iface
->iid
);
350 #ifdef GENERATE_TABLE_ENTRIES
351 ok(offset
== INTF_NOT_EXPOSED
, "%s: { %s0x%x, &%s },\n", class->name
, offset
< 0 ? "-" : "", offset
< 0 ? -offset
: offset
, iface
->name
);
353 ok(offset
== INTF_NOT_EXPOSED
, "%s exposes %s (offset %ld), but shouldn't\n", class->name
, iface
->name
, offset
);
357 // TODO: do some aggregation
359 IUnknown_Release(pUnk
);
366 _In_ PCWSTR ModuleName
,
367 _In_ PCCLASS_AND_INTERFACES ExpectedInterfaces
,
368 _In_ INT ExpectedInterfaceCount
)
371 PCCLASS_AND_INTERFACES
class;
375 result
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
, L
"Software\\Classes\\CLSID", 0, KEY_ENUMERATE_SUB_KEYS
, &hKeyClasses
);
376 ok(result
== NO_ERROR
, "Failed to open classes key, error %lu\n", result
);
377 if (!myskip(result
== NO_ERROR
, "No classes key\n"))
379 for (iClass
= 0; iClass
< ExpectedInterfaceCount
; iClass
++)
384 UNICODE_STRING clsid
;
388 PCWSTR expectedThreadingModel
;
390 class = &ExpectedInterfaces
[iClass
];
391 status
= RtlStringFromGUID(class->clsid
, &clsid
);
392 ok(status
== STATUS_SUCCESS
, "Failed to convert guid to string for %s, status %lx\n", class->name
, status
);
393 if (myskip(NT_SUCCESS(status
), "No guid string\n"))
396 result
= RegOpenKeyEx(hKeyClasses
, clsid
.Buffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hKey
);
397 ok(result
== NO_ERROR
, "Failed to open key for %s, error %lu\n", class->name
, result
);
398 RtlFreeUnicodeString(&clsid
);
399 if (myskip(result
== NO_ERROR
, "No key\n"))
402 result
= RegOpenKeyEx(hKey
, L
"InProcServer32", 0, KEY_QUERY_VALUE
, &hKeyServer
);
403 ok(result
== NO_ERROR
, "Failed to open key for %s, error %lu\n", class->name
, result
);
405 if (myskip(result
== NO_ERROR
, "No key\n"))
408 dataSize
= sizeof(data
);
409 result
= RegQueryValueEx(hKeyServer
, NULL
, NULL
, &type
, (PBYTE
)data
, &dataSize
);
410 ok(result
== NO_ERROR
, "Failed to query value for %s, error %lu\n", class->name
, result
);
411 if (!myskip(result
== NO_ERROR
, "No module name\n"))
413 ok(type
== REG_SZ
|| type
== REG_EXPAND_SZ
, "type %lu for %s\n", type
, class->name
);
414 ok(dataSize
% sizeof(WCHAR
) == 0, "size %lu for %s\n", dataSize
, class->name
);
415 ok(dataSize
<= sizeof(data
), "size %lu for %s\n", dataSize
, class->name
);
416 ok(data
[dataSize
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
, "Not null terminated for %s\n", class->name
);
417 // TODO: Use SearchPath (or assume everything's in system32) and do a proper full path compare
418 PathStripPathW(data
);
419 PathRemoveExtensionW(data
);
420 ok(!wcsicmp(data
, ModuleName
), "Server is %ls, expected %ls for %s\n", data
, ModuleName
, class->name
);
423 dataSize
= sizeof(data
);
424 result
= RegQueryValueEx(hKeyServer
, L
"ThreadingModel", NULL
, &type
, (PBYTE
)data
, &dataSize
);
425 ok(result
== NO_ERROR
, "Failed to query value for %s, error %lu\n", class->name
, result
);
426 if (!myskip(result
== NO_ERROR
, "No ThreadingModel\n"))
428 ok(type
== REG_SZ
|| type
== REG_EXPAND_SZ
, "type %lu for %s\n", type
, class->name
);
429 ok(dataSize
% sizeof(WCHAR
) == 0, "size %lu for %s\n", dataSize
, class->name
);
430 ok(dataSize
<= sizeof(data
), "size %lu for %s\n", dataSize
, class->name
);
431 ok(data
[dataSize
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
, "Not null terminated for %s\n", class->name
);
432 expectedThreadingModel
= class->ThreadingModel
;
433 if (!expectedThreadingModel
)
434 expectedThreadingModel
= L
"Apartment";
435 ok(!wcsicmp(data
, expectedThreadingModel
), "Server is %ls, expected %ls for %s\n", data
, expectedThreadingModel
, class->name
);
438 RegCloseKey(hKeyServer
);
440 RegCloseKey(hKeyClasses
);
446 TestManualInstantiation(
447 _In_ PCWSTR ModuleName
,
448 _In_ PCCLASS_AND_INTERFACES ExpectedInterfaces
,
449 _In_ INT ExpectedInterfaceCount
)
452 PCCLASS_AND_INTERFACES
class;
453 HRESULT (__stdcall
*DllGetClassObject
)(REFCLSID
, REFIID
, PVOID
*);
455 DllGetClassObject
= (PVOID
)GetProcAddress(GetModuleHandle(ModuleName
), "DllGetClassObject");
456 ok(DllGetClassObject
!= NULL
, "DllGetClassObject not found in %ls, error %lu\n", ModuleName
, GetLastError());
457 if (myskip(DllGetClassObject
!= NULL
, "No DllGetClassObject\n"))
460 for (iClass
= 0; iClass
< ExpectedInterfaceCount
; iClass
++)
464 class = &ExpectedInterfaces
[iClass
];
465 hr
= DllGetClassObject(class->clsid
, &IID_IClassFactory
, &pv
);
466 ok(hr
== S_OK
, "DllGetClassObject failed for %s, hr = 0x%lx\n", class->name
, hr
);
467 if (!myskip(SUCCEEDED(hr
), "No class factory\n"))
469 IClassFactory
*pCF
= pv
;
470 hr
= IClassFactory_CreateInstance(pCF
, NULL
, &IID_IUnknown
, &pv
);
471 ok(hr
== S_OK
, "IClassFactory::CreateInstance failed for %s, hr = 0x%lx\n", class->name
, hr
);
472 if (!myskip(SUCCEEDED(hr
), "No instance\n"))
475 IUnknown_Release(pUnk
);
477 IClassFactory_Release(pCF
);
484 _In_ PCWSTR ModuleName
,
485 _In_ PCCLASS_AND_INTERFACES ExpectedInterfaces
,
486 _In_ INT ExpectedInterfaceCount
)
490 hr
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
491 ok(hr
== S_OK
, "CoInitializeEx failed. hr=0x%lx\n", hr
);
492 if (myskip(SUCCEEDED(hr
), "Failed to initialize COM. Cannot perform tests\n"))
495 TestModuleInterfaces(ExpectedInterfaces
, ExpectedInterfaceCount
);
496 TestModuleRegistry(ModuleName
, ExpectedInterfaces
, ExpectedInterfaceCount
);
497 TestManualInstantiation(ModuleName
, ExpectedInterfaces
, ExpectedInterfaceCount
);
504 TestInterfaceRegistry(
505 _In_ PCKNOWN_INTERFACE Interfaces
,
506 _In_ INT InterfaceCount
)
512 result
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
, L
"Software\\Classes\\Interface", 0, KEY_ENUMERATE_SUB_KEYS
, &hKeyInterface
);
513 ok(result
== NO_ERROR
, "Failed to open interface key, error %lu\n", result
);
514 if (!myskip(result
== NO_ERROR
, "No interface key\n"))
516 for (i
= 0; i
< InterfaceCount
; i
++)
524 PCKNOWN_INTERFACE iface
;
527 iface
= &Interfaces
[i
];
528 status
= RtlStringFromGUID(iface
->iid
, &iid
);
529 ok(status
== STATUS_SUCCESS
, "Failed to convert guid to string for %s, status %lx\n", iface
->name
, status
);
530 if (myskip(NT_SUCCESS(status
), "No guid string\n"))
533 result
= RegOpenKeyEx(hKeyInterface
, iid
.Buffer
, 0, KEY_QUERY_VALUE
, &hKey
);
536 ok(result
== ERROR_FILE_NOT_FOUND
, "RegOpenKeyEx returned %lu for %s\n", result
, iface
->name
);
540 ok(result
== NO_ERROR
, "Failed to open key for %s, error %lu\n", iface
->name
, result
);
541 (void)myskip(result
== NO_ERROR
, "No key\n");
543 RtlFreeUnicodeString(&iid
);
544 if (result
!= NO_ERROR
)
547 dataSize
= sizeof(data
);
548 result
= RegQueryValueEx(hKey
, NULL
, NULL
, &type
, (PBYTE
)data
, &dataSize
);
549 ok(result
== NO_ERROR
, "Failed to query value for %s, error %lu\n", iface
->name
, result
);
550 if (!myskip(result
== NO_ERROR
, "No module name\n"))
552 ok(type
== REG_SZ
, "type %lu for %s\n", type
, iface
->name
);
553 ok(dataSize
% sizeof(WCHAR
) == 0, "size %lu for %s\n", dataSize
, iface
->name
);
554 ok(dataSize
<= sizeof(data
), "size %lu for %s\n", dataSize
, iface
->name
);
555 ok(data
[dataSize
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
, "Not null terminated for %s\n", iface
->name
);
556 expectedName
= wcschr(iface
->wname
, L
'_');
560 expectedName
= iface
->wname
;
561 ok(!wcsicmp(data
, expectedName
), "Name is %ls, expected %ls\n", data
, expectedName
);
566 RegCloseKey(hKeyInterface
);
570 START_TEST(interfaces
)
572 TestInterfaceRegistry(KnownInterfaces
, KnownInterfaceCount
);