atl: Host component implementation: IOleContainer.
[wine/wine64.git] / dlls / atl / atl_ax.c
blobfc7124d0f3e927e03dbcef87e953f45bbbb65a70
1 /*
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
21 #include <stdarg.h>
22 #include <stdio.h>
24 #define COBJMACROS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winerror.h"
30 #include "winuser.h"
31 #include "wine/debug.h"
32 #include "objbase.h"
33 #include "objidl.h"
34 #include "ole2.h"
35 #include "exdisp.h"
36 #include "atlbase.h"
37 #include "atliface.h"
38 #include "atlwin.h"
40 #include "wine/unicode.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(atl);
44 typedef struct IOCS {
45 const IOleClientSiteVtbl *lpOleClientSiteVtbl;
46 const IOleContainerVtbl *lpOleContainerVtbl;
48 LONG ref;
49 HWND hWnd;
50 IOleObject *control;
51 WNDPROC OrigWndProc;
52 } IOCS;
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) );
63 if (!ptr)
64 return 1;
65 GetWindowTextW( hWnd, ptr, len );
66 AtlAxCreateControlEx( ptr, hWnd, NULL, NULL, NULL, NULL, NULL );
67 HeapFree( GetProcessHeap(), 0, ptr );
68 return 0;
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.
78 * RETURNS
79 * TRUE or FALSE
82 BOOL WINAPI AtlAxWinInit(void)
84 WNDCLASSEXW wcex;
85 const WCHAR AtlAxWin[] = {'A','t','l','A','x','W','i','n',0};
87 FIXME("semi-stub\n");
89 if ( FAILED( OleInitialize(NULL) ) )
90 return FALSE;
92 wcex.cbSize = sizeof(wcex);
93 wcex.style = 0;
94 wcex.cbClsExtra = 0;
95 wcex.cbWndExtra = 0;
96 wcex.hInstance = GetModuleHandleW( NULL );
97 wcex.hIcon = NULL;
98 wcex.hCursor = NULL;
99 wcex.hbrBackground = NULL;
100 wcex.lpszMenuName = NULL;
101 wcex.hIconSm = 0;
103 wcex.lpfnWndProc = AtlAxWin_wndproc;
104 wcex.lpszClassName = AtlAxWin;
105 if ( !RegisterClassExW( &wcex ) )
106 return FALSE;
108 return TRUE;
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 );
122 return ref;
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)
130 *ppv = NULL;
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);
141 if (*ppv)
143 IOCS_AddRef( This );
144 return S_OK;
147 WARN("unsupported interface %s\n", debugstr_guid( riid ) );
148 *ppv = NULL;
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 );
159 if (!ref)
161 IOCS_Detach( This );
162 HeapFree( GetProcessHeap(), 0, This );
165 return ref;
168 #define DEFINE_THIS(cls,ifc,iface) ((cls*)((BYTE*)(iface)-offsetof(cls,lp ## ifc ## Vtbl)))
170 /****** IOleClientSite *****/
171 #undef IFACE2THIS
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 );
192 return E_NOTIMPL;
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 );
199 return E_NOTIMPL;
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 );
211 return S_OK;
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" );
217 return E_NOTIMPL;
219 static HRESULT WINAPI OleClientSite_RequestNewObjectLayout(IOleClientSite *iface)
221 IOCS *This = IFACE2THIS(iface);
222 FIXME( "(%p) - stub\n", This );
223 return E_NOTIMPL;
225 #undef IFACE2THIS
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 );
250 return E_NOTIMPL;
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 );
256 return E_NOTIMPL;
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" );
262 return E_NOTIMPL;
264 #undef IFACE2THIS
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,
281 OleContainer_AddRef,
282 OleContainer_Release,
283 OleContainer_ParseDisplayName,
284 OleContainer_EnumObjects,
285 OleContainer_LockContainer
288 static HRESULT IOCS_Detach( IOCS *This ) /* remove subclassing */
290 if ( This->hWnd )
292 SetWindowLongPtrW( This->hWnd, GWLP_WNDPROC, (ULONG_PTR) This->OrigWndProc );
293 SetWindowLongPtrW( This->hWnd, GWLP_USERDATA, (LONG_PTR) NULL );
294 This->hWnd = NULL;
296 if ( This->control )
298 IOleObject *control = This->control;
300 This->control = NULL;
301 IOleObject_SetClientSite( control, NULL );
302 IOleObject_Release( control );
304 return S_OK;
307 static void IOCS_OnSize( IOCS* This, LPCRECT rect )
309 SIZEL inPix, inHi;
311 if ( !This->control )
312 return;
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;
324 switch( uMsg )
326 case WM_DESTROY:
327 IOCS_Detach( This );
328 break;
329 case WM_SIZE:
331 RECT r;
332 r.left = r.top = 0;
333 r.right = LOWORD( lParam );
334 r.bottom = HIWORD( lParam );
335 IOCS_OnSize( This, &r );
337 break;
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 */
351 This->hWnd = 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 );
358 return S_OK;
361 static HRESULT IOCS_Init( IOCS *This )
363 RECT rect;
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 );
371 return S_OK;
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 )
379 HRESULT hr;
380 IOCS *This;
382 *ppSite = NULL;
383 This = HeapAlloc(GetProcessHeap(), 0, sizeof(IOCS));
385 if (!This)
386 return E_OUTOFMEMORY;
388 This->lpOleClientSiteVtbl = &OleClientSite_vtbl;
389 This->lpOleContainerVtbl = &OleContainer_vtbl;
390 This->ref = 1;
392 This->OrigWndProc = NULL;
393 This->hWnd = NULL;
395 hr = IOCS_Attach( This, hWnd, pUnkControl );
396 if ( SUCCEEDED( hr ) )
397 hr = IOCS_Init( This );
398 if ( SUCCEEDED( hr ) )
399 *ppSite = This;
400 else
401 IOCS_Release( This );
403 return hr;
407 /***********************************************************************
408 * AtlAxCreateControl [ATL.@]
410 HRESULT WINAPI AtlAxCreateControl(LPCOLESTR lpszName, HWND hWnd,
411 IStream *pStream, IUnknown **ppUnkContainer)
413 return AtlAxCreateControlEx( lpszName, hWnd, pStream, ppUnkContainer,
414 NULL, NULL, NULL );
417 /***********************************************************************
418 * AtlAxCreateControlEx [ATL.@]
420 * REMARKS
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)
428 CLSID controlId;
429 HRESULT hRes;
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 );
440 if ( FAILED(hRes) )
441 hRes = CLSIDFromProgID( lpszName, &controlId );
442 if ( SUCCEEDED( hRes ) )
443 content = IsGUID;
444 else {
445 /* FIXME - check for MSHTML: prefix! */
446 content = IsURL;
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 );
456 return hRes;
459 hRes = IOleObject_QueryInterface( pControl, &IID_IPersistStreamInit, (void**) &pPSInit );
460 if ( SUCCEEDED( hRes ) )
462 if (!pStream)
463 IPersistStreamInit_InitNew( pPSInit );
464 else
465 IPersistStreamInit_Load( pPSInit, pStream );
466 IPersistStreamInit_Release( pPSInit );
467 } else
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 );
483 if ( !browser )
484 WARN( "Cannot query IWebBrowser2 interface: %08x\n", hRes );
485 else {
486 VARIANT url;
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 );
502 if (ppUnkContainer)
504 *ppUnkContainer = pContainer;
505 if ( pContainer )
506 IUnknown_AddRef( pContainer );
508 if (ppUnkControl)
510 *ppUnkControl = pUnkControl;
511 if ( pUnkControl )
512 IUnknown_AddRef( pUnkControl );
515 IUnknown_Release( pUnkControl );
516 if ( pContainer )
517 IUnknown_Release( pContainer );
519 return S_OK;
522 /***********************************************************************
523 * AtlAxAttachControl [ATL.@]
525 HRESULT WINAPI AtlAxAttachControl(IUnknown* pControl, HWND hWnd, IUnknown** ppUnkContainer)
527 IOCS *pUnkContainer;
528 HRESULT hr;
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;
540 return hr;
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) );
552 if (!*pptr)
553 return FALSE;
555 RtlMoveMemory( *pptr+*pfilled, data, size * sizeof(WORD) );
556 *pfilled += size;
557 return TRUE;
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;
571 WORD *output;
572 DWORD allocated, filled; /* in WORDs */
573 BOOL ext;
574 WORD signature, dlgver, rescount;
575 DWORD style;
577 filled = 0; allocated = 256;
578 output = HeapAlloc( GetProcessHeap(), 0, allocated * sizeof(WORD) );
579 if (!output)
580 return NULL;
582 /* header */
583 tmp = src;
584 signature = GET_WORD(src);
585 dlgver = GET_WORD(src + 1);
586 if (signature == 1 && dlgver == 0xFFFF)
588 ext = TRUE;
589 src += 6;
590 style = GET_DWORD(src);
591 src += 2;
592 rescount = GET_WORD(src++);
593 src += 4;
594 if ( GET_WORD(src) == 0xFFFF ) /* menu */
595 src += 2;
596 else
597 src += strlenW(src) + 1;
598 if ( GET_WORD(src) == 0xFFFF ) /* class */
599 src += 2;
600 else
601 src += strlenW(src) + 1;
602 src += strlenW(src) + 1; /* title */
603 if ( style & (DS_SETFONT | DS_SHELLFONT) )
605 src += 3;
606 src += strlenW(src) + 1;
608 } else {
609 ext = FALSE;
610 style = GET_DWORD(src);
611 src += 4;
612 rescount = GET_WORD(src++);
613 src += 4;
614 if ( GET_WORD(src) == 0xFFFF ) /* menu */
615 src += 2;
616 else
617 src += strlenW(src) + 1;
618 if ( GET_WORD(src) == 0xFFFF ) /* class */
619 src += 2;
620 else
621 src += strlenW(src) + 1;
622 src += strlenW(src) + 1; /* title */
623 if ( style & DS_SETFONT )
625 src++;
626 src += strlenW(src) + 1;
629 PUT_BLOCK(tmp, src-tmp);
631 while(rescount--)
633 src = (const WORD *)( ( ((ULONG)src) + 3) & ~3); /* align on DWORD boundary */
634 filled = (filled + 1) & ~1; /* depends on DWORD-aligned allocation unit */
636 tmp = src;
637 if (ext)
638 src += 11;
639 else
640 src += 9;
641 PUT_BLOCK(tmp, src-tmp);
643 tmp = src;
644 if ( GET_WORD(src) == 0xFFFF ) /* class */
646 src += 2;
647 } else
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);
657 } else
658 PUT_BLOCK(tmp, src-tmp);
660 if ( GET_WORD(src) )
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);
664 src+=size;
666 else
668 PUT_WORD(0);
669 src++;
672 return (LPDLGTEMPLATEW) output;
675 /***********************************************************************
676 * AtlAxCreateDialogA [ATL.@]
678 * Creates a dialog window
680 * PARAMS
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
687 * RETURNS
688 * Window handle of dialog window.
690 HWND WINAPI AtlAxCreateDialogA(HINSTANCE hInst, LPCSTR name, HWND owner, DLGPROC dlgProc ,LPARAM param)
692 HWND res = NULL;
693 int length;
694 WCHAR *nameW;
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) );
701 if (nameW)
703 MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, length );
704 res = AtlAxCreateDialogW( hInst, nameW, owner, dlgProc, param );
705 HeapFree( GetProcessHeap(), 0, nameW );
707 return res;
710 /***********************************************************************
711 * AtlAxCreateDialogW [ATL.@]
713 * See AtlAxCreateDialogA
716 HWND WINAPI AtlAxCreateDialogW(HINSTANCE hInst, LPCWSTR name, HWND owner, DLGPROC dlgProc ,LPARAM param)
718 HRSRC hrsrc;
719 HGLOBAL hgl;
720 LPCDLGTEMPLATEW ptr;
721 LPDLGTEMPLATEW newptr;
722 HWND res;
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 );
727 if ( !hrsrc )
728 return NULL;
729 hgl = LoadResource (hInst, hrsrc);
730 if ( !hgl )
731 return NULL;
732 ptr = (LPCDLGTEMPLATEW)LockResource ( hgl );
733 if (!ptr)
735 FreeResource( hgl );
736 return NULL;
738 newptr = AX_ConvertDialogTemplate( ptr );
739 if ( newptr )
741 res = CreateDialogIndirectParamW( hInst, newptr, owner, dlgProc, param );
742 HeapFree( GetProcessHeap(), 0, newptr );
743 } else
744 res = NULL;
745 FreeResource ( hrsrc );
746 return res;