/* * Copyright 1999 Corel Corporation * Sean Langley * Copyright 2010 Geoffrey Hausheer * Copyright 2010 Piotr Caban for CodeWeavers * * 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 <stdarg.h> #define COBJMACROS #define NONAMELESSUNION #define NONAMELESSSTRUCT #include "windef.h" #include "winbase.h" #include "wingdi.h" #include "ole2.h" #include "olectl.h" #include "oledlg.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); typedef struct { IPropertyPageSite IPropertyPageSite_iface; LCID lcid; LONG ref; } PropertyPageSite; static inline PropertyPageSite *impl_from_IPropertyPageSite(IPropertyPageSite *iface) { return CONTAINING_RECORD(iface, PropertyPageSite, IPropertyPageSite_iface); } static INT_PTR CALLBACK property_sheet_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { IPropertyPage *property_page = (IPropertyPage*)GetWindowLongPtrW(hwnd, DWLP_USER); switch(msg) { case WM_INITDIALOG: { RECT rect; property_page = (IPropertyPage*)((LPPROPSHEETPAGEW)lparam)->lParam; GetClientRect(hwnd, &rect); IPropertyPage_Activate(property_page, hwnd, &rect, TRUE); IPropertyPage_Show(property_page, SW_SHOW); SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR)property_page); return FALSE; } case WM_DESTROY: IPropertyPage_Show(property_page, SW_HIDE); IPropertyPage_Deactivate(property_page); return FALSE; default: return FALSE; } } static HRESULT WINAPI PropertyPageSite_QueryInterface(IPropertyPageSite* iface, REFIID riid, void** ppv) { TRACE("(%p riid: %s)\n",iface, debugstr_guid(riid)); if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IPropertyPageSite, riid)) *ppv = iface; else { *ppv = NULL; return E_NOINTERFACE; } IUnknown_AddRef((IUnknown*)*ppv); return S_OK; } static ULONG WINAPI PropertyPageSite_AddRef(IPropertyPageSite* iface) { PropertyPageSite *this = impl_from_IPropertyPageSite(iface); LONG ref = InterlockedIncrement(&this->ref); TRACE("(%p) ref=%d\n", this, ref); return ref; } static ULONG WINAPI PropertyPageSite_Release(IPropertyPageSite* iface) { PropertyPageSite *this = impl_from_IPropertyPageSite(iface); LONG ref = InterlockedDecrement(&this->ref); TRACE("(%p) ref=%d\n", this, ref); if(!ref) HeapFree(GetProcessHeap(), 0, this); return ref; } static HRESULT WINAPI PropertyPageSite_OnStatusChange( IPropertyPageSite *iface, DWORD dwFlags) { TRACE("(%p, %x)\n", iface, dwFlags); return S_OK; } static HRESULT WINAPI PropertyPageSite_GetLocaleID( IPropertyPageSite *iface, LCID *pLocaleID) { PropertyPageSite *this = impl_from_IPropertyPageSite(iface); TRACE("(%p, %p)\n", iface, pLocaleID); *pLocaleID = this->lcid; return S_OK; } static HRESULT WINAPI PropertyPageSite_GetPageContainer( IPropertyPageSite* iface, IUnknown** ppUnk) { FIXME("(%p, %p)\n", iface, ppUnk); return E_NOTIMPL; } static HRESULT WINAPI PropertyPageSite_TranslateAccelerator( IPropertyPageSite* iface, MSG *pMsg) { FIXME("(%p, %p)\n", iface, pMsg); return E_NOTIMPL; } IPropertyPageSiteVtbl PropertyPageSiteVtbl = { PropertyPageSite_QueryInterface, PropertyPageSite_AddRef, PropertyPageSite_Release, PropertyPageSite_OnStatusChange, PropertyPageSite_GetLocaleID, PropertyPageSite_GetPageContainer, PropertyPageSite_TranslateAccelerator }; /*********************************************************************** * OleCreatePropertyFrameIndirect (OLEAUT32.416) */ HRESULT WINAPI OleCreatePropertyFrameIndirect(LPOCPFIPARAMS lpParams) { static const WCHAR comctlW[] = { 'c','o','m','c','t','l','3','2','.','d','l','l',0 }; PROPSHEETHEADERW property_sheet; PROPSHEETPAGEW property_sheet_page; struct { DLGTEMPLATE template; WORD menu; WORD class; WORD title; } *dialogs; IPropertyPage **property_page; PropertyPageSite *property_page_site; HRESULT res; int i; HMODULE hcomctl; HRSRC property_sheet_dialog_find = NULL; HGLOBAL property_sheet_dialog_load = NULL; WCHAR *property_sheet_dialog_data = NULL; HDC hdc; LOGFONTW font_desc; HFONT hfont; LONG font_width = 4, font_height = 8; if(!lpParams) return E_POINTER; TRACE("(%d %p %d %d %s %d %p %d %p %d %d)\n", lpParams->cbStructSize, lpParams->hWndOwner, lpParams->x, lpParams->y, debugstr_w(lpParams->lpszCaption), lpParams->cObjects, lpParams->lplpUnk, lpParams->cPages, lpParams->lpPages, lpParams->lcid, lpParams->dispidInitialProperty); if(!lpParams->lplpUnk || !lpParams->lpPages) return E_POINTER; if(lpParams->cbStructSize != sizeof(OCPFIPARAMS)) { WARN("incorrect structure size\n"); return E_INVALIDARG; } if(lpParams->dispidInitialProperty) FIXME("dispidInitialProperty not yet implemented\n"); hdc = GetDC(NULL); hcomctl = LoadLibraryW(comctlW); if(hcomctl) property_sheet_dialog_find = FindResourceW(hcomctl, MAKEINTRESOURCEW(1006 /*IDD_PROPSHEET*/), (LPWSTR)RT_DIALOG); if(property_sheet_dialog_find) property_sheet_dialog_load = LoadResource(hcomctl, property_sheet_dialog_find); if(property_sheet_dialog_load) property_sheet_dialog_data = LockResource(property_sheet_dialog_load); if(property_sheet_dialog_data) { if(property_sheet_dialog_data[1] == 0xffff) { ERR("Expected DLGTEMPLATE structure\n"); return E_OUTOFMEMORY; } property_sheet_dialog_data += sizeof(DLGTEMPLATE)/sizeof(WCHAR); /* Skip menu, class and title */ property_sheet_dialog_data += lstrlenW(property_sheet_dialog_data)+1; property_sheet_dialog_data += lstrlenW(property_sheet_dialog_data)+1; property_sheet_dialog_data += lstrlenW(property_sheet_dialog_data)+1; memset(&font_desc, 0, sizeof(LOGFONTW)); /* Calculate logical height */ font_desc.lfHeight = -MulDiv(property_sheet_dialog_data[0], GetDeviceCaps(hdc, LOGPIXELSY), 72); font_desc.lfCharSet = DEFAULT_CHARSET; memcpy(font_desc.lfFaceName, property_sheet_dialog_data+1, sizeof(WCHAR)*(lstrlenW(property_sheet_dialog_data+1)+1)); hfont = CreateFontIndirectW(&font_desc); if(hfont) { hfont = SelectObject(hdc, hfont); font_width = GdiGetCharDimensions(hdc, NULL, &font_height); SelectObject(hdc, hfont); } } if(hcomctl) FreeLibrary(hcomctl); ReleaseDC(NULL, hdc); memset(&property_sheet, 0, sizeof(property_sheet)); property_sheet.dwSize = sizeof(property_sheet); if(lpParams->lpszCaption) { property_sheet.dwFlags = PSH_PROPTITLE; property_sheet.pszCaption = lpParams->lpszCaption; } property_sheet.u3.phpage = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lpParams->cPages*sizeof(HPROPSHEETPAGE)); property_page = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lpParams->cPages*sizeof(IPropertyPage*)); dialogs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lpParams->cPages*sizeof(*dialogs)); if(!property_sheet.u3.phpage || !property_page || !dialogs) { HeapFree(GetProcessHeap(), 0, property_sheet.u3.phpage); HeapFree(GetProcessHeap(), 0, property_page); HeapFree(GetProcessHeap(), 0, dialogs); return E_OUTOFMEMORY; } memset(&property_sheet_page, 0, sizeof(PROPSHEETPAGEW)); property_sheet_page.dwSize = sizeof(PROPSHEETPAGEW); property_sheet_page.dwFlags = PSP_DLGINDIRECT|PSP_USETITLE; property_sheet_page.pfnDlgProc = property_sheet_proc; for(i=0; i<lpParams->cPages; i++) { PROPPAGEINFO page_info; res = CoCreateInstance(&lpParams->lpPages[i], NULL, CLSCTX_INPROC_SERVER, &IID_IPropertyPage, (void**)&property_page[i]); if(FAILED(res)) continue; property_page_site = HeapAlloc(GetProcessHeap(), 0, sizeof(PropertyPageSite)); if(!property_page_site) continue; property_page_site->IPropertyPageSite_iface.lpVtbl = &PropertyPageSiteVtbl; property_page_site->ref = 1; property_page_site->lcid = lpParams->lcid; res = IPropertyPage_SetPageSite(property_page[i], &property_page_site->IPropertyPageSite_iface); IPropertyPageSite_Release(&property_page_site->IPropertyPageSite_iface); if(FAILED(res)) continue; res = IPropertyPage_SetObjects(property_page[i], lpParams->cObjects, lpParams->lplpUnk); if(FAILED(res)) continue; res = IPropertyPage_GetPageInfo(property_page[i], &page_info); if(FAILED(res)) continue; dialogs[i].template.cx = MulDiv(page_info.size.cx, 4, font_width); dialogs[i].template.cy = MulDiv(page_info.size.cy, 8, font_height); property_sheet_page.u.pResource = &dialogs[i].template; property_sheet_page.lParam = (LPARAM)property_page[i]; property_sheet_page.pszTitle = page_info.pszTitle; property_sheet.u3.phpage[property_sheet.nPages++] = CreatePropertySheetPageW(&property_sheet_page); } PropertySheetW(&property_sheet); for(i=0; i<lpParams->cPages; i++) { if(property_page[i]) { IPropertyPage_SetPageSite(property_page[i], NULL); IPropertyPage_Release(property_page[i]); } } HeapFree(GetProcessHeap(), 0, dialogs); HeapFree(GetProcessHeap(), 0, property_page); HeapFree(GetProcessHeap(), 0, property_sheet.u3.phpage); return S_OK; } /*********************************************************************** * OleCreatePropertyFrame (OLEAUT32.417) */ HRESULT WINAPI OleCreatePropertyFrame( HWND hwndOwner, UINT x, UINT y, LPCOLESTR lpszCaption, ULONG cObjects, LPUNKNOWN* ppUnk, ULONG cPages, LPCLSID pPageClsID, LCID lcid, DWORD dwReserved, LPVOID pvReserved) { OCPFIPARAMS ocpf; ocpf.cbStructSize = sizeof(OCPFIPARAMS); ocpf.hWndOwner = hwndOwner; ocpf.x = x; ocpf.y = y; ocpf.lpszCaption = lpszCaption; ocpf.cObjects = cObjects; ocpf.lplpUnk = ppUnk; ocpf.cPages = cPages; ocpf.lpPages = pPageClsID; ocpf.lcid = lcid; ocpf.dispidInitialProperty = 0; return OleCreatePropertyFrameIndirect(&ocpf); }