Hello All,

At one time ernie and I were working on getting a Web Browser
control to inplace activate on a window. I did complete the code
but didn't transfer it to anyone. My harddrive crashed some time
ago and unfortunately, I'm now stuck on some of the original
problems I solved eariler:


2) Ensuring that my client site is well defined.

3) The return value from the LocalAlloc function in the
"CreateObject" function is the C++ "This" pointer.

4) Getting people to not loose respect for me
because of my QueryInterface code. It will be fixed...

See the source code attachment. Be sure to change the
paths in Browser.inc.

:alright: Xtreme
Posted on 2001-08-20 09:04:16 by Xtreme
According to calc.exe -5 = 0xFFFFxFFFB . What does your code do?
Posted on 2001-08-20 23:16:15 by eet_1024
1) My calc.exe agrees with eets. Basically, if you set HEX mode to DWORD, then set back to decimal mode, type in a negative number, then switch again to HEX, you get the HEX representation of the negative decimal number (IE, -5 becomes FFFFFFFB)

2) Huh? (guess I best read your source later)

3) exactly correct.

4) No comment, as long as you don't comment on my registrar script parser. QueryInterface will always look ugly until you do something like make it scan a table (at which point it becomes inintelegable and thus looks 'realy leet.')
Posted on 2001-08-21 06:39:07 by Ernie

This code should display the MS Web Browser control on a
window and allow one to display (D)HTML.

Note: You have to click the client area of the window to make it
create the control. Or you could move "invoke CreateWB" to

Unfortunately the DoVerb function of IOleObject fails and I don't
understand why...

Posted on 2001-08-21 07:51:14 by Xtreme
Just for completeness:

-5 =

0xB for 4-bit
0xFB for 8-bit
0xFFFB for 16-bit
0xFFFFFFFB for 32-bit
...you get the idea...
negitive numbers are a relitive concept, and the bit count includes one bit for sign.

I'll have to checkout that code when I have more time.
Posted on 2001-08-21 08:27:30 by bitRAKE

Thanks for the breakdown. The primary thing that confused me
was the 'L' in -5L. There are other number "extensions" in the
C++ header files that I don't get as well: U and t (note the case).
I suppose these mean Long, UINT, and t...(something).

At any rate the contant was defined correctly so there must be
a goof in my class definition (client site).
Posted on 2001-08-21 08:44:31 by Xtreme
I have the original C++ source (NO mfc) if anyone needs it.
I may just post it here anyway...
Posted on 2001-08-21 15:56:55 by Xtreme

Do you realize that when you're done you should be able to host most any activeX control on your window?

To host any control, you need to build a client site. Client sites are kinda generic.
Posted on 2001-08-22 07:03:09 by Ernie

The Object struct instance is the client site.
Any idea why DoVerb is failing?

Its probably something in "CreateObject"...


PS: When I'm finished I'll send you a formal version to put in the
COM section of the MASM32 package, along with a tut...
Posted on 2001-08-22 07:43:47 by Xtreme
Sorry, I never got that far into insertable objects to know the fine points of do verbs.

The general purpose stuff sounds great. You don't have to wait for me, you can publish on your own too. Want a link on my page?
Posted on 2001-08-22 20:16:55 by Ernie

code in CreateObject should look like:

mov ebx, eax
mov eax,pobj
mov [eax], ebx

mov (Object ptr [ebx]).nRefCount,0

that is because parameter is a pointer to an object, not the object itself.

After this change your program still crashes

Reason is: your parameter to SetClientSite is wrong. Be sure that your parameter is a pointer to an IClientSite interface.
May be you should change code to:

; Set the Web Browser Control's site
; coinvoke _pIOleObject, IOleObject, SetClientSite, [pif]
mov eax,pif
lea eax,[eax].Object.iOleClientSite.lpVtbl
coinvoke _pIOleObject, IOleObject, SetClientSite, eax

with this changes done, the OleClientSite procs are called, but after some time the program crashes.


Posted on 2001-08-23 07:27:17 by japheth
Heres the original C++ source code. Its actually useful in itself
because it doesn't use MFC.

The package includes an EXE that shows the WB Control in action.

Note: Right-click somewhere on the window background to see the IE context menu.
Posted on 2001-08-23 09:16:58 by Xtreme

I had a second look at your code.

you should think once again about your macro GETOBJECTPOINTER.

In my opinion it does not work correctly. Consider QueryInterface: this function can be called from any interface. To subtract a value depending just on the queriing interface will not work.

Have a look at Ernie's examples. For every supported Interface there exists an entry:

m_pVtbl DWORD 0 ; interface object
m_pBase DWORD 0 ; pointer to base
ObjectEntry ENDS

and the object (ASMCTRL i.e.) ist defined like:

AsmCtrlObject STRUCT
ObjectData0 ObjectData { } ; base values
AsmCtrlData0 AsmCtrlData { } ; custom object data
ObjectEntry0 ObjectEntry { } ; delegated Unknown
ObjectEntry1 ObjectEntry { } ; IAsmCtrl
ObjectEntry2 ObjectEntry { } ; IOleObject

this is more complicated I admit but it cannot be avoided.

Posted on 2001-08-23 10:32:22 by japheth

Bill T's original macro code to suit my needs. This
is a down side to having code "definitions" and source in different
files. The "Object.Interface" that Bill calls on does not exist in my


OOPs... I spoke too soon.

I didn't relize that Interface is a parameter passed to the macro.
How can this then be incorrect? Besides how can the
IOleClientSite procs get called if this is wrong?
Posted on 2001-08-23 11:20:09 by Xtreme

to get your code to work I have changed macro GETOBJECTPOINTER to:

mov eax, pif
sub eax,

the definition of Object to:

; declare the site structure

Object struct
iUnknown IIUnknown <?>
iBase0 dd ?
iOleWindow IIOleWindow <?>
iBase1 dd ?
iOleClientSite IIOleClientSite <?>
iBase2 dd ?
iOleInPlaceSite IIOleInPlaceSite <?>
iBase3 dd ?
iDispatch IIDispatch <?>
iBase4 dd ?
iDocHostUIHandler IIDocHostUIHandler <?>
iBase5 dd ?
iDocHostShowUI IIDocHostShowUI <?>
iBase6 dd ?
nRefCount dd ?
Object ends

and CreateObject to:

mov (Object ptr ).iOleInPlaceSite.lpVtbl, offset vtblIOleInPlaceSite ; save the offset(pointer) to the interface VTABLE in lpVtbl
mov (Object ptr ).iDispatch.lpVtbl, offset vtblIDispatch ; save the offset(pointer) to the interface VTABLE in lpVtbl
mov (Object ptr ).iDocHostUIHandler.lpVtbl, offset vtblIDocHostUIHandler ; save the offset(pointer) to the interface VTABLE in lpVtbl
mov (Object ptr ).iDocHostShowUI.lpVtbl, offset vtblIDocHostShowUI ; save the offset(pointer) to the interface VTABLE in lpVtbl
mov .Object.iBase0,0
mov .Object.iBase1,8
mov .Object.iBase2,16
mov .Object.iBase3,24
mov .Object.iBase4,32
mov .Object.iBase5,40
mov .Object.iBase6,48

with this changes QueryInterface always returns the correct interface. Without this changes the webbrowser control queries for IDispatch and gets IOleInPlaceSite (or was it IOleClientSite? I forgot). And the interface pointer to IOleClientSite is received by the object thru the call IOleObject:SetClientSite, not by QueryInterface.

when executing this code I get so far that IDispatch:Invoke is called from the webbrowser control twice. But then it crashes again. I had no time yet to check this.

Posted on 2001-08-24 03:13:55 by japheth

Last night I examined the macro more closely. I agree that is
is just too simple to work here. I also placed messageboxes
in the queryinterface function of both the C++ and ASM versions.
The C++ version doesn't call IOleClientSite at all (at least on start
up) but the ASM version does (its the second and fourth interface
call). This undoubtably means theres a problem with the ASM
QueryInterface function (As my second look at your post shows
you found!).

Also note that I found some errors in:

    [*]Declarations of IDispatch, IOleWindow, IOleClientSite,
    and IOleInPlaceSite. See Ernie's \masm32\COM\include\
    component.inc for proper declares. Or does it really matter
    that I declare a BOOL as BYTE and SIZE as SIZEL?

    [*]AddRef and Release. I uncommented them and used nRefCount
    as a "normal" (global) variable as in the C++ version.

    [*]Possibly the CoCreateInstance call: Why are the first, forth,
    and fifth parameters, pointers and in the C++ version only the
    fifth one is? If you remove the addrs assembly error occurs...


    The changes above wouldn't break the code to set the client
    site would it? It looks to me that there are now two ways to
    write that same code...
Posted on 2001-08-24 08:53:02 by Xtreme

to answer your questions:

1. No. Important is the number of parameters.
2. For the first step we can live without them
3. CoCreateInstance works definitely, this is no problem

Currently your modified program does not crash any more, it shows a "blank" page. QueryInterface works. 2 additional errors I have found so far are:

a. IOleInPlaceSite inherits from IOleWindow, not IUnknown. That is you must include GetWindow and ContextSensitiveHelp in the vtable.

b. IsEqualGUID is a function from OLE32.LIB. Better use this function than implement your own version. For your own version does not save esi and edi registers.

Posted on 2001-08-24 14:02:09 by japheth

I'm looking into your last post over the weekend...

Thank You!
Posted on 2001-08-24 14:17:47 by Xtreme

I have got it to work now.


- I have put your files together into one file (since without that VC could not display source code)

- I had no definition for IWebBrowser2 available, so I just included the minimum of IWebBrowser interface

- the path to frames.htm is hard coded in browser.asm

- changing of client area isnt implemented yet

It is a very interesting project. Next step is to implement event sinks (support IConnectionPointContainer).

Posted on 2001-08-24 15:47:38 by japheth

Only one problem Assembler can't find IWebBrowser_Navigate
at line 547....

I look at it at home as well as connectionpoint....

Posted on 2001-08-24 16:12:24 by Xtreme