1 /* 2 * Copyright 1999 Corel Corporation 3 * Sean Langley 4 * Copyright 2010 Geoffrey Hausheer 5 * Copyright 2010 Piotr Caban for CodeWeavers 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include "precomp.h" 23 24 #include <oledlg.h> 25 26 WINE_DEFAULT_DEBUG_CHANNEL(ole); 27 28 typedef struct { 29 IPropertyPageSite IPropertyPageSite_iface; 30 LCID lcid; 31 LONG ref; 32 } PropertyPageSite; 33 34 static inline PropertyPageSite *impl_from_IPropertyPageSite(IPropertyPageSite *iface) 35 { 36 return CONTAINING_RECORD(iface, PropertyPageSite, IPropertyPageSite_iface); 37 } 38 39 static INT_PTR CALLBACK property_sheet_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 40 { 41 IPropertyPage *property_page = (IPropertyPage*)GetWindowLongPtrW(hwnd, DWLP_USER); 42 43 switch(msg) { 44 case WM_INITDIALOG: { 45 RECT rect; 46 47 property_page = (IPropertyPage*)((LPPROPSHEETPAGEW)lparam)->lParam; 48 49 GetClientRect(hwnd, &rect); 50 IPropertyPage_Activate(property_page, hwnd, &rect, TRUE); 51 IPropertyPage_Show(property_page, SW_SHOW); 52 53 SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR)property_page); 54 return FALSE; 55 } 56 case WM_DESTROY: 57 IPropertyPage_Show(property_page, SW_HIDE); 58 IPropertyPage_Deactivate(property_page); 59 return FALSE; 60 default: 61 return FALSE; 62 } 63 } 64 65 static HRESULT WINAPI PropertyPageSite_QueryInterface(IPropertyPageSite* iface, 66 REFIID riid, void** ppv) 67 { 68 TRACE("(%p riid: %s)\n",iface, debugstr_guid(riid)); 69 70 if(IsEqualGUID(&IID_IUnknown, riid) 71 || IsEqualGUID(&IID_IPropertyPageSite, riid)) 72 *ppv = iface; 73 else { 74 *ppv = NULL; 75 return E_NOINTERFACE; 76 } 77 78 IUnknown_AddRef((IUnknown*)*ppv); 79 return S_OK; 80 } 81 82 static ULONG WINAPI PropertyPageSite_AddRef(IPropertyPageSite* iface) 83 { 84 PropertyPageSite *this = impl_from_IPropertyPageSite(iface); 85 LONG ref = InterlockedIncrement(&this->ref); 86 87 TRACE("(%p) ref=%d\n", this, ref); 88 return ref; 89 } 90 91 static ULONG WINAPI PropertyPageSite_Release(IPropertyPageSite* iface) 92 { 93 PropertyPageSite *this = impl_from_IPropertyPageSite(iface); 94 LONG ref = InterlockedDecrement(&this->ref); 95 96 TRACE("(%p) ref=%d\n", this, ref); 97 if(!ref) 98 HeapFree(GetProcessHeap(), 0, this); 99 return ref; 100 } 101 102 static HRESULT WINAPI PropertyPageSite_OnStatusChange( 103 IPropertyPageSite *iface, DWORD dwFlags) 104 { 105 TRACE("(%p, %x)\n", iface, dwFlags); 106 return S_OK; 107 } 108 109 static HRESULT WINAPI PropertyPageSite_GetLocaleID( 110 IPropertyPageSite *iface, LCID *pLocaleID) 111 { 112 PropertyPageSite *this = impl_from_IPropertyPageSite(iface); 113 114 TRACE("(%p, %p)\n", iface, pLocaleID); 115 *pLocaleID = this->lcid; 116 return S_OK; 117 } 118 119 static HRESULT WINAPI PropertyPageSite_GetPageContainer( 120 IPropertyPageSite* iface, IUnknown** ppUnk) 121 { 122 FIXME("(%p, %p)\n", iface, ppUnk); 123 return E_NOTIMPL; 124 } 125 126 static HRESULT WINAPI PropertyPageSite_TranslateAccelerator( 127 IPropertyPageSite* iface, MSG *pMsg) 128 { 129 FIXME("(%p, %p)\n", iface, pMsg); 130 return E_NOTIMPL; 131 } 132 133 static IPropertyPageSiteVtbl PropertyPageSiteVtbl = { 134 PropertyPageSite_QueryInterface, 135 PropertyPageSite_AddRef, 136 PropertyPageSite_Release, 137 PropertyPageSite_OnStatusChange, 138 PropertyPageSite_GetLocaleID, 139 PropertyPageSite_GetPageContainer, 140 PropertyPageSite_TranslateAccelerator 141 }; 142 143 /*********************************************************************** 144 * OleCreatePropertyFrameIndirect (OLEAUT32.416) 145 */ 146 HRESULT WINAPI OleCreatePropertyFrameIndirect(LPOCPFIPARAMS lpParams) 147 { 148 static const WCHAR comctlW[] = { 'c','o','m','c','t','l','3','2','.','d','l','l',0 }; 149 150 PROPSHEETHEADERW property_sheet; 151 PROPSHEETPAGEW property_sheet_page; 152 struct { 153 DLGTEMPLATE template; 154 WORD menu; 155 WORD class; 156 WORD title; 157 } *dialogs; 158 IPropertyPage **property_page; 159 PropertyPageSite *property_page_site; 160 HRESULT res; 161 ULONG i; 162 HMODULE hcomctl; 163 HRSRC property_sheet_dialog_find = NULL; 164 HGLOBAL property_sheet_dialog_load = NULL; 165 WCHAR *property_sheet_dialog_data = NULL; 166 HDC hdc; 167 LOGFONTW font_desc; 168 HFONT hfont; 169 LONG font_width = 4, font_height = 8; 170 171 if(!lpParams) 172 return E_POINTER; 173 174 TRACE("(%d %p %d %d %s %d %p %d %p %d %d)\n", lpParams->cbStructSize, 175 lpParams->hWndOwner, lpParams->x, lpParams->y, 176 debugstr_w(lpParams->lpszCaption), lpParams->cObjects, 177 lpParams->lplpUnk, lpParams->cPages, lpParams->lpPages, 178 lpParams->lcid, lpParams->dispidInitialProperty); 179 180 if(!lpParams->lplpUnk || !lpParams->lpPages) 181 return E_POINTER; 182 183 if(lpParams->cbStructSize != sizeof(OCPFIPARAMS)) { 184 WARN("incorrect structure size\n"); 185 return E_INVALIDARG; 186 } 187 188 if(lpParams->dispidInitialProperty) 189 FIXME("dispidInitialProperty not yet implemented\n"); 190 191 hdc = GetDC(NULL); 192 hcomctl = LoadLibraryW(comctlW); 193 if(hcomctl) 194 property_sheet_dialog_find = FindResourceW(hcomctl, 195 MAKEINTRESOURCEW(1006 /*IDD_PROPSHEET*/), (LPWSTR)RT_DIALOG); 196 if(property_sheet_dialog_find) 197 property_sheet_dialog_load = LoadResource(hcomctl, property_sheet_dialog_find); 198 if(property_sheet_dialog_load) 199 property_sheet_dialog_data = LockResource(property_sheet_dialog_load); 200 201 if(property_sheet_dialog_data) { 202 if(property_sheet_dialog_data[1] == 0xffff) { 203 ERR("Expected DLGTEMPLATE structure\n"); 204 return E_OUTOFMEMORY; 205 } 206 207 property_sheet_dialog_data += sizeof(DLGTEMPLATE)/sizeof(WCHAR); 208 /* Skip menu, class and title */ 209 property_sheet_dialog_data += lstrlenW(property_sheet_dialog_data)+1; 210 property_sheet_dialog_data += lstrlenW(property_sheet_dialog_data)+1; 211 property_sheet_dialog_data += lstrlenW(property_sheet_dialog_data)+1; 212 213 memset(&font_desc, 0, sizeof(LOGFONTW)); 214 /* Calculate logical height */ 215 font_desc.lfHeight = -MulDiv(property_sheet_dialog_data[0], 216 GetDeviceCaps(hdc, LOGPIXELSY), 72); 217 font_desc.lfCharSet = DEFAULT_CHARSET; 218 memcpy(font_desc.lfFaceName, property_sheet_dialog_data+1, 219 sizeof(WCHAR)*(lstrlenW(property_sheet_dialog_data+1)+1)); 220 hfont = CreateFontIndirectW(&font_desc); 221 222 if(hfont) { 223 hfont = SelectObject(hdc, hfont); 224 font_width = GdiGetCharDimensions(hdc, NULL, &font_height); 225 SelectObject(hdc, hfont); 226 } 227 } 228 if(hcomctl) 229 FreeLibrary(hcomctl); 230 ReleaseDC(NULL, hdc); 231 232 memset(&property_sheet, 0, sizeof(property_sheet)); 233 property_sheet.dwSize = sizeof(property_sheet); 234 if(lpParams->lpszCaption) { 235 property_sheet.dwFlags = PSH_PROPTITLE; 236 property_sheet.pszCaption = lpParams->lpszCaption; 237 } 238 239 property_sheet.u3.phpage = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 240 lpParams->cPages*sizeof(HPROPSHEETPAGE)); 241 property_page = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 242 lpParams->cPages*sizeof(IPropertyPage*)); 243 dialogs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 244 lpParams->cPages*sizeof(*dialogs)); 245 if(!property_sheet.u3.phpage || !property_page || !dialogs) { 246 HeapFree(GetProcessHeap(), 0, property_sheet.u3.phpage); 247 HeapFree(GetProcessHeap(), 0, property_page); 248 HeapFree(GetProcessHeap(), 0, dialogs); 249 return E_OUTOFMEMORY; 250 } 251 252 memset(&property_sheet_page, 0, sizeof(PROPSHEETPAGEW)); 253 property_sheet_page.dwSize = sizeof(PROPSHEETPAGEW); 254 property_sheet_page.dwFlags = PSP_DLGINDIRECT|PSP_USETITLE; 255 property_sheet_page.pfnDlgProc = property_sheet_proc; 256 257 for(i=0; i<lpParams->cPages; i++) { 258 PROPPAGEINFO page_info; 259 260 res = CoCreateInstance(&lpParams->lpPages[i], NULL, CLSCTX_INPROC_SERVER, 261 &IID_IPropertyPage, (void**)&property_page[i]); 262 if(FAILED(res)) 263 continue; 264 265 property_page_site = HeapAlloc(GetProcessHeap(), 0, sizeof(PropertyPageSite)); 266 if(!property_page_site) 267 continue; 268 property_page_site->IPropertyPageSite_iface.lpVtbl = &PropertyPageSiteVtbl; 269 property_page_site->ref = 1; 270 property_page_site->lcid = lpParams->lcid; 271 272 res = IPropertyPage_SetPageSite(property_page[i], 273 &property_page_site->IPropertyPageSite_iface); 274 IPropertyPageSite_Release(&property_page_site->IPropertyPageSite_iface); 275 if(FAILED(res)) 276 continue; 277 278 res = IPropertyPage_SetObjects(property_page[i], 279 lpParams->cObjects, lpParams->lplpUnk); 280 if(FAILED(res)) 281 continue; 282 283 res = IPropertyPage_GetPageInfo(property_page[i], &page_info); 284 if(FAILED(res)) 285 continue; 286 287 dialogs[i].template.cx = MulDiv(page_info.size.cx, 4, font_width); 288 dialogs[i].template.cy = MulDiv(page_info.size.cy, 8, font_height); 289 290 property_sheet_page.u.pResource = &dialogs[i].template; 291 property_sheet_page.lParam = (LPARAM)property_page[i]; 292 property_sheet_page.pszTitle = page_info.pszTitle; 293 294 property_sheet.u3.phpage[property_sheet.nPages++] = 295 CreatePropertySheetPageW(&property_sheet_page); 296 } 297 298 PropertySheetW(&property_sheet); 299 300 for(i=0; i<lpParams->cPages; i++) { 301 if(property_page[i]) { 302 IPropertyPage_SetPageSite(property_page[i], NULL); 303 IPropertyPage_Release(property_page[i]); 304 } 305 } 306 307 HeapFree(GetProcessHeap(), 0, dialogs); 308 HeapFree(GetProcessHeap(), 0, property_page); 309 HeapFree(GetProcessHeap(), 0, property_sheet.u3.phpage); 310 return S_OK; 311 } 312 313 /*********************************************************************** 314 * OleCreatePropertyFrame (OLEAUT32.417) 315 */ 316 HRESULT WINAPI OleCreatePropertyFrame( 317 HWND hwndOwner, UINT x, UINT y, LPCOLESTR lpszCaption, ULONG cObjects, 318 LPUNKNOWN* ppUnk, ULONG cPages, LPCLSID pPageClsID, LCID lcid, 319 DWORD dwReserved, LPVOID pvReserved) 320 { 321 OCPFIPARAMS ocpf; 322 323 ocpf.cbStructSize = sizeof(OCPFIPARAMS); 324 ocpf.hWndOwner = hwndOwner; 325 ocpf.x = x; 326 ocpf.y = y; 327 ocpf.lpszCaption = lpszCaption; 328 ocpf.cObjects = cObjects; 329 ocpf.lplpUnk = ppUnk; 330 ocpf.cPages = cPages; 331 ocpf.lpPages = pPageClsID; 332 ocpf.lcid = lcid; 333 ocpf.dispidInitialProperty = 0; 334 335 return OleCreatePropertyFrameIndirect(&ocpf); 336 } 337