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);
44 /**********************************************************************
45 * AtlAxWin class window procedure
47 LRESULT static CALLBACK AtlAxWin_wndproc( HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam )
49 if ( wMsg == WM_CREATE )
51 DWORD len = GetWindowTextLengthW( hWnd ) + 1;
52 WCHAR *ptr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
55 GetWindowTextW( hWnd, ptr, len );
56 AtlAxCreateControlEx( ptr, hWnd, NULL, NULL, NULL, NULL, NULL );
57 HeapFree( GetProcessHeap(), 0, ptr );
60 return DefWindowProcW( hWnd, wMsg, wParam, lParam );
63 /***********************************************************************
64 * AtlAxWinInit [ATL.@]
65 * Initializes the control-hosting code: registering the AtlAxWin,
66 * AtlAxWin7 and AtlAxWinLic7 window classes and some messages.
72 BOOL WINAPI AtlAxWinInit(void)
75 const WCHAR AtlAxWin[] = {'A','t','l','A','x','W','i','n',0};
79 if ( FAILED( OleInitialize(NULL) ) )
82 wcex.cbSize = sizeof(wcex);
86 wcex.hInstance = GetModuleHandleW( NULL );
89 wcex.hbrBackground = NULL;
90 wcex.lpszMenuName = NULL;
93 wcex.lpfnWndProc = AtlAxWin_wndproc;
94 wcex.lpszClassName = AtlAxWin;
95 if ( !RegisterClassExW( &wcex ) )
101 /***********************************************************************
102 * AtlAxCreateControl [ATL.@]
104 HRESULT WINAPI AtlAxCreateControl(LPCOLESTR lpszName, HWND hWnd,
105 IStream *pStream, IUnknown **ppUnkContainer)
107 return AtlAxCreateControlEx( lpszName, hWnd, pStream, ppUnkContainer,
111 /***********************************************************************
112 * AtlAxCreateControlEx [ATL.@]
115 * See http://www.codeproject.com/com/cwebpage.asp for some background
118 HRESULT WINAPI AtlAxCreateControlEx(LPCOLESTR lpszName, HWND hWnd,
119 IStream *pStream, IUnknown **ppUnkContainer, IUnknown **ppUnkControl,
120 REFIID iidSink, IUnknown *punkSink)
124 IOleObject *pControl;
125 IUnknown *pUnkControl;
126 IPersistStreamInit *pPSInit;
127 IUnknown *pContainer;
128 enum {IsGUID=0,IsHTML=1,IsURL=2} content;
130 TRACE("(%s %p %p %p %p %p %p)\n", debugstr_w(lpszName), hWnd, pStream,
131 ppUnkContainer, ppUnkControl, iidSink, punkSink);
133 hRes = CLSIDFromString( (LPOLESTR) lpszName, &controlId );
135 hRes = CLSIDFromProgID( lpszName, &controlId );
136 if ( SUCCEEDED( hRes ) )
139 /* FIXME - check for MSHTML: prefix! */
141 memcpy( &controlId, &CLSID_WebBrowser, sizeof(controlId) );
144 hRes = CoCreateInstance( &controlId, 0, CLSCTX_ALL, &IID_IOleObject,
145 (void**) &pControl );
146 if ( FAILED( hRes ) )
148 WARN( "cannot create ActiveX control %s instance - error 0x%08x\n",
149 debugstr_guid( &controlId ), hRes );
153 hRes = IOleObject_QueryInterface( pControl, &IID_IPersistStreamInit, (void**) &pPSInit );
154 if ( SUCCEEDED( hRes ) )
157 IPersistStreamInit_InitNew( pPSInit );
159 IPersistStreamInit_Load( pPSInit, pStream );
160 IPersistStreamInit_Release( pPSInit );
162 WARN("cannot get IID_IPersistStreamInit out of control\n");
164 IOleObject_QueryInterface( pControl, &IID_IUnknown, (void**) &pUnkControl );
165 IOleObject_Release( pControl );
168 hRes = AtlAxAttachControl( pUnkControl, hWnd, &pContainer );
169 if ( FAILED( hRes ) )
170 WARN("cannot attach control to window\n");
172 if ( content == IsURL )
174 IWebBrowser2 *browser;
176 hRes = IOleObject_QueryInterface( pControl, &IID_IWebBrowser2, (void**) &browser );
178 WARN( "Cannot query IWebBrowser2 interface: %08x\n", hRes );
182 IWebBrowser2_put_Visible( browser, VARIANT_TRUE ); /* it seems that native does this on URL (but do not on MSHTML:! why? */
184 V_VT(&url) = VT_BSTR;
185 V_BSTR(&url) = SysAllocString( lpszName );
187 hRes = IWebBrowser2_Navigate2( browser, &url, NULL, NULL, NULL, NULL );
188 if ( FAILED( hRes ) )
189 WARN( "IWebBrowser2::Navigate2 failed: %08x\n", hRes );
190 SysFreeString( V_BSTR(&url) );
192 IWebBrowser2_Release( browser );
198 *ppUnkContainer = pContainer;
200 IUnknown_AddRef( pContainer );
204 *ppUnkControl = pUnkControl;
206 IUnknown_AddRef( pUnkControl );
209 IUnknown_Release( pUnkControl );
211 IUnknown_Release( pContainer );
216 /***********************************************************************
217 * AtlAxAttachControl [ATL.@]
219 HRESULT WINAPI AtlAxAttachControl(IUnknown* pControl, HWND hWnd, IUnknown** ppUnkContainer)
221 FIXME( "(%p %p %p) - stub\n", pControl, hWnd, ppUnkContainer );
225 /**********************************************************************
226 * Helper function for AX_ConvertDialogTemplate
228 static inline BOOL advance_array(WORD **pptr, DWORD *palloc, DWORD *pfilled, const WORD *data, DWORD size)
230 if ( (*pfilled + size) > *palloc )
232 *palloc = ((*pfilled+size) + 0xFF) & ~0xFF;
233 *pptr = HeapReAlloc( GetProcessHeap(), 0, *pptr, *palloc * sizeof(WORD) );
237 RtlMoveMemory( *pptr+*pfilled, data, size * sizeof(WORD) );
242 /**********************************************************************
243 * Convert ActiveX control templates to AtlAxWin class instances
245 static LPDLGTEMPLATEW AX_ConvertDialogTemplate(LPCDLGTEMPLATEW src_tmpl)
247 #define GET_WORD(x) (*(const WORD *)(x))
248 #define GET_DWORD(x) (*(const DWORD *)(x))
249 #define PUT_BLOCK(x,y) do {if (!advance_array(&output, &allocated, &filled, (x), (y))) return NULL;} while (0)
250 #define PUT_WORD(x) do {WORD w = (x);PUT_BLOCK(&w, 1);} while(0)
251 #define PUT_DWORD(x) do {DWORD w = (x);PUT_BLOCK(&w, 2);} while(0)
252 const WORD *tmp, *src = (const WORD *)src_tmpl;
254 DWORD allocated, filled; /* in WORDs */
256 WORD signature, dlgver, rescount;
259 filled = 0; allocated = 256;
260 output = HeapAlloc( GetProcessHeap(), 0, allocated * sizeof(WORD) );
266 signature = GET_WORD(src);
267 dlgver = GET_WORD(src + 1);
268 if (signature == 1 && dlgver == 0xFFFF)
272 style = GET_DWORD(src);
274 rescount = GET_WORD(src++);
276 if ( GET_WORD(src) == 0xFFFF ) /* menu */
279 src += strlenW(src) + 1;
280 if ( GET_WORD(src) == 0xFFFF ) /* class */
283 src += strlenW(src) + 1;
284 src += strlenW(src) + 1; /* title */
285 if ( style & (DS_SETFONT | DS_SHELLFONT) )
288 src += strlenW(src) + 1;
292 style = GET_DWORD(src);
294 rescount = GET_WORD(src++);
296 if ( GET_WORD(src) == 0xFFFF ) /* menu */
299 src += strlenW(src) + 1;
300 if ( GET_WORD(src) == 0xFFFF ) /* class */
303 src += strlenW(src) + 1;
304 src += strlenW(src) + 1; /* title */
305 if ( style & DS_SETFONT )
308 src += strlenW(src) + 1;
311 PUT_BLOCK(tmp, src-tmp);
315 src = (const WORD *)( ( ((ULONG)src) + 3) & ~3); /* align on DWORD boundary */
316 filled = (filled + 1) & ~1; /* depends on DWORD-aligned allocation unit */
323 PUT_BLOCK(tmp, src-tmp);
326 if ( GET_WORD(src) == 0xFFFF ) /* class */
331 src += strlenW(src) + 1;
333 src += strlenW(src) + 1; /* title */
334 if ( GET_WORD(tmp) == '{' ) /* all this mess created because of this line */
336 const WCHAR AtlAxWin[9]={'A','t','l','A','x','W','i','n',0};
337 PUT_BLOCK(AtlAxWin, sizeof(AtlAxWin)/sizeof(WORD));
338 PUT_BLOCK(tmp, strlenW(tmp)+1);
340 PUT_BLOCK(tmp, src-tmp);
344 WORD size = (GET_WORD(src)+sizeof(WORD)-1) / sizeof(WORD); /* quite ugly :( Maybe use BYTE* instead of WORD* everywhere ? */
345 PUT_BLOCK(src, size);
354 return (LPDLGTEMPLATEW) output;
357 /***********************************************************************
358 * AtlAxCreateDialogA [ATL.@]
360 * Creates a dialog window
363 * hInst [I] Application instance
364 * name [I] Dialog box template name
365 * owner [I] Dialog box parent HWND
366 * dlgProc [I] Dialog box procedure
367 * param [I] This value will be passed to dlgProc as WM_INITDIALOG's message lParam
370 * Window handle of dialog window.
372 HWND WINAPI AtlAxCreateDialogA(HINSTANCE hInst, LPCSTR name, HWND owner, DLGPROC dlgProc ,LPARAM param)
378 if ( HIWORD(name) == 0 )
379 return AtlAxCreateDialogW( hInst, (LPCWSTR) name, owner, dlgProc, param );
381 length = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
382 nameW = HeapAlloc( GetProcessHeap(), 0, length * sizeof(WCHAR) );
385 MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, length );
386 res = AtlAxCreateDialogW( hInst, nameW, owner, dlgProc, param );
387 HeapFree( GetProcessHeap(), 0, nameW );
392 /***********************************************************************
393 * AtlAxCreateDialogW [ATL.@]
395 * See AtlAxCreateDialogA
398 HWND WINAPI AtlAxCreateDialogW(HINSTANCE hInst, LPCWSTR name, HWND owner, DLGPROC dlgProc ,LPARAM param)
403 LPDLGTEMPLATEW newptr;
406 FIXME("(%p %s %p %p %lx) - not tested\n", hInst, debugstr_w(name), owner, dlgProc, param);
408 hrsrc = FindResourceW( hInst, name, (LPWSTR)RT_DIALOG );
411 hgl = LoadResource (hInst, hrsrc);
414 ptr = (LPCDLGTEMPLATEW)LockResource ( hgl );
420 newptr = AX_ConvertDialogTemplate( ptr );
423 res = CreateDialogIndirectParamW( hInst, newptr, owner, dlgProc, param );
424 HeapFree( GetProcessHeap(), 0, newptr );
427 FreeResource ( hrsrc );