2 * Implementation of the Common Property Sheets User Interface
4 * Copyright 2006 Detlef Riekenberg
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "ddk/compstui.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(compstui
);
38 static HMODULE compstui_hmod
;
56 } PROPSHEETUI_INFO_HEADERAW
;
69 #define HANDLE_FIRST 0x43440001
70 static struct cps_data
81 struct cps_data
*next_free
;
83 struct propsheetpage
*psp
;
86 static struct cps_data
*first_free_handle
= handles
;
88 static CRITICAL_SECTION handles_cs
;
89 static CRITICAL_SECTION_DEBUG handles_cs_debug
=
92 { &handles_cs_debug
.ProcessLocksList
, &handles_cs_debug
.ProcessLocksList
},
93 0, 0, { (DWORD_PTR
)(__FILE__
": handles_cs") }
95 static CRITICAL_SECTION handles_cs
= { &handles_cs_debug
, -1, 0, 0, 0, 0 };
97 static struct cps_data
* get_handle_data(HANDLE handle
)
101 if ((ULONG_PTR
)handle
< HANDLE_FIRST
|| (ULONG_PTR
)handle
>= HANDLE_FIRST
+ ARRAY_SIZE(handles
))
104 ret
= &handles
[(ULONG_PTR
)handle
- HANDLE_FIRST
];
105 return ret
->type
== HANDLE_FREE
? NULL
: ret
;
108 static HANDLE
alloc_handle(struct cps_data
**cps_data
, int type
)
114 case HANDLE_PROPSHEET
:
115 data
= calloc(1, sizeof(struct propsheet
));
117 case HANDLE_PROPSHEETPAGE
:
118 data
= calloc(1, sizeof(struct propsheetpage
));
125 EnterCriticalSection(&handles_cs
);
127 if (first_free_handle
>= handles
+ ARRAY_SIZE(handles
))
129 LeaveCriticalSection(&handles_cs
);
130 FIXME("out of handles\n");
135 *cps_data
= first_free_handle
;
136 if ((*cps_data
)->next_free
)
137 first_free_handle
= (*cps_data
)->next_free
;
139 first_free_handle
= (*cps_data
) + 1;
140 LeaveCriticalSection(&handles_cs
);
142 (*cps_data
)->type
= type
;
143 (*cps_data
)->data
= data
;
144 return (HANDLE
)(HANDLE_FIRST
+ ((*cps_data
) - handles
));
147 static void free_handle(HANDLE handle
)
149 struct cps_data
*data
= get_handle_data(handle
);
154 data
->type
= HANDLE_FREE
;
157 EnterCriticalSection(&handles_cs
);
158 data
->next_free
= first_free_handle
;
159 first_free_handle
= data
;
160 LeaveCriticalSection(&handles_cs
);
163 static HANDLE
add_hpropsheetpage(HANDLE hcps
, HPROPSHEETPAGE hpsp
)
165 struct cps_data
*cps_data
= get_handle_data(hcps
);
166 struct cps_data
*cpsp_data
;
169 if (!cps_data
|| !hpsp
)
172 if (cps_data
->type
!= HANDLE_PROPSHEET
)
174 FIXME("unsupported handle type %d\n", cps_data
->type
);
178 if (cps_data
->ps
->pages_cnt
== ARRAY_SIZE(cps_data
->ps
->pages
))
181 ret
= alloc_handle(&cpsp_data
, HANDLE_PROPSHEETPAGE
);
184 cpsp_data
->psp
->hpsp
= hpsp
;
186 cps_data
->ps
->pages
[cps_data
->ps
->pages_cnt
++] = ret
;
190 static LONG_PTR WINAPI
cps_callback(HANDLE hcps
, UINT func
, LPARAM lparam1
, LPARAM lparam2
)
192 TRACE("(%p, %u, %Ix, %Ix\n", hcps
, func
, lparam1
, lparam2
);
196 case CPSFUNC_ADD_HPROPSHEETPAGE
:
197 return (LONG_PTR
)add_hpropsheetpage(hcps
, (HPROPSHEETPAGE
)lparam1
);
198 case CPSFUNC_ADD_PROPSHEETPAGEW
:
199 case CPSFUNC_ADD_PCOMPROPSHEETUIA
:
200 case CPSFUNC_ADD_PCOMPROPSHEETUIW
:
201 case CPSFUNC_ADD_PFNPROPSHEETUIA
:
202 case CPSFUNC_ADD_PFNPROPSHEETUIW
:
203 case CPSFUNC_DELETE_HCOMPROPSHEET
:
204 case CPSFUNC_SET_HSTARTPAGE
:
205 case CPSFUNC_GET_PAGECOUNT
:
206 case CPSFUNC_SET_RESULT
:
207 case CPSFUNC_GET_HPSUIPAGES
:
208 case CPSFUNC_LOAD_CPSUI_STRINGA
:
209 case CPSFUNC_LOAD_CPSUI_STRINGW
:
210 case CPSFUNC_LOAD_CPSUI_ICON
:
211 case CPSFUNC_GET_PFNPROPSHEETUI_ICON
:
212 case CPSFUNC_ADD_PROPSHEETPAGEA
:
213 case CPSFUNC_INSERT_PSUIPAGEA
:
214 case CPSFUNC_INSERT_PSUIPAGEW
:
215 case CPSFUNC_SET_PSUIPAGE_TITLEA
:
216 case CPSFUNC_SET_PSUIPAGE_TITLEW
:
217 case CPSFUNC_SET_PSUIPAGE_ICON
:
218 case CPSFUNC_SET_DATABLOCK
:
219 case CPSFUNC_QUERY_DATABLOCK
:
220 case CPSFUNC_SET_DMPUB_HIDEBITS
:
221 case CPSFUNC_IGNORE_CPSUI_PSN_APPLY
:
222 case CPSFUNC_DO_APPLY_CPSUI
:
223 case CPSFUNC_SET_FUSION_CONTEXT
:
224 FIXME("func not supported %d\n", func
);
227 ERR("unknown func: %d\n", func
);
232 static LONG
create_property_sheetW(struct propsheet
*ps
, PROPSHEETUI_INFO_HEADERAW
*header
)
234 HPROPSHEETPAGE hpsp
[100];
235 PROPSHEETHEADERW psh
;
241 return ERR_CPSUI_NO_PROPSHEETPAGE
;
243 memset(&psh
, 0, sizeof(psh
));
244 psh
.dwSize
= sizeof(psh
);
245 if (header
->flags
& PSUIHDRF_NOAPPLYNOW
)
246 psh
.dwFlags
|= PSH_NOAPPLYNOW
;
247 psh
.hwndParent
= header
->parent
;
248 psh
.hInstance
= header
->hinst
;
249 psh
.pszCaption
= title
;
251 if (!(header
->flags
& PSUIHDRF_USEHICON
) && !header
->icon_id
)
252 header
->icon_id
= IDI_CPSUI_OPTION
;
254 if (header
->flags
& PSUIHDRF_USEHICON
)
256 psh
.dwFlags
|= PSH_USEHICON
;
257 psh
.hIcon
= header
->hicon
;
259 else if (header
->icon_id
>= IDI_CPSUI_ICONID_FIRST
&&
260 header
->icon_id
<= IDI_CPSUI_ICONID_LAST
)
262 FIXME("icon not implemented: %Id\n", header
->icon_id
);
266 psh
.dwFlags
|= PSH_USEICONID
;
267 psh
.pszIcon
= (WCHAR
*)header
->icon_id
;
271 wcscpy_s(title
, ARRAY_SIZE(title
), header
->titleW
);
273 LoadStringW(compstui_hmod
, IDS_CPSUI_OPTIONS
, title
, ARRAY_SIZE(title
));
275 if ((header
->flags
& PSUIHDRF_DEFTITLE
) &&
276 (!header
->titleW
|| !(header
->flags
& PSUIHDRF_EXACT_PTITLE
)))
279 if (len
< ARRAY_SIZE(title
))
281 LoadStringW(compstui_hmod
, IDS_CPSUI_DEFAULT
, title
+ len
, ARRAY_SIZE(title
) - len
);
284 if ((header
->flags
& PSUIHDRF_PROPTITLE
) &&
285 (!header
->titleW
|| !(header
->flags
& PSUIHDRF_EXACT_PTITLE
)))
288 if (len
< ARRAY_SIZE(title
))
290 LoadStringW(compstui_hmod
, IDS_CPSUI_PROPERTIES
, title
+ len
, ARRAY_SIZE(title
) - len
);
293 psh
.nPages
= ps
->pages_cnt
;
295 for (i
= 0; i
< ps
->pages_cnt
; i
++)
296 hpsp
[i
] = get_handle_data(ps
->pages
[i
])->psp
->hpsp
;
298 ret
= PropertySheetW(&psh
);
303 return ERR_CPSUI_GETLASTERROR
;
304 case ID_PSREBOOTSYSTEM
:
305 return CPSUI_REBOOTSYSTEM
;
306 case ID_PSRESTARTWINDOWS
:
307 return CPSUI_RESTARTWINDOWS
;
313 static LONG
create_prop_dlg(HWND hwnd
, PFNPROPSHEETUI callback
, LPARAM lparam
, DWORD
*res
, BOOL unicode
)
315 PROPSHEETUI_INFO info
, callback_info
;
316 PROPSHEETUI_INFO_HEADERAW header
;
317 struct cps_data
*cps_data
;
322 if (!callback
|| !(cps_handle
= alloc_handle(&cps_data
, HANDLE_PROPSHEET
)))
325 return ERR_CPSUI_GETLASTERROR
;
328 memset(&info
, 0, sizeof(info
));
329 info
.cbSize
= sizeof(info
);
330 info
.lParamInit
= lparam
;
331 callback_info
= info
;
332 callback_info
.Reason
= PROPSHEETUI_REASON_BEFORE_INIT
;
333 callback(&callback_info
, lparam
);
335 info
.Version
= PROPSHEETUI_INFO_VERSION
;
336 info
.Flags
= unicode
? PSUIINFO_UNICODE
: 0;
337 info
.hComPropSheet
= cps_handle
;
338 info
.pfnComPropSheet
= cps_callback
;
339 callback_info
= info
;
340 callback_info
.Reason
= PROPSHEETUI_REASON_INIT
;
341 ret
= callback(&callback_info
, lparam
);
342 info
.UserData
= callback_info
.UserData
;
343 info
.Result
= callback_info
.Result
;
346 ret
= ERR_CPSUI_GETLASTERROR
;
350 memset(&header
, 0, sizeof(header
));
351 header
.size
= sizeof(header
);
352 header
.parent
= hwnd
;
353 callback_info
= info
;
354 callback_info
.Reason
= PROPSHEETUI_REASON_GET_INFO_HEADER
;
355 ret
= callback(&callback_info
, (LPARAM
)&header
);
356 info
.UserData
= callback_info
.UserData
;
357 info
.Result
= callback_info
.Result
;
360 ret
= ERR_CPSUI_GETLASTERROR
;
364 ret
= create_property_sheetW(cps_data
->ps
, &header
);
367 callback_info
= info
;
368 callback_info
.Reason
= PROPSHEETUI_REASON_DESTROY
;
369 callback(&callback_info
, ret
< 0 ? 0 : 0x100);
371 for (i
= 0; i
< cps_data
->ps
->pages_cnt
; i
++)
372 free_handle(cps_data
->ps
->pages
[i
]);
373 free_handle(cps_handle
);
375 if (res
) *res
= callback_info
.Result
;
379 /******************************************************************
380 * CommonPropertySheetUIA (COMPSTUI.@)
383 LONG WINAPI
CommonPropertySheetUIA(HWND hWnd
, PFNPROPSHEETUI pfnPropSheetUI
, LPARAM lparam
, LPDWORD pResult
)
385 FIXME("(%p, %p, 0x%Ix, %p)\n", hWnd
, pfnPropSheetUI
, lparam
, pResult
);
389 /******************************************************************
390 * CommonPropertySheetUIW (COMPSTUI.@)
393 LONG WINAPI
CommonPropertySheetUIW(HWND hwnd
, PFNPROPSHEETUI callback
, LPARAM lparam
, LPDWORD res
)
395 TRACE("(%p, %p, 0x%Ix, %p)\n", hwnd
, callback
, lparam
, res
);
396 return create_prop_dlg(hwnd
, callback
, lparam
, res
, TRUE
);
399 /******************************************************************
400 * GetCPSUIUserData (COMPSTUI.@)
403 ULONG_PTR WINAPI
GetCPSUIUserData(HWND hDlg
)
405 FIXME("(%p): stub\n", hDlg
);
409 /******************************************************************
410 * SetCPSUIUserData (COMPSTUI.@)
413 BOOL WINAPI
SetCPSUIUserData(HWND hDlg
, ULONG_PTR UserData
)
415 FIXME("(%p, %08Ix): stub\n", hDlg
, UserData
);
419 BOOL WINAPI
DllMain(HINSTANCE hinst
, DWORD reason
, void *reserved
)
421 if (reason
== DLL_PROCESS_ATTACH
)
422 compstui_hmod
= hinst
;