Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

497 lines
14 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: N C P R S H T . C P P
  7. //
  8. // Contents: NetCfg custom PropertySheet
  9. //
  10. // Notes:
  11. //
  12. // Author: billbe 8 Apr 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "ncprsht.h"
  18. #include <prsht.h>
  19. #include "nceh.h"
  20. // Necessary evil globals
  21. CAPAGES g_capPagesToAdd; // Counted array of pages to add after Property
  22. // Sheet is initialized
  23. CAINCP g_cai; // Counted array of INetCfgProperty pointers
  24. HRESULT g_hr; // Global error code
  25. BOOL g_fChanged; // Global flag representing whether a PSM_CHANGED
  26. // message was sent by a page
  27. DLGPROC lpfnOldWndProc; // Previous dialog procedure
  28. // NetCfg Property Sheet dialog procedure
  29. INT_PTR CALLBACK NetCfgPsDlgProc(HWND hDlg, UINT msg, WPARAM wParam,
  30. LPARAM lParam);
  31. //+---------------------------------------------------------------------------
  32. //
  33. // Function: SetLastHresult
  34. //
  35. // Purpose: This sets a global hresult variable. The function
  36. // is analogous to SetLastError
  37. //
  38. // Arguments:
  39. // HRESULT [in] Result to set
  40. //
  41. // Returns: nothing
  42. //
  43. // Author: billbe 8 Apr 1997
  44. //
  45. // Notes:
  46. //
  47. //
  48. inline void
  49. SetLastHresult(HRESULT hr)
  50. {
  51. g_hr = hr;
  52. }
  53. //+---------------------------------------------------------------------------
  54. //
  55. // Function: HrGetLastHresult
  56. //
  57. // Purpose: This returns the value of the global hresult variable.
  58. // The function is analogous to GetLastError
  59. //
  60. // Arguments:
  61. // none
  62. //
  63. // Returns: HRESULT. Value of the global g_hr.
  64. //
  65. // Author: billbe 8 Apr 1997
  66. //
  67. // Notes:
  68. //
  69. //
  70. inline HRESULT
  71. HrGetLastHresult()
  72. {
  73. return (g_hr);
  74. }
  75. //+---------------------------------------------------------------------------
  76. //
  77. // Function: ResetChanged
  78. //
  79. // Purpose: This resets the global changed flag. The reset state
  80. // indicates that a PSM_VHANGED message was not sent
  81. //
  82. // Arguments:
  83. // none
  84. //
  85. // Returns:
  86. // (nothing)
  87. //
  88. // Author: billbe 3 May 1997
  89. //
  90. // Notes:
  91. //
  92. //
  93. inline void
  94. ResetChanged()
  95. {
  96. g_fChanged = FALSE;
  97. }
  98. //+---------------------------------------------------------------------------
  99. //
  100. // Function: SetChanged
  101. //
  102. // Purpose: This sets the global changed flag. The set state indicates
  103. // that a PSM_CHANGED message was sent
  104. //
  105. // Arguments:
  106. // none
  107. //
  108. // Returns:
  109. // (nothing)
  110. //
  111. // Author: billbe 3 May 1997
  112. //
  113. // Notes:
  114. //
  115. //
  116. inline void
  117. SetChanged()
  118. {
  119. g_fChanged = TRUE;
  120. }
  121. //+---------------------------------------------------------------------------
  122. //
  123. // Function: FGetChanged
  124. //
  125. // Purpose: This returns the state of the global changed flag. The set
  126. // state indicates whether a PSM_CHANGED message was sent
  127. // or not.
  128. //
  129. // Arguments:
  130. // none
  131. //
  132. // Returns:
  133. // BOOL. Value of the global g_fChanged flag.
  134. //
  135. // Author: billbe 3 May 1997
  136. //
  137. // Notes:
  138. //
  139. //
  140. inline BOOL
  141. FGetChanged()
  142. {
  143. return (g_fChanged);
  144. }
  145. //+---------------------------------------------------------------------------
  146. //
  147. // Function: NetCfgPropSheetCallback
  148. //
  149. // Purpose: This callback is called after the aheet dialog is
  150. // initialized. We subclass the dialog and add any OEM
  151. // pages here (if common pages exist). See Win32 for
  152. // discussion of PropSheetProc
  153. //
  154. // Arguments:
  155. // HWND [in] hwndDlg handle to the property sheet dialog box
  156. // UINT uMsg [in] message identifier
  157. // LPARAM lParam [in] message parameter
  158. //
  159. // Returns: int, The function returns zero.
  160. //
  161. // Author: billbe 11 Nov 1996
  162. //
  163. // Notes:
  164. //
  165. //
  166. int
  167. CALLBACK NetCfgPropSheetCallback(HWND hwndDlg, UINT uMsg, LPARAM lParam)
  168. {
  169. // If the sheet has just been initialized
  170. if (uMsg == PSCB_INITIALIZED)
  171. {
  172. // Replace the original procedure with ours
  173. lpfnOldWndProc = (DLGPROC)SetWindowLongPtr(hwndDlg, DWLP_DLGPROC, (LONG_PTR) NetCfgPsDlgProc);
  174. Assert(lpfnOldWndProc);
  175. // Add the OEM pages that were scheduled for late add
  176. // This will cause them to be clipped if they are larger than
  177. // the common (default) pages. Note that this is the desired
  178. // result.
  179. //
  180. for (int i = 0; i < g_capPagesToAdd.nCount; i++)
  181. {
  182. PropSheet_AddPage(hwndDlg, g_capPagesToAdd.ahpsp[i]);
  183. }
  184. }
  185. return (0);
  186. }
  187. //+---------------------------------------------------------------------------
  188. //
  189. // Function: HrCallValidateProperties
  190. //
  191. // Purpose: This function calls the notify objects'
  192. // INetCfgProperties::ValidateProperties method.
  193. //
  194. // Arguments:
  195. // none
  196. //
  197. // Returns: HRESULT, S_OK if all of the INetCfgProperties return S_OK
  198. // of the result of the first interface that does not
  199. // return S_OK.
  200. //
  201. // Author: billbe 8 Apr 1997
  202. //
  203. // Notes: If one of the interfaces returns something other than S_OK, the
  204. // others will not be called and the function will return the hresult
  205. // of that interface.
  206. //
  207. HRESULT
  208. HrCallValidateProperties(HWND hwndSheet)
  209. {
  210. HRESULT hr = S_OK;
  211. // enumerate through the counted array of interfaces
  212. // and call ValidateProperties
  213. //
  214. for (int i = 0; i < g_cai.nCount; i++)
  215. {
  216. // At the first sign of non-S_OK get out
  217. if (S_OK != (hr = g_cai.apncp[i]->ValidateProperties(hwndSheet)))
  218. break;
  219. }
  220. TraceError("HrCallValidateProperties", hr);
  221. return (hr);
  222. }
  223. //+---------------------------------------------------------------------------
  224. //
  225. // Function: NetCfgPsDlgProc
  226. //
  227. // Purpose: This function is the dialog procedure for the property sheet
  228. // See Win32 documentation on DialogProc for more information
  229. //
  230. // Arguments:
  231. // hwndDlg [in] handle to dialog box
  232. // uMsg [in] message
  233. // wParam [in] first message parameter
  234. // lParam [in] second message parameter
  235. //
  236. // Returns: LONG, Except in response to the WM_INITDIALOG message, the
  237. // dialog box procedure should return nonzero if it processes
  238. // the message, and zero if it does not.
  239. //
  240. // Author: billbe 8 Apr 1997
  241. //
  242. // Notes:
  243. //
  244. INT_PTR CALLBACK NetCfgPsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  245. {
  246. switch (msg)
  247. {
  248. case WM_DESTROY:
  249. // restore the dialog procedure before we exit
  250. SetWindowLongPtr(hDlg, DWLP_DLGPROC, (LONG_PTR) lpfnOldWndProc);
  251. break;
  252. case WM_SYSCOMMAND:
  253. // The user is closing through the system menu. This is like
  254. // canceling
  255. if (SC_CLOSE == wParam)
  256. {
  257. SetLastHresult(HRESULT_FROM_WIN32(ERROR_CANCELLED));
  258. }
  259. break;
  260. case PSM_CHANGED:
  261. SetChanged();
  262. break;
  263. case WM_COMMAND:
  264. // If the user pressed OK
  265. if ((IDOK == LOWORD(wParam)) && (BN_CLICKED == HIWORD(wParam)))
  266. {
  267. // Send a KillActive message to the currect page. This echoes
  268. // what the Win32 propertysheet would do. This results in a
  269. // second KillActive message being sent to the active page
  270. // when the OK message is processed. It is necessary
  271. // to send it here because we need its result before we
  272. // call HrCallValidateProperties which is done before the OK
  273. // is processed.
  274. //
  275. NMHDR nmhdr;
  276. ZeroMemory(&nmhdr, sizeof(NMHDR));
  277. nmhdr.hwndFrom = hDlg;
  278. nmhdr.code = PSN_KILLACTIVE;
  279. if (SendMessage(PropSheet_GetCurrentPageHwnd(hDlg), WM_NOTIFY,
  280. 0, (LPARAM) &nmhdr))
  281. {
  282. // The page does not want the PropertySheet to go away so exit
  283. // without allowing the original procedure to get the message
  284. return (TRUE);
  285. }
  286. // The current page validated okay so now we must call all the
  287. // ValidateProperties necessary.
  288. if (S_OK != HrCallValidateProperties(hDlg))
  289. {
  290. // One of the interfaces returned something other than S_OK
  291. // from Validateproperties so we exit without letting
  292. // the original dialog procedure process the message.
  293. // This will keep the PropertySheet active.
  294. return (TRUE);
  295. }
  296. }
  297. else if (IDCANCEL == LOWORD(wParam) && BN_CLICKED == HIWORD(wParam))
  298. {
  299. // If Cancel was pressed set the last hresult
  300. SetLastHresult(HRESULT_FROM_WIN32(ERROR_CANCELLED));
  301. }
  302. break;
  303. }
  304. // call the original dialog procedure
  305. return (CallWindowProc((WNDPROC)lpfnOldWndProc, hDlg, msg, wParam, lParam));
  306. }
  307. //+---------------------------------------------------------------------------
  308. //
  309. // Function: VerifyCAPAGES
  310. //
  311. // Synopsis: function to check the validity of a given CAPAGES structure
  312. //
  313. // Arguments: [cap] --
  314. //
  315. // Returns: BOOL
  316. //
  317. // Notes: 14-Jan-1998 SumitC Created
  318. //
  319. //----------------------------------------------------------------------------
  320. BOOL
  321. FVerifyCAPAGES(const struct CAPAGES& cap)
  322. {
  323. BOOL fGood = FALSE;
  324. if (cap.nCount == 0)
  325. {
  326. fGood = (cap.ahpsp == NULL);
  327. }
  328. else
  329. {
  330. fGood = !IsBadReadPtr(cap.ahpsp, sizeof(HPROPSHEETPAGE) * cap.nCount);
  331. }
  332. return fGood;
  333. }
  334. //+---------------------------------------------------------------------------
  335. //
  336. // Function: HrNetCfgPropertySheet
  337. //
  338. // Purpose: This function is sets up our custom property sheet which is
  339. // a subclassed Win32 property sheet.
  340. // See Win32 documentation on PropertySheet for more information
  341. //
  342. // Arguments:
  343. // lppsh [in] a PROPSHEETHEADER
  344. // capOem [in] A counted array of Oem pages
  345. // pStartPage [in] Name of the initial page that appears when the property
  346. // sheet dialog box is created. This member can specify
  347. // either the identifier of a string resource or the
  348. // pointer to a string that specifies the name.
  349. // caiProperties [in] A counted array of INetCfgProperties interfaces
  350. //
  351. // Returns: HRESULT, S_OK if OK was pressed and changes were made,
  352. // S_FALSE if OK was pressed and no changes were
  353. // made. An error code otherwise.
  354. //
  355. // Author: billbe 8 Apr 1997
  356. //
  357. // Notes:
  358. // HRESULT_FROM_WIN32(ERROR_CANCELLED) is returned if the
  359. // cancel button was pressed
  360. //
  361. HRESULT
  362. HrNetCfgPropertySheet(
  363. IN OUT LPPROPSHEETHEADER lppsh,
  364. IN const CAPAGES& capOem,
  365. IN PCWSTR pStartPage,
  366. const CAINCP& caiProperties)
  367. {
  368. HRESULT hr = S_OK;
  369. Assert(lppsh);
  370. // The following should not be set since we are setting them
  371. Assert(0 == lppsh->nPages);
  372. Assert(NULL == lppsh->phpage);
  373. Assert(!(PSH_USECALLBACK & lppsh->dwFlags));
  374. Assert(!(PSH_PROPSHEETPAGE & lppsh->dwFlags));
  375. // If a start page was specified than there had better be Oem Pages
  376. Assert(FImplies(pStartPage, capOem.nCount));
  377. // We have to have at least one INetCfgProperties since we are here
  378. Assert(caiProperties.nCount);
  379. Assert(caiProperties.apncp);
  380. // Set our global CAINCP structure
  381. g_cai.nCount = caiProperties.nCount;
  382. g_cai.apncp = caiProperties.apncp;
  383. // Reset our global CAPAGES
  384. g_capPagesToAdd.nCount = 0;
  385. g_capPagesToAdd.ahpsp = NULL;
  386. // We need to set up a callback to subclass the dialog
  387. lppsh->dwFlags |= PSH_USECALLBACK;
  388. lppsh->pfnCallback = NetCfgPropSheetCallback;
  389. // There are no common pages to show so we will use the OEM pages
  390. // instead
  391. Assert(capOem.nCount);
  392. if (FVerifyCAPAGES(capOem))
  393. {
  394. lppsh->nPages = capOem.nCount;
  395. lppsh->phpage = capOem.ahpsp;
  396. }
  397. else
  398. {
  399. //$ REVIEW sumitc: or just return E_INVALIDARG?
  400. lppsh->nPages = 0;
  401. lppsh->phpage = NULL;
  402. }
  403. Assert(FImplies(lppsh->nPages, lppsh->phpage));
  404. // If a start page was specified, set the propsheet flag and
  405. // start page member.
  406. // Note: (billbe) This will not work if common pages exist since
  407. // that means Oem pages are added after the sheet is initialized
  408. if (pStartPage)
  409. {
  410. lppsh->dwFlags |= PSH_USEPSTARTPAGE;
  411. lppsh->pStartPage = pStartPage;
  412. }
  413. // Clear last hresult and changed flag
  414. SetLastHresult(S_OK);
  415. ResetChanged();
  416. // Call the Win32 property sheet
  417. NC_TRY
  418. {
  419. INT_PTR iRetVal = PropertySheet(lppsh);
  420. if (-1 == iRetVal)
  421. {
  422. // The Win32 Sheet failed so we return E_FAIL
  423. SetLastHresult(E_FAIL);
  424. }
  425. }
  426. NC_CATCH_ALL
  427. {
  428. hr = E_UNEXPECTED;
  429. }
  430. if (S_OK == hr)
  431. {
  432. // if the catch hasn't set hr to some error
  433. hr = HrGetLastHresult();
  434. }
  435. // if everthing went well, return the correct value based on whether
  436. // any of the pages changed
  437. //
  438. if (SUCCEEDED(hr))
  439. {
  440. // S_OK - changes were made, S_FALSE - no changes were made
  441. hr = FGetChanged() ? S_OK : S_FALSE;
  442. }
  443. TraceError("HrNetCfgPropertySheet",
  444. ((HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr) || (S_FALSE == hr)) ? S_OK : hr);
  445. return hr;
  446. }