Heavily confused by win32api + COM and an answer from SO
Question: From my other question here on SO, I asked how to retrieve the current playing
song from Windows Media Player and Zune, I got an answer from a c++ dev who
gave me an explanation of how I would do this for WMP.

However, I am no C++ dev, nor am I very experienced with the pywin32 library.
And on-top of all that, the documentation on all this (especially concerning
WMP) is _horrible_.

Therefor, I need your help understanding how I would do the following in
Python.

[Source](http://stackoverflow.com/questions/19452001/need-a-way-to-retrieve-
the-current-playing-song-from-zune-and-windows-media-play)

> I have working code in C++ to print the name of media currently playing in
> WMP. It's a simple console application (78 lines of code).
>
> Steps:
>
> **1)** implements a basic COM object implementing IUnknown, IOleClientSite,
> IServiceProvider and IWMPRemoteMediaServices. This is straightforward (sort
> of, your mileage may vary) using the ATL template CComObjectRootEx. The only
> methods needing (simple) code are IServiceProvider::QueryService and
> IWMPRemoteMediaServices::GetServiceType. All other methods may return
> E_NOTIMPL
>
> **2)** Instantiate the "WMPlayer.OCX" COM object (in my case, via
> CoCreateInstance)
>
> **3)** Retrieve from the object an IOleObject interface pointer via
> QueryInterface
>
> **4)** Instanciate an object from the class seen in 1) (I use the
> CComObject<>::CreateInstance template)
>
> **5)** Use the SetClientSite method from the interface you got at 3),
> passing a pointer to your OleClientSite implementation.
>
> **6)** During the SetClientSite call, WMP will callback you: fisrt asking
> for an IServiceProvider interface pointer, second calling the QueryService
> method, asking for an IWMPRemoteMediaServices interface pointer. Return your
> implementation of IWMPRemoteMediaServices and, third, you will be called
> again via GetServiceType. You must then return "Remote". You are now
> connected to the WMP running instance
>
> **7)** Query the COM object for an IWMPMedia interface pointer
>
> **8)** If 7) didn't gave NULL, read the the IWMPMedia::name property.
>
> **9)** DONE
>
> All the above was tested with VS2010 / Windows Seven, and with WMP running
> (if there is no Media Player process running, just do nothing).
>
> I don't know if yoy can/want to implement COM interface and object in
> Python. If you are interested by my C++ code, let me know. You could use
> that code in a C++ DLL, and then call it from python.

I know a little bit about the win32api.

At the first step, I really don't know what to do, googling IOleClientSite
results in the msdn documentation, it's an interface. However, that's where I
get stuck already. I can't find anything (might just be my horrendous googling
skills) on working with these things in Python.

The second step:

    
    
    WMP = win32com.client.Dispatch("WMPlayer.OCX")
    

Alright, that's doable.

On to the third step. QueryInterface -

> "regardless of the object you have, you can always call its QueryInterface()
> method to obtain a new interface, such as IStream."

[source](http://oreilly.com/catalog/pythonwin32/chapter/ch12.html)

However, not for me. As I understand his explanation, I think it means that
every com object sort of "inherits" three methods from IUnknown, one of which
is QueryInterface, however this does not seem the case since calling
QueryInterface on my `WMP` object fails miserably. `(Object has no attribute
'QueryInterface')`

I could ramble on, but I believe you got the point, I have no idea how to work
with this. Can anyone help me out with this one? Preferably with code
examples, but resources/documentation is welcome too.


Answer: Almost final answser but CAN'T finish. I seems that pythoncom can't be used to
implement custom Interface without the help of a C++ module. Here is an
answser from Mark Hammon (Mon, 13 Jan 2003): [How to create COM Servers with
IID_IDTExtensibility2 interface](http://computer-programming-
forum.com/56-python/d575f9041208b21f.htm)

> Sorry - you are SOL. To support arbitary interfaces, you need C++ support,
> in the form of an extension module. There is a new "Univgw" that may help
> you out, but I dont know much about this

I am not able to find anything about that "Univgw" thing...

The comtypes python module is intended to resolve the problem, and I found
links saying it does, but I can't make it works with my fresh new Python 3.3.
It's Python 2.x code. comtypes seems outdated and unmaintained.

Step 1 OK for IOleClientSite and IServiceProvider, KO for
IWMPRemoteMediaServices

Step 2, 3, 4 and 5 OK

Step 6, 7 and 8 can't be implemented without IWMPRemoteMediaServices :-(

disclaimer: complete newbie in Python, please don't yell

    
    
    import pythoncom
    import win32com.client as wc
    from win32com.axcontrol import axcontrol
    import win32com.server as ws
    from win32com.server import util
    from win32com.server.exception import COMException
    import winerror
    import pywintypes
    
    # Windows Media Player Custom Interface IWMPRemoteMediaServices
    IWMPRemoteMediaServices = pywintypes.IID("{CBB92747-741F-44FE-AB5B-F1A48F3B2A59}")
    
    class OleClientSite:
        _public_methods_ = [ 'SaveObject', 'GetMoniker', 'GetContainer', 'ShowObject', 'OnShowWindow', 'RequestNewObjectLayout', 'QueryService' ]
        _com_interfaces_ = [ axcontrol.IID_IOleClientSite, pythoncom.IID_IServiceProvider ]
    
        def SaveObject(self):
            print("SaveObject")
            raise COMException(hresult=winerror.E_NOTIMPL)
    
        def GetMoniker(self, dwAssign, dwWhichMoniker):
            print("GetMoniker ")
            raise COMException(hresult=winerror.E_NOTIMPL)
    
        def GetContainer(self):
            print("GetContainer")
            raise COMException(hresult=winerror.E_NOTIMPL)
    
        def ShowObject(self):
            print("ShowObject")
            raise COMException(hresult=winerror.E_NOTIMPL)
    
        def OnShowWindow(self, fShow):
            print("ShowObject" + str(fShow))
            raise COMException(hresult=winerror.E_NOTIMPL)
    
        def RequestNewObjectLayout(self):
            print("RequestNewObjectLayout")
            raise COMException(hresult=winerror.E_NOTIMPL)
    
        def QueryService(self, guidService, riid):
            print("QueryService",guidService,riid)
            if riid == IWMPRemoteMediaServices:
                print("Known Requested IID, but can't implement!")
                raise COMException(hresult=winerror.E_NOINTERFACE)
            else:
                print("Requested IID is not IWMPRemoteMediaServices" )
                raise COMException(hresult=winerror.E_NOINTERFACE)
    
    
    if __name__=='__main__':
        wmp = wc.Dispatch("WMPlayer.OCX")
        IOO = wmp._oleobj_.QueryInterface(axcontrol.IID_IOleObject)
        pyOCS = OleClientSite()
        comOCS = ws.util.wrap(pyOCS, axcontrol.IID_IOleClientSite)
        IOO.SetClientSite(comOCS)
    

