From: Piotr Caban piotr@codeweavers.com
--- dlls/compstui/compstui_main.c | 102 +++++++++++++++++++++++++++++++-- dlls/compstui/tests/compstui.c | 25 ++++++++ 2 files changed, 122 insertions(+), 5 deletions(-)
diff --git a/dlls/compstui/compstui_main.c b/dlls/compstui/compstui_main.c index b7a08e1c52b..c44942c60a3 100644 --- a/dlls/compstui/compstui_main.c +++ b/dlls/compstui/compstui_main.c @@ -32,6 +32,7 @@ #include "ddk/compstui.h"
#include "wine/debug.h" +#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(compstui);
@@ -59,6 +60,7 @@ struct propsheet { int pages_cnt; HANDLE pages[100]; + struct list funcs; };
struct propsheetpage @@ -66,6 +68,17 @@ struct propsheetpage HPROPSHEETPAGE hpsp; };
+struct propsheetfunc +{ + struct list entry; + HANDLE handle; + PFNPROPSHEETUI func; + LPARAM lparam; + BOOL unicode; + ULONG_PTR user_data; + ULONG_PTR result; +}; + #define HANDLE_FIRST 0x43440001 static struct cps_data { @@ -73,7 +86,8 @@ static struct cps_data { HANDLE_FREE = 0, HANDLE_PROPSHEET, - HANDLE_PROPSHEETPAGE + HANDLE_PROPSHEETPAGE, + HANDLE_PROPSHEETFUNC, } type; union { @@ -81,6 +95,7 @@ static struct cps_data struct cps_data *next_free; struct propsheet *ps; struct propsheetpage *psp; + struct propsheetfunc *psf; }; } handles[0x1000]; static struct cps_data *first_free_handle = handles; @@ -94,6 +109,8 @@ static CRITICAL_SECTION_DEBUG handles_cs_debug = }; static CRITICAL_SECTION handles_cs = { &handles_cs_debug, -1, 0, 0, 0, 0 };
+static LONG_PTR WINAPI cps_callback(HANDLE hcps, UINT func, LPARAM lparam1, LPARAM lparam2); + static struct cps_data* get_handle_data(HANDLE handle) { struct cps_data *ret; @@ -117,6 +134,9 @@ static HANDLE alloc_handle(struct cps_data **cps_data, int type) case HANDLE_PROPSHEETPAGE: data = calloc(1, sizeof(struct propsheetpage)); break; + case HANDLE_PROPSHEETFUNC: + data = calloc(1, sizeof(struct propsheetfunc)); + break; }
if (!data) @@ -187,6 +207,59 @@ static HANDLE add_hpropsheetpage(HANDLE hcps, HPROPSHEETPAGE hpsp) return ret; }
+static HANDLE add_propsheetfunc(HANDLE hcps, PFNPROPSHEETUI func, LPARAM lparam, BOOL unicode) +{ + struct cps_data *cps_data = get_handle_data(hcps); + struct cps_data *cpsf_data; + PROPSHEETUI_INFO info, callback_info; + HANDLE ret; + LONG lret; + + if (!cps_data || !func) + return 0; + + if (cps_data->type != HANDLE_PROPSHEET) + { + FIXME("unsupported handle type %d\n", cps_data->type); + return 0; + } + + ret = alloc_handle(&cpsf_data, HANDLE_PROPSHEETFUNC); + if (!ret) + return 0; + cpsf_data->psf->handle = ret; + cpsf_data->psf->func = func; + cpsf_data->psf->unicode = unicode; + cpsf_data->psf->lparam = lparam; + + memset(&info, 0, sizeof(info)); + info.cbSize = sizeof(info); + info.Version = PROPSHEETUI_INFO_VERSION; + info.Flags = unicode ? PSUIINFO_UNICODE : 0; + info.Reason = PROPSHEETUI_REASON_INIT; + info.hComPropSheet = hcps; + info.pfnComPropSheet = cps_callback; + info.lParamInit = lparam; + + callback_info = info; + lret = func(&callback_info, lparam); + cpsf_data->psf->user_data = callback_info.UserData; + cpsf_data->psf->result = callback_info.Result; + if (lret <= 0) + { + callback_info = info; + callback_info.Reason = PROPSHEETUI_REASON_DESTROY; + callback_info.UserData = cpsf_data->psf->user_data; + callback_info.Result = cpsf_data->psf->result; + free_handle(ret); + func(&callback_info, 0); + return 0; + } + + list_add_tail(&cps_data->ps->funcs, &cpsf_data->psf->entry); + return ret; +} + static LONG_PTR WINAPI cps_callback(HANDLE hcps, UINT func, LPARAM lparam1, LPARAM lparam2) { TRACE("(%p, %u, %Ix, %Ix\n", hcps, func, lparam1, lparam2); @@ -195,11 +268,13 @@ static LONG_PTR WINAPI cps_callback(HANDLE hcps, UINT func, LPARAM lparam1, LPAR { case CPSFUNC_ADD_HPROPSHEETPAGE: return (LONG_PTR)add_hpropsheetpage(hcps, (HPROPSHEETPAGE)lparam1); + case CPSFUNC_ADD_PFNPROPSHEETUIA: + case CPSFUNC_ADD_PFNPROPSHEETUIW: + return (LONG_PTR)add_propsheetfunc(hcps, (PFNPROPSHEETUI)lparam1, + lparam2, func == CPSFUNC_ADD_PFNPROPSHEETUIW); case CPSFUNC_ADD_PROPSHEETPAGEW: case CPSFUNC_ADD_PCOMPROPSHEETUIA: case CPSFUNC_ADD_PCOMPROPSHEETUIW: - case CPSFUNC_ADD_PFNPROPSHEETUIA: - case CPSFUNC_ADD_PFNPROPSHEETUIW: case CPSFUNC_DELETE_HCOMPROPSHEET: case CPSFUNC_SET_HSTARTPAGE: case CPSFUNC_GET_PAGECOUNT: @@ -324,6 +399,7 @@ static LONG create_prop_dlg(HWND hwnd, PFNPROPSHEETUI callback, LPARAM lparam, D SetLastError(0); return ERR_CPSUI_GETLASTERROR; } + list_init(&cps_data->ps->funcs);
memset(&info, 0, sizeof(info)); info.cbSize = sizeof(info); @@ -364,9 +440,25 @@ static LONG create_prop_dlg(HWND hwnd, PFNPROPSHEETUI callback, LPARAM lparam, D ret = create_property_sheetW(cps_data->ps, &header);
destroy: + info.Reason = PROPSHEETUI_REASON_DESTROY; + while (!list_empty(&cps_data->ps->funcs)) + { + struct propsheetfunc *func = LIST_ENTRY(list_head(&cps_data->ps->funcs), + struct propsheetfunc, entry); + + list_remove(&func->entry); + + callback_info = info; + callback_info.Flags = func->unicode ? PSUIINFO_UNICODE : 0; + callback_info.lParamInit = func->lparam; + callback_info.UserData = func->user_data; + callback_info.Result = func->result; + func->func(&callback_info, ret <= 0 ? 0 : 0x100); + free_handle(func->handle); + } + callback_info = info; - callback_info.Reason = PROPSHEETUI_REASON_DESTROY; - callback(&callback_info, ret < 0 ? 0 : 0x100); + callback(&callback_info, ret <= 0 ? 0 : 0x100);
for (i = 0; i < cps_data->ps->pages_cnt; i++) free_handle(cps_data->ps->pages[i]); diff --git a/dlls/compstui/tests/compstui.c b/dlls/compstui/tests/compstui.c index f4e3af459a9..be63c7645ec 100644 --- a/dlls/compstui/tests/compstui.c +++ b/dlls/compstui/tests/compstui.c @@ -45,6 +45,25 @@ static INT_PTR CALLBACK prop_page_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARA return FALSE; }
+static LONG WINAPI device_property_sheets(PROPSHEETUI_INFO *info, LPARAM lparam) +{ + ok(info->cbSize == sizeof(*info), "info->cbSize = %hd\n", info->cbSize); + ok(info->Version == PROPSHEETUI_INFO_VERSION, "info->Version = %hd\n", info->Version); + ok(info->Flags == info->lParamInit ? PSUIINFO_UNICODE : 0, "info->Flags = %hd\n", info->Flags); + ok(info->Reason == PROPSHEETUI_REASON_INIT || info->Reason == PROPSHEETUI_REASON_DESTROY, + "info->Reason = %hx\n", info->Reason); + ok(info->hComPropSheet != NULL, "info->hComPropSheet = NULL\n"); + ok(info->pfnComPropSheet != NULL, "info->pfnComPropSheet = NULL\n"); + if (info->Reason == PROPSHEETUI_REASON_INIT) + { + ok(info->lParamInit == lparam, "info->lParamInit = %Ix, lparam = %Ix\n", + info->lParamInit, lparam); + } + ok(!info->UserData, "info->UserData = %Ix\n", info->UserData); + ok(!info->Result, "info->Result = %Ix\n", info->Result); + return lparam; +} + #define ADD_PAGES 0x1
static LONG WINAPI propsheetui_callback(PROPSHEETUI_INFO *info, LPARAM lparam) @@ -93,6 +112,12 @@ static LONG WINAPI propsheetui_callback(PROPSHEETUI_INFO *info, LPARAM lparam) PROPSHEETPAGEW psp; LONG_PTR ret;
+ ret = info->pfnComPropSheet(info->hComPropSheet, CPSFUNC_ADD_PFNPROPSHEETUIA, (LPARAM)device_property_sheets, 0); + ok(!ret, "ret = %Ix\n", ret); + + ret = info->pfnComPropSheet(info->hComPropSheet, CPSFUNC_ADD_PFNPROPSHEETUIW, (LPARAM)device_property_sheets, 1); + ok(ret, "ret = 0\n"); + memset(&psp, 0, sizeof(psp)); psp.dwSize = sizeof(psp); U(psp).pszTemplate = L"prop_page1";