ReactOS  0.4.14-dev-583-g2a1ba2c
propsheet.c
Go to the documentation of this file.
1 /*
2  * Property Sheets
3  *
4  * Copyright 1998 Francis Beaudet
5  * Copyright 1999 Thuy Nguyen
6  * Copyright 2004 Maxime Bellenge
7  * Copyright 2004 Filip Navara
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  *
23  * This code was audited for completeness against the documented features
24  * of Comctl32.dll version 6.0 on Sep. 12, 2004, by Filip Navara.
25  *
26  * Unless otherwise noted, we believe this code to be complete, as per
27  * the specification mentioned above.
28  * If you discover missing features, or bugs, please note them below.
29  *
30  * TODO:
31  * - Tab order
32  * - Wizard 97 header resizing
33  * - Enforcing of minimal wizard size
34  * - Messages:
35  * o PSM_RECALCPAGESIZES
36  * o WM_HELP
37  * o WM_CONTEXTMENU
38  * - Notifications:
39  * o PSN_GETOBJECT
40  * o PSN_QUERYINITIALFOCUS
41  * o PSN_TRANSLATEACCELERATOR
42  * - Styles:
43  * o PSH_RTLREADING
44  * o PSH_STRETCHWATERMARK
45  * o PSH_USEPAGELANG
46  * o PSH_USEPSTARTPAGE
47  * - Page styles:
48  * o PSP_USEFUSIONCONTEXT
49  * o PSP_USEREFPARENT
50  */
51 
52 #include <stdarg.h>
53 #include <string.h>
54 
55 #define NONAMELESSUNION
56 
57 #include "windef.h"
58 #include "winbase.h"
59 #include "wingdi.h"
60 #include "winuser.h"
61 #include "winnls.h"
62 #include "commctrl.h"
63 #include "prsht.h"
64 #include "comctl32.h"
65 #include "uxtheme.h"
66 
67 #include "wine/debug.h"
68 #include "wine/unicode.h"
69 
70 /******************************************************************************
71  * Data structures
72  */
73 #include "pshpack2.h"
74 
75 typedef struct
76 {
83 
84 typedef struct
85 {
89  short x;
90  short y;
91  short cx;
92  short cy;
95 #include "poppack.h"
96 
97 typedef struct tagPropPageInfo
98 {
99  HPROPSHEETPAGE hpage; /* to keep track of pages not passed to PropertySheet */
106 } PropPageInfo;
107 
108 typedef struct tagPropSheetInfo
109 {
114  int nPages;
126  int width;
127  int height;
131 } PropSheetInfo;
132 
133 typedef struct
134 {
135  int x;
136  int y;
137 } PADDING_INFO;
138 
139 /******************************************************************************
140  * Defines and global variables
141  */
142 
143 static const WCHAR PropSheetInfoStr[] =
144  {'P','r','o','p','e','r','t','y','S','h','e','e','t','I','n','f','o',0 };
145 
146 #define PSP_INTERNAL_UNICODE 0x80000000
147 
148 #define MAX_CAPTION_LENGTH 255
149 #define MAX_TABTEXT_LENGTH 255
150 #define MAX_BUTTONTEXT_LENGTH 64
151 
152 #define INTRNL_ANY_WIZARD (PSH_WIZARD | PSH_WIZARD97_OLD | PSH_WIZARD97_NEW | PSH_WIZARD_LITE)
153 
154 /* Wizard metrics specified in DLUs */
155 #define WIZARD_PADDING 7
156 #define WIZARD_HEADER_HEIGHT 36
157 
158 /******************************************************************************
159  * Prototypes
160  */
162 static void PROPSHEET_SetTitleW(HWND hwndDlg, DWORD dwStyle, LPCWSTR lpszText);
163 static BOOL PROPSHEET_CanSetCurSel(HWND hwndDlg);
164 static BOOL PROPSHEET_SetCurSel(HWND hwndDlg,
165  int index,
166  int skipdir,
167  HPROPSHEETPAGE hpage);
168 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage, const PropSheetInfo* psInfo, int original_index);
169 static PADDING_INFO PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg, const PropSheetInfo* psInfo);
170 static BOOL PROPSHEET_DoCommand(HWND hwnd, WORD wID);
171 static BOOL PROPSHEET_RemovePage(HWND hwndDlg, int index, HPROPSHEETPAGE hpage);
172 
173 static INT_PTR CALLBACK
175 
176 WINE_DEFAULT_DEBUG_CHANNEL(propsheet);
177 
178 static WCHAR *heap_strdupW(const WCHAR *str)
179 {
180  int len = strlenW(str) + 1;
181  WCHAR *ret = Alloc(len * sizeof(WCHAR));
182  strcpyW(ret, str);
183  return ret;
184 }
185 
186 static WCHAR *heap_strdupAtoW(const char *str)
187 {
188  WCHAR *ret;
189  INT len;
190 
191  len = MultiByteToWideChar(CP_ACP, 0, str, -1, 0, 0);
192  ret = Alloc(len * sizeof(WCHAR));
193  MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
194 
195  return ret;
196 }
197 
198 #define add_flag(a) if (dwFlags & a) {strcat(string, #a );strcat(string," ");}
199 /******************************************************************************
200  * PROPSHEET_UnImplementedFlags
201  *
202  * Document use of flags we don't implement yet.
203  */
205 {
206  CHAR string[256];
207 
208  string[0] = '\0';
209 
210  /*
211  * unhandled header flags:
212  * PSH_RTLREADING 0x00000800
213  * PSH_STRETCHWATERMARK 0x00040000
214  * PSH_USEPAGELANG 0x00200000
215  */
216 
218  add_flag(PSH_STRETCHWATERMARK);
219  add_flag(PSH_USEPAGELANG);
220  if (string[0] != '\0')
221  FIXME("%s\n", string);
222 }
223 #undef add_flag
224 
225 /******************************************************************************
226  * PROPSHEET_GetPageRect
227  *
228  * Retrieve rect from tab control and map into the dialog for SetWindowPos
229  */
230 static void PROPSHEET_GetPageRect(const PropSheetInfo * psInfo, HWND hwndDlg,
231  RECT *rc, LPCPROPSHEETPAGEW ppshpage)
232 {
233  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD) {
234  HWND hwndChild;
235  RECT r;
236 
237  if (((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) &&
238  (psInfo->ppshheader.dwFlags & PSH_HEADER) &&
239  !(ppshpage->dwFlags & PSP_HIDEHEADER)) ||
240  (psInfo->ppshheader.dwFlags & PSH_WIZARD))
241  {
242  rc->left = rc->top = WIZARD_PADDING;
243  }
244  else
245  {
246  rc->left = rc->top = 0;
247  }
248  rc->right = psInfo->width - rc->left;
249  rc->bottom = psInfo->height - rc->top;
250  MapDialogRect(hwndDlg, rc);
251 
252  if ((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) &&
253  (psInfo->ppshheader.dwFlags & PSH_HEADER) &&
254  !(ppshpage->dwFlags & PSP_HIDEHEADER))
255  {
256  hwndChild = GetDlgItem(hwndDlg, IDC_SUNKEN_LINEHEADER);
257  GetClientRect(hwndChild, &r);
258  MapWindowPoints(hwndChild, hwndDlg, (LPPOINT) &r, 2);
259  rc->top += r.bottom + 1;
260  }
261  } else {
262  HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
263  GetClientRect(hwndTabCtrl, rc);
264  SendMessageW(hwndTabCtrl, TCM_ADJUSTRECT, FALSE, (LPARAM)rc);
265  MapWindowPoints(hwndTabCtrl, hwndDlg, (LPPOINT)rc, 2);
266  }
267 }
268 
269 /******************************************************************************
270  * PROPSHEET_FindPageByResId
271  *
272  * Find page index corresponding to page resource id.
273  */
274 static INT PROPSHEET_FindPageByResId(const PropSheetInfo * psInfo, LRESULT resId)
275 {
276  INT i;
277 
278  for (i = 0; i < psInfo->nPages; i++)
279  {
281 
282  /* Fixme: if resource ID is a string shall we use strcmp ??? */
283  if (lppsp->u.pszTemplate == (LPVOID)resId)
284  break;
285  }
286 
287  return i;
288 }
289 
290 /******************************************************************************
291  * PROPSHEET_CollectSheetInfoCommon
292  *
293  * Common code for PROPSHEET_CollectSheetInfoA/W
294  */
296 {
298 
299  psInfo->hasHelp = dwFlags & PSH_HASHELP;
300  psInfo->hasApply = !(dwFlags & PSH_NOAPPLYNOW);
302  psInfo->isModeless = dwFlags & PSH_MODELESS;
304  if (psInfo->active_page < 0 || psInfo->active_page >= psInfo->nPages)
305  psInfo->active_page = 0;
306 
307  psInfo->result = 0;
308  psInfo->hImageList = 0;
309  psInfo->activeValid = FALSE;
310 }
311 
312 /******************************************************************************
313  * PROPSHEET_CollectSheetInfoA
314  *
315  * Collect relevant data.
316  */
318  PropSheetInfo * psInfo)
319 {
320  DWORD dwSize = min(lppsh->dwSize,sizeof(PROPSHEETHEADERA));
321  DWORD dwFlags = lppsh->dwFlags;
322 
323  psInfo->useCallback = (dwFlags & PSH_USECALLBACK )&& (lppsh->pfnCallback);
324 
325  memcpy(&psInfo->ppshheader,lppsh,dwSize);
326  TRACE("\n** PROPSHEETHEADER **\ndwSize\t\t%d\ndwFlags\t\t%08x\nhwndParent\t%p\nhInstance\t%p\npszCaption\t'%s'\nnPages\t\t%d\npfnCallback\t%p\n",
327  lppsh->dwSize, lppsh->dwFlags, lppsh->hwndParent, lppsh->hInstance,
328  debugstr_a(lppsh->pszCaption), lppsh->nPages, lppsh->pfnCallback);
329 
330  if (lppsh->dwFlags & INTRNL_ANY_WIZARD)
331  psInfo->ppshheader.pszCaption = NULL;
332  else
333  {
334  if (!IS_INTRESOURCE(lppsh->pszCaption))
335  {
336  int len = MultiByteToWideChar(CP_ACP, 0, lppsh->pszCaption, -1, NULL, 0);
337  WCHAR *caption = Alloc( len*sizeof (WCHAR) );
338 
339  MultiByteToWideChar(CP_ACP, 0, lppsh->pszCaption, -1, caption, len);
340  psInfo->ppshheader.pszCaption = caption;
341  }
342  }
343  psInfo->nPages = lppsh->nPages;
344 
346  {
347  TRACE("PSH_USEPSTARTPAGE is on\n");
348  psInfo->active_page = 0;
349  }
350  else
351  psInfo->active_page = lppsh->u2.nStartPage;
352 
354 }
355 
356 /******************************************************************************
357  * PROPSHEET_CollectSheetInfoW
358  *
359  * Collect relevant data.
360  */
362  PropSheetInfo * psInfo)
363 {
364  DWORD dwSize = min(lppsh->dwSize,sizeof(PROPSHEETHEADERW));
365  DWORD dwFlags = lppsh->dwFlags;
366 
367  psInfo->useCallback = (dwFlags & PSH_USECALLBACK) && (lppsh->pfnCallback);
368 
369  memcpy(&psInfo->ppshheader,lppsh,dwSize);
370  TRACE("\n** PROPSHEETHEADER **\ndwSize\t\t%d\ndwFlags\t\t%08x\nhwndParent\t%p\nhInstance\t%p\npszCaption\t%s\nnPages\t\t%d\npfnCallback\t%p\n",
371  lppsh->dwSize, lppsh->dwFlags, lppsh->hwndParent, lppsh->hInstance, debugstr_w(lppsh->pszCaption), lppsh->nPages, lppsh->pfnCallback);
372 
373  if (lppsh->dwFlags & INTRNL_ANY_WIZARD)
374  psInfo->ppshheader.pszCaption = NULL;
375  else
376  {
377  if (!IS_INTRESOURCE(lppsh->pszCaption))
378  psInfo->ppshheader.pszCaption = heap_strdupW( lppsh->pszCaption );
379  }
380  psInfo->nPages = lppsh->nPages;
381 
383  {
384  TRACE("PSH_USEPSTARTPAGE is on\n");
385  psInfo->active_page = 0;
386  }
387  else
388  psInfo->active_page = lppsh->u2.nStartPage;
389 
391 }
392 
393 /******************************************************************************
394  * PROPSHEET_CollectPageInfo
395  *
396  * Collect property sheet data.
397  * With code taken from DIALOG_ParseTemplate32.
398  */
400  PropSheetInfo * psInfo,
401  int index, BOOL resize)
402 {
403  const DLGTEMPLATE* pTemplate;
404  const WORD* p;
405  DWORD dwFlags;
406  int width, height;
407 
408  if (!lppsp)
409  return FALSE;
410 
411  TRACE("\n");
412  psInfo->proppage[index].hpage = (HPROPSHEETPAGE)lppsp;
413  psInfo->proppage[index].hwndPage = 0;
414  psInfo->proppage[index].isDirty = FALSE;
415 
416  /*
417  * Process property page flags.
418  */
419  dwFlags = lppsp->dwFlags;
420  psInfo->proppage[index].useCallback = (dwFlags & PSP_USECALLBACK) && (lppsp->pfnCallback);
423 
424  /* as soon as we have a page with the help flag, set the sheet flag on */
425  if (psInfo->proppage[index].hasHelp)
426  psInfo->hasHelp = TRUE;
427 
428  /*
429  * Process page template.
430  */
431  if (dwFlags & PSP_DLGINDIRECT)
432  pTemplate = lppsp->u.pResource;
433  else if(dwFlags & PSP_INTERNAL_UNICODE )
434  {
435  HRSRC hResource = FindResourceW(lppsp->hInstance,
436  lppsp->u.pszTemplate,
437  (LPWSTR)RT_DIALOG);
438  HGLOBAL hTemplate = LoadResource(lppsp->hInstance,
439  hResource);
440  pTemplate = LockResource(hTemplate);
441  }
442  else
443  {
444  HRSRC hResource = FindResourceA(lppsp->hInstance,
445  (LPCSTR)lppsp->u.pszTemplate,
446  (LPSTR)RT_DIALOG);
447  HGLOBAL hTemplate = LoadResource(lppsp->hInstance,
448  hResource);
449  pTemplate = LockResource(hTemplate);
450  }
451 
452  /*
453  * Extract the size of the page and the caption.
454  */
455  if (!pTemplate)
456  return FALSE;
457 
458  p = (const WORD *)pTemplate;
459 
460  if (((const MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF)
461  {
462  /* DLGTEMPLATEEX (not defined in any std. header file) */
463 
464  p++; /* dlgVer */
465  p++; /* signature */
466  p += 2; /* help ID */
467  p += 2; /* ext style */
468  p += 2; /* style */
469  }
470  else
471  {
472  /* DLGTEMPLATE */
473 
474  p += 2; /* style */
475  p += 2; /* ext style */
476  }
477 
478  p++; /* nb items */
479  p++; /* x */
480  p++; /* y */
481  width = (WORD)*p; p++;
482  height = (WORD)*p; p++;
483 
484  if (lppsp->dwFlags & (PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE))
485  psInfo->ppshheader.dwFlags |= PSH_HEADER;
486 
487  /* Special calculation for interior wizard pages so the largest page is
488  * calculated correctly. We need to add all the padding and space occupied
489  * by the header so the width and height sums up to the whole wizard client
490  * area. */
491  if ((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)) &&
492  (psInfo->ppshheader.dwFlags & PSH_HEADER) &&
493  !(dwFlags & PSP_HIDEHEADER))
494  {
496  width += 2 * WIZARD_PADDING;
497  }
498  if (psInfo->ppshheader.dwFlags & PSH_WIZARD)
499  {
500  height += 2 * WIZARD_PADDING;
501  width += 2 * WIZARD_PADDING;
502  }
503 
504  /* remember the largest width and height */
505  if (resize)
506  {
507  if (width > psInfo->width)
508  psInfo->width = width;
509 
510  if (height > psInfo->height)
511  psInfo->height = height;
512  }
513 
514  /* menu */
515  switch ((WORD)*p)
516  {
517  case 0x0000:
518  p++;
519  break;
520  case 0xffff:
521  p += 2;
522  break;
523  default:
524  p += lstrlenW( p ) + 1;
525  break;
526  }
527 
528  /* class */
529  switch ((WORD)*p)
530  {
531  case 0x0000:
532  p++;
533  break;
534  case 0xffff:
535  p += 2;
536  break;
537  default:
538  p += lstrlenW( p ) + 1;
539  break;
540  }
541 
542  /* Extract the caption */
543  psInfo->proppage[index].pszText = p;
544  TRACE("Tab %d %s\n",index,debugstr_w( p ));
545 
546  if (dwFlags & PSP_USETITLE)
547  {
548  WCHAR szTitle[256];
549  const WCHAR *pTitle;
550  static const WCHAR pszNull[] = { '(','n','u','l','l',')',0 };
551 
552  if (IS_INTRESOURCE( lppsp->pszTitle ))
553  {
555  pTitle = szTitle;
556  else if (*p)
557  pTitle = p;
558  else
559  pTitle = pszNull;
560  }
561  else
562  pTitle = lppsp->pszTitle;
563 
564  psInfo->proppage[index].pszText = heap_strdupW( pTitle );
565  }
566 
567  /*
568  * Build the image list for icons
569  */
570  if ((dwFlags & PSP_USEHICON) || (dwFlags & PSP_USEICONID))
571  {
572  HICON hIcon;
573  int icon_cx = GetSystemMetrics(SM_CXSMICON);
574  int icon_cy = GetSystemMetrics(SM_CYSMICON);
575 
576  if (dwFlags & PSP_USEICONID)
577  hIcon = LoadImageW(lppsp->hInstance, lppsp->u2.pszIcon, IMAGE_ICON,
578  icon_cx, icon_cy, LR_DEFAULTCOLOR);
579  else
580  hIcon = lppsp->u2.hIcon;
581 
582  if ( hIcon )
583  {
584  if (psInfo->hImageList == 0 )
585  psInfo->hImageList = ImageList_Create(icon_cx, icon_cy, ILC_COLOR, 1, 1);
586 
588  }
589 
590  }
591 
592  return TRUE;
593 }
594 
595 /******************************************************************************
596  * PROPSHEET_CreateDialog
597  *
598  * Creates the actual property sheet.
599  */
601 {
602  LRESULT ret;
603  LPCVOID template;
604  LPVOID temp = 0;
605  HRSRC hRes;
606  DWORD resSize;
607  WORD resID = IDD_PROPSHEET;
608 
609  TRACE("(%p)\n", psInfo);
610  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD)
611  resID = IDD_WIZARD;
612 
613  if( psInfo->unicode )
614  {
615  if(!(hRes = FindResourceW(COMCTL32_hModule,
616  MAKEINTRESOURCEW(resID),
617  (LPWSTR)RT_DIALOG)))
618  return -1;
619  }
620  else
621  {
622  if(!(hRes = FindResourceA(COMCTL32_hModule,
623  MAKEINTRESOURCEA(resID),
624  (LPSTR)RT_DIALOG)))
625  return -1;
626  }
627 
628  if(!(template = LoadResource(COMCTL32_hModule, hRes)))
629  return -1;
630 
631  /*
632  * Make a copy of the dialog template.
633  */
634  resSize = SizeofResource(COMCTL32_hModule, hRes);
635 
636  temp = Alloc(2 * resSize);
637 
638  if (!temp)
639  return -1;
640 
641  memcpy(temp, template, resSize);
642 
643  if (psInfo->ppshheader.dwFlags & PSH_NOCONTEXTHELP)
644  {
645  if (((MyDLGTEMPLATEEX*)temp)->signature == 0xFFFF)
646  ((MyDLGTEMPLATEEX*)temp)->style &= ~DS_CONTEXTHELP;
647  else
649  }
650  if ((psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD) &&
652  {
653  if (((MyDLGTEMPLATEEX*)temp)->signature == 0xFFFF)
654  ((MyDLGTEMPLATEEX*)temp)->style |= DS_CONTEXTHELP;
655  else
657  }
658 
659  if (psInfo->useCallback)
660  (*(psInfo->ppshheader.pfnCallback))(0, PSCB_PRECREATE, (LPARAM)temp);
661 
662  /* NOTE: MSDN states "Returns a positive value if successful, or -1
663  * otherwise for modal property sheets.", but this is wrong. The
664  * actual return value is either TRUE (success), FALSE (cancel) or
665  * -1 (error). */
666  if( psInfo->unicode )
667  {
669  temp, psInfo->ppshheader.hwndParent,
670  PROPSHEET_DialogProc, (LPARAM)psInfo);
671  if ( !ret ) ret = -1;
672  }
673  else
674  {
676  temp, psInfo->ppshheader.hwndParent,
677  PROPSHEET_DialogProc, (LPARAM)psInfo);
678  if ( !ret ) ret = -1;
679  }
680 
681  Free(temp);
682 
683  return ret;
684 }
685 
686 /******************************************************************************
687  * PROPSHEET_SizeMismatch
688  *
689  * Verify that the tab control and the "largest" property sheet page dlg. template
690  * match in size.
691  */
692 static BOOL PROPSHEET_SizeMismatch(HWND hwndDlg, const PropSheetInfo* psInfo)
693 {
694  HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
695  RECT rcOrigTab, rcPage;
696 
697  /*
698  * Original tab size.
699  */
700  GetClientRect(hwndTabCtrl, &rcOrigTab);
701  TRACE("orig tab %s\n", wine_dbgstr_rect(&rcOrigTab));
702 
703  /*
704  * Biggest page size.
705  */
706  SetRect(&rcPage, 0, 0, psInfo->width, psInfo->height);
707  MapDialogRect(hwndDlg, &rcPage);
708  TRACE("biggest page %s\n", wine_dbgstr_rect(&rcPage));
709 
710  if ( (rcPage.right - rcPage.left) != (rcOrigTab.right - rcOrigTab.left) )
711  return TRUE;
712  if ( (rcPage.bottom - rcPage.top) != (rcOrigTab.bottom - rcOrigTab.top) )
713  return TRUE;
714 
715  return FALSE;
716 }
717 
718 /******************************************************************************
719  * PROPSHEET_AdjustSize
720  *
721  * Resizes the property sheet and the tab control to fit the largest page.
722  */
723 static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo* psInfo)
724 {
725  HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
726  HWND hwndButton = GetDlgItem(hwndDlg, IDOK);
727  RECT rc,tabRect;
728  int buttonHeight;
730  RECT units;
731  LONG style;
732 
733  /* Get the height of buttons */
734  GetClientRect(hwndButton, &rc);
735  buttonHeight = rc.bottom;
736 
737  /*
738  * Biggest page size.
739  */
740  SetRect(&rc, 0, 0, psInfo->width, psInfo->height);
741  MapDialogRect(hwndDlg, &rc);
742 
743  /* retrieve the dialog units */
744  units.left = units.right = 4;
745  units.top = units.bottom = 8;
746  MapDialogRect(hwndDlg, &units);
747 
748  /*
749  * Resize the tab control.
750  */
751  GetClientRect(hwndTabCtrl,&tabRect);
752 
753  SendMessageW(hwndTabCtrl, TCM_ADJUSTRECT, FALSE, (LPARAM)&tabRect);
754 
755  if ((rc.bottom - rc.top) < (tabRect.bottom - tabRect.top))
756  {
757  rc.bottom = rc.top + tabRect.bottom - tabRect.top;
758  psInfo->height = MulDiv((rc.bottom - rc.top),8,units.top);
759  }
760 
761  if ((rc.right - rc.left) < (tabRect.right - tabRect.left))
762  {
763  rc.right = rc.left + tabRect.right - tabRect.left;
764  psInfo->width = MulDiv((rc.right - rc.left),4,units.left);
765  }
766 
767  SendMessageW(hwndTabCtrl, TCM_ADJUSTRECT, TRUE, (LPARAM)&rc);
768 
769  rc.right -= rc.left;
770  rc.bottom -= rc.top;
771  TRACE("setting tab %p, rc (0,0)-(%d,%d)\n",
772  hwndTabCtrl, rc.right, rc.bottom);
773  SetWindowPos(hwndTabCtrl, 0, 0, 0, rc.right, rc.bottom,
775 
776  GetClientRect(hwndTabCtrl, &rc);
777 
778  TRACE("tab client rc %s\n", wine_dbgstr_rect(&rc));
779 
780  rc.right += (padding.x * 2);
781  rc.bottom += buttonHeight + (3 * padding.y);
782 
783  style = GetWindowLongW(hwndDlg, GWL_STYLE);
784  if (!(style & WS_CHILD))
786 
787  rc.right -= rc.left;
788  rc.bottom -= rc.top;
789 
790  /*
791  * Resize the property sheet.
792  */
793  TRACE("setting dialog %p, rc (0,0)-(%d,%d)\n",
794  hwndDlg, rc.right, rc.bottom);
795  SetWindowPos(hwndDlg, 0, 0, 0, rc.right, rc.bottom,
797  return TRUE;
798 }
799 
800 /******************************************************************************
801  * PROPSHEET_AdjustSizeWizard
802  *
803  * Resizes the property sheet to fit the largest page.
804  */
805 static BOOL PROPSHEET_AdjustSizeWizard(HWND hwndDlg, const PropSheetInfo* psInfo)
806 {
807  HWND hwndLine = GetDlgItem(hwndDlg, IDC_SUNKEN_LINE);
808  RECT rc, lineRect, dialogRect;
809 
810  /* Biggest page size */
811  SetRect(&rc, 0, 0, psInfo->width, psInfo->height);
812  MapDialogRect(hwndDlg, &rc);
813 
814  TRACE("Biggest page %s\n", wine_dbgstr_rect(&rc));
815 
816  /* Add space for the buttons row */
817  GetWindowRect(hwndLine, &lineRect);
818  MapWindowPoints(NULL, hwndDlg, (LPPOINT)&lineRect, 2);
819  GetClientRect(hwndDlg, &dialogRect);
820  rc.bottom += dialogRect.bottom - lineRect.top - 1;
821 
822  /* Convert the client coordinates to window coordinates */
824 
825  /* Resize the property sheet */
826  TRACE("setting dialog %p, rc (0,0)-(%d,%d)\n",
827  hwndDlg, rc.right, rc.bottom);
828  SetWindowPos(hwndDlg, 0, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
830 
831  return TRUE;
832 }
833 
834 /******************************************************************************
835  * PROPSHEET_AdjustButtons
836  *
837  * Adjusts the buttons' positions.
838  */
840 {
841  HWND hwndButton = GetDlgItem(hwndParent, IDOK);
842  RECT rcSheet;
843  int x, y;
844  int num_buttons = 2;
845  int buttonWidth, buttonHeight;
847 
848  if (psInfo->hasApply)
849  num_buttons++;
850 
851  if (psInfo->hasHelp)
852  num_buttons++;
853 
854  /*
855  * Obtain the size of the buttons.
856  */
857  GetClientRect(hwndButton, &rcSheet);
858  buttonWidth = rcSheet.right;
859  buttonHeight = rcSheet.bottom;
860 
861  /*
862  * Get the size of the property sheet.
863  */
864  GetClientRect(hwndParent, &rcSheet);
865 
866  /*
867  * All buttons will be at this y coordinate.
868  */
869  y = rcSheet.bottom - (padding.y + buttonHeight);
870 
871  /*
872  * Position OK button and make it default.
873  */
874  hwndButton = GetDlgItem(hwndParent, IDOK);
875 
876  x = rcSheet.right - ((padding.x + buttonWidth) * num_buttons);
877 
878  SetWindowPos(hwndButton, 0, x, y, 0, 0,
880 
882 
883 
884  /*
885  * Position Cancel button.
886  */
887  hwndButton = GetDlgItem(hwndParent, IDCANCEL);
888 
889  x += padding.x + buttonWidth;
890 
891  SetWindowPos(hwndButton, 0, x, y, 0, 0,
893 
894  /*
895  * Position Apply button.
896  */
897  hwndButton = GetDlgItem(hwndParent, IDC_APPLY_BUTTON);
898 
899  if(psInfo->hasApply)
900  x += padding.x + buttonWidth;
901  else
902  ShowWindow(hwndButton, SW_HIDE);
903 
904  SetWindowPos(hwndButton, 0, x, y, 0, 0,
906  EnableWindow(hwndButton, FALSE);
907 
908  /*
909  * Position Help button.
910  */
911  hwndButton = GetDlgItem(hwndParent, IDHELP);
912 
913  x += padding.x + buttonWidth;
914  SetWindowPos(hwndButton, 0, x, y, 0, 0,
916 
917  if(!psInfo->hasHelp)
918  ShowWindow(hwndButton, SW_HIDE);
919 
920  return TRUE;
921 }
922 
923 /******************************************************************************
924  * PROPSHEET_AdjustButtonsWizard
925  *
926  * Adjusts the buttons' positions.
927  */
929  const PropSheetInfo* psInfo)
930 {
931  HWND hwndButton = GetDlgItem(hwndParent, IDCANCEL);
933  HWND hwndLineHeader = GetDlgItem(hwndParent, IDC_SUNKEN_LINEHEADER);
934  RECT rcSheet;
935  int x, y;
936  int num_buttons = 3;
937  int buttonWidth, buttonHeight, lineHeight, lineWidth;
939 
940  if (psInfo->hasHelp)
941  num_buttons++;
942  if (psInfo->hasFinish)
943  num_buttons++;
944 
945  /*
946  * Obtain the size of the buttons.
947  */
948  GetClientRect(hwndButton, &rcSheet);
949  buttonWidth = rcSheet.right;
950  buttonHeight = rcSheet.bottom;
951 
952  GetClientRect(hwndLine, &rcSheet);
953  lineHeight = rcSheet.bottom;
954 
955  /*
956  * Get the size of the property sheet.
957  */
958  GetClientRect(hwndParent, &rcSheet);
959 
960  /*
961  * All buttons will be at this y coordinate.
962  */
963  y = rcSheet.bottom - (padding.y + buttonHeight);
964 
965  /*
966  * Position the Back button.
967  */
968  hwndButton = GetDlgItem(hwndParent, IDC_BACK_BUTTON);
969 
970  x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 1)) - buttonWidth;
971 
972  SetWindowPos(hwndButton, 0, x, y, 0, 0,
974 
975  /*
976  * Position the Next button.
977  */
978  hwndButton = GetDlgItem(hwndParent, IDC_NEXT_BUTTON);
979 
980  x += buttonWidth;
981 
982  SetWindowPos(hwndButton, 0, x, y, 0, 0,
984 
985  /*
986  * Position the Finish button.
987  */
988  hwndButton = GetDlgItem(hwndParent, IDC_FINISH_BUTTON);
989 
990  if (psInfo->hasFinish)
991  x += padding.x + buttonWidth;
992 
993  SetWindowPos(hwndButton, 0, x, y, 0, 0,
995 
996  if (!psInfo->hasFinish)
997  ShowWindow(hwndButton, SW_HIDE);
998 
999  /*
1000  * Position the Cancel button.
1001  */
1002  hwndButton = GetDlgItem(hwndParent, IDCANCEL);
1003 
1004  x += padding.x + buttonWidth;
1005 
1006  SetWindowPos(hwndButton, 0, x, y, 0, 0,
1008 
1009  /*
1010  * Position Help button.
1011  */
1012  hwndButton = GetDlgItem(hwndParent, IDHELP);
1013 
1014  if (psInfo->hasHelp)
1015  {
1016  x += padding.x + buttonWidth;
1017 
1018  SetWindowPos(hwndButton, 0, x, y, 0, 0,
1020  }
1021  else
1022  ShowWindow(hwndButton, SW_HIDE);
1023 
1024  if (psInfo->ppshheader.dwFlags &
1025  (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW | PSH_WIZARD_LITE))
1026  padding.x = 0;
1027 
1028  /*
1029  * Position and resize the sunken line.
1030  */
1031  x = padding.x;
1032  y = rcSheet.bottom - ((padding.y * 2) + buttonHeight + lineHeight);
1033 
1034  lineWidth = rcSheet.right - (padding.x * 2);
1035  SetWindowPos(hwndLine, 0, x, y, lineWidth, 2,
1037 
1038  /*
1039  * Position and resize the header sunken line.
1040  */
1041 
1042  SetWindowPos(hwndLineHeader, 0, 0, 0, rcSheet.right, 2,
1044  if (!(psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)))
1045  ShowWindow(hwndLineHeader, SW_HIDE);
1046 
1047  return TRUE;
1048 }
1049 
1050 /******************************************************************************
1051  * PROPSHEET_GetPaddingInfo
1052  *
1053  * Returns the layout information.
1054  */
1056 {
1057  HWND hwndTab = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1058  RECT rcTab;
1060 
1061  GetWindowRect(hwndTab, &rcTab);
1062  MapWindowPoints( 0, hwndDlg, (POINT *)&rcTab, 2 );
1063 
1064  padding.x = rcTab.left;
1065  padding.y = rcTab.top;
1066 
1067  return padding;
1068 }
1069 
1070 /******************************************************************************
1071  * PROPSHEET_GetPaddingInfoWizard
1072  *
1073  * Returns the layout information.
1074  * Vertical spacing is the distance between the line and the buttons.
1075  * Do NOT use the Help button to gather padding information when it isn't mapped
1076  * (PSH_HASHELP), as app writers aren't forced to supply correct coordinates
1077  * for it in this case !
1078  * FIXME: I'm not sure about any other coordinate problems with these evil
1079  * buttons. Fix it in case additional problems appear or maybe calculate
1080  * a padding in a completely different way, as this is somewhat messy.
1081  */
1083  psInfo)
1084 {
1086  RECT rc;
1087  HWND hwndControl;
1088  INT idButton;
1089  POINT ptButton, ptLine;
1090 
1091  TRACE("\n");
1092  if (psInfo->hasHelp)
1093  {
1094  idButton = IDHELP;
1095  }
1096  else
1097  {
1098  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD)
1099  {
1100  idButton = IDC_NEXT_BUTTON;
1101  }
1102  else
1103  {
1104  /* hopefully this is ok */
1105  idButton = IDCANCEL;
1106  }
1107  }
1108 
1109  hwndControl = GetDlgItem(hwndDlg, idButton);
1110  GetWindowRect(hwndControl, &rc);
1111  MapWindowPoints( 0, hwndDlg, (POINT *)&rc, 2 );
1112  ptButton.x = rc.left;
1113  ptButton.y = rc.top;
1114 
1115  /* Line */
1116  hwndControl = GetDlgItem(hwndDlg, IDC_SUNKEN_LINE);
1117  GetWindowRect(hwndControl, &rc);
1118  MapWindowPoints( 0, hwndDlg, (POINT *)&rc, 2 );
1119  ptLine.x = rc.left;
1120  ptLine.y = rc.bottom;
1121 
1122  padding.y = ptButton.y - ptLine.y;
1123 
1124  if (padding.y < 0)
1125  ERR("padding negative ! Please report this !\n");
1126 
1127  /* this is most probably not correct, but the best we have now */
1128  padding.x = padding.y;
1129  return padding;
1130 }
1131 
1132 /******************************************************************************
1133  * PROPSHEET_CreateTabControl
1134  *
1135  * Insert the tabs in the tab control.
1136  */
1138  const PropSheetInfo * psInfo)
1139 {
1140  HWND hwndTabCtrl = GetDlgItem(hwndParent, IDC_TABCONTROL);
1141  TCITEMW item;
1142  int i, nTabs;
1143  int iImage = 0;
1144 
1145  TRACE("\n");
1146  item.mask = TCIF_TEXT;
1147  item.cchTextMax = MAX_TABTEXT_LENGTH;
1148 
1149  nTabs = psInfo->nPages;
1150 
1151  /*
1152  * Set the image list for icons.
1153  */
1154  if (psInfo->hImageList)
1155  {
1156  SendMessageW(hwndTabCtrl, TCM_SETIMAGELIST, 0, (LPARAM)psInfo->hImageList);
1157  }
1158 
1159  SendMessageW(hwndTabCtrl, WM_SETREDRAW, 0, 0);
1160  for (i = 0; i < nTabs; i++)
1161  {
1162  if ( psInfo->proppage[i].hasIcon )
1163  {
1164  item.mask |= TCIF_IMAGE;
1165  item.iImage = iImage++;
1166  }
1167  else
1168  {
1169  item.mask &= ~TCIF_IMAGE;
1170  }
1171 
1172  item.pszText = (LPWSTR) psInfo->proppage[i].pszText;
1173  SendMessageW(hwndTabCtrl, TCM_INSERTITEMW, i, (LPARAM)&item);
1174  }
1175  SendMessageW(hwndTabCtrl, WM_SETREDRAW, 1, 0);
1176 
1177  return TRUE;
1178 }
1179 
1180 /******************************************************************************
1181  * PROPSHEET_WizardSubclassProc
1182  *
1183  * Subclassing window procedure for wizard exterior pages to prevent drawing
1184  * background and so drawing above the watermark.
1185  */
1186 static LRESULT CALLBACK
1188 {
1189  switch (uMsg)
1190  {
1191  case WM_ERASEBKGND:
1192  return TRUE;
1193 
1194  case WM_CTLCOLORSTATIC:
1197  }
1198 
1199  return DefSubclassProc(hwnd, uMsg, wParam, lParam);
1200 }
1201 
1202 /*
1203  * Get the size of an in-memory Template
1204  *
1205  *( Based on the code of PROPSHEET_CollectPageInfo)
1206  * See also dialog.c/DIALOG_ParseTemplate32().
1207  */
1208 
1209 static UINT GetTemplateSize(const DLGTEMPLATE* pTemplate)
1210 
1211 {
1212  const WORD* p = (const WORD *)pTemplate;
1213  BOOL istemplateex = (((const MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF);
1214  WORD nrofitems;
1215  UINT ret;
1216 
1217  if (istemplateex)
1218  {
1219  /* DLGTEMPLATEEX (not defined in any std. header file) */
1220 
1221  TRACE("is DLGTEMPLATEEX\n");
1222  p++; /* dlgVer */
1223  p++; /* signature */
1224  p += 2; /* help ID */
1225  p += 2; /* ext style */
1226  p += 2; /* style */
1227  }
1228  else
1229  {
1230  /* DLGTEMPLATE */
1231 
1232  TRACE("is DLGTEMPLATE\n");
1233  p += 2; /* style */
1234  p += 2; /* ext style */
1235  }
1236 
1237  nrofitems = (WORD)*p; p++; /* nb items */
1238  p++; /* x */
1239  p++; /* y */
1240  p++; /* width */
1241  p++; /* height */
1242 
1243  /* menu */
1244  switch ((WORD)*p)
1245  {
1246  case 0x0000:
1247  p++;
1248  break;
1249  case 0xffff:
1250  p += 2;
1251  break;
1252  default:
1253  TRACE("menu %s\n",debugstr_w( p ));
1254  p += lstrlenW( p ) + 1;
1255  break;
1256  }
1257 
1258  /* class */
1259  switch ((WORD)*p)
1260  {
1261  case 0x0000:
1262  p++;
1263  break;
1264  case 0xffff:
1265  p += 2; /* 0xffff plus predefined window class ordinal value */
1266  break;
1267  default:
1268  TRACE("class %s\n",debugstr_w( p ));
1269  p += lstrlenW( p ) + 1;
1270  break;
1271  }
1272 
1273  /* title */
1274  TRACE("title %s\n",debugstr_w( p ));
1275  p += lstrlenW( p ) + 1;
1276 
1277  /* font, if DS_SETFONT set */
1278  if ((DS_SETFONT & ((istemplateex)? ((const MyDLGTEMPLATEEX*)pTemplate)->style :
1279  pTemplate->style)))
1280  {
1281  p+=(istemplateex)?3:1;
1282  TRACE("font %s\n",debugstr_w( p ));
1283  p += lstrlenW( p ) + 1; /* the font name */
1284  }
1285 
1286  /* now process the DLGITEMTEMPLATE(EX) structs (plus custom data)
1287  * that are following the DLGTEMPLATE(EX) data */
1288  TRACE("%d items\n",nrofitems);
1289  while (nrofitems > 0)
1290  {
1291  p = (WORD*)(((DWORD_PTR)p + 3) & ~3); /* DWORD align */
1292 
1293  /* skip header */
1294  p += (istemplateex ? sizeof(MyDLGITEMTEMPLATEEX) : sizeof(DLGITEMTEMPLATE))/sizeof(WORD);
1295 
1296  /* check class */
1297  switch ((WORD)*p)
1298  {
1299  case 0x0000:
1300  p++;
1301  break;
1302  case 0xffff:
1303  TRACE("class ordinal 0x%08x\n",*(const DWORD*)p);
1304  p += 2;
1305  break;
1306  default:
1307  TRACE("class %s\n",debugstr_w( p ));
1308  p += lstrlenW( p ) + 1;
1309  break;
1310  }
1311 
1312  /* check title text */
1313  switch ((WORD)*p)
1314  {
1315  case 0x0000:
1316  p++;
1317  break;
1318  case 0xffff:
1319  TRACE("text ordinal 0x%08x\n",*(const DWORD*)p);
1320  p += 2;
1321  break;
1322  default:
1323  TRACE("text %s\n",debugstr_w( p ));
1324  p += lstrlenW( p ) + 1;
1325  break;
1326  }
1327  p += *p / sizeof(WORD) + 1; /* Skip extra data */
1328  --nrofitems;
1329  }
1330 
1331  ret = (p - (const WORD*)pTemplate) * sizeof(WORD);
1332  TRACE("%p %p size 0x%08x\n", p, pTemplate, ret);
1333  return ret;
1334 }
1335 
1336 #ifdef __REACTOS__
1337 static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage);
1338 #endif
1339 /******************************************************************************
1340  * PROPSHEET_CreatePage
1341  *
1342  * Creates a page.
1343  */
1345  int index,
1346  const PropSheetInfo * psInfo,
1347  LPCPROPSHEETPAGEW ppshpage)
1348 {
1349  const DLGTEMPLATE* pTemplate;
1350  HWND hwndPage;
1351  DWORD resSize;
1352  DLGTEMPLATE* pTemplateCopy = NULL;
1353 
1354  TRACE("index %d\n", index);
1355 
1356  if (ppshpage == NULL)
1357  {
1358  return FALSE;
1359  }
1360 
1361  if (ppshpage->dwFlags & PSP_DLGINDIRECT)
1362  {
1363  pTemplate = ppshpage->u.pResource;
1364  resSize = GetTemplateSize(pTemplate);
1365  }
1366  else if(ppshpage->dwFlags & PSP_INTERNAL_UNICODE)
1367  {
1368  HRSRC hResource;
1369  HANDLE hTemplate;
1370 
1371  hResource = FindResourceW(ppshpage->hInstance,
1372  ppshpage->u.pszTemplate,
1373  (LPWSTR)RT_DIALOG);
1374  if(!hResource)
1375  return FALSE;
1376 
1377  resSize = SizeofResource(ppshpage->hInstance, hResource);
1378 
1379  hTemplate = LoadResource(ppshpage->hInstance, hResource);
1380  if(!hTemplate)
1381  return FALSE;
1382 
1383  pTemplate = LockResource(hTemplate);
1384  /*
1385  * Make a copy of the dialog template to make it writable
1386  */
1387  }
1388  else
1389  {
1390  HRSRC hResource;
1391  HANDLE hTemplate;
1392 
1393  hResource = FindResourceA(ppshpage->hInstance,
1394  (LPCSTR)ppshpage->u.pszTemplate,
1395  (LPSTR)RT_DIALOG);
1396  if(!hResource)
1397  return FALSE;
1398 
1399  resSize = SizeofResource(ppshpage->hInstance, hResource);
1400 
1401  hTemplate = LoadResource(ppshpage->hInstance, hResource);
1402  if(!hTemplate)
1403  return FALSE;
1404 
1405  pTemplate = LockResource(hTemplate);
1406  /*
1407  * Make a copy of the dialog template to make it writable
1408  */
1409  }
1410  pTemplateCopy = Alloc(resSize);
1411  if (!pTemplateCopy)
1412  return FALSE;
1413 
1414  TRACE("copying pTemplate %p into pTemplateCopy %p (%d)\n", pTemplate, pTemplateCopy, resSize);
1415  memcpy(pTemplateCopy, pTemplate, resSize);
1416 
1417  if (((MyDLGTEMPLATEEX*)pTemplateCopy)->signature == 0xFFFF)
1418  {
1419  ((MyDLGTEMPLATEEX*)pTemplateCopy)->style |= WS_CHILD | WS_TABSTOP | DS_CONTROL;
1420  ((MyDLGTEMPLATEEX*)pTemplateCopy)->style &= ~DS_MODALFRAME;
1421  ((MyDLGTEMPLATEEX*)pTemplateCopy)->style &= ~WS_CAPTION;
1422  ((MyDLGTEMPLATEEX*)pTemplateCopy)->style &= ~WS_SYSMENU;
1423  ((MyDLGTEMPLATEEX*)pTemplateCopy)->style &= ~WS_POPUP;
1424  ((MyDLGTEMPLATEEX*)pTemplateCopy)->style &= ~WS_DISABLED;
1425  ((MyDLGTEMPLATEEX*)pTemplateCopy)->style &= ~WS_VISIBLE;
1426  ((MyDLGTEMPLATEEX*)pTemplateCopy)->style &= ~WS_THICKFRAME;
1427 
1428  ((MyDLGTEMPLATEEX*)pTemplateCopy)->exStyle |= WS_EX_CONTROLPARENT;
1429  }
1430  else
1431  {
1432  pTemplateCopy->style |= WS_CHILD | WS_TABSTOP | DS_CONTROL;
1433  pTemplateCopy->style &= ~DS_MODALFRAME;
1434  pTemplateCopy->style &= ~WS_CAPTION;
1435  pTemplateCopy->style &= ~WS_SYSMENU;
1436  pTemplateCopy->style &= ~WS_POPUP;
1437  pTemplateCopy->style &= ~WS_DISABLED;
1438  pTemplateCopy->style &= ~WS_VISIBLE;
1439  pTemplateCopy->style &= ~WS_THICKFRAME;
1440 
1441  pTemplateCopy->dwExtendedStyle |= WS_EX_CONTROLPARENT;
1442  }
1443 
1444  if (psInfo->proppage[index].useCallback)
1445  (*(ppshpage->pfnCallback))(0, PSPCB_CREATE,
1446  (LPPROPSHEETPAGEW)ppshpage);
1447 
1448  if(ppshpage->dwFlags & PSP_INTERNAL_UNICODE)
1449  hwndPage = CreateDialogIndirectParamW(ppshpage->hInstance,
1450  pTemplateCopy,
1451  hwndParent,
1452  ppshpage->pfnDlgProc,
1453  (LPARAM)ppshpage);
1454  else
1455  hwndPage = CreateDialogIndirectParamA(ppshpage->hInstance,
1456  pTemplateCopy,
1457  hwndParent,
1458  ppshpage->pfnDlgProc,
1459  (LPARAM)ppshpage);
1460  /* Free a no more needed copy */
1461  Free(pTemplateCopy);
1462 
1463  if(!hwndPage)
1464  return FALSE;
1465 
1466  psInfo->proppage[index].hwndPage = hwndPage;
1467 
1468  /* Subclass exterior wizard pages */
1469  if((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) &&
1470  (psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
1471  (ppshpage->dwFlags & PSP_HIDEHEADER))
1472  {
1473 #ifdef __REACTOS__
1474  if (psInfo->ppshheader.u4.hbmWatermark)
1475 #endif
1477  (DWORD_PTR)ppshpage);
1478  }
1479  if (!(psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD))
1481 
1482 #ifdef __REACTOS__
1483  PROPSHEET_UnChanged(hwndParent, hwndPage);
1484 #endif
1485  return TRUE;
1486 }
1487 
1488 /******************************************************************************
1489  * PROPSHEET_LoadWizardBitmaps
1490  *
1491  * Loads the watermark and header bitmaps for a wizard.
1492  */
1494 {
1495  if (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD))
1496  {
1497  /* if PSH_USEHBMWATERMARK is not set, load the resource from pszbmWatermark
1498  and put the HBITMAP in hbmWatermark. Thus all the rest of the code always
1499  considers hbmWatermark as valid. */
1500  if ((psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
1501  !(psInfo->ppshheader.dwFlags & PSH_USEHBMWATERMARK))
1502  {
1503  psInfo->ppshheader.u4.hbmWatermark =
1504  CreateMappedBitmap(psInfo->ppshheader.hInstance, (INT_PTR)psInfo->ppshheader.u4.pszbmWatermark, 0, NULL, 0);
1505  }
1506 
1507  /* Same behavior as for watermarks */
1508  if ((psInfo->ppshheader.dwFlags & PSH_HEADER) &&
1509  !(psInfo->ppshheader.dwFlags & PSH_USEHBMHEADER))
1510  {
1511  psInfo->ppshheader.u5.hbmHeader =
1512  CreateMappedBitmap(psInfo->ppshheader.hInstance, (INT_PTR)psInfo->ppshheader.u5.pszbmHeader, 0, NULL, 0);
1513  }
1514  }
1515 }
1516 
1517 
1518 /******************************************************************************
1519  * PROPSHEET_ShowPage
1520  *
1521  * Displays or creates the specified page.
1522  */
1523 static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo)
1524 {
1525  HWND hwndTabCtrl;
1526  HWND hwndLineHeader;
1527  HWND control;
1528  LPCPROPSHEETPAGEW ppshpage;
1529 
1530  TRACE("active_page %d, index %d\n", psInfo->active_page, index);
1531  if (index == psInfo->active_page)
1532  {
1533  if (GetTopWindow(hwndDlg) != psInfo->proppage[index].hwndPage)
1534  SetWindowPos(psInfo->proppage[index].hwndPage, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
1535  return TRUE;
1536  }
1537 
1538  ppshpage = (LPCPROPSHEETPAGEW)psInfo->proppage[index].hpage;
1539  if (psInfo->proppage[index].hwndPage == 0)
1540  {
1541  PROPSHEET_CreatePage(hwndDlg, index, psInfo, ppshpage);
1542  }
1543 
1544  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD)
1545  {
1546  PROPSHEET_SetTitleW(hwndDlg, psInfo->ppshheader.dwFlags,
1547  psInfo->proppage[index].pszText);
1548 
1549  control = GetNextDlgTabItem(psInfo->proppage[index].hwndPage, NULL, FALSE);
1550  if(control != NULL)
1551  SetFocus(control);
1552  }
1553 
1554  if (psInfo->active_page != -1)
1555  ShowWindow(psInfo->proppage[psInfo->active_page].hwndPage, SW_HIDE);
1556 
1558 
1559  /* Synchronize current selection with tab control
1560  * It seems to be needed even in case of PSH_WIZARD (no tab controls there) */
1561  hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1562  SendMessageW(hwndTabCtrl, TCM_SETCURSEL, index, 0);
1563 
1564  psInfo->active_page = index;
1565  psInfo->activeValid = TRUE;
1566 
1567  if (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW) )
1568  {
1569  hwndLineHeader = GetDlgItem(hwndDlg, IDC_SUNKEN_LINEHEADER);
1570  ppshpage = (LPCPROPSHEETPAGEW)psInfo->proppage[index].hpage;
1571 
1572  if ((ppshpage->dwFlags & PSP_HIDEHEADER) || (!(psInfo->ppshheader.dwFlags & PSH_HEADER)) )
1573  ShowWindow(hwndLineHeader, SW_HIDE);
1574  else
1575  ShowWindow(hwndLineHeader, SW_SHOW);
1576  }
1577 
1578  return TRUE;
1579 }
1580 
1581 /******************************************************************************
1582  * PROPSHEET_Back
1583  */
1584 static BOOL PROPSHEET_Back(HWND hwndDlg)
1585 {
1586  PSHNOTIFY psn;
1587  HWND hwndPage;
1588  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1589  LRESULT result;
1590  int idx;
1591 
1592  TRACE("active_page %d\n", psInfo->active_page);
1593  if (psInfo->active_page < 0)
1594  return FALSE;
1595 
1596  psn.hdr.code = PSN_WIZBACK;
1597  psn.hdr.hwndFrom = hwndDlg;
1598  psn.hdr.idFrom = 0;
1599  psn.lParam = 0;
1600 
1601  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1602 
1603  result = SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1604  if (result == -1)
1605  return FALSE;
1606  else if (result == 0)
1607  idx = psInfo->active_page - 1;
1608  else
1610 
1611  if (idx >= 0 && idx < psInfo->nPages)
1612  {
1613  if (PROPSHEET_CanSetCurSel(hwndDlg))
1614  {
1615  SetFocus(GetDlgItem(hwndDlg, IDC_BACK_BUTTON));
1617  PROPSHEET_SetCurSel(hwndDlg, idx, -1, 0);
1618  }
1619  }
1620  return TRUE;
1621 }
1622 
1623 /******************************************************************************
1624  * PROPSHEET_Next
1625  */
1626 static BOOL PROPSHEET_Next(HWND hwndDlg)
1627 {
1628  PSHNOTIFY psn;
1629  HWND hwndPage;
1630  LRESULT msgResult = 0;
1631  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1632  int idx;
1633 
1634  TRACE("active_page %d\n", psInfo->active_page);
1635  if (psInfo->active_page < 0)
1636  return FALSE;
1637 
1638  psn.hdr.code = PSN_WIZNEXT;
1639  psn.hdr.hwndFrom = hwndDlg;
1640  psn.hdr.idFrom = 0;
1641  psn.lParam = 0;
1642 
1643  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1644 
1645  msgResult = SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1646  if (msgResult == -1)
1647  return FALSE;
1648  else if (msgResult == 0)
1649  idx = psInfo->active_page + 1;
1650  else
1651  idx = PROPSHEET_FindPageByResId(psInfo, msgResult);
1652 
1653  if (idx < psInfo->nPages )
1654  {
1655  if (PROPSHEET_CanSetCurSel(hwndDlg) != FALSE)
1656  {
1657  SetFocus(GetDlgItem(hwndDlg, IDC_NEXT_BUTTON));
1659  PROPSHEET_SetCurSel(hwndDlg, idx, 1, 0);
1660  }
1661  }
1662 
1663  return TRUE;
1664 }
1665 
1666 /******************************************************************************
1667  * PROPSHEET_Finish
1668  */
1669 static BOOL PROPSHEET_Finish(HWND hwndDlg)
1670 {
1671  PSHNOTIFY psn;
1672  HWND hwndPage;
1673  LRESULT msgResult = 0;
1674  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1675 
1676  TRACE("active_page %d\n", psInfo->active_page);
1677  if (psInfo->active_page < 0)
1678  return FALSE;
1679 
1680  psn.hdr.code = PSN_WIZFINISH;
1681  psn.hdr.hwndFrom = hwndDlg;
1682  psn.hdr.idFrom = 0;
1683  psn.lParam = 0;
1684 
1685  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1686 
1687  msgResult = SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1688 
1689  TRACE("msg result %ld\n", msgResult);
1690 
1691  if (msgResult != 0)
1692  return FALSE;
1693 
1694  if (psInfo->result == 0)
1695  psInfo->result = IDOK;
1696  if (psInfo->isModeless)
1697  psInfo->activeValid = FALSE;
1698  else
1699  psInfo->ended = TRUE;
1700 
1701  return TRUE;
1702 }
1703 
1704 /******************************************************************************
1705  * PROPSHEET_Apply
1706  */
1708 {
1709  int i;
1710  HWND hwndPage;
1711  PSHNOTIFY psn;
1712  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1713 
1714  TRACE("active_page %d\n", psInfo->active_page);
1715  if (psInfo->active_page < 0)
1716  return FALSE;
1717 
1718  psn.hdr.hwndFrom = hwndDlg;
1719  psn.hdr.idFrom = 0;
1720  psn.lParam = 0;
1721 
1722 
1723  /*
1724  * Send PSN_KILLACTIVE to the current page.
1725  */
1726  psn.hdr.code = PSN_KILLACTIVE;
1727 
1728  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1729 
1730  if (SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn) != FALSE)
1731  return FALSE;
1732 
1733  /*
1734  * Send PSN_APPLY to all pages.
1735  */
1736  psn.hdr.code = PSN_APPLY;
1737  psn.lParam = lParam;
1738 
1739  for (i = 0; i < psInfo->nPages; i++)
1740  {
1741  hwndPage = psInfo->proppage[i].hwndPage;
1742  if (hwndPage)
1743  {
1744  switch (SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn))
1745  {
1746  case PSNRET_INVALID:
1747  PROPSHEET_ShowPage(hwndDlg, i, psInfo);
1748  /* fall through */
1750  return FALSE;
1751  }
1752  }
1753  }
1754 
1755  if(lParam)
1756  {
1757  psInfo->activeValid = FALSE;
1758  }
1759  else if(psInfo->active_page >= 0)
1760  {
1761  psn.hdr.code = PSN_SETACTIVE;
1762  psn.lParam = 0;
1763  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1764  SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1765  }
1766 
1767  return TRUE;
1768 }
1769 
1770 /******************************************************************************
1771  * PROPSHEET_Cancel
1772  */
1773 static void PROPSHEET_Cancel(HWND hwndDlg, LPARAM lParam)
1774 {
1775  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1776  HWND hwndPage;
1777  PSHNOTIFY psn;
1778  int i;
1779 
1780  TRACE("active_page %d\n", psInfo->active_page);
1781  if (psInfo->active_page < 0)
1782  return;
1783 
1784  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1785  psn.hdr.code = PSN_QUERYCANCEL;
1786  psn.hdr.hwndFrom = hwndDlg;
1787  psn.hdr.idFrom = 0;
1788  psn.lParam = 0;
1789 
1790  if (SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn))
1791  return;
1792 
1793  psn.hdr.code = PSN_RESET;
1794  psn.lParam = lParam;
1795 
1796  for (i = 0; i < psInfo->nPages; i++)
1797  {
1798  hwndPage = psInfo->proppage[i].hwndPage;
1799 
1800  if (hwndPage)
1801  SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1802  }
1803 
1804  if (psInfo->isModeless)
1805  {
1806  /* makes PSM_GETCURRENTPAGEHWND return NULL */
1807  psInfo->activeValid = FALSE;
1808  }
1809  else
1810  psInfo->ended = TRUE;
1811 }
1812 
1813 /******************************************************************************
1814  * PROPSHEET_Help
1815  */
1816 static void PROPSHEET_Help(HWND hwndDlg)
1817 {
1818  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1819  HWND hwndPage;
1820  PSHNOTIFY psn;
1821 
1822  TRACE("active_page %d\n", psInfo->active_page);
1823  if (psInfo->active_page < 0)
1824  return;
1825 
1826  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1827  psn.hdr.code = PSN_HELP;
1828  psn.hdr.hwndFrom = hwndDlg;
1829  psn.hdr.idFrom = 0;
1830  psn.lParam = 0;
1831 
1832  SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1833 }
1834 
1835 /******************************************************************************
1836  * PROPSHEET_Changed
1837  */
1838 static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage)
1839 {
1840  int i;
1841  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1842 
1843  TRACE("\n");
1844  if (!psInfo) return;
1845  /*
1846  * Set the dirty flag of this page.
1847  */
1848  for (i = 0; i < psInfo->nPages; i++)
1849  {
1850  if (psInfo->proppage[i].hwndPage == hwndDirtyPage)
1851  psInfo->proppage[i].isDirty = TRUE;
1852  }
1853 
1854  /*
1855  * Enable the Apply button.
1856  */
1857  if (psInfo->hasApply)
1858  {
1859  HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
1860 
1861  EnableWindow(hwndApplyBtn, TRUE);
1862  }
1863 }
1864 
1865 /******************************************************************************
1866  * PROPSHEET_UnChanged
1867  */
1868 static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage)
1869 {
1870  int i;
1871  BOOL noPageDirty = TRUE;
1872  HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
1873  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1874 
1875  TRACE("\n");
1876  if ( !psInfo ) return;
1877  for (i = 0; i < psInfo->nPages; i++)
1878  {
1879  /* set the specified page as clean */
1880  if (psInfo->proppage[i].hwndPage == hwndCleanPage)
1881  psInfo->proppage[i].isDirty = FALSE;
1882 
1883  /* look to see if there are any dirty pages */
1884  if (psInfo->proppage[i].isDirty)
1885  noPageDirty = FALSE;
1886  }
1887 
1888  /*
1889  * Disable Apply button.
1890  */
1891  if (noPageDirty)
1892  EnableWindow(hwndApplyBtn, FALSE);
1893 }
1894 
1895 /******************************************************************************
1896  * PROPSHEET_PressButton
1897  */
1898 static void PROPSHEET_PressButton(HWND hwndDlg, int buttonID)
1899 {
1900  TRACE("buttonID %d\n", buttonID);
1901  switch (buttonID)
1902  {
1903  case PSBTN_APPLYNOW:
1905  break;
1906  case PSBTN_BACK:
1907  PROPSHEET_Back(hwndDlg);
1908  break;
1909  case PSBTN_CANCEL:
1910  PROPSHEET_DoCommand(hwndDlg, IDCANCEL);
1911  break;
1912  case PSBTN_FINISH:
1913  PROPSHEET_Finish(hwndDlg);
1914  break;
1915  case PSBTN_HELP:
1916  PROPSHEET_DoCommand(hwndDlg, IDHELP);
1917  break;
1918  case PSBTN_NEXT:
1919  PROPSHEET_Next(hwndDlg);
1920  break;
1921  case PSBTN_OK:
1922  PROPSHEET_DoCommand(hwndDlg, IDOK);
1923  break;
1924  default:
1925  FIXME("Invalid button index %d\n", buttonID);
1926  }
1927 }
1928 
1929 
1930 /*************************************************************************
1931  * BOOL PROPSHEET_CanSetCurSel [Internal]
1932  *
1933  * Test whether the current page can be changed by sending a PSN_KILLACTIVE
1934  *
1935  * PARAMS
1936  * hwndDlg [I] handle to a Dialog hWnd
1937  *
1938  * RETURNS
1939  * TRUE if Current Selection can change
1940  *
1941  * NOTES
1942  */
1944 {
1945  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1946  HWND hwndPage;
1947  PSHNOTIFY psn;
1948  BOOL res = FALSE;
1949 
1950  if (!psInfo)
1951  {
1952  res = FALSE;
1953  goto end;
1954  }
1955 
1956  TRACE("active_page %d\n", psInfo->active_page);
1957  if (psInfo->active_page < 0)
1958  {
1959  res = TRUE;
1960  goto end;
1961  }
1962 
1963  /*
1964  * Notify the current page.
1965  */
1966  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1967  psn.hdr.code = PSN_KILLACTIVE;
1968  psn.hdr.hwndFrom = hwndDlg;
1969  psn.hdr.idFrom = 0;
1970  psn.lParam = 0;
1971 
1972  res = !SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1973 
1974 end:
1975  TRACE("<-- %d\n", res);
1976  return res;
1977 }
1978 
1979 /******************************************************************************
1980  * PROPSHEET_SetCurSel
1981  */
1983  int index,
1984  int skipdir,
1985  HPROPSHEETPAGE hpage
1986  )
1987 {
1988  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1989  HWND hwndHelp = GetDlgItem(hwndDlg, IDHELP);
1990  HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1991 
1992  TRACE("index %d, skipdir %d, hpage %p\n", index, skipdir, hpage);
1993 
1994  index = PROPSHEET_GetPageIndex(hpage, psInfo, index);
1995 
1996  if (index < 0 || index >= psInfo->nPages)
1997  {
1998  TRACE("Could not find page to select!\n");
1999  return FALSE;
2000  }
2001 
2002  /* unset active page while doing this transition. */
2003  if (psInfo->active_page != -1)
2004  ShowWindow(psInfo->proppage[psInfo->active_page].hwndPage, SW_HIDE);
2005  psInfo->active_page = -1;
2006 
2007  while (1) {
2008  int result;
2009  PSHNOTIFY psn;
2010  RECT rc;
2012 
2013  if (hwndTabControl)
2014  SendMessageW(hwndTabControl, TCM_SETCURSEL, index, 0);
2015 
2016  psn.hdr.code = PSN_SETACTIVE;
2017  psn.hdr.hwndFrom = hwndDlg;
2018  psn.hdr.idFrom = 0;
2019  psn.lParam = 0;
2020 
2021  if (!psInfo->proppage[index].hwndPage) {
2022  if(!PROPSHEET_CreatePage(hwndDlg, index, psInfo, ppshpage)) {
2023  PROPSHEET_RemovePage(hwndDlg, index, NULL);
2024  if(index >= psInfo->nPages)
2025  index--;
2026  if(index < 0)
2027  return FALSE;
2028  continue;
2029  }
2030  }
2031 
2032  /* Resize the property sheet page to the fit in the Tab control
2033  * (for regular property sheets) or to fit in the client area (for
2034  * wizards).
2035  * NOTE: The resizing happens every time the page is selected and
2036  * not only when it's created (some applications depend on it). */
2037  PROPSHEET_GetPageRect(psInfo, hwndDlg, &rc, ppshpage);
2038  TRACE("setting page %p, rc (%s) w=%d, h=%d\n",
2039  psInfo->proppage[index].hwndPage, wine_dbgstr_rect(&rc),
2040  rc.right - rc.left, rc.bottom - rc.top);
2042  rc.left, rc.top,
2043  rc.right - rc.left, rc.bottom - rc.top, 0);
2044 
2045  result = SendMessageW(psInfo->proppage[index].hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
2046  if (!result)
2047  break;
2048  if (result == -1) {
2049  index+=skipdir;
2050  if (index < 0) {
2051  index = 0;
2052  WARN("Tried to skip before first property sheet page!\n");
2053  break;
2054  }
2055  if (index >= psInfo->nPages) {
2056  WARN("Tried to skip after last property sheet page!\n");
2057  index = psInfo->nPages-1;
2058  break;
2059  }
2060  }
2061  else if (result != 0)
2062  {
2063  int old_index = index;
2065  if(index >= psInfo->nPages) {
2066  index = old_index;
2067  WARN("Tried to skip to nonexistent page by res id\n");
2068  break;
2069  }
2070  continue;
2071  }
2072  }
2073 
2074  /* Invalidate the header area */
2075  if ( (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)) &&
2076  (psInfo->ppshheader.dwFlags & PSH_HEADER) )
2077  {
2078  HWND hwndLineHeader = GetDlgItem(hwndDlg, IDC_SUNKEN_LINEHEADER);
2079  RECT r;
2080 
2081  GetClientRect(hwndLineHeader, &r);
2082  MapWindowPoints(hwndLineHeader, hwndDlg, (LPPOINT) &r, 2);
2083  SetRect(&r, 0, 0, r.right + 1, r.top - 1);
2084 
2085  InvalidateRect(hwndDlg, &r, TRUE);
2086  }
2087 
2088  /*
2089  * Display the new page.
2090  */
2091  PROPSHEET_ShowPage(hwndDlg, index, psInfo);
2092 
2093  if (psInfo->proppage[index].hasHelp)
2094  EnableWindow(hwndHelp, TRUE);
2095  else
2096  EnableWindow(hwndHelp, FALSE);
2097 
2098  return TRUE;
2099 }
2100 
2101 /******************************************************************************
2102  * PROPSHEET_SetCurSelId
2103  *
2104  * Selects the page, specified by resource id.
2105  */
2106 static void PROPSHEET_SetCurSelId(HWND hwndDlg, int id)
2107 {
2108  int idx;
2109  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2110 
2111  idx = PROPSHEET_FindPageByResId(psInfo, id);
2112  if (idx < psInfo->nPages )
2113  {
2114  if (PROPSHEET_CanSetCurSel(hwndDlg) != FALSE)
2115  PROPSHEET_SetCurSel(hwndDlg, idx, 1, 0);
2116  }
2117 }
2118 
2119 /******************************************************************************
2120  * PROPSHEET_SetTitleA
2121  */
2122 static void PROPSHEET_SetTitleA(HWND hwndDlg, DWORD dwStyle, LPCSTR lpszText)
2123 {
2124  if(!IS_INTRESOURCE(lpszText))
2125  {
2126  WCHAR szTitle[256];
2127  MultiByteToWideChar(CP_ACP, 0, lpszText, -1, szTitle, ARRAY_SIZE(szTitle));
2128  PROPSHEET_SetTitleW(hwndDlg, dwStyle, szTitle);
2129  }
2130  else
2131  {
2132  PROPSHEET_SetTitleW(hwndDlg, dwStyle, (LPCWSTR)lpszText);
2133  }
2134 }
2135 
2136 /******************************************************************************
2137  * PROPSHEET_SetTitleW
2138  */
2139 static void PROPSHEET_SetTitleW(HWND hwndDlg, DWORD dwStyle, LPCWSTR lpszText)
2140 {
2141  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2142  WCHAR szTitle[256];
2143 
2144  TRACE("%s (style %08x)\n", debugstr_w(lpszText), dwStyle);
2145  if (IS_INTRESOURCE(lpszText)) {
2146  if (!LoadStringW(psInfo->ppshheader.hInstance, LOWORD(lpszText), szTitle, ARRAY_SIZE(szTitle)))
2147  return;
2148  lpszText = szTitle;
2149  }
2150  if (dwStyle & PSH_PROPTITLE)
2151  {
2152  WCHAR* dest;
2153  int lentitle = strlenW(lpszText);
2154  int lenprop = strlenW(psInfo->strPropertiesFor);
2155 
2156  dest = Alloc( (lentitle + lenprop + 1)*sizeof (WCHAR));
2157  wsprintfW(dest, psInfo->strPropertiesFor, lpszText);
2158 
2159  SetWindowTextW(hwndDlg, dest);
2160  Free(dest);
2161  }
2162  else
2163  SetWindowTextW(hwndDlg, lpszText);
2164 }
2165 
2166 /******************************************************************************
2167  * PROPSHEET_SetFinishTextA
2168  */
2169 static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText)
2170 {
2171  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2172  HWND hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
2173 
2174  TRACE("'%s'\n", lpszText);
2175  /* Set text, show and enable the Finish button */
2176  SetWindowTextA(hwndButton, lpszText);
2177  ShowWindow(hwndButton, SW_SHOW);
2178  EnableWindow(hwndButton, TRUE);
2179 
2180  /* Make it default pushbutton */
2182 
2183  /* Hide Back button */
2184  hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
2185  ShowWindow(hwndButton, SW_HIDE);
2186 
2187  if (!psInfo->hasFinish)
2188  {
2189  /* Hide Next button */
2190  hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
2191  ShowWindow(hwndButton, SW_HIDE);
2192  }
2193 }
2194 
2195 /******************************************************************************
2196  * PROPSHEET_SetFinishTextW
2197  */
2198 static void PROPSHEET_SetFinishTextW(HWND hwndDlg, LPCWSTR lpszText)
2199 {
2200  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2201  HWND hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
2202 
2203  TRACE("%s\n", debugstr_w(lpszText));
2204  /* Set text, show and enable the Finish button */
2205  SetWindowTextW(hwndButton, lpszText);
2206  ShowWindow(hwndButton, SW_SHOW);
2207  EnableWindow(hwndButton, TRUE);
2208 
2209  /* Make it default pushbutton */
2211 
2212  /* Hide Back button */
2213  hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
2214  ShowWindow(hwndButton, SW_HIDE);
2215 
2216  if (!psInfo->hasFinish)
2217  {
2218  /* Hide Next button */
2219  hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
2220  ShowWindow(hwndButton, SW_HIDE);
2221  }
2222 }
2223 
2224 /******************************************************************************
2225  * PROPSHEET_QuerySiblings
2226  */
2229 {
2230  int i = 0;
2231  HWND hwndPage;
2232  LRESULT msgResult = 0;
2233  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2234 
2235  while ((i < psInfo->nPages) && (msgResult == 0))
2236  {
2237  hwndPage = psInfo->proppage[i].hwndPage;
2238  msgResult = SendMessageW(hwndPage, PSM_QUERYSIBLINGS, wParam, lParam);
2239  i++;
2240  }
2241 
2242  return msgResult;
2243 }
2244 
2245 /******************************************************************************
2246  * PROPSHEET_InsertPage
2247  */
2248 static BOOL PROPSHEET_InsertPage(HWND hwndDlg, HPROPSHEETPAGE hpageInsertAfter, HPROPSHEETPAGE hpage)
2249 {
2250  PropSheetInfo *psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2251  PropPageInfo *ppi, *prev_ppi = psInfo->proppage;
2252  HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
2253  LPCPROPSHEETPAGEW ppsp = (LPCPROPSHEETPAGEW)hpage;
2254  TCITEMW item;
2255  int index;
2256 
2257  TRACE("hwndDlg %p, hpageInsertAfter %p, hpage %p\n", hwndDlg, hpageInsertAfter, hpage);
2258 
2259  if (IS_INTRESOURCE(hpageInsertAfter))
2260  index = LOWORD(hpageInsertAfter);
2261  else
2262  {
2263  index = PROPSHEET_GetPageIndex(hpageInsertAfter, psInfo, -1);
2264  if (index < 0)
2265  {
2266  TRACE("Could not find page to insert after!\n");
2267  return FALSE;
2268  }
2269  index++;
2270  }
2271 
2272  if (index > psInfo->nPages)
2273  index = psInfo->nPages;
2274 
2275  ppi = Alloc(sizeof(PropPageInfo) * (psInfo->nPages + 1));
2276  if (!ppi)
2277  return FALSE;
2278 
2279  /*
2280  * Fill in a new PropPageInfo entry.
2281  */
2282  if (index > 0)
2283  memcpy(ppi, prev_ppi, index * sizeof(PropPageInfo));
2284  memset(&ppi[index], 0, sizeof(PropPageInfo));
2285  if (index < psInfo->nPages)
2286  memcpy(&ppi[index + 1], &prev_ppi[index], (psInfo->nPages - index) * sizeof(PropPageInfo));
2287  psInfo->proppage = ppi;
2288 
2289  if (!PROPSHEET_CollectPageInfo(ppsp, psInfo, index, FALSE))
2290  {
2291  psInfo->proppage = prev_ppi;
2292  Free(ppi);
2293  return FALSE;
2294  }
2295 
2296  psInfo->proppage[index].hpage = hpage;
2297 
2298  if (ppsp->dwFlags & PSP_PREMATURE)
2299  {
2300  /* Create the page but don't show it */
2301  if (!PROPSHEET_CreatePage(hwndDlg, index, psInfo, ppsp))
2302  {
2303  psInfo->proppage = prev_ppi;
2304  Free(ppi);
2305  return FALSE;
2306  }
2307  }
2308 
2309  Free(prev_ppi);
2310  psInfo->nPages++;
2312  psInfo->active_page++;
2313 
2314  /*
2315  * Add a new tab to the tab control.
2316  */
2317  item.mask = TCIF_TEXT;
2318  item.pszText = (LPWSTR) psInfo->proppage[index].pszText;
2319  item.cchTextMax = MAX_TABTEXT_LENGTH;
2320 
2321  if (psInfo->hImageList)
2322  SendMessageW(hwndTabControl, TCM_SETIMAGELIST, 0, (LPARAM)psInfo->hImageList);
2323 
2324  if (psInfo->proppage[index].hasIcon)
2325  {
2326  item.mask |= TCIF_IMAGE;
2327  item.iImage = index;
2328  }
2329 
2330  SendMessageW(hwndTabControl, TCM_INSERTITEMW, index, (LPARAM)&item);
2331 
2332  /* If it is the only page - show it */
2333  if (psInfo->nPages == 1)
2334  PROPSHEET_SetCurSel(hwndDlg, 0, 1, 0);
2335 
2336  return TRUE;
2337 }
2338 
2339 /******************************************************************************
2340  * PROPSHEET_AddPage
2341  */
2343 {
2344  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2345  TRACE("hwndDlg %p, hpage %p\n", hwndDlg, hpage);
2346  return PROPSHEET_InsertPage(hwndDlg, UlongToPtr(psInfo->nPages), hpage);
2347 }
2348 
2349 /******************************************************************************
2350  * PROPSHEET_RemovePage
2351  */
2353  int index,
2354  HPROPSHEETPAGE hpage)
2355 {
2356  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2357  HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
2358  PropPageInfo* oldPages;
2359 
2360  TRACE("index %d, hpage %p\n", index, hpage);
2361  if (!psInfo) {
2362  return FALSE;
2363  }
2364 
2365  index = PROPSHEET_GetPageIndex(hpage, psInfo, index);
2366 
2367  /* Make sure that index is within range */
2368  if (index < 0 || index >= psInfo->nPages)
2369  {
2370  TRACE("Could not find page to remove!\n");
2371  return FALSE;
2372  }
2373 
2374  TRACE("total pages %d removing page %d active page %d\n",
2375  psInfo->nPages, index, psInfo->active_page);
2376  /*
2377  * Check if we're removing the active page.
2378  */
2379  if (index == psInfo->active_page)
2380  {
2381  if (psInfo->nPages > 1)
2382  {
2383  if (index > 0)
2384  {
2385  /* activate previous page */
2386  PROPSHEET_SetCurSel(hwndDlg, index - 1, -1, 0);
2387  }
2388  else
2389  {
2390  /* activate the next page */
2391  PROPSHEET_SetCurSel(hwndDlg, index + 1, 1, 0);
2392  psInfo->active_page = index;
2393  }
2394  }
2395  else
2396  {
2397  psInfo->active_page = -1;
2398  if (!psInfo->isModeless)
2399  {
2400  psInfo->ended = TRUE;
2401  return TRUE;
2402  }
2403  }
2404  }
2405  else if (index < psInfo->active_page)
2406  psInfo->active_page--;
2407 
2408  /* Unsubclass the page dialog window */
2409  if((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD) &&
2410  (psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
2411  ((PROPSHEETPAGEW*)psInfo->proppage[index].hpage)->dwFlags & PSP_HIDEHEADER))
2412  {
2415  }
2416 
2417  /* Destroy page dialog window */
2419 
2420  /* Free page resources */
2421  if(psInfo->proppage[index].hpage)
2422  {
2423  PROPSHEETPAGEW* psp = (PROPSHEETPAGEW*)psInfo->proppage[index].hpage;
2424 
2425  if (psp->dwFlags & PSP_USETITLE)
2426  Free ((LPVOID)psInfo->proppage[index].pszText);
2427 
2429  }
2430 
2431  /* Remove the tab */
2432  SendMessageW(hwndTabControl, TCM_DELETEITEM, index, 0);
2433 
2434  oldPages = psInfo->proppage;
2435  psInfo->nPages--;
2436  psInfo->proppage = Alloc(sizeof(PropPageInfo) * psInfo->nPages);
2437 
2438  if (index > 0)
2439  memcpy(&psInfo->proppage[0], &oldPages[0], index * sizeof(PropPageInfo));
2440 
2441  if (index < psInfo->nPages)
2442  memcpy(&psInfo->proppage[index], &oldPages[index + 1],
2443  (psInfo->nPages - index) * sizeof(PropPageInfo));
2444 
2445  Free(oldPages);
2446 
2447  return FALSE;
2448 }
2449 
2450 /******************************************************************************
2451  * PROPSHEET_SetWizButtons
2452  *
2453  * This code will work if (and assumes that) the Next button is on top of the
2454  * Finish button. ie. Finish comes after Next in the Z order.
2455  * This means make sure the dialog template reflects this.
2456  *
2457  */
2459 {
2460  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2461  HWND hwndBack = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
2462  HWND hwndNext = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
2463  HWND hwndFinish = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
2464  BOOL enable_finish = ((dwFlags & PSWIZB_FINISH) || psInfo->hasFinish) && !(dwFlags & PSWIZB_DISABLEDFINISH);
2465 
2466 #ifdef __REACTOS__
2467  HWND hwndCancel = GetDlgItem(hwndDlg, IDCANCEL);
2468  INT iDefItem = 0;
2469  HWND hwndFocus;
2470 #endif
2471 
2472  TRACE("%d\n", dwFlags);
2473 
2474  EnableWindow(hwndBack, dwFlags & PSWIZB_BACK);
2475  EnableWindow(hwndNext, dwFlags & PSWIZB_NEXT);
2476  EnableWindow(hwndFinish, enable_finish);
2477 
2478 #ifndef __REACTOS__
2479  /* set the default pushbutton to an enabled button */
2480  if (enable_finish)
2482  else if (dwFlags & PSWIZB_NEXT)
2484  else if (dwFlags & PSWIZB_BACK)
2486  else
2487  SendMessageW(hwndDlg, DM_SETDEFID, IDCANCEL, 0);
2488 #endif
2489 
2490  if (!psInfo->hasFinish)
2491  {
2493  {
2494  /* Hide the Next button */
2495  ShowWindow(hwndNext, SW_HIDE);
2496 
2497  /* Show the Finish button */
2498  ShowWindow(hwndFinish, SW_SHOW);
2499  }
2500  else
2501  {
2502  /* Hide the Finish button */
2503  ShowWindow(hwndFinish, SW_HIDE);
2504  /* Show the Next button */
2505  ShowWindow(hwndNext, SW_SHOW);
2506  }
2507  }
2508 
2509 #ifdef __REACTOS__
2510  /* set the default pushbutton to an enabled button */
2511  if (((dwFlags & PSWIZB_FINISH) || psInfo->hasFinish) && !(dwFlags & PSWIZB_DISABLEDFINISH))
2512  iDefItem = IDC_FINISH_BUTTON;
2513  else if (dwFlags & PSWIZB_NEXT)
2514  iDefItem = IDC_NEXT_BUTTON;
2515  else if (dwFlags & PSWIZB_BACK)
2516  iDefItem = IDC_BACK_BUTTON;
2517  else
2518  iDefItem = IDCANCEL;
2519  SendMessageW(hwndDlg, DM_SETDEFID, iDefItem, 0);
2520 
2521  /* Set focus if no control has it */
2522  hwndFocus = GetFocus();
2523  if (!hwndFocus || hwndFocus == hwndCancel)
2524  SetFocus(GetDlgItem(hwndDlg, iDefItem));
2525 #endif
2526 
2527 }
2528 
2529 /******************************************************************************
2530  * PROPSHEET_SetHeaderTitleW
2531  */
2532 static void PROPSHEET_SetHeaderTitleW(HWND hwndDlg, UINT page_index, const WCHAR *title)
2533 {
2534  PropSheetInfo *psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2536 
2537  TRACE("(%p, %u, %s)\n", hwndDlg, page_index, debugstr_w(title));
2538 
2539  if (page_index >= psInfo->nPages)
2540  return;
2541 
2542  page = (PROPSHEETPAGEW *)psInfo->proppage[page_index].hpage;
2543 
2544  if (!IS_INTRESOURCE(page->pszHeaderTitle))
2545  Free((void *)page->pszHeaderTitle);
2546 
2547  page->pszHeaderTitle = heap_strdupW(title);
2548  page->dwFlags |= PSP_USEHEADERTITLE;
2549 }
2550 
2551 /******************************************************************************
2552  * PROPSHEET_SetHeaderTitleA
2553  */
2554 static void PROPSHEET_SetHeaderTitleA(HWND hwndDlg, UINT page_index, const char *title)
2555 {
2556  WCHAR *titleW;
2557 
2558  TRACE("(%p, %u, %s)\n", hwndDlg, page_index, debugstr_a(title));
2559 
2561  PROPSHEET_SetHeaderTitleW(hwndDlg, page_index, titleW);
2562  Free(titleW);
2563 }
2564 
2565 /******************************************************************************
2566  * PROPSHEET_SetHeaderSubTitleW
2567  */
2568 static void PROPSHEET_SetHeaderSubTitleW(HWND hwndDlg, UINT page_index, const WCHAR *subtitle)
2569 {
2570  PropSheetInfo *psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2572 
2573  TRACE("(%p, %u, %s)\n", hwndDlg, page_index, debugstr_w(subtitle));
2574 
2575  if (page_index >= psInfo->nPages)
2576  return;
2577 
2578  page = (PROPSHEETPAGEW *)psInfo->proppage[page_index].hpage;
2579 
2580  if (!IS_INTRESOURCE(page->pszHeaderSubTitle))
2581  Free((void *)page->pszHeaderSubTitle);
2582 
2583  page->pszHeaderSubTitle = heap_strdupW(subtitle);
2584  page->dwFlags |= PSP_USEHEADERSUBTITLE;
2585 }
2586 
2587 /******************************************************************************
2588  * PROPSHEET_SetHeaderSubTitleA
2589  */
2590 static void PROPSHEET_SetHeaderSubTitleA(HWND hwndDlg, UINT page_index, const char *subtitle)
2591 {
2592  WCHAR *subtitleW;
2593 
2594  TRACE("(%p, %u, %s)\n", hwndDlg, page_index, debugstr_a(subtitle));
2595 
2596  subtitleW = heap_strdupAtoW(subtitle);
2597  PROPSHEET_SetHeaderSubTitleW(hwndDlg, page_index, subtitleW);
2598  Free(subtitleW);
2599 }
2600 
2601 /******************************************************************************
2602  * PROPSHEET_HwndToIndex
2603  */
2604 static LRESULT PROPSHEET_HwndToIndex(HWND hwndDlg, HWND hPageDlg)
2605 {
2606  int index;
2607  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2608 
2609  TRACE("(%p, %p)\n", hwndDlg, hPageDlg);
2610 
2611  for (index = 0; index < psInfo->nPages; index++)
2612  if (psInfo->proppage[index].hwndPage == hPageDlg)
2613  return index;
2614  WARN("%p not found\n", hPageDlg);
2615  return -1;
2616 }
2617 
2618 /******************************************************************************
2619  * PROPSHEET_IndexToHwnd
2620  */
2621 static LRESULT PROPSHEET_IndexToHwnd(HWND hwndDlg, int iPageIndex)
2622 {
2623  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2624  TRACE("(%p, %d)\n", hwndDlg, iPageIndex);
2625  if (!psInfo)
2626  return 0;
2627  if (iPageIndex<0 || iPageIndex>=psInfo->nPages) {
2628  WARN("%d out of range.\n", iPageIndex);
2629  return 0;
2630  }
2631  return (LRESULT)psInfo->proppage[iPageIndex].hwndPage;
2632 }
2633 
2634 /******************************************************************************
2635  * PROPSHEET_PageToIndex
2636  */
2638 {
2639  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2640 
2641  TRACE("(%p, %p)\n", hwndDlg, hPage);
2642 
2643  return PROPSHEET_GetPageIndex(hPage, psInfo, -1);
2644 }
2645 
2646 /******************************************************************************
2647  * PROPSHEET_IndexToPage
2648  */
2649 static LRESULT PROPSHEET_IndexToPage(HWND hwndDlg, int iPageIndex)
2650 {
2651  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2652  TRACE("(%p, %d)\n", hwndDlg, iPageIndex);
2653  if (iPageIndex<0 || iPageIndex>=psInfo->nPages) {
2654  WARN("%d out of range.\n", iPageIndex);
2655  return 0;
2656  }
2657  return (LRESULT)psInfo->proppage[iPageIndex].hpage;
2658 }
2659 
2660 /******************************************************************************
2661  * PROPSHEET_IdToIndex
2662  */
2663 static LRESULT PROPSHEET_IdToIndex(HWND hwndDlg, int iPageId)
2664 {
2665  int index;
2666  LPCPROPSHEETPAGEW psp;
2667  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2668  TRACE("(%p, %d)\n", hwndDlg, iPageId);
2669  for (index = 0; index < psInfo->nPages; index++) {
2670  psp = (LPCPROPSHEETPAGEW)psInfo->proppage[index].hpage;
2671  if (psp->u.pszTemplate == MAKEINTRESOURCEW(iPageId))
2672  return index;
2673  }
2674 
2675  return -1;
2676 }
2677 
2678 /******************************************************************************
2679  * PROPSHEET_IndexToId
2680  */
2681 static LRESULT PROPSHEET_IndexToId(HWND hwndDlg, int iPageIndex)
2682 {
2683  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2684  LPCPROPSHEETPAGEW psp;
2685  TRACE("(%p, %d)\n", hwndDlg, iPageIndex);
2686  if (iPageIndex<0 || iPageIndex>=psInfo->nPages) {
2687  WARN("%d out of range.\n", iPageIndex);
2688  return 0;
2689  }
2690  psp = (LPCPROPSHEETPAGEW)psInfo->proppage[iPageIndex].hpage;
2691  if (psp->dwFlags & PSP_DLGINDIRECT || !IS_INTRESOURCE(psp->u.pszTemplate)) {
2692  return 0;
2693  }
2694  return (LRESULT)psp->u.pszTemplate;
2695 }
2696 
2697 /******************************************************************************
2698  * PROPSHEET_GetResult
2699  */
2701 {
2702  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2703  return psInfo->result;
2704 }
2705 
2706 /******************************************************************************
2707  * PROPSHEET_RecalcPageSizes
2708  */
2710 {
2711  FIXME("(%p): stub\n", hwndDlg);
2712  return FALSE;
2713 }
2714 
2715 /******************************************************************************
2716  * PROPSHEET_GetPageIndex
2717  *
2718  * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
2719  * the array of PropPageInfo. If page is not found original index is used
2720  * (page takes precedence over index).
2721  */
2722 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE page, const PropSheetInfo* psInfo, int original_index)
2723 {
2724  int index;
2725 
2726  TRACE("page %p index %d\n", page, original_index);
2727 
2728  for (index = 0; index < psInfo->nPages; index++)
2729  if (psInfo->proppage[index].hpage == page)
2730  return index;
2731 
2732  return original_index;
2733 }
2734 
2735 /******************************************************************************
2736  * PROPSHEET_CleanUp
2737  */
2738 static void PROPSHEET_CleanUp(HWND hwndDlg)
2739 {
2740  int i;
2741  PropSheetInfo* psInfo = RemovePropW(hwndDlg, PropSheetInfoStr);
2742 
2743  TRACE("\n");
2744  if (!psInfo) return;
2745  if (!IS_INTRESOURCE(psInfo->ppshheader.pszCaption))
2746  Free ((LPVOID)psInfo->ppshheader.pszCaption);
2747 
2748  for (i = 0; i < psInfo->nPages; i++)
2749  {
2750  PROPSHEETPAGEA* psp = (PROPSHEETPAGEA*)psInfo->proppage[i].hpage;
2751 
2752  /* Unsubclass the page dialog window */
2753  if((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) &&
2754  (psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
2755  (psp->dwFlags & PSP_HIDEHEADER))
2756  {
2759  }
2760 
2761  if(psInfo->proppage[i].hwndPage)
2762  DestroyWindow(psInfo->proppage[i].hwndPage);
2763 
2764  if(psp)
2765  {
2766  if (psp->dwFlags & PSP_USETITLE)
2767  Free ((LPVOID)psInfo->proppage[i].pszText);
2768 
2770  }
2771  }
2772 
2773  DeleteObject(psInfo->hFont);
2774  DeleteObject(psInfo->hFontBold);
2775  /* If we created the bitmaps, destroy them */
2776  if ((psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
2777  (!(psInfo->ppshheader.dwFlags & PSH_USEHBMWATERMARK)) )
2778  DeleteObject(psInfo->ppshheader.u4.hbmWatermark);
2779  if ((psInfo->ppshheader.dwFlags & PSH_HEADER) &&
2780  (!(psInfo->ppshheader.dwFlags & PSH_USEHBMHEADER)) )
2781  DeleteObject(psInfo->ppshheader.u5.hbmHeader);
2782 
2783  Free(psInfo->proppage);
2784  Free(psInfo->strPropertiesFor);
2785  ImageList_Destroy(psInfo->hImageList);
2786 
2787  GlobalFree(psInfo);
2788 }
2789 
2790 static INT do_loop(const PropSheetInfo *psInfo)
2791 {
2792  MSG msg;
2793  INT ret = -1;
2794  HWND hwnd = psInfo->hwnd;
2795  HWND parent = psInfo->ppshheader.hwndParent;
2796 
2797  while(IsWindow(hwnd) && !psInfo->ended && (ret = GetMessageW(&msg, NULL, 0, 0)))
2798  {
2799  if(ret == -1)
2800  break;
2801 
2802  if(!IsDialogMessageW(hwnd, &msg))
2803  {
2806  }
2807  }
2808 
2809  if(ret == 0)
2810  {
2811  PostQuitMessage(msg.wParam);
2812  ret = -1;
2813  }
2814 
2815  if(ret != -1)
2816  ret = psInfo->result;
2817 
2818  if(parent)
2820 
2822  return ret;
2823 }
2824 
2825 /******************************************************************************
2826  * PROPSHEET_PropertySheet
2827  *
2828  * Common code between PropertySheetA/W
2829  */
2831 {
2832  INT_PTR bRet = 0;
2833  HWND parent = NULL;
2834  if (psInfo->active_page >= psInfo->nPages) psInfo->active_page = 0;
2835  TRACE("startpage: %d of %d pages\n", psInfo->active_page, psInfo->nPages);
2836 
2837  psInfo->unicode = unicode;
2838  psInfo->ended = FALSE;
2839 
2840  if(!psInfo->isModeless)
2841  {
2842  parent = psInfo->ppshheader.hwndParent;
2844  }
2845  bRet = PROPSHEET_CreateDialog(psInfo);
2846  if(!psInfo->isModeless)
2847  bRet = do_loop(psInfo);
2848  return bRet;
2849 }
2850 
2851 /******************************************************************************
2852  * PropertySheet (COMCTL32.@)
2853  * PropertySheetA (COMCTL32.@)
2854  *
2855  * Creates a property sheet in the specified property sheet header.
2856  *
2857  * RETURNS
2858  * Modal property sheets: Positive if successful or -1 otherwise.
2859  * Modeless property sheets: Property sheet handle.
2860  * Or:
2861  *| ID_PSREBOOTSYSTEM - The user must reboot the computer for the changes to take effect.
2862  *| ID_PSRESTARTWINDOWS - The user must restart Windows for the changes to take effect.
2863  */
2865 {
2866  PropSheetInfo* psInfo = GlobalAlloc(GPTR, sizeof(PropSheetInfo));
2867  UINT i, n;
2868  const BYTE* pByte;
2869 
2870  TRACE("(%p)\n", lppsh);
2871 
2872  PROPSHEET_CollectSheetInfoA(lppsh, psInfo);
2873 
2874  psInfo->proppage = Alloc(sizeof(PropPageInfo) * lppsh->nPages);
2875  pByte = (const BYTE*) psInfo->ppshheader.u3.ppsp;
2876 
2877  for (n = i = 0; i < lppsh->nPages; i++, n++)
2878  {
2879  if (!psInfo->usePropPage)
2880  psInfo->proppage[n].hpage = psInfo->ppshheader.u3.phpage[i];
2881  else
2882  {
2884  pByte += ((LPCPROPSHEETPAGEA)pByte)->dwSize;
2885  }
2886 
2888  psInfo, n, TRUE))
2889  {
2890  if (psInfo->usePropPage)
2892  n--;
2893  psInfo->nPages--;
2894  }
2895  }
2896 
2897  return PROPSHEET_PropertySheet(psInfo, FALSE);
2898 }
2899 
2900 /******************************************************************************
2901  * PropertySheetW (COMCTL32.@)
2902  *
2903  * See PropertySheetA.
2904  */
2906 {
2907  PropSheetInfo* psInfo = GlobalAlloc(GPTR, sizeof(PropSheetInfo));
2908  UINT i, n;
2909  const BYTE* pByte;
2910 
2911  TRACE("(%p)\n", lppsh);
2912 
2913  PROPSHEET_CollectSheetInfoW(lppsh, psInfo);
2914 
2915  psInfo->proppage = Alloc(sizeof(PropPageInfo) * lppsh->nPages);
2916  pByte = (const BYTE*) psInfo->ppshheader.u3.ppsp;
2917 
2918  for (n = i = 0; i < lppsh->nPages; i++, n++)
2919  {
2920  if (!psInfo->usePropPage)
2921  psInfo->proppage[n].hpage = psInfo->ppshheader.u3.phpage[i];
2922  else
2923  {
2925  pByte += ((LPCPROPSHEETPAGEW)pByte)->dwSize;
2926  }
2927 
2929  psInfo, n, TRUE))
2930  {
2931  if (psInfo->usePropPage)
2933  n--;
2934  psInfo->nPages--;
2935  }
2936  }
2937 
2938  return PROPSHEET_PropertySheet(psInfo, TRUE);
2939 }
2940 
2942 {
2943  LPWSTR ret;
2944 
2945  if (IS_INTRESOURCE(str))
2946  {
2947  HRSRC hrsrc;
2948  HGLOBAL hmem;
2949  WCHAR *ptr;
2950  WORD i, id = LOWORD(str);
2951  UINT len;
2952 
2953  if (!(hrsrc = FindResourceW( instance, MAKEINTRESOURCEW((id >> 4) + 1), (LPWSTR)RT_STRING )))
2954  return NULL;
2955  if (!(hmem = LoadResource( instance, hrsrc ))) return NULL;
2956  if (!(ptr = LockResource( hmem ))) return NULL;
2957  for (i = id & 0x0f; i > 0; i--) ptr += *ptr + 1;
2958  len = *ptr;
2959  if (!len) return NULL;
2960  ret = Alloc( (len + 1) * sizeof(WCHAR) );
2961  if (ret)
2962  {
2963  memcpy( ret, ptr + 1, len * sizeof(WCHAR) );
2964  ret[len] = 0;
2965  }
2966  }
2967  else
2968  {
2969  int len = (strlenW(str) + 1) * sizeof(WCHAR);
2970  ret = Alloc( len );
2971  if (ret) memcpy( ret, str, len );
2972  }
2973  return ret;
2974 }
2975 
2976 
2977 /******************************************************************************
2978  * CreatePropertySheetPage (COMCTL32.@)
2979  * CreatePropertySheetPageA (COMCTL32.@)
2980  *
2981  * Creates a new property sheet page.
2982  *
2983  * RETURNS
2984  * Success: Handle to new property sheet page.
2985  * Failure: NULL.
2986  *
2987  * NOTES
2988  * An application must use the PSM_ADDPAGE message to add the new page to
2989  * an existing property sheet.
2990  */
2992  LPCPROPSHEETPAGEA lpPropSheetPage)
2993 {
2994  PROPSHEETPAGEW *ppsp;
2995 
2996  if (lpPropSheetPage->dwSize < PROPSHEETPAGEA_V1_SIZE)
2997  return NULL;
2998 
2999  /* original data is used for callback notifications */
3000  if ((lpPropSheetPage->dwFlags & PSP_USECALLBACK) && lpPropSheetPage->pfnCallback)
3001  {
3002  ppsp = Alloc(2 * sizeof(*ppsp));
3003  memcpy(ppsp, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEA)));
3004  memcpy(ppsp + 1, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEA)));
3005  }
3006  else
3007  {
3008  ppsp = Alloc(sizeof(*ppsp));
3009  memcpy(ppsp, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEA)));
3010  }
3011 
3012  ppsp->dwFlags &= ~PSP_INTERNAL_UNICODE;
3013 
3014  if ( !(ppsp->dwFlags & PSP_DLGINDIRECT) )
3015  {
3016  if (!IS_INTRESOURCE( ppsp->u.pszTemplate ))
3017  {
3018  int len = strlen(lpPropSheetPage->u.pszTemplate) + 1;
3019  char *template = Alloc( len );
3020 
3021  ppsp->u.pszTemplate = (LPWSTR)strcpy( template, lpPropSheetPage->u.pszTemplate );
3022  }
3023  }
3024 
3025  if (ppsp->dwFlags & PSP_USEICONID)
3026  {
3027  if (!IS_INTRESOURCE( ppsp->u2.pszIcon ))
3028  ppsp->u2.pszIcon = heap_strdupAtoW( lpPropSheetPage->u2.pszIcon );
3029  }
3030 
3031  if (ppsp->dwFlags & PSP_USETITLE)
3032  {
3033  if (IS_INTRESOURCE( ppsp->pszTitle ))
3034  ppsp->pszTitle = load_string( ppsp->hInstance, ppsp->pszTitle );
3035  else
3036  ppsp->pszTitle = heap_strdupAtoW( lpPropSheetPage->pszTitle );
3037  }
3038  else
3039  ppsp->pszTitle = NULL;
3040 
3041  if (ppsp->dwFlags & PSP_HIDEHEADER)
3042  ppsp->dwFlags &= ~(PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE);
3043 
3044  if (ppsp->dwFlags & PSP_USEHEADERTITLE)
3045  {
3046  if (IS_INTRESOURCE( ppsp->pszHeaderTitle ))
3047  ppsp->pszHeaderTitle = load_string( ppsp->hInstance, ppsp->pszHeaderTitle );
3048  else
3049  ppsp->pszHeaderTitle = heap_strdupAtoW( lpPropSheetPage->pszHeaderTitle );
3050  }
3051  else
3052  ppsp->pszHeaderTitle = NULL;
3053 
3054  if (ppsp->dwFlags & PSP_USEHEADERSUBTITLE)
3055  {
3056  if (IS_INTRESOURCE( ppsp->pszHeaderSubTitle ))
3057  ppsp->pszHeaderSubTitle = load_string( ppsp->hInstance, ppsp->pszHeaderSubTitle );
3058  else
3059  ppsp->pszHeaderSubTitle = heap_strdupAtoW( lpPropSheetPage->pszHeaderSubTitle );
3060  }
3061  else
3062  ppsp->pszHeaderSubTitle = NULL;
3063 
3064  if ((ppsp->dwFlags & PSP_USECALLBACK) && ppsp->dwSize > PROPSHEETPAGEA_V1_SIZE && ppsp->pfnCallback)
3065  ppsp->pfnCallback(0, PSPCB_ADDREF, ppsp + 1);
3066 
3067  return (HPROPSHEETPAGE)ppsp;
3068 }
3069 
3070 /******************************************************************************
3071  * CreatePropertySheetPageW (COMCTL32.@)
3072  *
3073  * See CreatePropertySheetA.
3074  */
3076 {
3077  PROPSHEETPAGEW *ppsp;
3078 
3079  if (lpPropSheetPage->dwSize < PROPSHEETPAGEW_V1_SIZE)
3080  return NULL;
3081 
3082  /* original data is used for callback notifications */
3083  if ((lpPropSheetPage->dwFlags & PSP_USECALLBACK) && lpPropSheetPage->pfnCallback)
3084  {
3085  ppsp = Alloc(2 * sizeof(*ppsp));
3086  memcpy(ppsp, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEW)));
3087  memcpy(ppsp + 1, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEW)));
3088  }
3089  else
3090  {
3091  ppsp = Alloc(sizeof(*ppsp));
3092  memcpy(ppsp, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEW)));
3093  }
3094 
3095  ppsp->dwFlags |= PSP_INTERNAL_UNICODE;
3096 
3097  if ( !(ppsp->dwFlags & PSP_DLGINDIRECT) )
3098  {
3099  if (!IS_INTRESOURCE( ppsp->u.pszTemplate ))
3100  ppsp->u.pszTemplate = heap_strdupW( lpPropSheetPage->u.pszTemplate );
3101  }
3102 
3103  if ( ppsp->dwFlags & PSP_USEICONID )
3104  {
3105  if (!IS_INTRESOURCE( ppsp->u2.pszIcon ))
3106  ppsp->u2.pszIcon = heap_strdupW( lpPropSheetPage->u2.pszIcon );
3107  }
3108 
3109  if (ppsp->dwFlags & PSP_USETITLE)
3110  ppsp->pszTitle = load_string( ppsp->hInstance, ppsp->pszTitle );
3111  else
3112  ppsp->pszTitle = NULL;
3113 
3114  if (ppsp->dwFlags & PSP_HIDEHEADER)
3115  ppsp->dwFlags &= ~(PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE);
3116 
3117  if (ppsp->dwFlags & PSP_USEHEADERTITLE)
3118  ppsp->pszHeaderTitle = load_string( ppsp->hInstance, ppsp->pszHeaderTitle );
3119  else
3120  ppsp->pszHeaderTitle = NULL;
3121 
3122  if (ppsp->dwFlags & PSP_USEHEADERSUBTITLE)
3123  ppsp->pszHeaderSubTitle = load_string( ppsp->hInstance, ppsp->pszHeaderSubTitle );
3124  else
3125  ppsp->pszHeaderSubTitle = NULL;
3126 
3127  if ((ppsp->dwFlags & PSP_USECALLBACK) && ppsp->dwSize > PROPSHEETPAGEW_V1_SIZE && ppsp->pfnCallback)
3128  ppsp->pfnCallback(0, PSPCB_ADDREF, ppsp + 1);
3129 
3130  return (HPROPSHEETPAGE)ppsp;
3131 }
3132 
3133 /******************************************************************************
3134  * DestroyPropertySheetPage (COMCTL32.@)
3135  *
3136  * Destroys a property sheet page previously created with
3137  * CreatePropertySheetA() or CreatePropertySheetW() and frees the associated
3138  * memory.
3139  *
3140  * RETURNS
3141  * Success: TRUE
3142  * Failure: FALSE
3143  */
3145 {
3146  PROPSHEETPAGEW *psp = (PROPSHEETPAGEW *)hPropPage;
3147 
3148  if (!psp)
3149  return FALSE;
3150 
3151  if ((psp->dwFlags & PSP_USECALLBACK) && psp->pfnCallback)
3152  psp->pfnCallback(0, PSPCB_RELEASE, psp + 1);
3153 
3154  if (!(psp->dwFlags & PSP_DLGINDIRECT) && !IS_INTRESOURCE( psp->u.pszTemplate ))
3155  Free ((LPVOID)psp->u.pszTemplate);
3156 
3157  if ((psp->dwFlags & PSP_USEICONID) && !IS_INTRESOURCE( psp->u2.pszIcon ))
3158  Free ((LPVOID)psp->u2.pszIcon);
3159 
3160  if ((psp->dwFlags & PSP_USETITLE) && !IS_INTRESOURCE( psp->pszTitle ))
3161  Free ((LPVOID)psp->pszTitle);
3162 
3163  if ((psp->dwFlags & PSP_USEHEADERTITLE) && !IS_INTRESOURCE( psp->pszHeaderTitle ))
3164  Free ((LPVOID)psp->pszHeaderTitle);
3165 
3166  if ((psp->dwFlags & PSP_USEHEADERSUBTITLE) && !IS_INTRESOURCE( psp->pszHeaderSubTitle ))
3167  Free ((LPVOID)psp->pszHeaderSubTitle);
3168 
3169  Free(hPropPage);
3170 
3171  return TRUE;
3172 }
3173 
3174 /******************************************************************************
3175  * PROPSHEET_IsDialogMessage
3176  */
3178 {
3180 
3181  TRACE("\n");
3182  if (!psInfo || (hwnd != lpMsg->hwnd && !IsChild(hwnd, lpMsg->hwnd)))
3183  return FALSE;
3184 
3185  if (lpMsg->message == WM_KEYDOWN && (GetKeyState(VK_CONTROL) & 0x8000))
3186  {
3187  int new_page = 0;
3188  INT dlgCode = SendMessageW(lpMsg->hwnd, WM_GETDLGCODE, 0, (LPARAM)lpMsg);
3189 
3190  if (!(dlgCode & DLGC_WANTMESSAGE))
3191  {
3192  switch (lpMsg->wParam)
3193  {
3194  case VK_TAB:
3195  if (GetKeyState(VK_SHIFT) & 0x8000)
3196  new_page = -1;
3197  else
3198  new_page = 1;
3199  break;
3200 
3201  case VK_NEXT: new_page = 1; break;
3202  case VK_PRIOR: new_page = -1; break;
3203  }
3204  }
3205 
3206  if (new_page)
3207  {
3209  {
3210  new_page += psInfo->active_page;
3211 
3212  if (new_page < 0)
3213  new_page = psInfo->nPages - 1;
3214  else if (new_page >= psInfo->nPages)
3215  new_page = 0;
3216 
3217  PROPSHEET_SetCurSel(hwnd, new_page, 1, 0);
3218  }
3219 
3220  return TRUE;
3221  }
3222  }
3223 
3224  return IsDialogMessageW(hwnd, lpMsg);
3225 }
3226 
3227 /******************************************************************************
3228  * PROPSHEET_DoCommand
3229  */
3231 {
3232 
3233  switch (wID) {
3234 
3235  case IDOK:
3236  case IDC_APPLY_BUTTON:
3237  {
3238  HWND hwndApplyBtn = GetDlgItem(hwnd, IDC_APPLY_BUTTON);
3239 
3240  if (PROPSHEET_Apply(hwnd, wID == IDOK ? 1: 0) == FALSE)
3241  break;
3242 
3243  if (wID == IDOK)
3244  {
3246 
3247  /* don't overwrite ID_PSRESTARTWINDOWS or ID_PSREBOOTSYSTEM */
3248  if (psInfo->result == 0)
3249  psInfo->result = IDOK;
3250 
3251  if (psInfo->isModeless)
3252  psInfo->activeValid = FALSE;
3253  else
3254  psInfo->ended = TRUE;
3255  }
3256  else
3257  EnableWindow(hwndApplyBtn, FALSE);
3258 
3259  break;
3260  }
3261 
3262  case IDC_BACK_BUTTON:
3264  break;
3265 
3266  case IDC_NEXT_BUTTON:
3268  break;
3269 
3270  case IDC_FINISH_BUTTON:
3272  break;
3273 
3274  case IDCANCEL:
3275  PROPSHEET_Cancel(hwnd, 0);
3276  break;
3277 
3278  case IDHELP:
3280  break;
3281 
3282  default:
3283  return FALSE;
3284  }
3285 
3286  return TRUE;
3287 }
3288 
3289 /******************************************************************************
3290  * PROPSHEET_Paint
3291  */
3293 {
3295  PAINTSTRUCT ps;
3296  HDC hdc, hdcSrc;
3297  BITMAP bm;
3298  HBITMAP hbmp;
3299  HPALETTE hOldPal = 0;
3300  int offsety = 0;
3301  HBRUSH hbr;
3302  RECT r, rzone;
3303  LPCPROPSHEETPAGEW ppshpage;
3304  WCHAR szBuffer[256];
3305  int nLength;
3306 
3307  hdc = hdcParam ? hdcParam : BeginPaint(hwnd, &ps);
3308  if (!hdc) return 1;
3309 
3311 
3312  if (psInfo->ppshheader.dwFlags & PSH_USEHPLWATERMARK)
3313  hOldPal = SelectPalette(hdc, psInfo->ppshheader.hplWatermark, FALSE);
3314 
3315  if (psInfo->active_page < 0)
3316  ppshpage = NULL;
3317  else
3318  ppshpage = (LPCPROPSHEETPAGEW)psInfo->proppage[psInfo->active_page].hpage;
3319 
3320  if ( (ppshpage && !(ppshpage->dwFlags & PSP_HIDEHEADER)) &&
3321  (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)) &&
3322  (psInfo->ppshheader.dwFlags & PSH_HEADER) )
3323  {
3324  HWND hwndLineHeader = GetDlgItem(hwnd, IDC_SUNKEN_LINEHEADER);
3325  HFONT hOldFont;
3326  COLORREF clrOld = 0;
3327  int oldBkMode = 0;
3328 
3329  GetClientRect(hwndLineHeader, &r);
3330  MapWindowPoints(hwndLineHeader, hwnd, (LPPOINT) &r, 2);
3331  SetRect(&rzone, 0, 0, r.right + 1, r.top - 1);
3332 
3333  hOldFont = SelectObject(hdc, psInfo->hFontBold);
3334 
3335 #ifdef __REACTOS__
3336  if (psInfo->ppshheader.u5.hbmHeader)
3337 #else
3338  if (psInfo->ppshheader.dwFlags & PSH_USEHBMHEADER)
3339 #endif
3340  {
3341  hbmp = SelectObject(hdcSrc, psInfo->ppshheader.u5.hbmHeader);
3342 
3343  GetObjectW(psInfo->ppshheader.u5.hbmHeader, sizeof(BITMAP), &bm);
3344  if (psInfo->ppshheader.dwFlags & PSH_WIZARD97_OLD)
3345  {
3346  /* Fill the unoccupied part of the header with color of the
3347  * left-top pixel, but do it only when needed.
3348  */
3349  if (bm.bmWidth < r.right || bm.bmHeight < r.bottom)
3350  {
3351  hbr = CreateSolidBrush(GetPixel(hdcSrc, 0, 0));
3352  r = rzone;
3353  if (bm.bmWidth < r.right)
3354  {
3355  r.left = bm.bmWidth;
3356  FillRect(hdc, &r, hbr);
3357  }
3358  if (bm.bmHeight < r.bottom)
3359  {
3360  r.left = 0;
3361  r.top = bm.bmHeight;
3362  FillRect(hdc, &r, hbr);
3363  }
3364  DeleteObject(hbr);
3365  }
3366 
3367  /* Draw the header itself. */
3368  BitBlt(hdc, 0, 0, bm.bmWidth, min(bm.bmHeight, rzone.bottom),
3369  hdcSrc, 0, 0, SRCCOPY);
3370  }
3371  else
3372  {
3373  int margin;
3375  FillRect(hdc, &rzone, hbr);
3376 
3377  /* Draw the header bitmap. It's always centered like a
3378  * common 49 x 49 bitmap. */
3379  margin = (rzone.bottom - 49) / 2;
3380  BitBlt(hdc, rzone.right - 49 - margin, margin,
3381  min(bm.bmWidth, 49), min(bm.bmHeight, 49),
3382  hdcSrc, 0, 0, SRCCOPY);
3383 
3384  /* NOTE: Native COMCTL32 draws a white stripe over the bitmap
3385  * if its height is smaller than 49 pixels. Because the reason
3386  * for this bug is unknown the current code doesn't try to
3387  * replicate it. */
3388  }
3389 
3391  }
3392 
3393  clrOld = SetTextColor (hdc, 0x00000000);
3394  oldBkMode = SetBkMode (hdc, TRANSPARENT);
3395 
3396  if (ppshpage->dwFlags & PSP_USEHEADERTITLE) {
3397  SetRect(&r, 20, 10, 0, 0);
3398  if (!IS_INTRESOURCE(ppshpage->pszHeaderTitle))
3399  DrawTextW(hdc, ppshpage->pszHeaderTitle, -1, &r, DT_LEFT | DT_SINGLELINE | DT_NOCLIP);
3400  else
3401  {
3402  nLength = LoadStringW(ppshpage->hInstance, (UINT_PTR)ppshpage->pszHeaderTitle,
3403  szBuffer, 256);
3404  if (nLength != 0)
3405  {
3406  DrawTextW(hdc, szBuffer, nLength, &r, DT_LEFT | DT_SINGLELINE | DT_NOCLIP);
3407  }
3408  }
3409  }
3410 
3411  if (ppshpage->dwFlags & PSP_USEHEADERSUBTITLE) {
3412  SelectObject(hdc, psInfo->hFont);
3413  SetRect(&r, 40, 25, rzone.right - 69, rzone.bottom);
3414 #ifdef __REACTOS__
3415  if (!IS_INTRESOURCE(ppshpage->pszHeaderSubTitle))
3416 #else
3417  if (!IS_INTRESOURCE(ppshpage->pszHeaderTitle))
3418 #endif
3419  DrawTextW(hdc, ppshpage->pszHeaderSubTitle, -1, &r, DT_LEFT | DT_WORDBREAK);
3420  else
3421  {
3422  nLength = LoadStringW(ppshpage->hInstance, (UINT_PTR)ppshpage->pszHeaderSubTitle,
3423  szBuffer, 256);
3424  if (nLength != 0)
3425  {
3426  DrawTextW(hdc, szBuffer, nLength, &r, DT_LEFT | DT_WORDBREAK);
3427  }
3428  }
3429  }
3430 
3431  offsety = rzone.bottom + 2;
3432 
3433  SetTextColor(hdc, clrOld);
3434  SetBkMode(hdc, oldBkMode);
3435  SelectObject(hdc, hOldFont);
3436  }
3437 
3438  if ( (ppshpage && (ppshpage->dwFlags & PSP_HIDEHEADER)) &&
3439  (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)) &&
3440 #ifdef __REACTOS__
3441  (psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
3442  (psInfo->ppshheader.u4.hbmWatermark) )
3443 #else
3444  (psInfo->ppshheader.dwFlags & PSH_WATERMARK) )
3445 #endif
3446  {
3447  HWND hwndLine = GetDlgItem(hwnd, IDC_SUNKEN_LINE);
3448 
3449  GetClientRect(hwndLine, &r);
3450  MapWindowPoints(hwndLine, hwnd, (LPPOINT) &r, 2);
3451  SetRect(&rzone, 0, 0, r.right, r.top - 1);
3452 
3454  FillRect(hdc, &rzone, hbr);
3455 
3456  GetObjectW(psInfo->ppshheader.u4.hbmWatermark, sizeof(BITMAP), &bm);
3457  hbmp = SelectObject(hdcSrc, psInfo->ppshheader.u4.hbmWatermark);
3458 
3459  /* The watermark is truncated to a width of 164 pixels */
3460  r.right = min(r.right, 164);
3461  BitBlt(hdc, 0, offsety, min(bm.bmWidth, r.right),
3462  min(bm.bmHeight, r.bottom), hdcSrc, 0, 0, SRCCOPY);
3463 
3464  /* If the bitmap is not big enough, fill the remaining area
3465  with the color of pixel (0,0) of bitmap - see MSDN */
3466  if (r.top > bm.bmHeight) {
3467  r.bottom = r.top - 1;
3468  r.top = bm.bmHeight;
3469  r.left = 0;
3470  r.right = bm.bmWidth;
3471  hbr = CreateSolidBrush(GetPixel(hdcSrc, 0, 0));
3472  FillRect(hdc, &r, hbr);
3473  DeleteObject(hbr);
3474  }
3475 
3477  }
3478 
3479  if (psInfo->ppshheader.dwFlags & PSH_USEHPLWATERMARK)
3480  SelectPalette(hdc, hOldPal, FALSE);
3481 
3482  DeleteDC(hdcSrc);
3483 
3484  if (!hdcParam) EndPaint(hwnd, &ps);
3485 
3486  return 0;
3487 }
3488 
3489 /******************************************************************************
3490  * PROPSHEET_DialogProc
3491  */
3492 static INT_PTR CALLBACK
3494 {
3495  TRACE("hwnd=%p msg=0x%04x wparam=%lx lparam=%lx\n",
3496  hwnd, uMsg, wParam, lParam);
3497 
3498  switch (uMsg)
3499  {
3500  case WM_INITDIALOG:
3501  {
3502  PropSheetInfo* psInfo = (PropSheetInfo*) lParam;
3503  WCHAR* strCaption = Alloc(MAX_CAPTION_LENGTH*sizeof(WCHAR));
3504  HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
3505  int idx;
3506  LOGFONTW logFont;
3507 
3508  /* Using PropSheetInfoStr to store extra data doesn't match the native
3509  * common control: native uses TCM_[GS]ETITEM
3510  */
3511  SetPropW(hwnd, PropSheetInfoStr, psInfo);
3512 
3513  /*
3514  * psInfo->hwnd is not being used by WINE code - it exists
3515  * for compatibility with "real" Windoze. The same about
3516  * SetWindowLongPtr - WINE is only using the PropSheetInfoStr
3517  * property.
3518  */
3519  psInfo->hwnd = hwnd;
3521 
3522  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD)
3523  {
3524  /* set up the Next and Back buttons by default */
3526  }
3527 
3528  /* Set up fonts */
3530  psInfo->hFont = CreateFontIndirectW (&logFont);
3531  logFont.lfWeight = FW_BOLD;
3532  psInfo->hFontBold = CreateFontIndirectW (&logFont);
3533 
3534  /*
3535  * Small icon in the title bar.
3536  */
3537  if ((psInfo->ppshheader.dwFlags & PSH_USEICONID) ||
3538  (psInfo->ppshheader.dwFlags & PSH_USEHICON))
3539  {
3540  HICON hIcon;
3541  int icon_cx = GetSystemMetrics(SM_CXSMICON);
3542  int icon_cy = GetSystemMetrics(SM_CYSMICON);
3543 
3544  if (psInfo->ppshheader.dwFlags & PSH_USEICONID)
3545  hIcon = LoadImageW(psInfo->ppshheader.hInstance,
3546  psInfo->ppshheader.u.pszIcon,
3547  IMAGE_ICON,
3548  icon_cx, icon_cy,
3549  LR_DEFAULTCOLOR);
3550  else
3551  hIcon = psInfo->ppshheader.u.hIcon;
3552 
3553  SendMessageW(hwnd, WM_SETICON, 0, (LPARAM)hIcon);
3554  }
3555 
3556  if (psInfo->ppshheader.dwFlags & PSH_USEHICON)
3557  SendMessageW(hwnd, WM_SETICON, 0, (LPARAM)psInfo->ppshheader.u.hIcon);
3558 
3559  psInfo->strPropertiesFor = strCaption;
3560 
3561  GetWindowTextW(hwnd, psInfo->strPropertiesFor, MAX_CAPTION_LENGTH);
3562 
3564 
3566 
3567  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD)
3568  {
3569  ShowWindow(hwndTabCtrl, SW_HIDE);
3573  }
3574  else
3575  {
3576  if (PROPSHEET_SizeMismatch(hwnd, psInfo))
3577  {
3578  PROPSHEET_AdjustSize(hwnd, psInfo);
3579  PROPSHEET_AdjustButtons(hwnd, psInfo);
3580  }
3582  }
3583 
3584  if (IS_INTRESOURCE(psInfo->ppshheader.pszCaption) &&
3585  psInfo->ppshheader.hInstance)
3586  {
3587  WCHAR szText[256];
3588 
3589  if (LoadStringW(psInfo->ppshheader.hInstance,
3590  (UINT_PTR)psInfo->ppshheader.pszCaption, szText, 255))
3591  PROPSHEET_SetTitleW(hwnd, psInfo->ppshheader.dwFlags, szText);
3592  }
3593  else
3594  {
3595  PROPSHEET_SetTitleW(hwnd, psInfo->ppshheader.dwFlags,
3596  psInfo->ppshheader.pszCaption);
3597  }
3598 
3599 
3600  if (psInfo->useCallback)
3601  (*(psInfo->ppshheader.pfnCallback))(hwnd, PSCB_INITIALIZED, 0);
3602 
3603  idx = psInfo->active_page;
3604  psInfo->active_page = -1;
3605 
3606  PROPSHEET_SetCurSel(hwnd, idx, 1, psInfo->proppage[idx].hpage);
3607 
3608  /* doing TCM_SETCURSEL seems to be needed even in case of PSH_WIZARD,
3609  * as some programs call TCM_GETCURSEL to get the current selection
3610  * from which to switch to the next page */
3611  SendMessageW(hwndTabCtrl, TCM_SETCURSEL, psInfo->active_page, 0);
3612 
3614 
3615  /* wizards set their focus during init */
3616  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD)
3617  return FALSE;
3618 
3619  return TRUE;
3620  }
3621 
3622  case WM_PRINTCLIENT:
3623  case WM_PAINT:
3625  return TRUE;
3626 
3627  case WM_DESTROY:
3629  return TRUE;
3630 
3631  case WM_CLOSE:
3632  PROPSHEET_Cancel(hwnd, 1);
3633  return FALSE; /* let DefDlgProc post us WM_COMMAND/IDCANCEL */
3634 
3635  case WM_COMMAND:
3637  {
3639 
3640  if (!psInfo)
3641  return FALSE;
3642 
3643  /* No default handler, forward notification to active page */
3644  if (psInfo->activeValid && psInfo->active_page != -1)
3645  {
3646  HWND hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
3647  SendMessageW(hwndPage, WM_COMMAND, wParam, lParam);
3648  }
3649  }
3650  return TRUE;
3651 
3652  case WM_NOTIFY:
3653  {
3654  NMHDR* pnmh = (LPNMHDR) lParam;
3655 
3656  if (pnmh->code == TCN_SELCHANGE)
3657  {
3658  int index = SendMessageW(pnmh->hwndFrom, TCM_GETCURSEL, 0, 0);
3659  PROPSHEET_SetCurSel(hwnd, index, 1, 0);
3660  }
3661 
3662  if(pnmh->code == TCN_SELCHANGING)
3663  {
3666  return TRUE;
3667  }
3668 
3669  return FALSE;
3670  }
3671 
3672  case WM_SYSCOLORCHANGE:
3674  return FALSE;
3675 
3677  {
3679  HWND hwndPage = 0;
3680 
3681  if (!psInfo)
3682  return FALSE;
3683 
3684  if (psInfo->activeValid && psInfo->active_page != -1)
3685  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
3686 
3688 
3689  return TRUE;
3690  }
3691 
3692  case PSM_CHANGED:
3694  return TRUE;
3695 
3696  case PSM_UNCHANGED:
3698  return TRUE;
3699 
3700  case PSM_GETTABCONTROL:
3701  {
3702  HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
3703 
3705 
3706  return TRUE;
3707  }
3708 
3709  case PSM_SETCURSEL:
3710  {
3711  BOOL msgResult;
3712 
3713  msgResult = PROPSHEET_CanSetCurSel(hwnd);
3714  if(msgResult != FALSE)
3715  {
3716  msgResult = PROPSHEET_SetCurSel(hwnd,
3717  (int)wParam,
3718  1,
3720  }
3721 
3722  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3723 
3724  return TRUE;
3725  }
3726 
3727  case PSM_CANCELTOCLOSE:
3728  {
3730  HWND hwndOK = GetDlgItem(hwnd, IDOK);
3731  HWND hwndCancel = GetDlgItem(hwnd, IDCANCEL);
3732 
3733  EnableWindow(hwndCancel, FALSE);
3735  SetWindowTextW(hwndOK, buf);
3736 
3737  return FALSE;
3738  }
3739 
3740  case PSM_RESTARTWINDOWS:
3741  {
3743 
3744  if (!psInfo)
3745  return FALSE;
3746 
3747  /* reboot system takes precedence over restart windows */
3748  if (psInfo->result != ID_PSREBOOTSYSTEM)
3749  psInfo->result = ID_PSRESTARTWINDOWS;
3750 
3751  return TRUE;
3752  }
3753 
3754  case PSM_REBOOTSYSTEM:
3755  {
3757 
3758  if (!psInfo)
3759  return FALSE;
3760 
3761  psInfo->result = ID_PSREBOOTSYSTEM;
3762 
3763  return TRUE;
3764  }
3765 
3766  case PSM_SETTITLEA:
3768  return TRUE;
3769 
3770  case PSM_SETTITLEW:
3772  return TRUE;
3773 
3774  case PSM_APPLY:
3775  {
3776  BOOL msgResult = PROPSHEET_Apply(hwnd, 0);
3777 
3778  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3779 
3780  return TRUE;
3781  }
3782 
3783  case PSM_QUERYSIBLINGS:
3784  {
3786 
3787  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3788 
3789  return TRUE;
3790  }
3791 
3792  case PSM_ADDPAGE:
3793  {
3794  /*
3795  * Note: MSVC++ 6.0 documentation says that PSM_ADDPAGE does not have
3796  * a return value. This is not true. PSM_ADDPAGE returns TRUE
3797  * on success or FALSE otherwise, as specified on MSDN Online.
3798  * Also see the MFC code for
3799  * CPropertySheet::AddPage(CPropertyPage* pPage).
3800  */
3801 
3803 
3804  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3805 
3806  return TRUE;
3807  }
3808 
3809  case PSM_REMOVEPAGE:
3811  return TRUE;
3812 
3813  case PSM_ISDIALOGMESSAGE:
3814  {
3816  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3817  return TRUE;
3818  }
3819 
3820  case PSM_PRESSBUTTON:
3822  return TRUE;
3823 
3824  case PSM_SETFINISHTEXTA:
3826  return TRUE;
3827 
3828  case PSM_SETWIZBUTTONS:
3830  return TRUE;
3831 
3832  case PSM_SETCURSELID:
3834  return TRUE;
3835 
3836  case PSM_SETFINISHTEXTW:
3838  return FALSE;
3839 
3840  case PSM_INSERTPAGE:
3841  {
3843  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3844  return TRUE;
3845  }
3846 
3847  case PSM_SETHEADERTITLEW:
3849  return TRUE;
3850 
3851  case PSM_SETHEADERTITLEA:
3853  return TRUE;
3854 
3855  case PSM_SETHEADERSUBTITLEW:
3857  return TRUE;
3858 
3859  case PSM_SETHEADERSUBTITLEA:
3861  return TRUE;
3862 
3863  case PSM_HWNDTOINDEX:
3864  {
3865  LRESULT msgResult = PROPSHEET_HwndToIndex(hwnd, (HWND)wParam);
3866  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3867  return TRUE;
3868  }
3869 
3870  case PSM_INDEXTOHWND:
3871  {
3872  LRESULT msgResult = PROPSHEET_IndexToHwnd(hwnd, (int)wParam);
3873  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3874  return TRUE;
3875  }
3876 
3877  case PSM_PAGETOINDEX:
3878  {
3880  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3881  return TRUE;
3882  }
3883 
3884  case PSM_INDEXTOPAGE:
3885  {
3886  LRESULT msgResult = PROPSHEET_IndexToPage(hwnd, (int)wParam);
3887  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3888  return TRUE;
3889  }
3890 
3891  case PSM_IDTOINDEX:
3892  {
3893  LRESULT msgResult = PROPSHEET_IdToIndex(hwnd, (int)lParam);
3894  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3895  return TRUE;
3896  }
3897 
3898  case PSM_INDEXTOID:
3899  {
3900  LRESULT msgResult = PROPSHEET_IndexToId(hwnd, (int)wParam);
3901  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3902  return TRUE;
3903  }
3904 
3905  case PSM_GETRESULT:
3906  {
3907  LRESULT msgResult = PROPSHEET_GetResult(hwnd);
3908  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3909  return TRUE;
3910  }
3911 
3912  case PSM_RECALCPAGESIZES:
3913  {
3914  LRESULT msgResult = PROPSHEET_RecalcPageSizes(hwnd);
3915  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3916  return TRUE;
3917  }
3918 
3919  default:
3920  return FALSE;
3921  }
3922 }
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
static LRESULT PROPSHEET_HwndToIndex(HWND hwndDlg, HWND hPageDlg)
Definition: propsheet.c:2604
#define PSH_WIZARDHASFINISH
Definition: prsht.h:44
static LRESULT PROPSHEET_Paint(HWND hwnd, HDC hdcParam)
Definition: propsheet.c:3292
#define TCM_GETCURSEL
Definition: commctrl.h:4058
#define WS_DISABLED
Definition: pedump.c:621
HWND hwndParent
Definition: prsht.h:277
#define WS_THICKFRAME
Definition: pedump.c:630
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
#define PSH_USEHICON
Definition: prsht.h:41
GLint GLint GLsizei width
Definition: gl.h:1546
#define WM_SYSCOLORCHANGE
Definition: winuser.h:1608
#define WIZARD_HEADER_HEIGHT
Definition: propsheet.c:156
BOOL WINAPI TranslateMessage(_In_ const MSG *)
static HICON
Definition: imagelist.c:84
#define TRUE
Definition: types.h:120
#define INTRNL_ANY_WIZARD
Definition: propsheet.c:152
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
#define IDOK
Definition: winuser.h:824
#define IMAGE_ICON
Definition: winuser.h:212
#define DLGC_WANTMESSAGE
Definition: winuser.h:2588
#define MAX_TABTEXT_LENGTH
Definition: propsheet.c:149
static void PROPSHEET_Help(HWND hwndDlg)
Definition: propsheet.c:1816
LPCPROPSHEETPAGEW ppsp
Definition: prsht.h:290
#define PSH_NOAPPLYNOW
Definition: prsht.h:47
static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText)
Definition: propsheet.c:2169
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
#define IDC_APPLY_BUTTON
Definition: propsheet.c:13
LPCWSTR pszTemplate
Definition: prsht.h:209
long y
Definition: polytest.cpp:48
#define WM_GETDLGCODE
Definition: winuser.h:1671
int WINAPI MapWindowPoints(_In_opt_ HWND hWndFrom, _In_opt_ HWND hWndTo, _Inout_updates_(cPoints) LPPOINT lpPoints, _In_ UINT cPoints)
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
BOOL WINAPI IsWindow(_In_opt_ HWND)
#define GPTR
Definition: winbase.h:293
DWORD dwSize
Definition: prsht.h:177
long x
Definition: polytest.cpp:48
#define PSH_RTLREADING
Definition: prsht.h:51
#define IDC_SUNKEN_LINE
Definition: comctl32.h:51
#define TCM_ADJUSTRECT
Definition: commctrl.h:4081
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define PSM_GETTABCONTROL
Definition: prsht.h:80
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
struct tagPropPageInfo PropPageInfo
#define PSN_HELP
Definition: prsht.h:119
#define ID_PSREBOOTSYSTEM
Definition: prsht.h:133
#define SW_HIDE
Definition: winuser.h:762
BOOL WINAPI DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage)
Definition: propsheet.c:3144
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define CP_ACP
Definition: compat.h:99
PROPSHEETHEADERW ppshheader
Definition: propsheet.c:111
#define WM_CTLCOLORSTATIC
Definition: winuser.h:1754
char CHAR
Definition: xmlstorage.h:175
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
#define DT_WORDBREAK
Definition: winuser.h:544
#define IDC_FINISH_BUTTON
Definition: comctl32.h:50
#define WARN(fmt,...)
Definition: debug.h:111
HRSRC WINAPI FindResourceA(HMODULE hModule, LPCSTR name, LPCSTR type)
Definition: res.c:155
LPCDLGTEMPLATE pResource
Definition: prsht.h:210
LPCSTR pszCaption
Definition: prsht.h:248
static HDC
Definition: imagelist.c:92
#define CALLBACK
Definition: compat.h:27
_In_ DWORD nLength
Definition: wincon.h:461
#define WM_SETREDRAW
Definition: winuser.h:1598
#define PSBTN_APPLYNOW
Definition: prsht.h:150
static INT_PTR(WINAPI *pPropertySheetA)(const PROPSHEETHEADERA *header)
LPCSTR pszTitle
Definition: prsht.h:188
GLdouble n
Definition: glext.h:7729
LONG top
Definition: windef.h:307
#define PSWIZB_NEXT
Definition: prsht.h:154
BOOL WINAPI MapDialogRect(_In_ HWND, _Inout_ LPRECT)
#define PSM_REMOVEPAGE
Definition: prsht.h:166
static BOOL PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp, PropSheetInfo *psInfo, int index, BOOL resize)
Definition: propsheet.c:399
static BOOL PROPSHEET_AddPage(HWND hwndDlg, HPROPSHEETPAGE hpage)
Definition: propsheet.c:2342
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1497
HWND WINAPI CreateDialogIndirectParamW(_In_opt_ HINSTANCE, _In_ LPCDLGTEMPLATE, _In_opt_ HWND, _In_opt_ DLGPROC, _In_ LPARAM)
BOOL WINAPI DeleteObject(_In_ HGDIOBJ)
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
#define DM_SETDEFID
Definition: winuser.h:2081
LPCSTR pszTemplate
Definition: prsht.h:181
#define HWND_TOP
Definition: winuser.h:1193
#define SM_CYSMICON
Definition: winuser.h:1003
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
#define PSBTN_HELP
Definition: prsht.h:152
#define MAKEINTRESOURCEA(i)
Definition: winuser.h:581
#define TCM_SETCURSEL
Definition: commctrl.h:4061
HWND WINAPI SetFocus(_In_opt_ HWND)
#define PSP_USEICONID
Definition: prsht.h:25
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
#define PSWIZB_DISABLEDFINISH
Definition: prsht.h:156
#define PSP_USECALLBACK
Definition: prsht.h:30
BOOL WINAPI SetWindowTextW(_In_ HWND, _In_opt_ LPCWSTR)
static BOOL PROPSHEET_RecalcPageSizes(HWND hwndDlg)
Definition: propsheet.c:2709
UINT_PTR WPARAM
Definition: windef.h:207
struct tagPropSheetInfo PropSheetInfo
#define VK_TAB
Definition: winuser.h:2174
GLuint GLuint end
Definition: gl.h:1545
#define PSBTN_FINISH
Definition: prsht.h:148
#define WS_CHILD
Definition: pedump.c:617
#define VK_PRIOR
Definition: winuser.h:2195
#define TCIF_TEXT
Definition: commctrl.h:3967
#define PSH_WIZARD
Definition: prsht.h:45
#define PSN_APPLY
Definition: prsht.h:117
LONG left
Definition: windef.h:306
#define SWP_NOZORDER
Definition: winuser.h:1232
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
static HDC hdcSrc
Definition: xlate.c:32
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
int32_t INT_PTR
Definition: typedefs.h:62
#define PSH_MODELESS
Definition: prsht.h:50
#define PSH_USECALLBACK
Definition: prsht.h:48
char * LPSTR
Definition: xmlstorage.h:182
static const WCHAR PropSheetInfoStr[]
Definition: propsheet.c:143
DWORD GetPixel(LPDIRECTDRAWSURFACE7 Surface, UINT x, UINT y)
Definition: blt.cpp:2
LONG right
Definition: windef.h:308
HWND WINAPI GetNextDlgTabItem(_In_ HWND, _In_opt_ HWND, _In_ BOOL)
#define lstrlenW
Definition: compat.h:415
BOOL WINAPI DestroyWindow(_In_ HWND)
#define PSN_SETACTIVE
Definition: prsht.h:115
static void PROPSHEET_SetHeaderTitleA(HWND hwndDlg, UINT page_index, const char *title)
Definition: propsheet.c:2554
static VOID NTAPI BitBlt(IN ULONG Left, IN ULONG Top, IN ULONG Width, IN ULONG Height, IN PUCHAR Buffer, IN ULONG BitsPerPixel, IN ULONG Delta)
Definition: vga.c:410
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
#define COLOR_WINDOW
Definition: winuser.h:908
int32_t INT
Definition: typedefs.h:56
#define PSM_SETFINISHTEXTW
Definition: prsht.h:105
static UINT GetTemplateSize(const DLGTEMPLATE *pTemplate)
Definition: propsheet.c:1209
DWORD WINAPI GetSysColor(_In_ int)
WPARAM wParam
Definition: combotst.c:138
HRSRC WINAPI FindResourceW(HINSTANCE hModule, LPCWSTR name, LPCWSTR type)
Definition: res.c:176
HWND WINAPI GetTopWindow(_In_opt_ HWND)
#define DWLP_MSGRESULT
Definition: winuser.h:864
struct tagNMHDR * LPNMHDR
HANDLE WINAPI RemovePropW(_In_ HWND, _In_ LPCWSTR)
#define MAX_BUTTONTEXT_LENGTH
Definition: propsheet.c:150
#define WM_PRINTCLIENT
Definition: richedit.h:70
static BOOL PROPSHEET_IsDialogMessage(HWND hwnd, LPMSG lpMsg)
Definition: propsheet.c:3177
UINT nStartPage
Definition: prsht.h:251
#define VK_NEXT
Definition: winuser.h:2196
_In_opt_ PALLOCATE_FUNCTION _In_opt_ PFREE_FUNCTION Free
Definition: exfuncs.h:656
#define ID_PSRESTARTWINDOWS
Definition: prsht.h:132
#define PSM_ISDIALOGMESSAGE
Definition: prsht.h:96
BOOL WINAPI ImageList_Destroy(HIMAGELIST himl)
Definition: imagelist.c:928
#define IDHELP
Definition: resource_2.h:8
static BOOL PROPSHEET_AdjustButtonsWizard(HWND hwndParent, const PropSheetInfo *psInfo)
Definition: propsheet.c:928
#define PSM_SETCURSEL
Definition: prsht.h:167
#define PSN_QUERYCANCEL
Definition: prsht.h:123
UINT code
Definition: winuser.h:3134
static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage)
Definition: propsheet.c:1838
COLORREF WINAPI SetBkColor(_In_ HDC, _In_ COLORREF)
Definition: dc.c:975
#define DS_MODALFRAME
Definition: winuser.h:375
NMHDR hdr
Definition: prsht.h:312
static void PROPSHEET_SetHeaderTitleW(HWND hwndDlg, UINT page_index, const WCHAR *title)
Definition: propsheet.c:2532
static INT PROPSHEET_FindPageByResId(const PropSheetInfo *psInfo, LRESULT resId)
Definition: propsheet.c:274
BOOL WINAPI AdjustWindowRect(_Inout_ LPRECT, _In_ DWORD, _In_ BOOL)
LPWSTR strPropertiesFor
Definition: propsheet.c:113
static BOOL PROPSHEET_CanSetCurSel(HWND hwndDlg)
Definition: propsheet.c:1943
int WINAPI SetBkMode(_In_ HDC, _In_ int)
Definition: dc.c:1032
#define IDD_PROPSHEET
Definition: comctl32.h:43
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static void PROPSHEET_GetPageRect(const PropSheetInfo *psInfo, HWND hwndDlg, RECT *rc, LPCPROPSHEETPAGEW ppshpage)
Definition: propsheet.c:230
#define WS_EX_CONTROLPARENT
Definition: winuser.h:387
HIMAGELIST WINAPI ImageList_Create(INT cx, INT cy, UINT flags, INT cInitial, INT cGrow)
Definition: imagelist.c:804
#define PSN_KILLACTIVE
Definition: prsht.h:116
DWORD dwSize
Definition: prsht.h:205
#define PSH_USEICONID
Definition: prsht.h:42
static LONG active_page
Definition: propsheet.c:37
#define DT_LEFT
Definition: winuser.h:534
#define PSN_WIZFINISH
Definition: prsht.h:122
static const WCHAR szText[]
Definition: dialog.c:139
LRESULT WINAPI DispatchMessageW(_In_ const MSG *)
HIMAGELIST hImageList
Definition: propsheet.c:128
LPCWSTR pszCaption
Definition: prsht.h:283
static void PROPSHEET_Cancel(HWND hwndDlg, LPARAM lParam)
Definition: propsheet.c:1773
HWND hwndParent
Definition: prsht.h:242
unsigned int BOOL
Definition: ntddk_ex.h:94
DLGPROC pfnDlgProc
Definition: prsht.h:217
HANDLE WINAPI LoadImageW(_In_opt_ HINSTANCE, _In_ LPCWSTR, _In_ UINT, _In_ int, _In_ int, _In_ UINT)
Definition: cursoricon.c:2172
long LONG
Definition: pedump.c:60
HDC WINAPI BeginPaint(_In_ HWND, _Out_ LPPAINTSTRUCT)
static WCHAR * heap_strdupW(const WCHAR *str)
Definition: propsheet.c:178
UINT_PTR idFrom
Definition: winuser.h:3133
static BOOL PROPSHEET_Next(HWND hwndDlg)
Definition: propsheet.c:1626
#define debugstr_w
Definition: kernel32.h:32
struct _PSP * HPROPSHEETPAGE
Definition: mstask.idl:90
#define PSH_WIZARDCONTEXTHELP
Definition: prsht.h:52
#define FIXME(fmt,...)
Definition: debug.h:110
#define ILC_COLOR
Definition: commctrl.h:348
#define PSM_SETWIZBUTTONS
Definition: prsht.h:157
#define TCM_DELETEITEM
Definition: commctrl.h:4049
static PVOID ptr
Definition: dispmode.c:27
PFNPROPSHEETCALLBACK pfnCallback
Definition: prsht.h:293
unsigned int idx
Definition: utils.c:41
#define TRANSPARENT
Definition: wingdi.h:949
static BOOL PROPSHEET_CreateTabControl(HWND hwndParent, const PropSheetInfo *psInfo)
Definition: propsheet.c:1137
static void PROPSHEET_SetCurSelId(HWND hwndDlg, int id)
Definition: propsheet.c:2106
#define VK_SHIFT
Definition: winuser.h:2177
#define PSCB_PRECREATE
Definition: prsht.h:76
PFNPROPSHEETCALLBACK pfnCallback
Definition: prsht.h:258
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
const WCHAR * str
LONG WINAPI GetWindowLongW(_In_ HWND, _In_ int)
#define TCM_INSERTITEMW
Definition: commctrl.h:4043
static void PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh, PropSheetInfo *psInfo)
Definition: propsheet.c:361
#define PSNRET_INVALID_NOCHANGEPAGE
Definition: prsht.h:131
HPALETTE WINAPI SelectPalette(_In_ HDC, _In_ HPALETTE, _In_ BOOL)
static INT_PTR PROPSHEET_CreateDialog(PropSheetInfo *psInfo)
Definition: propsheet.c:600
smooth NULL
Definition: ftsmooth.c:416
HFONT WINAPI CreateFontIndirectW(_In_ const LOGFONTW *)
struct _PROPSHEETPAGEW * LPPROPSHEETPAGEW
static HWND hwndParent
Definition: cryptui.c:300
LPCSTR pszIcon
Definition: prsht.h:186
#define PSN_WIZNEXT
Definition: prsht.h:121
#define ETDT_ENABLETAB
Definition: dxdiag.c:30
#define WM_KEYDOWN
Definition: winuser.h:1697
LONG_PTR LPARAM
Definition: windef.h:208
Definition: module.h:566
#define PSM_SETCURSELID
Definition: prsht.h:104
static PADDING_INFO PROPSHEET_GetPaddingInfo(HWND hwndDlg)
Definition: propsheet.c:1055
LPCWSTR pszText
Definition: propsheet.c:102
static LRESULT PROPSHEET_IdToIndex(HWND hwndDlg, int iPageId)
Definition: propsheet.c:2663
INT_PTR WINAPI PropertySheetW(LPCPROPSHEETHEADERW lppsh)
Definition: propsheet.c:2905
LRESULT WINAPI DefSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: commctrl.c:1496
GLuint index
Definition: glext.h:6031
HBITMAP WINAPI CreateMappedBitmap(HINSTANCE hInstance, INT_PTR idBitmap, UINT wFlags, LPCOLORMAP lpColorMap, INT iNumMaps)
Definition: commctrl.c:998
static BOOL PROPSHEET_SizeMismatch(HWND hwndDlg, const PropSheetInfo *psInfo)
Definition: propsheet.c:692
const char * LPCSTR
Definition: xmlstorage.h:183
static void PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh, PropSheetInfo *psInfo)
Definition: propsheet.c:317
LPCWSTR pszTitle
Definition: prsht.h:216
#define SW_SHOW
Definition: winuser.h:769
INT_PTR WINAPI PropertySheetA(LPCPROPSHEETHEADERA lppsh)
Definition: propsheet.c:2864
#define PSPCB_RELEASE
Definition: prsht.h:37
static BOOL PROPSHEET_Back(HWND hwndDlg)
Definition: propsheet.c:1584
#define UlongToPtr(u)
Definition: config.h:106
#define WM_DESTROY
Definition: winuser.h:1591
#define IDS_CLOSE
Definition: comctl32.h:54
#define PSBTN_CANCEL
Definition: prsht.h:151
#define PSM_REBOOTSYSTEM
Definition: prsht.h:162
#define RT_DIALOG
Definition: pedump.c:367
SHORT WINAPI GetKeyState(_In_ int)
HPROPSHEETPAGE WINAPI CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage)
Definition: propsheet.c:3075
#define PSWIZB_FINISH
Definition: prsht.h:155
HBITMAP hbmp
BOOL WINAPI SetWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uIDSubclass, DWORD_PTR dwRef)
Definition: commctrl.c:1261
#define WS_CAPTION
Definition: pedump.c:624
BOOL WINAPI SystemParametersInfoW(_In_ UINT, _In_ UINT, _Inout_opt_ PVOID, _In_ UINT)
#define TCN_SELCHANGE
Definition: commctrl.h:4128
#define PSM_APPLY
Definition: prsht.h:158
static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags)
Definition: propsheet.c:2458
static void PROPSHEET_SetFinishTextW(HWND hwndDlg, LPCWSTR lpszText)
Definition: propsheet.c:2198
static VOID PROPSHEET_UnImplementedFlags(DWORD dwFlags)
Definition: propsheet.c:204
static VOID PROPSHEET_LoadWizardBitmaps(PropSheetInfo *psInfo)
Definition: propsheet.c:1493
#define TRACE(s)
Definition: solgame.cpp:4
unsigned int padding
Definition: isohybrid.c:50
#define IS_INTRESOURCE(i)
Definition: winuser.h:580
#define IDC_SUNKEN_LINEHEADER
Definition: comctl32.h:52
BOOL WINAPI SetPropW(_In_ HWND, _In_ LPCWSTR, _In_opt_ HANDLE)
r parent
Definition: btrfs.c:2869
static BOOL PROPSHEET_AdjustButtons(HWND hwndParent, const PropSheetInfo *psInfo)
Definition: propsheet.c:839
if(!(yy_init))
Definition: macro.lex.yy.c:714
HWND WINAPI GetDlgItem(_In_opt_ HWND, _In_ int)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define PSWIZB_BACK
Definition: prsht.h:153
#define debugstr_a
Definition: kernel32.h:31
#define PSM_CANCELTOCLOSE
Definition: prsht.h:161
#define PSH_PROPTITLE
Definition: prsht.h:40
BOOL WINAPI SetWindowTextA(_In_ HWND, _In_opt_ LPCSTR)
#define SWP_NOACTIVATE
Definition: winuser.h:1227
DWORD COLORREF
Definition: windef.h:300
HINSTANCE hInstance
Definition: prsht.h:278
HRESULT WINAPI EnableThemeDialogTexture(_In_ HWND hwnd, _In_ DWORD dwFlags)
Definition: uxthemesupp.c:55
DWORD dwSize
Definition: prsht.h:240
#define PROPSHEETPAGEA_V1_SIZE
Definition: prsht.h:200
#define PSH_USEPSTARTPAGE
Definition: prsht.h:46
#define WM_CLOSE
Definition: winuser.h:1603
#define PSH_HASHELP
Definition: prsht.h:49
HWND WINAPI CreateDialogIndirectParamA(_In_opt_ HINSTANCE, _In_ LPCDLGTEMPLATE, _In_opt_ HWND, _In_opt_ DLGPROC, _In_ LPARAM)
#define WINAPI
Definition: msvc.h:6
const char * wine_dbgstr_rect(const RECT *rect)
BOOL WINAPI InvalidateRect(_In_opt_ HWND, _In_opt_ LPCRECT, _In_ BOOL)
PVOID Alloc(IN DWORD dwFlags, IN SIZE_T dwBytes)
Definition: main.c:63
static const WCHAR titleW[]
Definition: htmlelem.c:1067
unsigned short WORD
Definition: ntddk_ex.h:93
int WINAPI GetSystemMetrics(_In_ int)
#define PSM_GETRESULT
Definition: window.cpp:1319
#define for
Definition: utility.h:88
unsigned long DWORD
Definition: ntddk_ex.h:95
static BOOL PROPSHEET_AdjustSizeWizard(HWND hwndDlg, const PropSheetInfo *psInfo)
Definition: propsheet.c:805
const PROPSHEETPAGEA * LPCPROPSHEETPAGEA
Definition: prsht.h:199
#define PSM_GETCURRENTPAGEHWND
Definition: prsht.h:81
HGLOBAL NTAPI GlobalFree(HGLOBAL hMem)
Definition: heapmem.c:611
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
DWORD dwSize
Definition: prsht.h:275
INT WINAPI ImageList_AddIcon(HIMAGELIST himl, HICON hIcon)
Definition: imagelist.c:540
#define PSM_RESTARTWINDOWS
Definition: prsht.h:163
#define PSBTN_OK
Definition: prsht.h:149
DWORD dwFlags
Definition: prsht.h:276
TCHAR szTitle[MAX_LOADSTRING]
Definition: magnifier.c:35
static BOOL PROPSHEET_SetCurSel(HWND hwndDlg, int index, int skipdir, HPROPSHEETPAGE hpage)
Definition: propsheet.c:1982
#define WM_PAINT
Definition: winuser.h:1602
#define SM_CXSMICON
Definition: winuser.h:1002
static BOOL PROPSHEET_InsertPage(HWND hwndDlg, HPROPSHEETPAGE hpageInsertAfter, HPROPSHEETPAGE hpage)
Definition: propsheet.c:2248
DWORD dwFlags
Definition: prsht.h:241
#define IDD_WIZARD
Definition: comctl32.h:44
#define IDC_BACK_BUTTON
Definition: comctl32.h:48
int ret
static WCHAR * heap_strdupAtoW(const char *str)
Definition: propsheet.c:186
static LRESULT PROPSHEET_IndexToHwnd(HWND hwndDlg, int iPageIndex)
Definition: propsheet.c:2621
#define PSPCB_CREATE
Definition: prsht.h:38
#define index(s, c)
Definition: various.h:29
HDC hdc
Definition: main.c:9
#define DS_SETFONT
Definition: winuser.h:378
static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo *psInfo)
Definition: propsheet.c:723
#define DWLP_USER
Definition: winuser.h:866
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
#define DS_CONTEXTHELP
Definition: winuser.h:371
HINSTANCE hInstance
Definition: prsht.h:207
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
#define RT_STRING
Definition: pedump.c:368
#define WS_TABSTOP
Definition: pedump.c:634
#define PSM_ADDPAGE
Definition: prsht.h:165
#define PSM_UNCHANGED
Definition: prsht.h:159
#define WM_COMMAND
Definition: winuser.h:1722
DWORD dwFlags
Definition: prsht.h:178
static INT do_loop(const PropSheetInfo *psInfo)
Definition: propsheet.c:2790
HWND hwndFrom
Definition: winuser.h:3132
uint32_t DWORD_PTR
Definition: typedefs.h:63
#define PSP_USETITLE
Definition: prsht.h:26
#define PSBTN_NEXT
Definition: prsht.h:147
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
static void PROPSHEET_SetHeaderSubTitleA(HWND hwndDlg, UINT page_index, const char *subtitle)
Definition: propsheet.c:2590
HICON hIcon
Definition: prsht.h:213
BOOL WINAPI EnableWindow(_In_ HWND, _In_ BOOL)
HPROPSHEETPAGE * phpage
Definition: prsht.h:291
const PROPSHEETPAGEW * LPCPROPSHEETPAGEW
Definition: prsht.h:227
#define SWP_NOSIZE
Definition: winuser.h:1230
#define ERR(fmt,...)
Definition: debug.h:109
static BOOL PROPSHEET_CreatePage(HWND hwndParent, int index, const PropSheetInfo *psInfo, LPCPROPSHEETPAGEW ppshpage)
Definition: propsheet.c:1344
#define GWL_STYLE
Definition: winuser.h:846
#define DT_NOCLIP
Definition: winuser.h:536
COLORREF WINAPI SetTextColor(_In_ HDC, _In_ COLORREF)
Definition: text.c:888
int WINAPI GetObjectW(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
#define WIZARD_PADDING
Definition: propsheet.c:155
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
#define TCM_SETIMAGELIST
Definition: commctrl.h:3961
#define MAX_CAPTION_LENGTH
Definition: propsheet.c:148
#define DT_SINGLELINE
Definition: winuser.h:540
BOOL WINAPI SetRect(_Out_ LPRECT, _In_ int, _In_ int, _In_ int, _In_ int)
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219