[OLEAUT32]
[reactos.git] / reactos / dll / win32 / oleaut32 / olepropframe.c
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 #define NONAMELESSSTRUCT
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "ole2.h"
32 #include "olectl.h"
33 #include "oledlg.h"
34 #include "wine/debug.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(ole);
37
38 typedef struct {
39 IPropertyPageSite IPropertyPageSite_iface;
40 LCID lcid;
41 LONG ref;
42 } PropertyPageSite;
43
44 static inline PropertyPageSite *impl_from_IPropertyPageSite(IPropertyPageSite *iface)
45 {
46 return CONTAINING_RECORD(iface, PropertyPageSite, IPropertyPageSite_iface);
47 }
48
49 static INT_PTR CALLBACK property_sheet_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
50 {
51 IPropertyPage *property_page = (IPropertyPage*)GetWindowLongPtrW(hwnd, DWLP_USER);
52
53 switch(msg) {
54 case WM_INITDIALOG: {
55 RECT rect;
56
57 property_page = (IPropertyPage*)((LPPROPSHEETPAGEW)lparam)->lParam;
58
59 GetClientRect(hwnd, &rect);
60 IPropertyPage_Activate(property_page, hwnd, &rect, TRUE);
61 IPropertyPage_Show(property_page, SW_SHOW);
62
63 SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR)property_page);
64 return FALSE;
65 }
66 case WM_DESTROY:
67 IPropertyPage_Show(property_page, SW_HIDE);
68 IPropertyPage_Deactivate(property_page);
69 return FALSE;
70 default:
71 return FALSE;
72 }
73 }
74
75 static HRESULT WINAPI PropertyPageSite_QueryInterface(IPropertyPageSite* iface,
76 REFIID riid, void** ppv)
77 {
78 TRACE("(%p riid: %s)\n",iface, debugstr_guid(riid));
79
80 if(IsEqualGUID(&IID_IUnknown, riid)
81 || IsEqualGUID(&IID_IPropertyPageSite, riid))
82 *ppv = iface;
83 else {
84 *ppv = NULL;
85 return E_NOINTERFACE;
86 }
87
88 IUnknown_AddRef((IUnknown*)*ppv);
89 return S_OK;
90 }
91
92 static ULONG WINAPI PropertyPageSite_AddRef(IPropertyPageSite* iface)
93 {
94 PropertyPageSite *this = impl_from_IPropertyPageSite(iface);
95 LONG ref = InterlockedIncrement(&this->ref);
96
97 TRACE("(%p) ref=%d\n", this, ref);
98 return ref;
99 }
100
101 static ULONG WINAPI PropertyPageSite_Release(IPropertyPageSite* iface)
102 {
103 PropertyPageSite *this = impl_from_IPropertyPageSite(iface);
104 LONG ref = InterlockedDecrement(&this->ref);
105
106 TRACE("(%p) ref=%d\n", this, ref);
107 if(!ref)
108 HeapFree(GetProcessHeap(), 0, this);
109 return ref;
110 }
111
112 static HRESULT WINAPI PropertyPageSite_OnStatusChange(
113 IPropertyPageSite *iface, DWORD dwFlags)
114 {
115 TRACE("(%p, %x)\n", iface, dwFlags);
116 return S_OK;
117 }
118
119 static HRESULT WINAPI PropertyPageSite_GetLocaleID(
120 IPropertyPageSite *iface, LCID *pLocaleID)
121 {
122 PropertyPageSite *this = impl_from_IPropertyPageSite(iface);
123
124 TRACE("(%p, %p)\n", iface, pLocaleID);
125 *pLocaleID = this->lcid;
126 return S_OK;
127 }
128
129 static HRESULT WINAPI PropertyPageSite_GetPageContainer(
130 IPropertyPageSite* iface, IUnknown** ppUnk)
131 {
132 FIXME("(%p, %p)\n", iface, ppUnk);
133 return E_NOTIMPL;
134 }
135
136 static HRESULT WINAPI PropertyPageSite_TranslateAccelerator(
137 IPropertyPageSite* iface, MSG *pMsg)
138 {
139 FIXME("(%p, %p)\n", iface, pMsg);
140 return E_NOTIMPL;
141 }
142
143 IPropertyPageSiteVtbl PropertyPageSiteVtbl = {
144 PropertyPageSite_QueryInterface,
145 PropertyPageSite_AddRef,
146 PropertyPageSite_Release,
147 PropertyPageSite_OnStatusChange,
148 PropertyPageSite_GetLocaleID,
149 PropertyPageSite_GetPageContainer,
150 PropertyPageSite_TranslateAccelerator
151 };
152
153 /***********************************************************************
154 * OleCreatePropertyFrameIndirect (OLEAUT32.416)
155 */
156 HRESULT WINAPI OleCreatePropertyFrameIndirect(LPOCPFIPARAMS lpParams)
157 {
158 static const WCHAR comctlW[] = { 'c','o','m','c','t','l','3','2','.','d','l','l',0 };
159
160 PROPSHEETHEADERW property_sheet;
161 PROPSHEETPAGEW property_sheet_page;
162 struct {
163 DLGTEMPLATE template;
164 WORD menu;
165 WORD class;
166 WORD title;
167 } *dialogs;
168 IPropertyPage **property_page;
169 PropertyPageSite *property_page_site;
170 HRESULT res;
171 int i;
172 HMODULE hcomctl;
173 HRSRC property_sheet_dialog_find = NULL;
174 HGLOBAL property_sheet_dialog_load = NULL;
175 WCHAR *property_sheet_dialog_data = NULL;
176 HDC hdc;
177 LOGFONTW font_desc;
178 HFONT hfont;
179 LONG font_width = 4, font_height = 8;
180
181 if(!lpParams)
182 return E_POINTER;
183
184 TRACE("(%d %p %d %d %s %d %p %d %p %d %d)\n", lpParams->cbStructSize,
185 lpParams->hWndOwner, lpParams->x, lpParams->y,
186 debugstr_w(lpParams->lpszCaption), lpParams->cObjects,
187 lpParams->lplpUnk, lpParams->cPages, lpParams->lpPages,
188 lpParams->lcid, lpParams->dispidInitialProperty);
189
190 if(!lpParams->lplpUnk || !lpParams->lpPages)
191 return E_POINTER;
192
193 if(lpParams->cbStructSize != sizeof(OCPFIPARAMS)) {
194 WARN("incorrect structure size\n");
195 return E_INVALIDARG;
196 }
197
198 if(lpParams->dispidInitialProperty)
199 FIXME("dispidInitialProperty not yet implemented\n");
200
201 hdc = GetDC(NULL);
202 hcomctl = LoadLibraryW(comctlW);
203 if(hcomctl)
204 property_sheet_dialog_find = FindResourceW(hcomctl,
205 MAKEINTRESOURCEW(1006 /*IDD_PROPSHEET*/), (LPWSTR)RT_DIALOG);
206 if(property_sheet_dialog_find)
207 property_sheet_dialog_load = LoadResource(hcomctl, property_sheet_dialog_find);
208 if(property_sheet_dialog_load)
209 property_sheet_dialog_data = LockResource(property_sheet_dialog_load);
210
211 if(property_sheet_dialog_data) {
212 if(property_sheet_dialog_data[1] == 0xffff) {
213 ERR("Expected DLGTEMPLATE structure\n");
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 continue;
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_SetPageSite(property_page[i], NULL);
313 IPropertyPage_Release(property_page[i]);
314 }
315 }
316
317 HeapFree(GetProcessHeap(), 0, dialogs);
318 HeapFree(GetProcessHeap(), 0, property_page);
319 HeapFree(GetProcessHeap(), 0, property_sheet.u3.phpage);
320 return S_OK;
321 }
322
323 /***********************************************************************
324 * OleCreatePropertyFrame (OLEAUT32.417)
325 */
326 HRESULT WINAPI OleCreatePropertyFrame(
327 HWND hwndOwner, UINT x, UINT y, LPCOLESTR lpszCaption, ULONG cObjects,
328 LPUNKNOWN* ppUnk, ULONG cPages, LPCLSID pPageClsID, LCID lcid,
329 DWORD dwReserved, LPVOID pvReserved)
330 {
331 OCPFIPARAMS ocpf;
332
333 ocpf.cbStructSize = sizeof(OCPFIPARAMS);
334 ocpf.hWndOwner = hwndOwner;
335 ocpf.x = x;
336 ocpf.y = y;
337 ocpf.lpszCaption = lpszCaption;
338 ocpf.cObjects = cObjects;
339 ocpf.lplpUnk = ppUnk;
340 ocpf.cPages = cPages;
341 ocpf.lpPages = pPageClsID;
342 ocpf.lcid = lcid;
343 ocpf.dispidInitialProperty = 0;
344
345 return OleCreatePropertyFrameIndirect(&ocpf);
346 }