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.

461 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 = 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. //NTRAID#NTBUG9-572007-2002/03/10-jmessec If Init called multiple times, memory is leaked
  117. //NTRAID#NTBUG9-572007-2002/03/10-jmessec If second allocation fails, m_pwszObjPathName points to an uninitialized buffer
  118. m_pwzObjPathName = new WCHAR[wcslen(pwzObjName) + 1];
  119. if (m_pwzObjPathName == NULL )
  120. {
  121. return E_OUTOFMEMORY;
  122. }
  123. m_pwzObjClass = new WCHAR[wcslen(pwzClass) + 1];
  124. if (m_pwzObjClass == NULL)
  125. {
  126. return E_OUTOFMEMORY;
  127. }
  128. wcscpy(m_pwzObjPathName, pwzObjName);
  129. wcscpy(m_pwzObjClass, pwzClass);
  130. //
  131. // NOTIFY_OBJ
  132. // Contact the notification object for the initialization info.
  133. //
  134. ADSPROPINITPARAMS InitParams = {0};
  135. InitParams.dwSize = sizeof (ADSPROPINITPARAMS);
  136. if (!ADsPropGetInitInfo(m_hNotifyObj, &InitParams))
  137. {
  138. m_hrInit = E_FAIL;
  139. return E_FAIL;
  140. }
  141. if (FAILED(InitParams.hr))
  142. {
  143. m_hrInit = InitParams.hr;
  144. return m_hrInit;
  145. }
  146. m_pwzRDName = new WCHAR[wcslen(InitParams.pwzCN) + 1];
  147. if (m_pwzRDName == NULL)
  148. {
  149. m_hrInit = E_OUTOFMEMORY;
  150. return E_OUTOFMEMORY;
  151. }
  152. m_pDsObj = InitParams.pDsObj;
  153. m_pDsObj->AddRef();
  154. m_pWritableAttrs = InitParams.pWritableAttrs;
  155. return S_OK;
  156. }
  157. //+----------------------------------------------------------------------------
  158. //
  159. // Method: StaticDlgProc
  160. //
  161. // Sysnopsis: static dialog proc
  162. //
  163. //-----------------------------------------------------------------------------
  164. BOOL CALLBACK
  165. StaticDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  166. {
  167. CDsPropPage * pPage = (CDsPropPage *)GetWindowLongPtr(hDlg, DWLP_USER);
  168. if (uMsg == WM_INITDIALOG)
  169. {
  170. LPPROPSHEETPAGE ppsp = (LPPROPSHEETPAGE)lParam;
  171. pPage = (CDsPropPage *) ppsp->lParam;
  172. pPage->m_hPage = hDlg;
  173. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pPage);
  174. }
  175. switch (uMsg)
  176. {
  177. case WM_INITDIALOG:
  178. pPage->m_fInInit = TRUE;
  179. pPage->OnInitDialog(lParam);
  180. pPage->m_fInInit = FALSE;
  181. return TRUE;
  182. case WM_COMMAND:
  183. return pPage->OnCommand(LOWORD(wParam),(HWND)lParam, HIWORD(wParam));
  184. case WM_NOTIFY:
  185. return pPage->OnNotify(uMsg, wParam, lParam);
  186. }
  187. return FALSE;
  188. }
  189. //+----------------------------------------------------------------------------
  190. //
  191. // Method: CDsPropPage::OnInitDialog
  192. //
  193. // Sysnopsis: Handles dialog initialization messages
  194. //
  195. //-----------------------------------------------------------------------------
  196. LRESULT
  197. CDsPropPage::OnInitDialog(LPARAM lParam)
  198. {
  199. PADS_ATTR_INFO pAttrs = NULL;
  200. DWORD cAttrs = 0;
  201. HRESULT hr = S_OK;
  202. //
  203. // NOTIFY_OBJ
  204. // Send the notification object the page's window handle.
  205. //
  206. if (!ADsPropSetHwnd(m_hNotifyObj, m_hPage))
  207. {
  208. m_pWritableAttrs = NULL;
  209. }
  210. //
  211. // Disable the edit control if the user does not have write permission on
  212. // the attribute.
  213. //
  214. if (!ADsPropCheckIfWritable(wzSpendingLimit, m_pWritableAttrs))
  215. {
  216. EnableWindow(GetDlgItem (m_hPage, IDC_SPENDING_EDIT), FALSE);
  217. }
  218. //
  219. // Get the attribute value.
  220. //
  221. PWSTR rgpwzAttrNames[] = {wzSpendingLimit};
  222. hr = m_pDsObj->GetObjectAttributes(rgpwzAttrNames, 1, &pAttrs, &cAttrs);
  223. if (FAILED(hr))
  224. {
  225. // Display an error.
  226. return TRUE;
  227. }
  228. if (cAttrs == 1 && pAttrs->dwNumValues > 0)
  229. {
  230. // Display the value.
  231. //
  232. SetWindowText(GetDlgItem (m_hPage, IDC_SPENDING_EDIT),
  233. pAttrs->pADsValues->CaseIgnoreString);
  234. }
  235. return TRUE;
  236. }
  237. //+----------------------------------------------------------------------------
  238. //
  239. // Method: CDsPropPage::OnNotify
  240. //
  241. // Sysnopsis: Handles notification messages
  242. //
  243. //-----------------------------------------------------------------------------
  244. LRESULT
  245. CDsPropPage::OnNotify(UINT uMessage, WPARAM wParam, LPARAM lParam)
  246. {
  247. switch (((LPNMHDR)lParam)->code)
  248. {
  249. case PSN_APPLY:
  250. if (!m_fPageDirty)
  251. {
  252. return PSNRET_NOERROR;
  253. }
  254. {
  255. LRESULT lResult = OnApply();
  256. // Store the result into the dialog
  257. SetWindowLongPtr(m_hPage, DWLP_MSGRESULT, lResult);
  258. }
  259. return TRUE;
  260. case PSN_RESET:
  261. return FALSE; // allow the property sheet to be destroyed.
  262. case PSN_SETACTIVE:
  263. return OnPSNSetActive(lParam);
  264. case PSN_KILLACTIVE:
  265. return OnPSNKillActive(lParam);
  266. }
  267. return TRUE;
  268. }
  269. //+----------------------------------------------------------------------------
  270. //
  271. // Method: CDsPropPage::OnCommand
  272. //
  273. // Sysnopsis: Handles the WM_COMMAND message
  274. //
  275. //-----------------------------------------------------------------------------
  276. LRESULT
  277. CDsPropPage::OnCommand(int id, HWND hwndCtl, UINT codeNotify)
  278. {
  279. if ((codeNotify == EN_CHANGE) && !m_fInInit)
  280. {
  281. SetDirty();
  282. }
  283. if ((codeNotify == BN_CLICKED) && (id == IDCANCEL))
  284. {
  285. //
  286. // Pressing ESC in a multi-line edit control results in this
  287. // WM_COMMAND being sent. Pass it on to the parent (the sheet proc) to
  288. // close the sheet.
  289. //
  290. PostMessage(GetParent(m_hPage), WM_COMMAND, MAKEWPARAM(id, codeNotify),
  291. (LPARAM)hwndCtl);
  292. }
  293. return 0;
  294. }
  295. //+----------------------------------------------------------------------------
  296. //
  297. // Method: CDsPropPage::OnApply
  298. //
  299. // Sysnopsis: Handles the PSN_APPLY notification message
  300. //
  301. //-----------------------------------------------------------------------------
  302. LRESULT
  303. CDsPropPage::OnApply()
  304. {
  305. HRESULT hr = S_OK;
  306. DWORD cModified;
  307. ADS_ATTR_INFO aAttrs[1];
  308. PADS_ATTR_INFO pAttrs = aAttrs;
  309. WCHAR wzEdit[MAX_PATH];
  310. UINT cch;
  311. ADSVALUE Value;
  312. PWSTR rgpwzAttrNames[] = {wzSpendingLimit};
  313. cch = GetDlgItemText(m_hPage, IDC_SPENDING_EDIT, wzEdit, MAX_PATH);
  314. pAttrs[0].dwADsType = ADSTYPE_CASE_IGNORE_STRING;
  315. pAttrs[0].pszAttrName = rgpwzAttrNames[0];
  316. if (cch > 0)
  317. {
  318. Value.dwType = ADSTYPE_CASE_IGNORE_STRING;
  319. Value.CaseIgnoreString = wzEdit;
  320. pAttrs[0].pADsValues = &Value;
  321. pAttrs[0].dwNumValues = 1;
  322. pAttrs[0].dwControlCode = ADS_ATTR_UPDATE;
  323. }
  324. else
  325. {
  326. pAttrs[0].pADsValues = NULL;
  327. pAttrs[0].dwNumValues = 0;
  328. pAttrs[0].dwControlCode = ADS_ATTR_CLEAR;
  329. }
  330. //
  331. // Write the changes.
  332. //
  333. hr = m_pDsObj->SetObjectAttributes(pAttrs, 1, &cModified);
  334. //
  335. // NOTIFY_OBJ
  336. // Signal the change notification. Note that the notify-apply
  337. // message must be sent even if the page is not dirty so that the
  338. // notify ref-counting will properly decrement.
  339. //
  340. SendMessage(m_hNotifyObj, WM_ADSPROP_NOTIFY_APPLY, TRUE, 0);
  341. m_fPageDirty = FALSE;
  342. return FALSE;
  343. }
  344. //+----------------------------------------------------------------------------
  345. //
  346. // Method: CDsPropPage::OnPSNSetActive
  347. //
  348. // Sysnopsis: Page activation event.
  349. //
  350. //-----------------------------------------------------------------------------
  351. LRESULT
  352. CDsPropPage::OnPSNSetActive(LPARAM lParam)
  353. {
  354. SetWindowLongPtr(m_hPage, DWLP_MSGRESULT, 0);
  355. return TRUE;
  356. }
  357. //+----------------------------------------------------------------------------
  358. //
  359. // Method: CDsPropPage::OnPSNKillActive
  360. //
  361. // Sysnopsis: Page deactivation event (when other pages cover this one).
  362. //
  363. //-----------------------------------------------------------------------------
  364. LRESULT
  365. CDsPropPage::OnPSNKillActive(LPARAM lParam)
  366. {
  367. SetWindowLongPtr(m_hPage, DWLP_MSGRESULT, 0);
  368. return TRUE;
  369. }
  370. //+----------------------------------------------------------------------------
  371. //
  372. // Method: CDsPropPage::PageCallback
  373. //
  374. // Sysnopsis: Callback used to free the CDsPropPage object when the
  375. // property sheet has been destroyed.
  376. //
  377. //-----------------------------------------------------------------------------
  378. UINT CALLBACK
  379. CDsPropPage::PageCallback(HWND hDlg, UINT uMsg, LPPROPSHEETPAGE ppsp)
  380. {
  381. if (uMsg == PSPCB_RELEASE)
  382. {
  383. //
  384. // Determine instance that invoked this static function
  385. //
  386. CDsPropPage * pPage = (CDsPropPage *) ppsp->lParam;
  387. if (IsWindow(pPage->m_hNotifyObj))
  388. {
  389. //
  390. // NOTIFY_OBJ
  391. // Tell the notification object to shut down.
  392. //
  393. SendMessage(pPage->m_hNotifyObj, WM_ADSPROP_NOTIFY_EXIT, 0, 0);
  394. }
  395. delete pPage;
  396. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)NULL);
  397. }
  398. return TRUE;
  399. }