1

I'm trying to implement Manipulating the zone identifier to specify where a file was download from – The Old New Thing - MSDN blogs in Python.

At CoCreateInstance:

pythoncom.CoCreateInstance(
        pywintypes.IID('{0968e258-16c7-4dba-aa86-462dd61e31a3}'),    #CLSID_PersistentZoneIdentifier
        None,pythoncom.CLSCTX_ALL,
        pywintypes.IID('{cd45f185-1b21-48e2-967b-ead743a8914e}'))    #IID_IZoneIdentifier

I get an error:

TypeError: There is no interface object registered that supports this IID

(No stacktrace as this is an extension function)

If I replace the IZoneIdentifier IID with pythoncom.IID_IUnknown or pythoncom.IID_IPersistFile, it works, but a QueryInterface with the right IID fails with the same error.

Indeed, in HKCR\Interface, I see nothing like IZoneIdentifier but do see an IPersistFile.


Having disassembled urlmon.dll, I see that it indeed implements the interface, but doesn't register it in its DllRegisterServer. Searching further, I see that IPersistFile is being registered by ole32.dll - but not IZoneIdentifier.

MSDN documents this interface to be available since IE6. But it's not there in either IE7 or IE8. Since this is XP (and with all the updates allegedly), I've nothing else to try.

Likewise, the interface is present in Windows SDK 7.0 in the urlmon.h file mentioned in the MSDN article.

The questions are:

  • Was this interface silently dropped in favour of something else without MSDN reflecting that or something? Alternatively, is this a known issue? Is it available in later versions of IE?
  • What components do ole32.dll and urlmon.dll pertain to (so I can try (un)installing updates for them)?
ivan_pozdeev
  • 33,874
  • 19
  • 107
  • 152
  • 3
    Not every interface is mentioned in the registry - only those that have marshaling support (the whole point of registering the interface is to tell the system how it's marshaled). Apparently, `IZoneIdentifier` doesn't allow marshaling. – Igor Tandetnik Nov 06 '16 at 22:41
  • I would guess that Python needs a type library describing the interface, in order to know which methods it provides. The set of interfaces described in a type library is smaller still than the set of interfaces registered for marshaling. – Igor Tandetnik Nov 06 '16 at 22:44
  • @IgorTandetnik The original C++ program works. So, it's indeed something wrong with Python's requirements. All that is left is find out what exactly. It's definitely not TypeLib because `pythoncom` can work with late binding just fine. This is quite disappoining, as `pywin32` functions generally strive to be mere pythonic wrappers over the underlying API, with only the minimal necessary amount of additional logic. – ivan_pozdeev Nov 07 '16 at 01:13
  • A C++ program doesn't generally require that the interface be described in a type library; a description in a C++ header file (that the program can `#include`) is sufficient. I imagine Python cannot read C++ headers, that's why it needs the description of an interface in a different form. `IZoneIdentifier` is not derived from `IDispatch`, so can't be used via late binding either. – Igor Tandetnik Nov 07 '16 at 01:17
  • @IgorTandetnik I just now checked: `IPersistFile` is also based on `IUnknown` and not `IDispatch`. So, the answer should ultimately lie in `pythoncom`'s source. – ivan_pozdeev Nov 07 '16 at 02:52

1 Answers1

2

There's nothing wrong with IZoneIdentifier. The original C++ program runs just fine. As @IgorTandetnik pointed out, not every interface an object implements is going to be registered in the registry, only those that support marshalling.

The error comes from pythoncom itself (a hint is that it's a TypeError, not pythoncom.com_error, and the error message is always in English rather than the system's UI language).

The cause is that pythoncom indeed requires IDispatch support by the interface - or it wouldn't be able to deduce how to work with the interface's functions and values they accept/return.

The only exception is a number of IUnknown-based interfaces support for which is compiled in (IPersistFile is one of them; the full list is in pythoncom.InterfaceNames apparently).

Support for other IUnknown-based interfaces can be added with a "pythoncom extension" module. Some (very scarce) documentation on them can be found in pywin32 docs in the Python and COM - Implementation Details article.

ivan_pozdeev
  • 33,874
  • 19
  • 107
  • 152