diff --git a/dlls/atl/atl.spec b/dlls/atl/atl.spec index db9ca9afc68..12d5a194eb0 100644 --- a/dlls/atl/atl.spec +++ b/dlls/atl/atl.spec @@ -28,8 +28,8 @@ 34 stub AtlGetVersion 35 stub AtlAxDialogBoxW 36 stub AtlAxDialogBoxA -37 stub AtlAxCreateDialogW -38 stub AtlAxCreateDialogA +37 stdcall AtlAxCreateDialogW(long wstr long ptr long) +38 stdcall AtlAxCreateDialogA(long str long ptr long) 39 stdcall AtlAxCreateControl(ptr ptr ptr ptr) 40 stdcall AtlAxCreateControlEx(ptr ptr ptr ptr ptr ptr ptr) 41 stub AtlAxAttachControl diff --git a/dlls/atl/atl_ax.c b/dlls/atl/atl_ax.c index 1170cb82855..bb393f12631 100644 --- a/dlls/atl/atl_ax.c +++ b/dlls/atl/atl_ax.c @@ -221,3 +221,209 @@ HRESULT WINAPI AtlAxAttachControl(IUnknown* pControl, HWND hWnd, IUnknown** ppUn FIXME( "(%p %p %p) - stub\n", pControl, hWnd, ppUnkContainer ); return E_NOTIMPL; } + +/********************************************************************** + * 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) +#define PUT_DWORD(x) do {DWORD w = (x);PUT_BLOCK(&w, 2);} 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)src) + 3) & ~3); /* align on DWORD boundary */ + filled = (filled + 1) & ~1; /* depends on DWORD-aligned allocation unit */ + + tmp = src; + if (ext) + src += 11; + 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 */ + { + const WCHAR AtlAxWin[9]={'A','t','l','A','x','W','i','n',0}; + PUT_BLOCK(AtlAxWin, sizeof(AtlAxWin)/sizeof(WORD)); + 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 [ATL.@] + * + * 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 ( HIWORD(name) == 0 ) + 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 [ATL.@] + * + * 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; + + FIXME("(%p %s %p %p %lx) - not tested\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 = (LPCDLGTEMPLATEW)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; +} diff --git a/dlls/atl/atliface.idl b/dlls/atl/atliface.idl index 884d187331d..bb5cb2e7aa6 100644 --- a/dlls/atl/atliface.idl +++ b/dlls/atl/atliface.idl @@ -73,3 +73,7 @@ cpp_quote("DEFINE_GUID(CLSID_ATLRegistrar,0x44ec053a,0x400f,0x11d0,0x9d,0xcd,0x0 cpp_quote("HRESULT WINAPI AtlAxCreateControl(LPCOLESTR,HWND,IStream*,IUnknown**);") cpp_quote("HRESULT WINAPI AtlAxCreateControlEx(LPCOLESTR,HWND,IStream*,IUnknown**,IUnknown**,REFIID,IUnknown*);") cpp_quote("BOOL WINAPI AtlAxWinInit(void);") + +cpp_quote("HWND WINAPI AtlAxCreateDialogW(HINSTANCE,LPCWSTR,HWND,DLGPROC,LPARAM);"); +cpp_quote("HWND WINAPI AtlAxCreateDialogA(HINSTANCE,LPCSTR,HWND,DLGPROC,LPARAM);"); +cpp_quote("#define AtlAxCreateDialog WINELIB_NAME_AW(AtlAxCreateDialog");