2 * Active Template Library ActiveX functions (atl.dll)
4 * Copyright 2006 Andrey Turkin
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wine/debug.h"
40 #include "wine/unicode.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(atl
);
45 const IOleClientSiteVtbl
*lpOleClientSiteVtbl
;
46 const IOleContainerVtbl
*lpOleContainerVtbl
;
54 /**********************************************************************
55 * AtlAxWin class window procedure
57 static LRESULT CALLBACK
AtlAxWin_wndproc( HWND hWnd
, UINT wMsg
, WPARAM wParam
, LPARAM lParam
)
59 if ( wMsg
== WM_CREATE
)
61 DWORD len
= GetWindowTextLengthW( hWnd
) + 1;
62 WCHAR
*ptr
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
65 GetWindowTextW( hWnd
, ptr
, len
);
66 AtlAxCreateControlEx( ptr
, hWnd
, NULL
, NULL
, NULL
, NULL
, NULL
);
67 HeapFree( GetProcessHeap(), 0, ptr
);
70 return DefWindowProcW( hWnd
, wMsg
, wParam
, lParam
);
73 /***********************************************************************
74 * AtlAxWinInit [ATL.@]
75 * Initializes the control-hosting code: registering the AtlAxWin,
76 * AtlAxWin7 and AtlAxWinLic7 window classes and some messages.
82 BOOL WINAPI
AtlAxWinInit(void)
85 const WCHAR AtlAxWin
[] = {'A','t','l','A','x','W','i','n',0};
89 if ( FAILED( OleInitialize(NULL
) ) )
92 wcex
.cbSize
= sizeof(wcex
);
96 wcex
.hInstance
= GetModuleHandleW( NULL
);
99 wcex
.hbrBackground
= NULL
;
100 wcex
.lpszMenuName
= NULL
;
103 wcex
.lpfnWndProc
= AtlAxWin_wndproc
;
104 wcex
.lpszClassName
= AtlAxWin
;
105 if ( !RegisterClassExW( &wcex
) )
111 /***********************************************************************
112 * Atl container component implementation
116 static ULONG WINAPI
IOCS_AddRef(IOCS
*This
)
118 ULONG ref
= InterlockedIncrement(&This
->ref
);
120 TRACE( "(%p) : AddRef from %d\n", This
, ref
- 1 );
125 #define THIS2IOLECLIENTSITE(This) ((IOleClientSite*)&This->lpOleClientSiteVtbl)
126 #define THIS2IOLECONTAINER(This) ((IOleContainer*)&This->lpOleContainerVtbl)
128 static HRESULT WINAPI
IOCS_QueryInterface(IOCS
*This
, REFIID riid
, void **ppv
)
132 if ( IsEqualIID( &IID_IUnknown
, riid
)
133 || IsEqualIID( &IID_IOleClientSite
, riid
) )
135 *ppv
= THIS2IOLECLIENTSITE(This
);
136 } else if ( IsEqualIID( &IID_IOleContainer
, riid
) )
138 *ppv
= THIS2IOLECONTAINER(This
);
147 WARN("unsupported interface %s\n", debugstr_guid( riid
) );
149 return E_NOINTERFACE
;
152 static HRESULT
IOCS_Detach( IOCS
*This
);
153 static ULONG WINAPI
IOCS_Release(IOCS
*This
)
155 ULONG ref
= InterlockedDecrement(&This
->ref
);
157 TRACE( "(%p) : ReleaseRef to %d\n", This
, ref
);
162 HeapFree( GetProcessHeap(), 0, This
);
168 #define DEFINE_THIS(cls,ifc,iface) ((cls*)((BYTE*)(iface)-offsetof(cls,lp ## ifc ## Vtbl)))
170 /****** IOleClientSite *****/
172 #define IFACE2THIS(iface) DEFINE_THIS(IOCS,OleClientSite, iface)
173 static HRESULT WINAPI
OleClientSite_QueryInterface(IOleClientSite
*iface
, REFIID riid
, void **ppv
)
175 IOCS
*This
= IFACE2THIS(iface
);
176 return IOCS_QueryInterface(This
, riid
, ppv
);
178 static ULONG WINAPI
OleClientSite_AddRef(IOleClientSite
*iface
)
180 IOCS
*This
= IFACE2THIS(iface
);
181 return IOCS_AddRef(This
);
183 static ULONG WINAPI
OleClientSite_Release(IOleClientSite
*iface
)
185 IOCS
*This
= IFACE2THIS(iface
);
186 return IOCS_Release(This
);
188 static HRESULT WINAPI
OleClientSite_SaveObject(IOleClientSite
*iface
)
190 IOCS
*This
= IFACE2THIS(iface
);
191 FIXME( "(%p) - stub\n", This
);
194 static HRESULT WINAPI
OleClientSite_GetMoniker(IOleClientSite
*iface
, DWORD dwAssign
, DWORD dwWhichMoniker
, IMoniker
**ppmk
)
196 IOCS
*This
= IFACE2THIS(iface
);
198 FIXME( "(%p, 0x%x, 0x%x, %p)\n", This
, dwAssign
, dwWhichMoniker
, ppmk
);
201 static HRESULT WINAPI
OleClientSite_GetContainer(IOleClientSite
*iface
, IOleContainer
**ppContainer
)
203 IOCS
*This
= IFACE2THIS(iface
);
204 TRACE( "(%p, %p)\n", This
, ppContainer
);
205 return OleClientSite_QueryInterface( iface
, &IID_IOleContainer
, (void**)ppContainer
);
207 static HRESULT WINAPI
OleClientSite_ShowObject(IOleClientSite
*iface
)
209 IOCS
*This
= IFACE2THIS(iface
);
210 FIXME( "(%p) - stub\n", This
);
213 static HRESULT WINAPI
OleClientSite_OnShowWindow(IOleClientSite
*iface
, BOOL fShow
)
215 IOCS
*This
= IFACE2THIS(iface
);
216 FIXME( "(%p, %s) - stub\n", This
, fShow
? "TRUE" : "FALSE" );
219 static HRESULT WINAPI
OleClientSite_RequestNewObjectLayout(IOleClientSite
*iface
)
221 IOCS
*This
= IFACE2THIS(iface
);
222 FIXME( "(%p) - stub\n", This
);
228 /****** IOleContainer *****/
229 #define IFACE2THIS(iface) DEFINE_THIS(IOCS, OleContainer, iface)
230 static HRESULT WINAPI
OleContainer_QueryInterface( IOleContainer
* iface
, REFIID riid
, void** ppv
)
232 IOCS
*This
= IFACE2THIS(iface
);
233 return IOCS_QueryInterface( This
, riid
, ppv
);
235 static ULONG WINAPI
OleContainer_AddRef(IOleContainer
* iface
)
237 IOCS
*This
= IFACE2THIS(iface
);
238 return IOCS_AddRef(This
);
240 static ULONG WINAPI
OleContainer_Release(IOleContainer
* iface
)
242 IOCS
*This
= IFACE2THIS(iface
);
243 return IOCS_Release(This
);
245 static HRESULT WINAPI
OleContainer_ParseDisplayName(IOleContainer
* iface
, IBindCtx
* pbc
,
246 LPOLESTR pszDisplayName
, ULONG
* pchEaten
, IMoniker
** ppmkOut
)
248 IOCS
*This
= IFACE2THIS(iface
);
249 FIXME( "(%p,%p,%s,%p,%p) - stub\n", This
, pbc
, debugstr_w(pszDisplayName
), pchEaten
, ppmkOut
);
252 static HRESULT WINAPI
OleContainer_EnumObjects(IOleContainer
* iface
, DWORD grfFlags
, IEnumUnknown
** ppenum
)
254 IOCS
*This
= IFACE2THIS(iface
);
255 FIXME( "(%p, %u, %p) - stub\n", This
, grfFlags
, ppenum
);
258 static HRESULT WINAPI
OleContainer_LockContainer(IOleContainer
* iface
, BOOL fLock
)
260 IOCS
*This
= IFACE2THIS(iface
);
261 FIXME( "(%p, %s) - stub\n", This
, fLock
?"TRUE":"FALSE" );
268 static const IOleClientSiteVtbl OleClientSite_vtbl
= {
269 OleClientSite_QueryInterface
,
270 OleClientSite_AddRef
,
271 OleClientSite_Release
,
272 OleClientSite_SaveObject
,
273 OleClientSite_GetMoniker
,
274 OleClientSite_GetContainer
,
275 OleClientSite_ShowObject
,
276 OleClientSite_OnShowWindow
,
277 OleClientSite_RequestNewObjectLayout
279 static const IOleContainerVtbl OleContainer_vtbl
= {
280 OleContainer_QueryInterface
,
282 OleContainer_Release
,
283 OleContainer_ParseDisplayName
,
284 OleContainer_EnumObjects
,
285 OleContainer_LockContainer
288 static HRESULT
IOCS_Detach( IOCS
*This
) /* remove subclassing */
292 SetWindowLongPtrW( This
->hWnd
, GWLP_WNDPROC
, (ULONG_PTR
) This
->OrigWndProc
);
293 SetWindowLongPtrW( This
->hWnd
, GWLP_USERDATA
, (LONG_PTR
) NULL
);
298 IOleObject
*control
= This
->control
;
300 This
->control
= NULL
;
301 IOleObject_SetClientSite( control
, NULL
);
302 IOleObject_Release( control
);
307 static void IOCS_OnSize( IOCS
* This
, LPCRECT rect
)
311 if ( !This
->control
)
314 inPix
.cx
= rect
->right
- rect
->left
;
315 inPix
.cy
= rect
->bottom
- rect
->top
;
316 AtlPixelToHiMetric( &inPix
, &inHi
);
317 IOleObject_SetExtent( This
->control
, DVASPECT_CONTENT
, &inHi
);
320 static LRESULT
IOCS_OnWndProc( IOCS
*This
, HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
322 WNDPROC OrigWndProc
= This
->OrigWndProc
;
333 r
.right
= LOWORD( lParam
);
334 r
.bottom
= HIWORD( lParam
);
335 IOCS_OnSize( This
, &r
);
340 return OrigWndProc( hWnd
, uMsg
, wParam
, lParam
);
343 static LRESULT CALLBACK
AtlHost_wndproc( HWND hWnd
, UINT wMsg
, WPARAM wParam
, LPARAM lParam
)
345 IOCS
*This
= (IOCS
*) GetWindowLongPtrW( hWnd
, GWLP_USERDATA
);
346 return IOCS_OnWndProc( This
, hWnd
, wMsg
, wParam
, lParam
);
349 static HRESULT
IOCS_Attach( IOCS
*This
, HWND hWnd
, IUnknown
*pUnkControl
) /* subclass hWnd */
352 IUnknown_QueryInterface( pUnkControl
, &IID_IOleObject
, (void**)&This
->control
);
353 IOleObject_SetClientSite( This
->control
, THIS2IOLECLIENTSITE( This
) );
354 This
->OrigWndProc
= (WNDPROC
) GetWindowLongPtrW( This
->hWnd
, GWLP_WNDPROC
);
355 SetWindowLongPtrW( hWnd
, GWLP_USERDATA
, (ULONG_PTR
) This
);
356 SetWindowLongPtrW( hWnd
, GWLP_WNDPROC
, (ULONG_PTR
) AtlHost_wndproc
);
361 static HRESULT
IOCS_Init( IOCS
*This
)
364 static const WCHAR AXWIN
[] = {'A','X','W','I','N',0};
366 IOleObject_SetHostNames( This
->control
, AXWIN
, AXWIN
);
368 GetClientRect( This
->hWnd
, &rect
);
369 IOCS_OnSize( This
, &rect
);
374 /**********************************************************************
375 * Create new instance of Atl host component and attach it to window *
377 static HRESULT
IOCS_Create( HWND hWnd
, IUnknown
*pUnkControl
, IOCS
**ppSite
)
383 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(IOCS
));
386 return E_OUTOFMEMORY
;
388 This
->lpOleClientSiteVtbl
= &OleClientSite_vtbl
;
389 This
->lpOleContainerVtbl
= &OleContainer_vtbl
;
392 This
->OrigWndProc
= NULL
;
395 hr
= IOCS_Attach( This
, hWnd
, pUnkControl
);
396 if ( SUCCEEDED( hr
) )
397 hr
= IOCS_Init( This
);
398 if ( SUCCEEDED( hr
) )
401 IOCS_Release( This
);
407 /***********************************************************************
408 * AtlAxCreateControl [ATL.@]
410 HRESULT WINAPI
AtlAxCreateControl(LPCOLESTR lpszName
, HWND hWnd
,
411 IStream
*pStream
, IUnknown
**ppUnkContainer
)
413 return AtlAxCreateControlEx( lpszName
, hWnd
, pStream
, ppUnkContainer
,
417 /***********************************************************************
418 * AtlAxCreateControlEx [ATL.@]
421 * See http://www.codeproject.com/com/cwebpage.asp for some background
424 HRESULT WINAPI
AtlAxCreateControlEx(LPCOLESTR lpszName
, HWND hWnd
,
425 IStream
*pStream
, IUnknown
**ppUnkContainer
, IUnknown
**ppUnkControl
,
426 REFIID iidSink
, IUnknown
*punkSink
)
430 IOleObject
*pControl
;
431 IUnknown
*pUnkControl
;
432 IPersistStreamInit
*pPSInit
;
433 IUnknown
*pContainer
;
434 enum {IsGUID
=0,IsHTML
=1,IsURL
=2} content
;
436 TRACE("(%s %p %p %p %p %p %p)\n", debugstr_w(lpszName
), hWnd
, pStream
,
437 ppUnkContainer
, ppUnkControl
, iidSink
, punkSink
);
439 hRes
= CLSIDFromString( (LPOLESTR
) lpszName
, &controlId
);
441 hRes
= CLSIDFromProgID( lpszName
, &controlId
);
442 if ( SUCCEEDED( hRes
) )
445 /* FIXME - check for MSHTML: prefix! */
447 memcpy( &controlId
, &CLSID_WebBrowser
, sizeof(controlId
) );
450 hRes
= CoCreateInstance( &controlId
, 0, CLSCTX_ALL
, &IID_IOleObject
,
451 (void**) &pControl
);
452 if ( FAILED( hRes
) )
454 WARN( "cannot create ActiveX control %s instance - error 0x%08x\n",
455 debugstr_guid( &controlId
), hRes
);
459 hRes
= IOleObject_QueryInterface( pControl
, &IID_IPersistStreamInit
, (void**) &pPSInit
);
460 if ( SUCCEEDED( hRes
) )
463 IPersistStreamInit_InitNew( pPSInit
);
465 IPersistStreamInit_Load( pPSInit
, pStream
);
466 IPersistStreamInit_Release( pPSInit
);
468 WARN("cannot get IID_IPersistStreamInit out of control\n");
470 IOleObject_QueryInterface( pControl
, &IID_IUnknown
, (void**) &pUnkControl
);
471 IOleObject_Release( pControl
);
474 hRes
= AtlAxAttachControl( pUnkControl
, hWnd
, &pContainer
);
475 if ( FAILED( hRes
) )
476 WARN("cannot attach control to window\n");
478 if ( content
== IsURL
)
480 IWebBrowser2
*browser
;
482 hRes
= IOleObject_QueryInterface( pControl
, &IID_IWebBrowser2
, (void**) &browser
);
484 WARN( "Cannot query IWebBrowser2 interface: %08x\n", hRes
);
488 IWebBrowser2_put_Visible( browser
, VARIANT_TRUE
); /* it seems that native does this on URL (but do not on MSHTML:! why? */
490 V_VT(&url
) = VT_BSTR
;
491 V_BSTR(&url
) = SysAllocString( lpszName
);
493 hRes
= IWebBrowser2_Navigate2( browser
, &url
, NULL
, NULL
, NULL
, NULL
);
494 if ( FAILED( hRes
) )
495 WARN( "IWebBrowser2::Navigate2 failed: %08x\n", hRes
);
496 SysFreeString( V_BSTR(&url
) );
498 IWebBrowser2_Release( browser
);
504 *ppUnkContainer
= pContainer
;
506 IUnknown_AddRef( pContainer
);
510 *ppUnkControl
= pUnkControl
;
512 IUnknown_AddRef( pUnkControl
);
515 IUnknown_Release( pUnkControl
);
517 IUnknown_Release( pContainer
);
522 /***********************************************************************
523 * AtlAxAttachControl [ATL.@]
525 HRESULT WINAPI
AtlAxAttachControl(IUnknown
* pControl
, HWND hWnd
, IUnknown
** ppUnkContainer
)
530 TRACE( "%p %p %p\n", pControl
, hWnd
, ppUnkContainer
);
532 *ppUnkContainer
= NULL
;
534 hr
= IOCS_Create( hWnd
, pControl
, &pUnkContainer
);
535 if ( SUCCEEDED( hr
) )
537 *ppUnkContainer
= (IUnknown
*) pUnkContainer
;
543 /**********************************************************************
544 * Helper function for AX_ConvertDialogTemplate
546 static inline BOOL
advance_array(WORD
**pptr
, DWORD
*palloc
, DWORD
*pfilled
, const WORD
*data
, DWORD size
)
548 if ( (*pfilled
+ size
) > *palloc
)
550 *palloc
= ((*pfilled
+size
) + 0xFF) & ~0xFF;
551 *pptr
= HeapReAlloc( GetProcessHeap(), 0, *pptr
, *palloc
* sizeof(WORD
) );
555 RtlMoveMemory( *pptr
+*pfilled
, data
, size
* sizeof(WORD
) );
560 /**********************************************************************
561 * Convert ActiveX control templates to AtlAxWin class instances
563 static LPDLGTEMPLATEW
AX_ConvertDialogTemplate(LPCDLGTEMPLATEW src_tmpl
)
565 #define GET_WORD(x) (*(const WORD *)(x))
566 #define GET_DWORD(x) (*(const DWORD *)(x))
567 #define PUT_BLOCK(x,y) do {if (!advance_array(&output, &allocated, &filled, (x), (y))) return NULL;} while (0)
568 #define PUT_WORD(x) do {WORD w = (x);PUT_BLOCK(&w, 1);} while(0)
569 #define PUT_DWORD(x) do {DWORD w = (x);PUT_BLOCK(&w, 2);} while(0)
570 const WORD
*tmp
, *src
= (const WORD
*)src_tmpl
;
572 DWORD allocated
, filled
; /* in WORDs */
574 WORD signature
, dlgver
, rescount
;
577 filled
= 0; allocated
= 256;
578 output
= HeapAlloc( GetProcessHeap(), 0, allocated
* sizeof(WORD
) );
584 signature
= GET_WORD(src
);
585 dlgver
= GET_WORD(src
+ 1);
586 if (signature
== 1 && dlgver
== 0xFFFF)
590 style
= GET_DWORD(src
);
592 rescount
= GET_WORD(src
++);
594 if ( GET_WORD(src
) == 0xFFFF ) /* menu */
597 src
+= strlenW(src
) + 1;
598 if ( GET_WORD(src
) == 0xFFFF ) /* class */
601 src
+= strlenW(src
) + 1;
602 src
+= strlenW(src
) + 1; /* title */
603 if ( style
& (DS_SETFONT
| DS_SHELLFONT
) )
606 src
+= strlenW(src
) + 1;
610 style
= GET_DWORD(src
);
612 rescount
= GET_WORD(src
++);
614 if ( GET_WORD(src
) == 0xFFFF ) /* menu */
617 src
+= strlenW(src
) + 1;
618 if ( GET_WORD(src
) == 0xFFFF ) /* class */
621 src
+= strlenW(src
) + 1;
622 src
+= strlenW(src
) + 1; /* title */
623 if ( style
& DS_SETFONT
)
626 src
+= strlenW(src
) + 1;
629 PUT_BLOCK(tmp
, src
-tmp
);
633 src
= (const WORD
*)( ( ((ULONG
)src
) + 3) & ~3); /* align on DWORD boundary */
634 filled
= (filled
+ 1) & ~1; /* depends on DWORD-aligned allocation unit */
641 PUT_BLOCK(tmp
, src
-tmp
);
644 if ( GET_WORD(src
) == 0xFFFF ) /* class */
649 src
+= strlenW(src
) + 1;
651 src
+= strlenW(src
) + 1; /* title */
652 if ( GET_WORD(tmp
) == '{' ) /* all this mess created because of this line */
654 const WCHAR AtlAxWin
[9]={'A','t','l','A','x','W','i','n',0};
655 PUT_BLOCK(AtlAxWin
, sizeof(AtlAxWin
)/sizeof(WORD
));
656 PUT_BLOCK(tmp
, strlenW(tmp
)+1);
658 PUT_BLOCK(tmp
, src
-tmp
);
662 WORD size
= (GET_WORD(src
)+sizeof(WORD
)-1) / sizeof(WORD
); /* quite ugly :( Maybe use BYTE* instead of WORD* everywhere ? */
663 PUT_BLOCK(src
, size
);
672 return (LPDLGTEMPLATEW
) output
;
675 /***********************************************************************
676 * AtlAxCreateDialogA [ATL.@]
678 * Creates a dialog window
681 * hInst [I] Application instance
682 * name [I] Dialog box template name
683 * owner [I] Dialog box parent HWND
684 * dlgProc [I] Dialog box procedure
685 * param [I] This value will be passed to dlgProc as WM_INITDIALOG's message lParam
688 * Window handle of dialog window.
690 HWND WINAPI
AtlAxCreateDialogA(HINSTANCE hInst
, LPCSTR name
, HWND owner
, DLGPROC dlgProc
,LPARAM param
)
696 if ( HIWORD(name
) == 0 )
697 return AtlAxCreateDialogW( hInst
, (LPCWSTR
) name
, owner
, dlgProc
, param
);
699 length
= MultiByteToWideChar( CP_ACP
, 0, name
, -1, NULL
, 0 );
700 nameW
= HeapAlloc( GetProcessHeap(), 0, length
* sizeof(WCHAR
) );
703 MultiByteToWideChar( CP_ACP
, 0, name
, -1, nameW
, length
);
704 res
= AtlAxCreateDialogW( hInst
, nameW
, owner
, dlgProc
, param
);
705 HeapFree( GetProcessHeap(), 0, nameW
);
710 /***********************************************************************
711 * AtlAxCreateDialogW [ATL.@]
713 * See AtlAxCreateDialogA
716 HWND WINAPI
AtlAxCreateDialogW(HINSTANCE hInst
, LPCWSTR name
, HWND owner
, DLGPROC dlgProc
,LPARAM param
)
721 LPDLGTEMPLATEW newptr
;
724 FIXME("(%p %s %p %p %lx) - not tested\n", hInst
, debugstr_w(name
), owner
, dlgProc
, param
);
726 hrsrc
= FindResourceW( hInst
, name
, (LPWSTR
)RT_DIALOG
);
729 hgl
= LoadResource (hInst
, hrsrc
);
732 ptr
= (LPCDLGTEMPLATEW
)LockResource ( hgl
);
738 newptr
= AX_ConvertDialogTemplate( ptr
);
741 res
= CreateDialogIndirectParamW( hInst
, newptr
, owner
, dlgProc
, param
);
742 HeapFree( GetProcessHeap(), 0, newptr
);
745 FreeResource ( hrsrc
);