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