/* * Active Template Library ActiveX functions (atl.dll) * * Copyright 2006 Andrey Turkin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #define COBJMACROS #include "windef.h" #include "winbase.h" #include "winerror.h" #include "winuser.h" #include "wine/debug.h" #include "objbase.h" #include "objidl.h" #include "ole2.h" #include "exdisp.h" #include "atlbase.h" #include "atliface.h" #include "atlwin.h" #include "shlwapi.h" #include "wine/unicode.h" WINE_DEFAULT_DEBUG_CHANNEL(atl); typedef struct IOCS { IOleClientSite IOleClientSite_iface; IOleContainer IOleContainer_iface; IOleInPlaceSiteWindowless IOleInPlaceSiteWindowless_iface; IOleInPlaceFrame IOleInPlaceFrame_iface; IOleControlSite IOleControlSite_iface; LONG ref; HWND hWnd; IOleObject *control; RECT size; WNDPROC OrigWndProc; BOOL fActive, fInPlace, fWindowless; } IOCS; static const WCHAR wine_atl_iocsW[] = {'_','_','W','I','N','E','_','A','T','L','_','I','O','C','S','\0'}; /********************************************************************** * AtlAxWin class window procedure */ static LRESULT CALLBACK AtlAxWin_wndproc( HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam ) { if ( wMsg == WM_CREATE ) { DWORD len = GetWindowTextLengthW( hWnd ) + 1; WCHAR *ptr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); if (!ptr) return 1; GetWindowTextW( hWnd, ptr, len ); AtlAxCreateControlEx( ptr, hWnd, NULL, NULL, NULL, NULL, NULL ); HeapFree( GetProcessHeap(), 0, ptr ); return 0; } return DefWindowProcW( hWnd, wMsg, wParam, lParam ); } /*********************************************************************** * AtlAxWinInit [atl100.@] * Initializes the control-hosting code: registering the AtlAxWin, * AtlAxWin7 and AtlAxWinLic7 window classes and some messages. * * RETURNS * TRUE or FALSE */ BOOL WINAPI AtlAxWinInit(void) { WNDCLASSEXW wcex; #if _ATL_VER <= _ATL_VER_30 #define ATL_NAME_SUFFIX 0 #elif _ATL_VER == _ATL_VER_80 #define ATL_NAME_SUFFIX '8','0',0 #elif _ATL_VER == _ATL_VER_90 #define ATL_NAME_SUFFIX '9','0',0 #elif _ATL_VER == _ATL_VER_100 #define ATL_NAME_SUFFIX '1','0','0',0 #elif _ATL_VER == _ATL_VER_110 #define ATL_NAME_SUFFIX '1','1','0',0 #else #error Unsupported version #endif const WCHAR AtlAxWinW[] = {'A','t','l','A','x','W','i','n',ATL_NAME_SUFFIX}; FIXME("version %04x semi-stub\n", _ATL_VER); if ( FAILED( OleInitialize(NULL) ) ) return FALSE; wcex.cbSize = sizeof(wcex); wcex.style = CS_GLOBALCLASS | (_ATL_VER > _ATL_VER_30 ? CS_DBLCLKS : 0); wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = GetModuleHandleW( NULL ); wcex.hIcon = NULL; wcex.hCursor = NULL; wcex.hbrBackground = NULL; wcex.lpszMenuName = NULL; wcex.hIconSm = 0; wcex.lpfnWndProc = AtlAxWin_wndproc; wcex.lpszClassName = AtlAxWinW; if ( !RegisterClassExW( &wcex ) ) return FALSE; if(_ATL_VER > _ATL_VER_30) { const WCHAR AtlAxWinLicW[] = {'A','t','l','A','x','W','i','n','L','i','c',ATL_NAME_SUFFIX}; wcex.lpszClassName = AtlAxWinLicW; if ( !RegisterClassExW( &wcex ) ) return FALSE; } return TRUE; } /*********************************************************************** * Atl container component implementation */ /****** IOleClientSite *****/ static inline IOCS *impl_from_IOleClientSite(IOleClientSite *iface) { return CONTAINING_RECORD(iface, IOCS, IOleClientSite_iface); } static HRESULT IOCS_Detach( IOCS *This ) /* remove subclassing */ { if ( This->hWnd ) { SetWindowLongPtrW( This->hWnd, GWLP_WNDPROC, (ULONG_PTR) This->OrigWndProc ); RemovePropW( This->hWnd, wine_atl_iocsW); This->hWnd = NULL; } if ( This->control ) { IOleObject *control = This->control; This->control = NULL; IOleObject_Close( control, OLECLOSE_NOSAVE ); IOleObject_SetClientSite( control, NULL ); IOleObject_Release( control ); } return S_OK; } static HRESULT WINAPI OleClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv) { IOCS *This = impl_from_IOleClientSite(iface); TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); *ppv = NULL; if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IOleClientSite, riid)) { *ppv = iface; } else if (IsEqualIID(&IID_IOleContainer, riid)) { *ppv = &This->IOleContainer_iface; } else if (IsEqualIID(&IID_IOleInPlaceSite, riid) || IsEqualIID(&IID_IOleInPlaceSiteEx, riid) || IsEqualIID(&IID_IOleInPlaceSiteWindowless, riid)) { *ppv = &This->IOleInPlaceSiteWindowless_iface; } else if (IsEqualIID(&IID_IOleInPlaceFrame, riid)) { *ppv = &This->IOleInPlaceFrame_iface; } else if (IsEqualIID(&IID_IOleControlSite, riid)) { *ppv = &This->IOleControlSite_iface; } if (*ppv) { IOleClientSite_AddRef(iface); return S_OK; } WARN("unsupported interface %s\n", debugstr_guid(riid)); return E_NOINTERFACE; } static ULONG WINAPI OleClientSite_AddRef(IOleClientSite *iface) { IOCS *This = impl_from_IOleClientSite(iface); ULONG ref = InterlockedIncrement(&This->ref); TRACE("(%p)->(%d)\n", This, ref); return ref; } static ULONG WINAPI OleClientSite_Release(IOleClientSite *iface) { IOCS *This = impl_from_IOleClientSite(iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p)->(%d)\n", This, ref); if (!ref) { IOCS_Detach( This ); HeapFree( GetProcessHeap(), 0, This ); } return ref; } static HRESULT WINAPI OleClientSite_SaveObject(IOleClientSite *iface) { IOCS *This = impl_from_IOleClientSite(iface); FIXME( "(%p) - stub\n", This ); return E_NOTIMPL; } static HRESULT WINAPI OleClientSite_GetMoniker(IOleClientSite *iface, DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk) { IOCS *This = impl_from_IOleClientSite(iface); FIXME( "(%p, 0x%x, 0x%x, %p)\n", This, dwAssign, dwWhichMoniker, ppmk ); return E_NOTIMPL; } static HRESULT WINAPI OleClientSite_GetContainer(IOleClientSite *iface, IOleContainer **container) { IOCS *This = impl_from_IOleClientSite(iface); TRACE("(%p, %p)\n", This, container); return IOleClientSite_QueryInterface(iface, &IID_IOleContainer, (void**)container); } static HRESULT WINAPI OleClientSite_ShowObject(IOleClientSite *iface) { IOCS *This = impl_from_IOleClientSite(iface); FIXME( "(%p) - stub\n", This ); return S_OK; } static HRESULT WINAPI OleClientSite_OnShowWindow(IOleClientSite *iface, BOOL fShow) { IOCS *This = impl_from_IOleClientSite(iface); FIXME( "(%p, %s) - stub\n", This, fShow ? "TRUE" : "FALSE" ); return E_NOTIMPL; } static HRESULT WINAPI OleClientSite_RequestNewObjectLayout(IOleClientSite *iface) { IOCS *This = impl_from_IOleClientSite(iface); FIXME( "(%p) - stub\n", This ); return E_NOTIMPL; } /****** IOleContainer *****/ static inline IOCS *impl_from_IOleContainer(IOleContainer *iface) { return CONTAINING_RECORD(iface, IOCS, IOleContainer_iface); } static HRESULT WINAPI OleContainer_QueryInterface( IOleContainer* iface, REFIID riid, void** ppv) { IOCS *This = impl_from_IOleContainer(iface); return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv); } static ULONG WINAPI OleContainer_AddRef(IOleContainer* iface) { IOCS *This = impl_from_IOleContainer(iface); return IOleClientSite_AddRef(&This->IOleClientSite_iface); } static ULONG WINAPI OleContainer_Release(IOleContainer* iface) { IOCS *This = impl_from_IOleContainer(iface); return IOleClientSite_Release(&This->IOleClientSite_iface); } static HRESULT WINAPI OleContainer_ParseDisplayName(IOleContainer* iface, IBindCtx* pbc, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut) { IOCS *This = impl_from_IOleContainer(iface); FIXME( "(%p,%p,%s,%p,%p) - stub\n", This, pbc, debugstr_w(pszDisplayName), pchEaten, ppmkOut ); return E_NOTIMPL; } static HRESULT WINAPI OleContainer_EnumObjects(IOleContainer* iface, DWORD grfFlags, IEnumUnknown** ppenum) { IOCS *This = impl_from_IOleContainer(iface); FIXME( "(%p, %u, %p) - stub\n", This, grfFlags, ppenum ); return E_NOTIMPL; } static HRESULT WINAPI OleContainer_LockContainer(IOleContainer* iface, BOOL fLock) { IOCS *This = impl_from_IOleContainer(iface); FIXME( "(%p, %s) - stub\n", This, fLock?"TRUE":"FALSE" ); return E_NOTIMPL; } /****** IOleInPlaceSiteWindowless *******/ static inline IOCS *impl_from_IOleInPlaceSiteWindowless(IOleInPlaceSiteWindowless *iface) { return CONTAINING_RECORD(iface, IOCS, IOleInPlaceSiteWindowless_iface); } static HRESULT WINAPI OleInPlaceSiteWindowless_QueryInterface(IOleInPlaceSiteWindowless *iface, REFIID riid, void **ppv) { IOCS *This = impl_from_IOleInPlaceSiteWindowless(iface); return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv); } static ULONG WINAPI OleInPlaceSiteWindowless_AddRef(IOleInPlaceSiteWindowless *iface) { IOCS *This = impl_from_IOleInPlaceSiteWindowless(iface); return IOleClientSite_AddRef(&This->IOleClientSite_iface); } static ULONG WINAPI OleInPlaceSiteWindowless_Release(IOleInPlaceSiteWindowless *iface) { IOCS *This = impl_from_IOleInPlaceSiteWindowless(iface); return IOleClientSite_Release(&This->IOleClientSite_iface); } static HRESULT WINAPI OleInPlaceSiteWindowless_GetWindow(IOleInPlaceSiteWindowless* iface, HWND* phwnd) { IOCS *This = impl_from_IOleInPlaceSiteWindowless(iface); TRACE("(%p,%p)\n", This, phwnd); *phwnd = This->hWnd; return S_OK; } static HRESULT WINAPI OleInPlaceSiteWindowless_ContextSensitiveHelp(IOleInPlaceSiteWindowless* iface, BOOL fEnterMode) { IOCS *This = impl_from_IOleInPlaceSiteWindowless(iface); FIXME("(%p,%d) - stub\n", This, fEnterMode); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceSiteWindowless_CanInPlaceActivate(IOleInPlaceSiteWindowless *iface) { IOCS *This = impl_from_IOleInPlaceSiteWindowless(iface); TRACE("(%p)\n", This); return S_OK; } static HRESULT WINAPI OleInPlaceSiteWindowless_OnInPlaceActivate(IOleInPlaceSiteWindowless *iface) { IOCS *This = impl_from_IOleInPlaceSiteWindowless(iface); TRACE("(%p)\n", This); This->fInPlace = TRUE; return S_OK; } static HRESULT WINAPI OleInPlaceSiteWindowless_OnUIActivate(IOleInPlaceSiteWindowless *iface) { IOCS *This = impl_from_IOleInPlaceSiteWindowless(iface); TRACE("(%p)\n", This); return S_OK; } static HRESULT WINAPI OleInPlaceSiteWindowless_GetWindowContext(IOleInPlaceSiteWindowless *iface, IOleInPlaceFrame **frame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo) { IOCS *This = impl_from_IOleInPlaceSiteWindowless(iface); TRACE("(%p,%p,%p,%p,%p,%p)\n", This, frame, ppDoc, lprcPosRect, lprcClipRect, lpFrameInfo); if ( lprcClipRect ) *lprcClipRect = This->size; if ( lprcPosRect ) *lprcPosRect = This->size; if ( frame ) { *frame = &This->IOleInPlaceFrame_iface; IOleInPlaceFrame_AddRef(*frame); } if ( ppDoc ) *ppDoc = NULL; if ( lpFrameInfo ) { lpFrameInfo->fMDIApp = FALSE; lpFrameInfo->hwndFrame = This->hWnd; lpFrameInfo->haccel = NULL; lpFrameInfo->cAccelEntries = 0; } return S_OK; } static HRESULT WINAPI OleInPlaceSiteWindowless_Scroll(IOleInPlaceSiteWindowless *iface, SIZE scrollExtent) { IOCS *This = impl_from_IOleInPlaceSiteWindowless(iface); FIXME("(%p) - stub\n", This); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceSiteWindowless_OnUIDeactivate(IOleInPlaceSiteWindowless *iface, BOOL fUndoable) { IOCS *This = impl_from_IOleInPlaceSiteWindowless(iface); FIXME("(%p,%d) - stub\n", This, fUndoable); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceSiteWindowless_OnInPlaceDeactivate(IOleInPlaceSiteWindowless *iface) { IOCS *This = impl_from_IOleInPlaceSiteWindowless(iface); TRACE("(%p)\n", This); This->fInPlace = This->fWindowless = FALSE; return S_OK; } static HRESULT WINAPI OleInPlaceSiteWindowless_DiscardUndoState(IOleInPlaceSiteWindowless *iface) { IOCS *This = impl_from_IOleInPlaceSiteWindowless(iface); FIXME("(%p) - stub\n", This); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceSiteWindowless_DeactivateAndUndo(IOleInPlaceSiteWindowless *iface) { IOCS *This = impl_from_IOleInPlaceSiteWindowless(iface); FIXME("(%p) - stub\n", This); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceSiteWindowless_OnPosRectChange(IOleInPlaceSiteWindowless *iface, LPCRECT lprcPosRect) { IOCS *This = impl_from_IOleInPlaceSiteWindowless(iface); FIXME("(%p,%p) - stub\n", This, lprcPosRect); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceSiteWindowless_OnInPlaceActivateEx( IOleInPlaceSiteWindowless *iface, BOOL* pfNoRedraw, DWORD dwFlags) { IOCS *This = impl_from_IOleInPlaceSiteWindowless(iface); TRACE("\n"); This->fActive = This->fInPlace = TRUE; if ( dwFlags & ACTIVATE_WINDOWLESS ) This->fWindowless = TRUE; return S_OK; } static HRESULT WINAPI OleInPlaceSiteWindowless_OnInPlaceDeactivateEx( IOleInPlaceSiteWindowless *iface, BOOL fNoRedraw) { IOCS *This = impl_from_IOleInPlaceSiteWindowless(iface); TRACE("\n"); This->fActive = This->fInPlace = This->fWindowless = FALSE; return S_OK; } static HRESULT WINAPI OleInPlaceSiteWindowless_RequestUIActivate( IOleInPlaceSiteWindowless *iface) { FIXME("\n"); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceSiteWindowless_CanWindowlessActivate( IOleInPlaceSiteWindowless *iface) { FIXME("\n"); return S_OK; } static HRESULT WINAPI OleInPlaceSiteWindowless_GetCapture( IOleInPlaceSiteWindowless *iface) { FIXME("\n"); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceSiteWindowless_SetCapture( IOleInPlaceSiteWindowless *iface, BOOL fCapture) { FIXME("\n"); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceSiteWindowless_GetFocus( IOleInPlaceSiteWindowless *iface) { FIXME("\n"); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceSiteWindowless_SetFocus( IOleInPlaceSiteWindowless *iface, BOOL fFocus) { FIXME("\n"); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceSiteWindowless_GetDC( IOleInPlaceSiteWindowless *iface, LPCRECT pRect, DWORD grfFlags, HDC* phDC) { FIXME("\n"); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceSiteWindowless_ReleaseDC( IOleInPlaceSiteWindowless *iface, HDC hDC) { FIXME("\n"); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceSiteWindowless_InvalidateRect( IOleInPlaceSiteWindowless *iface, LPCRECT pRect, BOOL fErase) { FIXME("\n"); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceSiteWindowless_InvalidateRgn( IOleInPlaceSiteWindowless *iface, HRGN hRGN, BOOL fErase) { FIXME("\n"); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceSiteWindowless_ScrollRect( IOleInPlaceSiteWindowless *iface, INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip) { FIXME("\n"); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceSiteWindowless_AdjustRect( IOleInPlaceSiteWindowless *iface, LPRECT prc) { FIXME("\n"); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceSiteWindowless_OnDefWindowMessage( IOleInPlaceSiteWindowless *iface, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plResult) { FIXME("\n"); return E_NOTIMPL; } /****** IOleInPlaceFrame *******/ static inline IOCS *impl_from_IOleInPlaceFrame(IOleInPlaceFrame *iface) { return CONTAINING_RECORD(iface, IOCS, IOleInPlaceFrame_iface); } static HRESULT WINAPI OleInPlaceFrame_QueryInterface(IOleInPlaceFrame *iface, REFIID riid, void **ppv) { IOCS *This = impl_from_IOleInPlaceFrame(iface); return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv); } static ULONG WINAPI OleInPlaceFrame_AddRef(IOleInPlaceFrame *iface) { IOCS *This = impl_from_IOleInPlaceFrame(iface); return IOleClientSite_AddRef(&This->IOleClientSite_iface); } static ULONG WINAPI OleInPlaceFrame_Release(IOleInPlaceFrame *iface) { IOCS *This = impl_from_IOleInPlaceFrame(iface); return IOleClientSite_Release(&This->IOleClientSite_iface); } static HRESULT WINAPI OleInPlaceFrame_GetWindow(IOleInPlaceFrame *iface, HWND *phWnd) { IOCS *This = impl_from_IOleInPlaceFrame(iface); TRACE( "(%p,%p)\n", This, phWnd ); *phWnd = This->hWnd; return S_OK; } static HRESULT WINAPI OleInPlaceFrame_ContextSensitiveHelp(IOleInPlaceFrame *iface, BOOL fEnterMode) { IOCS *This = impl_from_IOleInPlaceFrame(iface); FIXME( "(%p,%d) - stub\n", This, fEnterMode ); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceFrame_GetBorder(IOleInPlaceFrame *iface, LPRECT lprectBorder) { IOCS *This = impl_from_IOleInPlaceFrame(iface); FIXME( "(%p,%p) - stub\n", This, lprectBorder ); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceFrame_RequestBorderSpace(IOleInPlaceFrame *iface, LPCBORDERWIDTHS pborderwidths) { IOCS *This = impl_from_IOleInPlaceFrame(iface); FIXME( "(%p,%p) - stub\n", This, pborderwidths ); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceFrame_SetBorderSpace(IOleInPlaceFrame *iface, LPCBORDERWIDTHS pborderwidths) { IOCS *This = impl_from_IOleInPlaceFrame(iface); FIXME( "(%p,%p) - stub\n", This, pborderwidths ); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceFrame_SetActiveObject(IOleInPlaceFrame *iface, IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName) { IOCS *This = impl_from_IOleInPlaceFrame(iface); FIXME( "(%p,%p,%s) - stub\n", This, pActiveObject, debugstr_w(pszObjName) ); return S_OK; } static HRESULT WINAPI OleInPlaceFrame_InsertMenus(IOleInPlaceFrame *iface, HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) { IOCS *This = impl_from_IOleInPlaceFrame(iface); FIXME( "(%p,%p,%p) - stub\n", This, hmenuShared, lpMenuWidths ); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceFrame_SetMenu(IOleInPlaceFrame *iface, HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject) { IOCS *This = impl_from_IOleInPlaceFrame(iface); FIXME( "(%p,%p,%p,%p) - stub\n", This, hmenuShared, holemenu, hwndActiveObject ); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceFrame_RemoveMenus(IOleInPlaceFrame *iface, HMENU hmenuShared) { IOCS *This = impl_from_IOleInPlaceFrame(iface); FIXME( "(%p, %p) - stub\n", This, hmenuShared ); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceFrame_SetStatusText(IOleInPlaceFrame *iface, LPCOLESTR pszStatusText) { IOCS *This = impl_from_IOleInPlaceFrame(iface); FIXME( "(%p, %s) - stub\n", This, debugstr_w( pszStatusText ) ); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceFrame_EnableModeless(IOleInPlaceFrame *iface, BOOL fEnable) { IOCS *This = impl_from_IOleInPlaceFrame(iface); FIXME( "(%p, %d) - stub\n", This, fEnable ); return E_NOTIMPL; } static HRESULT WINAPI OleInPlaceFrame_TranslateAccelerator(IOleInPlaceFrame *iface, LPMSG lpmsg, WORD wID) { IOCS *This = impl_from_IOleInPlaceFrame(iface); FIXME( "(%p, %p, %x) - stub\n", This, lpmsg, wID ); return E_NOTIMPL; } /****** IOleControlSite *******/ static inline IOCS *impl_from_IOleControlSite(IOleControlSite *iface) { return CONTAINING_RECORD(iface, IOCS, IOleControlSite_iface); } static HRESULT WINAPI OleControlSite_QueryInterface(IOleControlSite *iface, REFIID riid, void **ppv) { IOCS *This = impl_from_IOleControlSite(iface); return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv); } static ULONG WINAPI OleControlSite_AddRef(IOleControlSite *iface) { IOCS *This = impl_from_IOleControlSite(iface); return IOleClientSite_AddRef(&This->IOleClientSite_iface); } static ULONG WINAPI OleControlSite_Release(IOleControlSite *iface) { IOCS *This = impl_from_IOleControlSite(iface); return IOleClientSite_Release(&This->IOleClientSite_iface); } static HRESULT WINAPI OleControlSite_OnControlInfoChanged( IOleControlSite* This) { FIXME( "\n" ); return E_NOTIMPL; } static HRESULT WINAPI OleControlSite_LockInPlaceActive( IOleControlSite* This, BOOL fLock) { FIXME( "\n" ); return E_NOTIMPL; } static HRESULT WINAPI OleControlSite_GetExtendedControl( IOleControlSite* This, IDispatch** ppDisp) { FIXME( "\n" ); return E_NOTIMPL; } static HRESULT WINAPI OleControlSite_TransformCoords( IOleControlSite* This, POINTL* pPtlHimetric, POINTF* pPtfContainer, DWORD dwFlags) { FIXME( "\n" ); return E_NOTIMPL; } static HRESULT WINAPI OleControlSite_TranslateAccelerator( IOleControlSite* This, MSG* pMsg, DWORD grfModifiers) { FIXME( "\n" ); return E_NOTIMPL; } static HRESULT WINAPI OleControlSite_OnFocus( IOleControlSite* This, BOOL fGotFocus) { FIXME( "\n" ); return E_NOTIMPL; } static HRESULT WINAPI OleControlSite_ShowPropertyFrame( IOleControlSite* This) { FIXME( "\n" ); return E_NOTIMPL; } static const IOleClientSiteVtbl OleClientSite_vtbl = { OleClientSite_QueryInterface, OleClientSite_AddRef, OleClientSite_Release, OleClientSite_SaveObject, OleClientSite_GetMoniker, OleClientSite_GetContainer, OleClientSite_ShowObject, OleClientSite_OnShowWindow, OleClientSite_RequestNewObjectLayout }; static const IOleContainerVtbl OleContainer_vtbl = { OleContainer_QueryInterface, OleContainer_AddRef, OleContainer_Release, OleContainer_ParseDisplayName, OleContainer_EnumObjects, OleContainer_LockContainer }; static const IOleInPlaceSiteWindowlessVtbl OleInPlaceSiteWindowless_vtbl = { OleInPlaceSiteWindowless_QueryInterface, OleInPlaceSiteWindowless_AddRef, OleInPlaceSiteWindowless_Release, OleInPlaceSiteWindowless_GetWindow, OleInPlaceSiteWindowless_ContextSensitiveHelp, OleInPlaceSiteWindowless_CanInPlaceActivate, OleInPlaceSiteWindowless_OnInPlaceActivate, OleInPlaceSiteWindowless_OnUIActivate, OleInPlaceSiteWindowless_GetWindowContext, OleInPlaceSiteWindowless_Scroll, OleInPlaceSiteWindowless_OnUIDeactivate, OleInPlaceSiteWindowless_OnInPlaceDeactivate, OleInPlaceSiteWindowless_DiscardUndoState, OleInPlaceSiteWindowless_DeactivateAndUndo, OleInPlaceSiteWindowless_OnPosRectChange, OleInPlaceSiteWindowless_OnInPlaceActivateEx, OleInPlaceSiteWindowless_OnInPlaceDeactivateEx, OleInPlaceSiteWindowless_RequestUIActivate, OleInPlaceSiteWindowless_CanWindowlessActivate, OleInPlaceSiteWindowless_GetCapture, OleInPlaceSiteWindowless_SetCapture, OleInPlaceSiteWindowless_GetFocus, OleInPlaceSiteWindowless_SetFocus, OleInPlaceSiteWindowless_GetDC, OleInPlaceSiteWindowless_ReleaseDC, OleInPlaceSiteWindowless_InvalidateRect, OleInPlaceSiteWindowless_InvalidateRgn, OleInPlaceSiteWindowless_ScrollRect, OleInPlaceSiteWindowless_AdjustRect, OleInPlaceSiteWindowless_OnDefWindowMessage }; static const IOleInPlaceFrameVtbl OleInPlaceFrame_vtbl = { OleInPlaceFrame_QueryInterface, OleInPlaceFrame_AddRef, OleInPlaceFrame_Release, OleInPlaceFrame_GetWindow, OleInPlaceFrame_ContextSensitiveHelp, OleInPlaceFrame_GetBorder, OleInPlaceFrame_RequestBorderSpace, OleInPlaceFrame_SetBorderSpace, OleInPlaceFrame_SetActiveObject, OleInPlaceFrame_InsertMenus, OleInPlaceFrame_SetMenu, OleInPlaceFrame_RemoveMenus, OleInPlaceFrame_SetStatusText, OleInPlaceFrame_EnableModeless, OleInPlaceFrame_TranslateAccelerator }; static const IOleControlSiteVtbl OleControlSite_vtbl = { OleControlSite_QueryInterface, OleControlSite_AddRef, OleControlSite_Release, OleControlSite_OnControlInfoChanged, OleControlSite_LockInPlaceActive, OleControlSite_GetExtendedControl, OleControlSite_TransformCoords, OleControlSite_TranslateAccelerator, OleControlSite_OnFocus, OleControlSite_ShowPropertyFrame }; static void IOCS_OnSize( IOCS* This, LPCRECT rect ) { SIZEL inPix, inHi; This->size = *rect; if ( !This->control ) return; inPix.cx = rect->right - rect->left; inPix.cy = rect->bottom - rect->top; AtlPixelToHiMetric( &inPix, &inHi ); IOleObject_SetExtent( This->control, DVASPECT_CONTENT, &inHi ); if ( This->fInPlace ) { IOleInPlaceObject *wl; if ( SUCCEEDED( IOleObject_QueryInterface( This->control, &IID_IOleInPlaceObject, (void**)&wl ) ) ) { IOleInPlaceObject_SetObjectRects( wl, rect, rect ); IOleInPlaceObject_Release( wl ); } } } static void IOCS_OnShow( IOCS *This, BOOL fShow ) { if (!This->control || This->fActive || !fShow ) return; This->fActive = TRUE; } static void IOCS_OnDraw( IOCS *This ) { IViewObject *view; if ( !This->control || !This->fWindowless ) return; if ( SUCCEEDED( IOleObject_QueryInterface( This->control, &IID_IViewObject, (void**)&view ) ) ) { HDC dc = GetDC( This->hWnd ); RECTL rect; rect.left = This->size.left; rect.top = This->size.top; rect.bottom = This->size.bottom; rect.right = This->size.right; IViewObject_Draw( view, DVASPECT_CONTENT, ~0, NULL, NULL, 0, dc, &rect, &rect, NULL, 0 ); IViewObject_Release( view ); ReleaseDC( This->hWnd, dc ); } } static LRESULT IOCS_OnWndProc( IOCS *This, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { WNDPROC OrigWndProc = This->OrigWndProc; switch( uMsg ) { case WM_DESTROY: IOCS_Detach( This ); break; case WM_SIZE: { RECT r; SetRect(&r, 0, 0, LOWORD(lParam), HIWORD(lParam)); IOCS_OnSize( This, &r ); } break; case WM_SHOWWINDOW: IOCS_OnShow( This, (BOOL) wParam ); break; case WM_PAINT: IOCS_OnDraw( This ); break; } return CallWindowProcW( OrigWndProc, hWnd, uMsg, wParam, lParam ); } static LRESULT CALLBACK AtlHost_wndproc( HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam ) { IOCS *This = (IOCS*) GetPropW( hWnd, wine_atl_iocsW ); return IOCS_OnWndProc( This, hWnd, wMsg, wParam, lParam ); } static HRESULT IOCS_Attach( IOCS *This, HWND hWnd, IUnknown *pUnkControl ) /* subclass hWnd */ { This->hWnd = hWnd; IUnknown_QueryInterface( pUnkControl, &IID_IOleObject, (void**)&This->control ); IOleObject_SetClientSite( This->control, &This->IOleClientSite_iface ); SetPropW( hWnd, wine_atl_iocsW, This ); This->OrigWndProc = (WNDPROC)SetWindowLongPtrW( hWnd, GWLP_WNDPROC, (ULONG_PTR) AtlHost_wndproc ); return S_OK; } static HRESULT IOCS_Init( IOCS *This ) { RECT rect; static const WCHAR AXWIN[] = {'A','X','W','I','N',0}; IOleObject_SetHostNames( This->control, AXWIN, AXWIN ); GetClientRect( This->hWnd, &rect ); IOCS_OnSize( This, &rect ); IOleObject_DoVerb( This->control, OLEIVERB_INPLACEACTIVATE, NULL, &This->IOleClientSite_iface, 0, This->hWnd, &rect ); return S_OK; } /********************************************************************** * Create new instance of Atl host component and attach it to window * */ static HRESULT IOCS_Create( HWND hWnd, IUnknown *pUnkControl, IUnknown **container ) { HRESULT hr; IOCS *This; if (!container) return S_OK; *container = NULL; This = HeapAlloc(GetProcessHeap(), 0, sizeof(IOCS)); if (!This) return E_OUTOFMEMORY; This->IOleClientSite_iface.lpVtbl = &OleClientSite_vtbl; This->IOleContainer_iface.lpVtbl = &OleContainer_vtbl; This->IOleInPlaceSiteWindowless_iface.lpVtbl = &OleInPlaceSiteWindowless_vtbl; This->IOleInPlaceFrame_iface.lpVtbl = &OleInPlaceFrame_vtbl; This->IOleControlSite_iface.lpVtbl = &OleControlSite_vtbl; This->ref = 1; This->OrigWndProc = NULL; This->hWnd = NULL; This->fWindowless = This->fActive = This->fInPlace = FALSE; hr = IOCS_Attach( This, hWnd, pUnkControl ); if ( SUCCEEDED( hr ) ) hr = IOCS_Init( This ); if ( SUCCEEDED( hr ) ) *container = (IUnknown*)&This->IOleClientSite_iface; else { IOCS_Detach( This ); HeapFree(GetProcessHeap(), 0, This); } return hr; } /*********************************************************************** * AtlAxCreateControl [atl100.@] */ HRESULT WINAPI AtlAxCreateControl(LPCOLESTR lpszName, HWND hWnd, IStream *pStream, IUnknown **ppUnkContainer) { return AtlAxCreateControlEx( lpszName, hWnd, pStream, ppUnkContainer, NULL, NULL, NULL ); } enum content { IsEmpty = 0, IsGUID = 1, IsHTML = 2, IsURL = 3, IsUnknown = 4 }; static enum content get_content_type(LPCOLESTR name, CLSID *control_id) { WCHAR new_urlW[MAX_PATH]; DWORD size = MAX_PATH; WCHAR mshtml_prefixW[] = {'m','s','h','t','m','l',':','\0'}; if (!name || !name[0]) { WARN("name %s\n", wine_dbgstr_w(name)); return IsEmpty; } if (CLSIDFromString(name, control_id) == S_OK || CLSIDFromProgID(name, control_id) == S_OK) return IsGUID; if (PathIsURLW (name) || UrlApplySchemeW(name, new_urlW, &size, URL_APPLY_GUESSSCHEME|URL_APPLY_GUESSFILE) == S_OK) { *control_id = CLSID_WebBrowser; return IsURL; } if (!strncmpiW(name, mshtml_prefixW, 7)) { FIXME("mshtml prefix not implemented\n"); *control_id = CLSID_WebBrowser; return IsHTML; } return IsUnknown; } /*********************************************************************** * AtlAxCreateControlLicEx [atl100.@] * * REMARKS * See http://www.codeproject.com/com/cwebpage.asp for some background * */ HRESULT WINAPI AtlAxCreateControlLicEx(LPCOLESTR lpszName, HWND hWnd, IStream *pStream, IUnknown **ppUnkContainer, IUnknown **ppUnkControl, REFIID iidSink, IUnknown *punkSink, BSTR lic) { CLSID controlId; HRESULT hRes; IOleObject *pControl; IUnknown *pUnkControl = NULL; IPersistStreamInit *pPSInit; IUnknown *pContainer = NULL; enum content content; TRACE("(%s %p %p %p %p %p %p %s)\n", debugstr_w(lpszName), hWnd, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink, debugstr_w(lic)); if (lic) FIXME("semi stub\n"); if (ppUnkContainer) *ppUnkContainer = NULL; if (ppUnkControl) *ppUnkControl = NULL; content = get_content_type(lpszName, &controlId); if (content == IsEmpty) return S_OK; if (content == IsUnknown) return CO_E_CLASSSTRING; hRes = CoCreateInstance( &controlId, 0, CLSCTX_ALL, &IID_IOleObject, (void**) &pControl ); if ( FAILED( hRes ) ) { WARN( "cannot create ActiveX control %s instance - error 0x%08x\n", debugstr_guid( &controlId ), hRes ); return hRes; } hRes = IOleObject_QueryInterface( pControl, &IID_IPersistStreamInit, (void**) &pPSInit ); if ( SUCCEEDED( hRes ) ) { if (!pStream) IPersistStreamInit_InitNew( pPSInit ); else IPersistStreamInit_Load( pPSInit, pStream ); IPersistStreamInit_Release( pPSInit ); } else WARN("cannot get IID_IPersistStreamInit out of control\n"); IOleObject_QueryInterface( pControl, &IID_IUnknown, (void**) &pUnkControl ); IOleObject_Release( pControl ); hRes = AtlAxAttachControl( pUnkControl, hWnd, &pContainer ); if ( FAILED( hRes ) ) WARN("cannot attach control to window\n"); if ( content == IsURL ) { IWebBrowser2 *browser; hRes = IOleObject_QueryInterface( pControl, &IID_IWebBrowser2, (void**) &browser ); if ( !browser ) WARN( "Cannot query IWebBrowser2 interface: %08x\n", hRes ); else { VARIANT url; IWebBrowser2_put_Visible( browser, VARIANT_TRUE ); /* it seems that native does this on URL (but do not on MSHTML:! why? */ V_VT(&url) = VT_BSTR; V_BSTR(&url) = SysAllocString( lpszName ); hRes = IWebBrowser2_Navigate2( browser, &url, NULL, NULL, NULL, NULL ); if ( FAILED( hRes ) ) WARN( "IWebBrowser2::Navigate2 failed: %08x\n", hRes ); SysFreeString( V_BSTR(&url) ); IWebBrowser2_Release( browser ); } } if (ppUnkContainer) { *ppUnkContainer = pContainer; if ( pContainer ) IUnknown_AddRef( pContainer ); } if (ppUnkControl) { *ppUnkControl = pUnkControl; if ( pUnkControl ) IUnknown_AddRef( pUnkControl ); } if ( pUnkControl ) IUnknown_Release( pUnkControl ); if ( pContainer ) IUnknown_Release( pContainer ); return S_OK; } /*********************************************************************** * AtlAxAttachControl [atl100.@] */ HRESULT WINAPI AtlAxAttachControl(IUnknown *control, HWND hWnd, IUnknown **container) { HRESULT hr; TRACE("(%p %p %p)\n", control, hWnd, container); if (!control) return E_INVALIDARG; hr = IOCS_Create( hWnd, control, container ); return hWnd ? hr : S_FALSE; } /********************************************************************** * Helper function for AX_ConvertDialogTemplate */ static inline BOOL advance_array(WORD **pptr, DWORD *palloc, DWORD *pfilled, const WORD *data, DWORD size) { if ( (*pfilled + size) > *palloc ) { *palloc = ((*pfilled+size) + 0xFF) & ~0xFF; *pptr = HeapReAlloc( GetProcessHeap(), 0, *pptr, *palloc * sizeof(WORD) ); if (!*pptr) return FALSE; } RtlMoveMemory( *pptr+*pfilled, data, size * sizeof(WORD) ); *pfilled += size; return TRUE; } /********************************************************************** * Convert ActiveX control templates to AtlAxWin class instances */ static LPDLGTEMPLATEW AX_ConvertDialogTemplate(LPCDLGTEMPLATEW src_tmpl) { #define GET_WORD(x) (*(const WORD *)(x)) #define GET_DWORD(x) (*(const DWORD *)(x)) #define PUT_BLOCK(x,y) do {if (!advance_array(&output, &allocated, &filled, (x), (y))) return NULL;} while (0) #define PUT_WORD(x) do {WORD w = (x);PUT_BLOCK(&w, 1);} while(0) const WORD *tmp, *src = (const WORD *)src_tmpl; WORD *output; DWORD allocated, filled; /* in WORDs */ BOOL ext; WORD signature, dlgver, rescount; DWORD style; filled = 0; allocated = 256; output = HeapAlloc( GetProcessHeap(), 0, allocated * sizeof(WORD) ); if (!output) return NULL; /* header */ tmp = src; signature = GET_WORD(src); dlgver = GET_WORD(src + 1); if (signature == 1 && dlgver == 0xFFFF) { ext = TRUE; src += 6; style = GET_DWORD(src); src += 2; rescount = GET_WORD(src++); src += 4; if ( GET_WORD(src) == 0xFFFF ) /* menu */ src += 2; else src += strlenW(src) + 1; if ( GET_WORD(src) == 0xFFFF ) /* class */ src += 2; else src += strlenW(src) + 1; src += strlenW(src) + 1; /* title */ if ( style & (DS_SETFONT | DS_SHELLFONT) ) { src += 3; src += strlenW(src) + 1; } } else { ext = FALSE; style = GET_DWORD(src); src += 4; rescount = GET_WORD(src++); src += 4; if ( GET_WORD(src) == 0xFFFF ) /* menu */ src += 2; else src += strlenW(src) + 1; if ( GET_WORD(src) == 0xFFFF ) /* class */ src += 2; else src += strlenW(src) + 1; src += strlenW(src) + 1; /* title */ if ( style & DS_SETFONT ) { src++; src += strlenW(src) + 1; } } PUT_BLOCK(tmp, src-tmp); while(rescount--) { src = (const WORD *)( ( ((ULONG_PTR)src) + 3) & ~3); /* align on DWORD boundary */ filled = (filled + 1) & ~1; /* depends on DWORD-aligned allocation unit */ tmp = src; if (ext) src += 12; else src += 9; PUT_BLOCK(tmp, src-tmp); tmp = src; if ( GET_WORD(src) == 0xFFFF ) /* class */ { src += 2; } else { src += strlenW(src) + 1; } src += strlenW(src) + 1; /* title */ if ( GET_WORD(tmp) == '{' ) /* all this mess created because of this line */ { static const WCHAR AtlAxWin[] = {'A','t','l','A','x','W','i','n', 0}; PUT_BLOCK(AtlAxWin, sizeof(AtlAxWin)/sizeof(WCHAR)); PUT_BLOCK(tmp, strlenW(tmp)+1); } else PUT_BLOCK(tmp, src-tmp); if ( GET_WORD(src) ) { WORD size = (GET_WORD(src)+sizeof(WORD)-1) / sizeof(WORD); /* quite ugly :( Maybe use BYTE* instead of WORD* everywhere ? */ PUT_BLOCK(src, size); src+=size; } else { PUT_WORD(0); src++; } } return (LPDLGTEMPLATEW) output; } /*********************************************************************** * AtlAxCreateDialogA [atl100.@] * * Creates a dialog window * * PARAMS * hInst [I] Application instance * name [I] Dialog box template name * owner [I] Dialog box parent HWND * dlgProc [I] Dialog box procedure * param [I] This value will be passed to dlgProc as WM_INITDIALOG's message lParam * * RETURNS * Window handle of dialog window. */ HWND WINAPI AtlAxCreateDialogA(HINSTANCE hInst, LPCSTR name, HWND owner, DLGPROC dlgProc ,LPARAM param) { HWND res = NULL; int length; WCHAR *nameW; if (IS_INTRESOURCE(name)) return AtlAxCreateDialogW( hInst, (LPCWSTR) name, owner, dlgProc, param ); length = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 ); nameW = HeapAlloc( GetProcessHeap(), 0, length * sizeof(WCHAR) ); if (nameW) { MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, length ); res = AtlAxCreateDialogW( hInst, nameW, owner, dlgProc, param ); HeapFree( GetProcessHeap(), 0, nameW ); } return res; } /*********************************************************************** * AtlAxCreateDialogW [atl100.@] * * See AtlAxCreateDialogA * */ HWND WINAPI AtlAxCreateDialogW(HINSTANCE hInst, LPCWSTR name, HWND owner, DLGPROC dlgProc ,LPARAM param) { HRSRC hrsrc; HGLOBAL hgl; LPCDLGTEMPLATEW ptr; LPDLGTEMPLATEW newptr; HWND res; TRACE("(%p %s %p %p %lx)\n", hInst, debugstr_w(name), owner, dlgProc, param); hrsrc = FindResourceW( hInst, name, (LPWSTR)RT_DIALOG ); if ( !hrsrc ) return NULL; hgl = LoadResource (hInst, hrsrc); if ( !hgl ) return NULL; ptr = LockResource ( hgl ); if (!ptr) { FreeResource( hgl ); return NULL; } newptr = AX_ConvertDialogTemplate( ptr ); if ( newptr ) { res = CreateDialogIndirectParamW( hInst, newptr, owner, dlgProc, param ); HeapFree( GetProcessHeap(), 0, newptr ); } else res = NULL; FreeResource ( hrsrc ); return res; } /*********************************************************************** * AtlAxGetHost [atl100.@] * */ HRESULT WINAPI AtlAxGetHost(HWND hWnd, IUnknown **host) { IOCS *This; TRACE("(%p, %p)\n", hWnd, host); *host = NULL; This = (IOCS*) GetPropW( hWnd, wine_atl_iocsW ); if ( !This ) { WARN("No container attached to %p\n", hWnd ); return E_FAIL; } return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, &IID_IUnknown, (void**)host); } /*********************************************************************** * AtlAxGetControl [atl100.@] * */ HRESULT WINAPI AtlAxGetControl(HWND hWnd, IUnknown **pUnk) { IOCS *This; TRACE( "(%p, %p)\n", hWnd, pUnk ); *pUnk = NULL; This = (IOCS*) GetPropW( hWnd, wine_atl_iocsW ); if ( !This || !This->control ) { WARN("No control attached to %p\n", hWnd ); return E_FAIL; } return IOleObject_QueryInterface( This->control, &IID_IUnknown, (void**) pUnk ); } /*********************************************************************** * AtlAxDialogBoxW [atl100.35] * */ INT_PTR WINAPI AtlAxDialogBoxW(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam) { FIXME("(%p %s %p %p %lx)\n", hInstance, debugstr_w(lpTemplateName), hWndParent, lpDialogProc, dwInitParam); return 0; } /*********************************************************************** * AtlAxDialogBoxA [atl100.36] * */ INT_PTR WINAPI AtlAxDialogBoxA(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam) { FIXME("(%p %s %p %p %lx)\n", hInstance, debugstr_a(lpTemplateName), hWndParent, lpDialogProc, dwInitParam); return 0; } /*********************************************************************** * AtlAxCreateControlLic [atl100.59] * */ HRESULT WINAPI AtlAxCreateControlLic(const WCHAR *lpTricsData, HWND hwnd, IStream *stream, IUnknown **container, BSTR lic) { return AtlAxCreateControlLicEx(lpTricsData, hwnd, stream, container, NULL, NULL, NULL, lic); } /*********************************************************************** * AtlAxCreateControlEx [atl100.@] * */ HRESULT WINAPI AtlAxCreateControlEx(const WCHAR *lpTricsData, HWND hwnd, IStream *stream, IUnknown **container, IUnknown **control, REFIID iidSink, IUnknown *punkSink) { return AtlAxCreateControlLicEx(lpTricsData, hwnd, stream, container, control, iidSink, punkSink, NULL); }