The traditional way to determine the function pointed to by [edi+1Ch] is as follows:
Find the Interface Definition Language (IDL) file for the given interface. In your case, the interface is IShellWindows. According to the documentation for IShellWindows, its interface is defined in IDL file Exdisp.idl. That IDL file is included in the Windows SDK (downloadable for free), and will be installed to a location such as C:\Program Files\Microsoft SDKs\Windows\v7.1A\Include\Exdisp.idl. You can open that Exdisp.idl file with a text editor to see the Interface Definition of IShellWindows:
[
uuid(85CB6900-4D95-11CF-960C-0080C7F4EE85), // IID_IShellWindows
helpstring("Definition of interface IShellWindows"),
oleautomation,
dual,
odl,
]
interface IShellWindows : IDispatch
{
//Properties
[propget, helpstring("Get count of open Shell windows")]
HRESULT Count([out, retval] long *Count);
//Methods
[id(0), helpstring("Return the shell window for the given index")]
HRESULT Item([in,optional] VARIANT index, [out, retval]IDispatch **Folder);
[id(-4), helpstring("Enumerates the figures")]
HRESULT _NewEnum([out, retval] IUnknown **ppunk);
// Some private hidden members to allow shell windows to add and
// remove themself from the list. We mark them hidden to keep
// random VB apps from trying to Register...
[helpstring("Register a window with the list"), hidden]
HRESULT Register([in] IDispatch *pid,
[in] long hwnd,
[in] int swClass,
[out]long *plCookie);
[helpstring("Register a pending open with the list"), hidden]
HRESULT RegisterPending([in] long lThreadId,
[in] VARIANT* pvarloc, // will hold pidl that is being opened.
[in] VARIANT* pvarlocRoot, // Optional root pidl
[in] int swClass,
[out]long *plCookie);
[helpstring("Remove a window from the list"), hidden]
HRESULT Revoke([in]long lCookie);
// As an optimization, each window notifies the new location
// only when
// (1) it's being deactivated
// (2) getFullName is called (we overload it to force update)
[helpstring("Notifies the new location"), hidden]
HRESULT OnNavigate([in]long lCookie, [in] VARIANT* pvarLoc);
[helpstring("Notifies the activation"), hidden]
HRESULT OnActivated([in]long lCookie, [in] VARIANT_BOOL fActive);
[helpstring("Find the window based on the location"), hidden]
HRESULT FindWindowSW([in] VARIANT* pvarLoc,
[in] VARIANT* pvarLocRoot, /* unused */
[in] int swClass,
[out] long * phwnd,
[in] int swfwOptions,
[out,retval] IDispatch** ppdispOut);
[helpstring("Notifies on creation and frame name set"), hidden]
HRESULT OnCreated([in]long lCookie,[in] IUnknown *punk);
[helpstring("Used by IExplore to register different processes"), hidden]
HRESULT ProcessAttachDetach([in] VARIANT_BOOL fAttach);
}
We can see that the IShellWindows interface has the following vtable entries:
- Count()
- Item()
- _NewEnum()
- Register()
- RegisterPending()
- Revoke()
- OnNavigate()
- OnActivated()
- FindWindowSW()
- OnCreated()
- ProcessAttachDetach()
However, you can also see in the IDL that the IShellWindows interface inherits from IDispatch. IDispatch has the following vtable entries (from OAIdl.idl):
- GetTypeInfoCount()
- GetTypeInfo()
- GetIDsOfNames()
- Invoke()
The IDL for IDispatch in OAIdl.idl also specifies that IDispatch inherits from IUnknown. IUnknown has the following vtable entries (from Unknwn.idl):
- QueryInterface()
- AddRef()
- Release()
So now we know that IShellWindows inherits from IDispatch, which inherits from IUnknown. As such, the full layout of the vtable for IShellWindows is as follows:
*ppv+00h = QueryInterface()
*ppv+04h = AddRef()
*ppv+08h = Release()
*ppv+0Ch = GetTypeInfoCount()
*ppv+10h = GetTypeInfo()
*ppv+14h = GetIDsOfNames()
*ppv+18h = Invoke()
*ppv+1Ch = Count()
*ppv+20h = Item()
*ppv+24h = _NewEnum()
*ppv+28h = Register()
...
Looking back at your code, we see a call to *ppv+1Ch, which we see from our constructed vtable above is a call to the function IShellWindows::Count(), and &var_C is the pointer to IShellWindows::Count()'s [out, retval] long *Count parameter.
The dynamic way to determine the function pointed to by [edi+1Ch] is as follows:
Run your code above in a debugger, set a breakpoint on call dword ptr [edi+1Ch], and see what function that instruction calls.
The easiest way to determine the function pointed to by [edi+1Ch] is as follows:
Use COMView (wayback machine link to COMView) to inspect the IShellWindows interface:

You can see in the screenshot above that the function at vtable offset 28 (1Ch) is Count().