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