This should work on any machine that has a VC installation - shout foul if it doesn't:
- extract the DLL from attachment to \Masm32\MasmBasic\Plugins\GetComInterface.dll
- launch \Masm32\MasmBasic\RichMasm (http://masm32.com/board/index.php?topic=5314.0).exe
- select text such as IFilterGraph, IDispatch, IWebBrowser2, etc...
- go to menu System & Plugins and click on Get COM interface
(background: I needed the IGraphBuilder interface, so I went to MSDN (https://msdn.microsoft.com/en-us/library/windows/desktop/dd390085(v=vs.85).aspx) and copied the members by hand. Disgusting experience, and my code crashed. So I checked, and checked, and checked three times, until I vaguely remembered that I had stumbled over this problem before... the reason for my crashes was that MSDN lists the members, but not in the correct order. It's Micros**t... :()
P.S.: Pick version 2 below, called GetComInterfacePlugin.zip - autocorrection for members called "invoke" or "pause".
strmif.h (IGraphBuilder : public IFilterGraph)
typedef struct IGraphBuilderVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IGraphBuilder * This,
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
IGraphBuilder * This);
ULONG ( STDMETHODCALLTYPE *Release )(
IGraphBuilder * This);
HRESULT ( STDMETHODCALLTYPE *AddFilter )(
IGraphBuilder * This,
/* [in] */ IBaseFilter *pFilter,
/* [string][in] */ LPCWSTR pName);
HRESULT ( STDMETHODCALLTYPE *RemoveFilter )(
IGraphBuilder * This,
/* [in] */ IBaseFilter *pFilter);
HRESULT ( STDMETHODCALLTYPE *EnumFilters )(
IGraphBuilder * This,
/* [annotation][out] */
__out IEnumFilters **ppEnum);
HRESULT ( STDMETHODCALLTYPE *FindFilterByName )(
IGraphBuilder * This,
/* [string][in] */ LPCWSTR pName,
/* [annotation][out] */
__out IBaseFilter **ppFilter);
HRESULT ( STDMETHODCALLTYPE *ConnectDirect )(
IGraphBuilder * This,
/* [in] */ IPin *ppinOut,
/* [in] */ IPin *ppinIn,
/* [annotation][unique][in] */
__in_opt const AM_MEDIA_TYPE *pmt);
HRESULT ( STDMETHODCALLTYPE *Reconnect )(
IGraphBuilder * This,
/* [in] */ IPin *ppin);
HRESULT ( STDMETHODCALLTYPE *Disconnect )(
IGraphBuilder * This,
/* [in] */ IPin *ppin);
HRESULT ( STDMETHODCALLTYPE *SetDefaultSyncSource )(
IGraphBuilder * This);
HRESULT ( STDMETHODCALLTYPE *Connect )(
IGraphBuilder * This,
/* [in] */ IPin *ppinOut,
/* [in] */ IPin *ppinIn);
HRESULT ( STDMETHODCALLTYPE *Render )(
IGraphBuilder * This,
/* [in] */ IPin *ppinOut);
HRESULT ( STDMETHODCALLTYPE *RenderFile )(
IGraphBuilder * This,
/* [in] */ LPCWSTR lpcwstrFile,
/* [annotation][unique][in] */
__in_opt LPCWSTR lpcwstrPlayList);
HRESULT ( STDMETHODCALLTYPE *AddSourceFilter )(
IGraphBuilder * This,
/* [in] */ LPCWSTR lpcwstrFileName,
/* [annotation][unique][in] */
__in_opt LPCWSTR lpcwstrFilterName,
/* [annotation][out] */
__out IBaseFilter **ppFilter);
HRESULT ( STDMETHODCALLTYPE *SetLogFile )(
IGraphBuilder * This,
/* [in] */ DWORD_PTR hFile);
HRESULT ( STDMETHODCALLTYPE *Abort )(
IGraphBuilder * This);
HRESULT ( STDMETHODCALLTYPE *ShouldOperationContinue )(
IGraphBuilder * This);
END_INTERFACE
} IGraphBuilderVtbl;
interface IGraphBuilder
{
CONST_VTBL struct IGraphBuilderVtbl *lpVtbl;
};
What is the problem? I get this:IGraphBuilder STRUCT
QueryInterface dd ?
AddRef dd ?
Release dd ?
AddFilter dd ?
RemoveFilter dd ?
EnumFilters dd ?
FindFilterByName dd ?
ConnectDirect dd ?
Reconnect dd ?
Disconnect dd ?
SetDefaultSyncSource dd ?
Connect dd ?
Render dd ?
RenderFile dd ?
AddSourceFilter dd ?
SetLogFile dd ?
Abort dd ?
ShouldOperationContinue dd ?
IGraphBuilder ENDS
Maybe have a look at my directshow webcam example. It uses the IGraphBuilder interface.
Webcam: http://masm32.com/board/index.php?topic=4858.msg52908#msg52908
You mean this one? How did you generate it?_vtIGraphBuilder MACRO CastName:REQ
_vtIUnknown CastName
&CastName&_AddFilter comethod3 ?
&CastName&_RemoveFilter comethod2 ?
&CastName&_EnumFilters comethod2 ?
&CastName&_FindFilterByName comethod3 ?
&CastName&_ConnectDirect comethod4 ?
&CastName&_Reconnect comethod2 ?
&CastName&_Disconnect comethod2 ?
&CastName&_SetDefaultSyncSource comethod1 ?
&CastName&_Connect comethod3 ?
&CastName&_Render comethod2 ?
&CastName&_RenderFile comethod3 ?
&CastName&_AddSourceFilter comethod4 ?
&CastName&_SetLogFile comethod2 ?
&CastName&_Abort comethod1 ?
&CastName&_ShouldOperationContinue comethod1 ?
ENDM
I got it from "strmif.h" and converted it by hand to asm so i could use it with the coinvoke macro.
The interface GUIDS are in it as well.
MIDL_INTERFACE("56a868a9-0ad4-11ce-b03a-0020af0ba770")
IGraphBuilder : public IFilterGraph
#define IGraphBuilder_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define IGraphBuilder_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define IGraphBuilder_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define IGraphBuilder_AddFilter(This,pFilter,pName) \
( (This)->lpVtbl -> AddFilter(This,pFilter,pName) )
#define IGraphBuilder_RemoveFilter(This,pFilter) \
( (This)->lpVtbl -> RemoveFilter(This,pFilter) )
#define IGraphBuilder_EnumFilters(This,ppEnum) \
( (This)->lpVtbl -> EnumFilters(This,ppEnum) )
#define IGraphBuilder_FindFilterByName(This,pName,ppFilter) \
( (This)->lpVtbl -> FindFilterByName(This,pName,ppFilter) )
#define IGraphBuilder_ConnectDirect(This,ppinOut,ppinIn,pmt) \
( (This)->lpVtbl -> ConnectDirect(This,ppinOut,ppinIn,pmt) )
#define IGraphBuilder_Reconnect(This,ppin) \
( (This)->lpVtbl -> Reconnect(This,ppin) )
#define IGraphBuilder_Disconnect(This,ppin) \
( (This)->lpVtbl -> Disconnect(This,ppin) )
#define IGraphBuilder_SetDefaultSyncSource(This) \
( (This)->lpVtbl -> SetDefaultSyncSource(This) )
#define IGraphBuilder_Connect(This,ppinOut,ppinIn) \
( (This)->lpVtbl -> Connect(This,ppinOut,ppinIn) )
#define IGraphBuilder_Render(This,ppinOut) \
( (This)->lpVtbl -> Render(This,ppinOut) )
#define IGraphBuilder_RenderFile(This,lpcwstrFile,lpcwstrPlayList) \
( (This)->lpVtbl -> RenderFile(This,lpcwstrFile,lpcwstrPlayList) )
#define IGraphBuilder_AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter) \
( (This)->lpVtbl -> AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter) )
#define IGraphBuilder_SetLogFile(This,hFile) \
( (This)->lpVtbl -> SetLogFile(This,hFile) )
#define IGraphBuilder_Abort(This) \
( (This)->lpVtbl -> Abort(This) )
#define IGraphBuilder_ShouldOperationContinue(This) \
( (This)->lpVtbl -> ShouldOperationContinue(This) )
Quote from: Siekmanski on June 10, 2017, 04:49:12 AM
I got it from "strmif.h" and converted it by hand to asm
That's what I tried, too - but I am lazy, so I coded a plugin. There are over 400 header files that contain OLE interfaces, with over 100,000 members :biggrin:
Attachment #1 has a new version of the GetComInterface plugin; extract the DLL as \Masm32\MasmBasic\Plugins\GetComInterface.dll, then restart RichMasm with DSound8.asc file from the second attachment.
How does it work?
The IDirectSound8 is not included in the Masm32 SDK (this is one of the rare things that are missing - Hutch has included almost everything relevant :t). So what to do?
- select IDirectSound8 in your source
- click menu System & Plugins/Get COM interface
- when you see the MessageBox, click OK to copy it
- paste it on top of your code
- use with CoInvoke (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1138) as demonstrated below
include \masm32\MasmBasic\MasmBasic.inc ; download (http://masm32.com/board/index.php?topic=94.0)
include MiscDsound.inc
SetGlobals pDs8, dscaps:DSCAPS
Init
.if !rv(DirectSoundCreate8, 0, addr pDs8, 0)
m2m dscaps.dwSize, DSCAPS ; this structure must be initialised
CoInvoke pDs8, IDirectSound8.GetCaps, addr dscaps
deb 4, "IDirectSound8.GetCaps", dscaps.dwMinSecondarySampleRate, dscaps.dwMaxSecondarySampleRate
.endif
EndOfCode
Output on my machine:IDirectSound8.GetCaps
dscaps.dwMinSecondarySampleRate 100
dscaps.dwMaxSecondarySampleRate 200000
Here is a simple program that opens a Microsoft Internet Explorer window and loads a well-known web page:
include \masm32\MasmBasic\MasmBasic.inc
Init ; ## COM demo: open Internet Explorer ##
invoke OleInitialize, NULL
.if eax==S_OK
push Chr$("http://masm32.com/board/index.php?action=unread")
call MyBrowser
.endif
invoke OleUninitialize
Exit
CLSID_IExplorer GuidFromString("0002DF01-0000-0000-C000-000000000046") ; either use quoted text syntax or...
IID_IWebBrowser2 GuidFromString({D30C1661-CDAF-11D0-8A3E-00C04FC9E26E}) ; ... paste copied registry key name
MyBrowser proc uses esi url
LOCAL vEmpty:VARIANT, hWin
ClearLocals
push eax ; create a DWORD variable on the stack
; now ask the OS gently to create a table with addresses that you can call to configure your Explorer Window (MSDN (https://msdn.microsoft.com/en-us/library/windows/desktop/ms686615%28v=vs.85%29.aspx))
invoke CoCreateInstance, addr CLSID_IExplorer, NULL, CLSCTX_LOCAL_SERVER, addr IID_IWebBrowser2, esp ; esp is the address of that variable
pop esi ; CoCreateInstance has filled the variable with the address to the vtable
pInterface equ esi
.if eax==S_OK
CoInvoke pInterface, IWebBrowserVtbl.put_StatusBar, VARIANT_FALSE ; OK, now configure the browser
CoInvoke pInterface, IWebBrowserVtbl.put_MenuBar, VARIANT_TRUE ; false = no menu
CoInvoke pInterface, IWebBrowserVtbl.put_Visible, VARIANT_TRUE
; CoInvoke pInterface, IWebBrowserVtbl.get_HWND, addr hWin ; optional: get handle of the Explorer window
lea edx, vEmpty ; Navigate needs pointers to four empty VARIANTS
; Ole$(url): COM wants a BSTR, so the ANSI URL needs to be converted
CoInvoke pInterface, IWebBrowserVtbl.Navigate, Ole$(url), edx, edx, edx, edx
.endif
ret
MyBrowser endp
end start
If you love cryptic jargon, open the MSDN link above; otherwise, continue reading: What does this code do?
- after initialisation, it pushes the URL and calls MyBrowser
- push eax decreases esp and thus creates a DWORD slot for the OS
- CoCreateInstance uses the two GUID identifiers to find out what the user wants, and then fills the DWORD slot with a pointer to a so-called "interface"
- we pop that pointer into esi
- CoInvoke pInterface, IWebBrowserVtbl.put_StatusBar, VARIANT_FALSE does the following:
- it pushes one argument on the stack (VARIANT_FALSE)
- it gets the address of a proc called "put_StatusBar" that needs one argument on the stack:
push 0 ; VARIANT_FALSE
push esi ; pInterface
mov eax, [esi] ; get first DWORD from that interface
call near [eax+0AC] ; call the address in the put_StatusBar offset
That's all, folks. It is that simple.
Now one might ask the developers of COM why CoCreateInstance needs the address of a variable to deliver pInterface, instead of simply returning it in eax. The answer will be "it's by design" or "why do something simple if there is a more complicated way?". Redmond speaking... 8)
New version attached: if you select e.g. IWebBrowser2 in RichMasm and click System & Plugins/Get COM interface, you'll get this (the lousy formatting is a SMF quirk, it looks better in the editor):
IWebBrowser2 STRUCT
QueryInterface dd ?
AddRef dd ?
Release dd ?
GetTypeInfoCount dd ?
GetTypeInfo dd ?
GetIDsOfNames dd ?
Invoke_ dd ?
GoBack dd ?
GoForward dd ?
GoHome dd ?
GoSearch dd ?
Navigate dd ?
Refresh dd ?
Refresh2 dd ?
Stop dd ?
get_Application dd ?
get_Parent dd ?
get_Container dd ?
get_Document dd ?
get_TopLevelContainer dd ?
get_Type dd ?
get_Left dd ?
put_Left dd ?
get_Top dd ?
put_Top dd ?
get_Width dd ?
put_Width dd ?
get_Height dd ?
put_Height dd ?
...
get_AddressBar dd ?
put_AddressBar dd ?
get_Resizable dd ?
put_Resizable dd ?
IWebBrowser2 ENDS ; modified (_ appended): Invoke
IID_IWebBrowser2 GuidFromString("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E")
extracted from D:\Masm32\C_Headers\ExDisp.h
Note the last line: my GetComInterface.ini contains the string D:\Masm32\C_Headers\*.h because the default, i.e. the Registry key HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows, CurrentInstallFolder is not present on my machine.
In this example, only invoke was modified to invoke_ to avoid a name conflict. The software does that currently for invoke & pause (case-insensitive), plus Open (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1034), Close (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1035), Seek (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1036), Delete (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1135) (case-sensitive MasmBasic macros). Please let me know if you stumble over other name conflicts.
The next version of the RichMasm IDE will allow to insert links to the registry:
(http://www.jj2007.eu/pics/RegistryLink.png)
When clicking on the link, you can copy the results to the clipboard :cool: