Source code of Windows XP (NT5)
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.

458 lines
12 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Windows NT Active Directory Property Page Sample
  4. //
  5. // The code contained in this source file is for demonstration purposes only.
  6. // No warrantee is expressed or implied and Microsoft disclaims all liability
  7. // for the consequenses of the use of this source code.
  8. //
  9. // Microsoft Windows
  10. // Copyright (C) Microsoft Corporation, 1992 - 1999
  11. //
  12. // File: page.cxx
  13. //
  14. // Contents: CDsPropPage, the class that implements the sample property
  15. // page.
  16. //
  17. // History: 8-Sep-97 Eric Brown created
  18. // 24-Sep-98 " " revised to include notification object.
  19. //
  20. //-----------------------------------------------------------------------------
  21. #include "page.h"
  22. WCHAR wzSpendingLimit[] = L"spendingLimit";
  23. //+----------------------------------------------------------------------------
  24. //
  25. // Member: CDsPropPage::CDsPropPage
  26. //
  27. //-----------------------------------------------------------------------------
  28. CDsPropPage::CDsPropPage(HWND hNotifyObj) :
  29. m_hPage(NULL),
  30. m_pDsObj(NULL),
  31. m_fInInit(FALSE),
  32. m_fPageDirty(FALSE),
  33. m_pwzObjPathName(NULL),
  34. m_pwzObjClass(NULL),
  35. m_pwzRDName(NULL),
  36. m_hNotifyObj(hNotifyObj),
  37. m_pWritableAttrs(NULL),
  38. m_hrInit(S_OK)
  39. {
  40. }
  41. //+----------------------------------------------------------------------------
  42. //
  43. // Member: CDsPropPage::~CDsPropPage
  44. //
  45. // Notes: m_pWritableAttrs does not need to be freed. It refers to
  46. // memory held by the notify object and freed when the notify
  47. // object is destroyed.
  48. //
  49. //-----------------------------------------------------------------------------
  50. CDsPropPage::~CDsPropPage()
  51. {
  52. if (m_pDsObj)
  53. {
  54. m_pDsObj->Release();
  55. }
  56. if (m_pwzObjPathName)
  57. {
  58. delete m_pwzObjPathName;
  59. }
  60. if (m_pwzObjClass)
  61. {
  62. delete m_pwzObjClass;
  63. }
  64. if (m_pwzRDName)
  65. {
  66. delete m_pwzRDName;
  67. }
  68. }
  69. //+----------------------------------------------------------------------------
  70. //
  71. // Method: CDsPropPage::CreatePage
  72. //
  73. // Sysnopsis: Create the prop page
  74. //
  75. // Notes: if m_hrInit contains a failure code at this point, then an
  76. // error page template could be substituted for the regular one.
  77. //
  78. //-----------------------------------------------------------------------------
  79. HRESULT
  80. CDsPropPage::CreatePage(HPROPSHEETPAGE * phPage)
  81. {
  82. TCHAR szTitle[MAX_PATH];
  83. if (!LoadString(g_hInstance, IDS_PAGE_TITLE, szTitle, MAX_PATH - 1))
  84. {
  85. DWORD dwErr = GetLastError();
  86. return HRESULT_FROM_WIN32(GetLastError());
  87. }
  88. PROPSHEETPAGE psp;
  89. psp.dwSize = sizeof(PROPSHEETPAGE);
  90. psp.dwFlags = PSP_USECALLBACK | PSP_USETITLE;
  91. psp.pszTemplate = (LPCTSTR)IDD_SAMPLE_PAGE;
  92. psp.pfnDlgProc = (DLGPROC)StaticDlgProc;
  93. psp.pfnCallback = PageCallback;
  94. psp.pcRefParent = NULL; // do not set PSP_USEREFPARENT
  95. psp.lParam = (LPARAM) this;
  96. psp.hInstance = g_hInstance;
  97. psp.pszTitle = L"Spending Limit";
  98. *phPage = CreatePropertySheetPage(&psp);
  99. if (*phPage == NULL)
  100. {
  101. return HRESULT_FROM_WIN32(GetLastError());
  102. }
  103. return S_OK;
  104. }
  105. //+----------------------------------------------------------------------------
  106. //
  107. // Method: CDsPropPage::Init
  108. //
  109. // Sysnopsis: Initialize the page object. This is the second part of a two
  110. // phase creation where operations that could fail are located.
  111. //
  112. //-----------------------------------------------------------------------------
  113. HRESULT
  114. CDsPropPage::Init(PWSTR pwzObjName, PWSTR pwzClass)
  115. {
  116. m_pwzObjPathName = new WCHAR[wcslen(pwzObjName) + 1];
  117. if (m_pwzObjPathName == NULL )
  118. {
  119. return E_OUTOFMEMORY;
  120. }
  121. m_pwzObjClass = new WCHAR[wcslen(pwzClass) + 1];
  122. if (m_pwzObjClass == NULL)
  123. {
  124. return E_OUTOFMEMORY;
  125. }
  126. wcscpy(m_pwzObjPathName, pwzObjName);
  127. wcscpy(m_pwzObjClass, pwzClass);
  128. //
  129. // NOTIFY_OBJ
  130. // Contact the notification object for the initialization info.
  131. //
  132. ADSPROPINITPARAMS InitParams = {0};
  133. InitParams.dwSize = sizeof (ADSPROPINITPARAMS);
  134. if (!ADsPropGetInitInfo(m_hNotifyObj, &InitParams))
  135. {
  136. m_hrInit = E_FAIL;
  137. return E_FAIL;
  138. }
  139. if (FAILED(InitParams.hr))
  140. {
  141. m_hrInit = InitParams.hr;
  142. return m_hrInit;
  143. }
  144. m_pwzRDName = new WCHAR[wcslen(InitParams.pwzCN) + 1];
  145. if (m_pwzRDName == NULL)
  146. {
  147. m_hrInit = E_OUTOFMEMORY;
  148. return E_OUTOFMEMORY;
  149. }
  150. m_pDsObj = InitParams.pDsObj;
  151. m_pDsObj->AddRef();
  152. m_pWritableAttrs = InitParams.pWritableAttrs;
  153. return S_OK;
  154. }
  155. //+----------------------------------------------------------------------------
  156. //
  157. // Method: StaticDlgProc
  158. //
  159. // Sysnopsis: static dialog proc
  160. //
  161. //-----------------------------------------------------------------------------
  162. LRESULT CALLBACK
  163. StaticDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  164. {
  165. CDsPropPage * pPage = (CDsPropPage *)GetWindowLongPtr(hDlg, DWLP_USER);
  166. if (uMsg == WM_INITDIALOG)
  167. {
  168. LPPROPSHEETPAGE ppsp = (LPPROPSHEETPAGE)lParam;
  169. pPage = (CDsPropPage *) ppsp->lParam;
  170. pPage->m_hPage = hDlg;
  171. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pPage);
  172. }
  173. switch (uMsg)
  174. {
  175. case WM_INITDIALOG:
  176. pPage->m_fInInit = TRUE;
  177. pPage->OnInitDialog(lParam);
  178. pPage->m_fInInit = FALSE;
  179. return TRUE;
  180. case WM_COMMAND:
  181. return pPage->OnCommand(LOWORD(wParam),(HWND)lParam, HIWORD(wParam));
  182. case WM_NOTIFY:
  183. return pPage->OnNotify(uMsg, wParam, lParam);
  184. }
  185. return FALSE;
  186. }
  187. //+----------------------------------------------------------------------------
  188. //
  189. // Method: CDsPropPage::OnInitDialog
  190. //
  191. // Sysnopsis: Handles dialog initialization messages
  192. //
  193. //-----------------------------------------------------------------------------
  194. LRESULT
  195. CDsPropPage::OnInitDialog(LPARAM lParam)
  196. {
  197. PADS_ATTR_INFO pAttrs = NULL;
  198. DWORD cAttrs = 0;
  199. HRESULT hr = S_OK;
  200. //
  201. // NOTIFY_OBJ
  202. // Send the notification object the page's window handle.
  203. //
  204. if (!ADsPropSetHwnd(m_hNotifyObj, m_hPage, NULL))
  205. {
  206. m_pWritableAttrs = NULL;
  207. }
  208. //
  209. // Disable the edit control if the user does not have write permission on
  210. // the attribute.
  211. //
  212. if (!ADsPropCheckIfWritable(wzSpendingLimit, m_pWritableAttrs))
  213. {
  214. EnableWindow(GetDlgItem (m_hPage, IDC_SPENDING_EDIT), FALSE);
  215. }
  216. //
  217. // Get the attribute value.
  218. //
  219. PWSTR rgpwzAttrNames[] = {wzSpendingLimit};
  220. hr = m_pDsObj->GetObjectAttributes(rgpwzAttrNames, 1, &pAttrs, &cAttrs);
  221. if (FAILED(hr))
  222. {
  223. // Display an error.
  224. return TRUE;
  225. }
  226. if (cAttrs == 1 && pAttrs->dwNumValues > 0)
  227. {
  228. // Display the value.
  229. //
  230. SetWindowText(GetDlgItem (m_hPage, IDC_SPENDING_EDIT),
  231. pAttrs->pADsValues->CaseIgnoreString);
  232. }
  233. return TRUE;
  234. }
  235. //+----------------------------------------------------------------------------
  236. //
  237. // Method: CDsPropPage::OnNotify
  238. //
  239. // Sysnopsis: Handles notification messages
  240. //
  241. //-----------------------------------------------------------------------------
  242. LRESULT
  243. CDsPropPage::OnNotify(UINT uMessage, WPARAM wParam, LPARAM lParam)
  244. {
  245. switch (((LPNMHDR)lParam)->code)
  246. {
  247. case PSN_APPLY:
  248. if (!m_fPageDirty)
  249. {
  250. return PSNRET_NOERROR;
  251. }
  252. {
  253. LRESULT lResult = OnApply();
  254. // Store the result into the dialog
  255. SetWindowLongPtr(m_hPage, DWLP_MSGRESULT, lResult);
  256. }
  257. return TRUE;
  258. case PSN_RESET:
  259. return FALSE; // allow the property sheet to be destroyed.
  260. case PSN_SETACTIVE:
  261. return OnPSNSetActive(lParam);
  262. case PSN_KILLACTIVE:
  263. return OnPSNKillActive(lParam);
  264. }
  265. return TRUE;
  266. }
  267. //+----------------------------------------------------------------------------
  268. //
  269. // Method: CDsPropPage::OnCommand
  270. //
  271. // Sysnopsis: Handles the WM_COMMAND message
  272. //
  273. //-----------------------------------------------------------------------------
  274. LRESULT
  275. CDsPropPage::OnCommand(int id, HWND hwndCtl, UINT codeNotify)
  276. {
  277. if ((codeNotify == EN_CHANGE) && !m_fInInit)
  278. {
  279. SetDirty();
  280. }
  281. if ((codeNotify == BN_CLICKED) && (id == IDCANCEL))
  282. {
  283. //
  284. // Pressing ESC in a multi-line edit control results in this
  285. // WM_COMMAND being sent. Pass it on to the parent (the sheet proc) to
  286. // close the sheet.
  287. //
  288. PostMessage(GetParent(m_hPage), WM_COMMAND, MAKEWPARAM(id, codeNotify),
  289. (LPARAM)hwndCtl);
  290. }
  291. return 0;
  292. }
  293. //+----------------------------------------------------------------------------
  294. //
  295. // Method: CDsPropPage::OnApply
  296. //
  297. // Sysnopsis: Handles the PSN_APPLY notification message
  298. //
  299. //-----------------------------------------------------------------------------
  300. LRESULT
  301. CDsPropPage::OnApply()
  302. {
  303. HRESULT hr = S_OK;
  304. DWORD cModified;
  305. ADS_ATTR_INFO aAttrs[1];
  306. PADS_ATTR_INFO pAttrs = aAttrs;
  307. WCHAR wzEdit[MAX_PATH];
  308. UINT cch;
  309. ADSVALUE Value;
  310. PWSTR rgpwzAttrNames[] = {wzSpendingLimit};
  311. cch = GetDlgItemText(m_hPage, IDC_SPENDING_EDIT, wzEdit, MAX_PATH);
  312. pAttrs[0].dwADsType = ADSTYPE_CASE_IGNORE_STRING;
  313. pAttrs[0].pszAttrName = rgpwzAttrNames[0];
  314. if (cch > 0)
  315. {
  316. Value.dwType = ADSTYPE_CASE_IGNORE_STRING;
  317. Value.CaseIgnoreString = wzEdit;
  318. pAttrs[0].pADsValues = &Value;
  319. pAttrs[0].dwNumValues = 1;
  320. pAttrs[0].dwControlCode = ADS_ATTR_UPDATE;
  321. }
  322. else
  323. {
  324. pAttrs[0].pADsValues = NULL;
  325. pAttrs[0].dwNumValues = 0;
  326. pAttrs[0].dwControlCode = ADS_ATTR_CLEAR;
  327. }
  328. //
  329. // Write the changes.
  330. //
  331. hr = m_pDsObj->SetObjectAttributes(pAttrs, 1, &cModified);
  332. //
  333. // NOTIFY_OBJ
  334. // Signal the change notification. Note that the notify-apply
  335. // message must be sent even if the page is not dirty so that the
  336. // notify ref-counting will properly decrement.
  337. //
  338. SendMessage(m_hNotifyObj, WM_ADSPROP_NOTIFY_APPLY, TRUE, 0);
  339. m_fPageDirty = FALSE;
  340. return FALSE;
  341. }
  342. //+----------------------------------------------------------------------------
  343. //
  344. // Method: CDsPropPage::OnPSNSetActive
  345. //
  346. // Sysnopsis: Page activation event.
  347. //
  348. //-----------------------------------------------------------------------------
  349. LRESULT
  350. CDsPropPage::OnPSNSetActive(LPARAM lParam)
  351. {
  352. SetWindowLongPtr(m_hPage, DWLP_MSGRESULT, 0);
  353. return TRUE;
  354. }
  355. //+----------------------------------------------------------------------------
  356. //
  357. // Method: CDsPropPage::OnPSNKillActive
  358. //
  359. // Sysnopsis: Page deactivation event (when other pages cover this one).
  360. //
  361. //-----------------------------------------------------------------------------
  362. LRESULT
  363. CDsPropPage::OnPSNKillActive(LPARAM lParam)
  364. {
  365. SetWindowLongPtr(m_hPage, DWLP_MSGRESULT, 0);
  366. return TRUE;
  367. }
  368. //+----------------------------------------------------------------------------
  369. //
  370. // Method: CDsPropPage::PageCallback
  371. //
  372. // Sysnopsis: Callback used to free the CDsPropPage object when the
  373. // property sheet has been destroyed.
  374. //
  375. //-----------------------------------------------------------------------------
  376. UINT CALLBACK
  377. CDsPropPage::PageCallback(HWND hDlg, UINT uMsg, LPPROPSHEETPAGE ppsp)
  378. {
  379. if (uMsg == PSPCB_RELEASE)
  380. {
  381. //
  382. // Determine instance that invoked this static function
  383. //
  384. CDsPropPage * pPage = (CDsPropPage *) ppsp->lParam;
  385. if (IsWindow(pPage->m_hNotifyObj))
  386. {
  387. //
  388. // NOTIFY_OBJ
  389. // Tell the notification object to shut down.
  390. //
  391. SendMessage(pPage->m_hNotifyObj, WM_ADSPROP_NOTIFY_EXIT, 0, 0);
  392. }
  393. delete pPage;
  394. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)NULL);
  395. }
  396. return TRUE;
  397. }