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.

876 lines
16 KiB

  1. /*++
  2. Copyright (c) 1994-95 Microsoft Corporation
  3. Module Name:
  4. mapppgs.cpp
  5. Abstract:
  6. Mapping property page (settings) implementation.
  7. Author:
  8. Don Ryan (donryan) 02-Feb-1995
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. Jeff Parham (jeffparh) 30-Jan-1996
  13. o Added new element to LV_COLUMN_ENTRY to differentiate the string
  14. used for the column header from the string used in the menus
  15. (so that the menu option can contain hot keys).
  16. --*/
  17. #include "stdafx.h"
  18. #include "llsmgr.h"
  19. #include "mapppgs.h"
  20. #include "ausrdlg.h"
  21. #include "mainfrm.h"
  22. static LV_COLUMN_INFO g_userColumnInfo = {0, 0, 1, {0, 0, 0, -1}};
  23. #ifdef _DEBUG
  24. #undef THIS_FILE
  25. static char BASED_CODE THIS_FILE[] = __FILE__;
  26. #endif
  27. IMPLEMENT_DYNCREATE(CMappingPropertyPageSettings, CPropertyPage)
  28. BEGIN_MESSAGE_MAP(CMappingPropertyPageSettings, CPropertyPage)
  29. //{{AFX_MSG_MAP(CMappingPropertyPageSettings)
  30. ON_BN_CLICKED(IDC_PP_MAPPING_SETTINGS_ADD, OnAdd)
  31. ON_BN_CLICKED(IDC_PP_MAPPING_SETTINGS_DELETE, OnDelete)
  32. ON_NOTIFY(UDN_DELTAPOS, IDC_PP_MAPPING_SETTINGS_SPIN, OnDeltaPosSpin)
  33. ON_NOTIFY(LVN_GETDISPINFO, IDC_PP_MAPPING_SETTINGS_USERS, OnGetDispInfoUsers)
  34. ON_EN_UPDATE(IDC_PP_MAPPING_SETTINGS_LICENSES, OnUpdateQuantity)
  35. ON_WM_DESTROY()
  36. //}}AFX_MSG_MAP
  37. END_MESSAGE_MAP()
  38. CMappingPropertyPageSettings::CMappingPropertyPageSettings()
  39. : CPropertyPage(CMappingPropertyPageSettings::IDD)
  40. /*++
  41. Routine Description:
  42. Constructor for mapping property page (settings).
  43. Arguments:
  44. None.
  45. Return Values:
  46. None.
  47. --*/
  48. {
  49. //{{AFX_DATA_INIT(CMappingPropertyPageSettings)
  50. m_strDescription = _T("");
  51. m_nLicenses = 0;
  52. m_nLicensesMin = 0;
  53. m_strName = _T("");
  54. //}}AFX_DATA_INIT
  55. m_pMapping = NULL;
  56. m_pUpdateHint = NULL;
  57. m_bAreCtrlsInitialized = FALSE;
  58. }
  59. CMappingPropertyPageSettings::~CMappingPropertyPageSettings()
  60. /*++
  61. Routine Description:
  62. Destructor for mapping property page (settings).
  63. Arguments:
  64. None.
  65. Return Values:
  66. None.
  67. --*/
  68. {
  69. //
  70. // Nothing to do here...
  71. //
  72. }
  73. void CMappingPropertyPageSettings::DoDataExchange(CDataExchange* pDX)
  74. /*++
  75. Routine Description:
  76. Called by framework to exchange dialog data.
  77. Arguments:
  78. pDX - data exchange object.
  79. Return Values:
  80. None.
  81. --*/
  82. {
  83. CPropertyPage::DoDataExchange(pDX);
  84. //{{AFX_DATA_MAP(CMappingPropertyPageSettings)
  85. DDX_Control(pDX, IDC_PP_MAPPING_SETTINGS_DESCRIPTION, m_desEdit);
  86. DDX_Control(pDX, IDC_PP_MAPPING_SETTINGS_LICENSES, m_licEdit);
  87. DDX_Control(pDX, IDC_PP_MAPPING_SETTINGS_DELETE, m_delBtn);
  88. DDX_Control(pDX, IDC_PP_MAPPING_SETTINGS_ADD, m_addBtn);
  89. DDX_Control(pDX, IDC_PP_MAPPING_SETTINGS_SPIN, m_spinCtrl);
  90. DDX_Control(pDX, IDC_PP_MAPPING_SETTINGS_USERS, m_userList);
  91. DDX_Text(pDX, IDC_PP_MAPPING_SETTINGS_DESCRIPTION, m_strDescription);
  92. DDX_Text(pDX, IDC_PP_MAPPING_SETTINGS_LICENSES, m_nLicenses);
  93. DDV_MinMaxDWord(pDX, m_nLicenses, m_nLicensesMin, 999999);
  94. DDX_Text(pDX, IDC_PP_MAPPING_SETTINGS_NAME, m_strName);
  95. //}}AFX_DATA_MAP
  96. }
  97. void CMappingPropertyPageSettings::InitCtrls()
  98. /*++
  99. Routine Description:
  100. Initializes property page controls.
  101. Arguments:
  102. None.
  103. Return Values:
  104. None.
  105. --*/
  106. {
  107. m_strName = m_pMapping->m_strName;
  108. m_strDescription = m_pMapping->m_strDescription;
  109. m_nLicenses = m_pMapping->GetInUse();
  110. UpdateData(FALSE); // upload;
  111. m_delBtn.EnableWindow(FALSE);
  112. m_spinCtrl.SetRange(0, UD_MAXVAL);
  113. m_licEdit.LimitText(6);
  114. m_desEdit.LimitText(256);
  115. m_bAreCtrlsInitialized = TRUE;
  116. ::LvInitColumns(&m_userList, &g_userColumnInfo);
  117. }
  118. void CMappingPropertyPageSettings::InitPage(CMapping* pMapping, DWORD* pUpdateHint)
  119. /*++
  120. Routine Description:
  121. Initializes property page.
  122. Arguments:
  123. pMapping - mapping object.
  124. pUpdateHint - update hints.
  125. Return Values:
  126. None.
  127. --*/
  128. {
  129. ASSERT(pUpdateHint);
  130. VALIDATE_OBJECT(pMapping, CMapping);
  131. m_pMapping = pMapping;
  132. m_pUpdateHint = pUpdateHint;
  133. }
  134. void CMappingPropertyPageSettings::AbortPageIfNecessary()
  135. /*++
  136. Routine Description:
  137. Displays status and aborts if connection lost.
  138. Arguments:
  139. None.
  140. Return Values:
  141. None.
  142. --*/
  143. {
  144. theApp.DisplayLastStatus();
  145. if (IsConnectionDropped(LlsGetLastStatus()))
  146. {
  147. AbortPage(); // bail...
  148. }
  149. }
  150. void CMappingPropertyPageSettings::AbortPage()
  151. /*++
  152. Routine Description:
  153. Aborts property page.
  154. Arguments:
  155. None.
  156. Return Values:
  157. None.
  158. --*/
  159. {
  160. *m_pUpdateHint = UPDATE_INFO_ABORT;
  161. GetParent()->PostMessage(WM_COMMAND, IDCANCEL);
  162. }
  163. BOOL CMappingPropertyPageSettings::OnInitDialog()
  164. /*++
  165. Routine Description:
  166. Message handler for WM_INITDIALOG.
  167. Arguments:
  168. None.
  169. Return Values:
  170. Returns false if focus set to control manually.
  171. --*/
  172. {
  173. CPropertyPage::OnInitDialog();
  174. PostMessage(WM_COMMAND, ID_INIT_CTRLS);
  175. return TRUE;
  176. }
  177. void CMappingPropertyPageSettings::OnDestroy()
  178. /*++
  179. Routine Description:
  180. Message handler for WM_DESTROY.
  181. Arguments:
  182. None.
  183. Return Values:
  184. None.
  185. --*/
  186. {
  187. ::LvReleaseObArray(&m_userList); // release now...
  188. while (!m_deleteList.IsEmpty())
  189. {
  190. CUser* pUserDel = (CUser*)m_deleteList.RemoveHead();
  191. VALIDATE_OBJECT(pUserDel, CUser);
  192. pUserDel->InternalRelease(); // release now...
  193. }
  194. CPropertyPage::OnDestroy();
  195. }
  196. BOOL CMappingPropertyPageSettings::OnSetActive()
  197. /*++
  198. Routine Description:
  199. Activates property page.
  200. Arguments:
  201. None.
  202. Return Values:
  203. Returns true if focus accepted.
  204. --*/
  205. {
  206. BOOL bIsActivated;
  207. if (bIsActivated = CPropertyPage::OnSetActive())
  208. {
  209. if (IsGroupInfoUpdated(*m_pUpdateHint) && !RefreshCtrls())
  210. {
  211. AbortPageIfNecessary(); // display error...
  212. }
  213. }
  214. return bIsActivated;
  215. }
  216. void CMappingPropertyPageSettings::OnAdd()
  217. /*++
  218. Routine Description:
  219. Adds users to list.
  220. Arguments:
  221. None.
  222. Return Values:
  223. None.
  224. --*/
  225. {
  226. CObList newUserList;
  227. CAddUsersDialog addDlg;
  228. addDlg.InitDialog(&newUserList);
  229. if (addDlg.DoModal() == IDOK)
  230. {
  231. int nUsers = m_userList.GetItemCount();
  232. while (!newUserList.IsEmpty())
  233. {
  234. CUser* pUser = (CUser*)newUserList.RemoveHead();
  235. VALIDATE_OBJECT(pUser, CUser);
  236. LV_FINDINFO lvFindInfo;
  237. lvFindInfo.flags = LVFI_STRING;
  238. lvFindInfo.psz = MKSTR(pUser->m_strName);
  239. if (m_userList.FindItem(&lvFindInfo, -1) == -1)
  240. {
  241. //
  242. // Check if already deleted once
  243. //
  244. CUser* pUserDel;
  245. POSITION curPos;
  246. POSITION nextPos;
  247. nextPos = m_deleteList.GetHeadPosition();
  248. while (curPos = nextPos)
  249. {
  250. pUserDel = (CUser*)m_deleteList.GetNext(nextPos);
  251. VALIDATE_OBJECT(pUserDel, CUser);
  252. if (!pUserDel->m_strName.CompareNoCase(pUser->m_strName))
  253. {
  254. m_deleteList.RemoveAt(curPos);
  255. pUser->InternalRelease(); // release new...
  256. pUser = pUserDel; // replace with old...
  257. break;
  258. }
  259. }
  260. LV_ITEM lvItem;
  261. lvItem.mask = LVIF_TEXT|
  262. LVIF_PARAM|
  263. LVIF_IMAGE;
  264. lvItem.iItem = nUsers++; // append...
  265. lvItem.iSubItem = 0;
  266. lvItem.pszText = LPSTR_TEXTCALLBACK;
  267. lvItem.cchTextMax = LPSTR_TEXTCALLBACK_MAX;
  268. lvItem.iImage = I_IMAGECALLBACK;
  269. lvItem.lParam = (LPARAM)(LPVOID)pUser;
  270. m_userList.InsertItem(&lvItem);
  271. }
  272. else
  273. {
  274. pUser->InternalRelease(); // allocated in add user dialog...
  275. }
  276. }
  277. VERIFY(m_userList.SortItems(CompareUsersInMapping, 0)); // use column info...
  278. ::LvSelObjIfNecessary(&m_userList, TRUE); // ensure selection...
  279. PostMessage(WM_COMMAND, ID_INIT_CTRLS);
  280. }
  281. }
  282. void CMappingPropertyPageSettings::OnDelete()
  283. /*++
  284. Routine Description:
  285. Removes users from list.
  286. Arguments:
  287. None.
  288. Return Values:
  289. None.
  290. --*/
  291. {
  292. CUser* pUser;
  293. CMapping* pMapping;
  294. int iItem = -1;
  295. while (pUser = (CUser*)::LvGetNextObj(&m_userList, &iItem))
  296. {
  297. VALIDATE_OBJECT(pUser, CUser);
  298. //
  299. // Only cache users with this mapping as a parent
  300. //
  301. if (pMapping = (CMapping*)MKOBJ(pUser->GetParent()))
  302. {
  303. ASSERT(m_pMapping == pMapping);
  304. pMapping->InternalRelease(); // just checking...
  305. m_deleteList.AddTail(pUser);
  306. }
  307. else
  308. {
  309. pUser->InternalRelease(); // release now...
  310. }
  311. VERIFY(m_userList.DeleteItem(iItem));
  312. iItem = -1;
  313. }
  314. ::LvSelObjIfNecessary(&m_userList, TRUE); // ensure selection...
  315. PostMessage(WM_COMMAND, ID_INIT_CTRLS);
  316. }
  317. BOOL CMappingPropertyPageSettings::RefreshCtrls()
  318. /*++
  319. Routine Description:
  320. Refreshs dialog controls.
  321. Arguments:
  322. None.
  323. Return Values:
  324. Returns true if controls refreshed.
  325. --*/
  326. {
  327. VALIDATE_OBJECT(m_pMapping, CMapping);
  328. BOOL bIsRefreshed = FALSE;
  329. VARIANT va;
  330. VariantInit(&va);
  331. BeginWaitCursor(); // hourglass...
  332. CUsers* pUsers = (CUsers*)MKOBJ(m_pMapping->GetUsers(va));
  333. if (pUsers)
  334. {
  335. VALIDATE_OBJECT(pUsers, CUsers);
  336. bIsRefreshed = ::LvRefreshObArray(
  337. &m_userList,
  338. &g_userColumnInfo,
  339. pUsers->m_pObArray
  340. );
  341. pUsers->InternalRelease(); // add ref'd individually...
  342. }
  343. if (!bIsRefreshed)
  344. {
  345. ::LvReleaseObArray(&m_userList); // reset list now...
  346. }
  347. EndWaitCursor(); // hourglass...
  348. PostMessage(WM_COMMAND, ID_INIT_CTRLS);
  349. return bIsRefreshed;
  350. }
  351. BOOL CMappingPropertyPageSettings::OnKillActive()
  352. /*++
  353. Routine Description:
  354. Processes property page.
  355. Arguments:
  356. None.
  357. Return Values:
  358. Returns true if processed successfully.
  359. --*/
  360. {
  361. if (!IsQuantityValid())
  362. return FALSE;
  363. NTSTATUS NtStatus = STATUS_SUCCESS;
  364. LLS_GROUP_INFO_1 MappingInfo1;
  365. //
  366. // Update information if necessary....
  367. //
  368. BeginWaitCursor(); // hourglass...
  369. if ((m_nLicenses != m_pMapping->GetInUse()) ||
  370. lstrcmp(MKSTR(m_strDescription), MKSTR(m_pMapping->m_strDescription)))
  371. {
  372. MappingInfo1.Name = MKSTR(m_strName);
  373. MappingInfo1.Comment = MKSTR(m_strDescription);
  374. MappingInfo1.Licenses = m_nLicenses;
  375. NtStatus = ::LlsGroupInfoSet(
  376. LlsGetActiveHandle(),
  377. MKSTR(m_strName),
  378. 1,
  379. (LPBYTE)&MappingInfo1
  380. );
  381. LlsSetLastStatus(NtStatus); // called api...
  382. *m_pUpdateHint |= NT_SUCCESS(NtStatus) ? UPDATE_GROUP_ALTERED : 0;
  383. }
  384. //
  385. // Delete specified users
  386. //
  387. while (NT_SUCCESS(NtStatus) && !m_deleteList.IsEmpty())
  388. {
  389. CUser* pUserDel = (CUser*)m_deleteList.RemoveHead();
  390. VALIDATE_OBJECT(pUserDel, CUser);
  391. NtStatus = ::LlsGroupUserDelete(
  392. LlsGetActiveHandle(),
  393. MKSTR(m_strName),
  394. MKSTR(pUserDel->m_strName)
  395. );
  396. pUserDel->InternalRelease(); // release now...
  397. if (NtStatus == STATUS_OBJECT_NAME_NOT_FOUND)
  398. NtStatus = STATUS_SUCCESS;
  399. LlsSetLastStatus(NtStatus); // called api...
  400. *m_pUpdateHint |= NT_SUCCESS(NtStatus) ? UPDATE_GROUP_ALTERED : 0;
  401. }
  402. CUser* pUserAdd;
  403. CMapping* pMapping;
  404. int iItem = -1;
  405. while (NT_SUCCESS(NtStatus) &&
  406. (pUserAdd = (CUser*)::LvGetNextObj(&m_userList, &iItem, LVNI_ALL)))
  407. {
  408. VALIDATE_OBJECT(pUserAdd, CUser);
  409. //
  410. // Do not add users with this mapping as a parent
  411. //
  412. if (pMapping = (CMapping*)MKOBJ(pUserAdd->GetParent()))
  413. {
  414. ASSERT(m_pMapping == pMapping);
  415. pMapping->InternalRelease(); // just checking...
  416. }
  417. else
  418. {
  419. NtStatus = ::LlsGroupUserAdd(
  420. LlsGetActiveHandle(),
  421. MKSTR(m_strName),
  422. MKSTR(pUserAdd->m_strName)
  423. );
  424. LlsSetLastStatus(NtStatus); // called api...
  425. *m_pUpdateHint |= NT_SUCCESS(NtStatus) ? UPDATE_GROUP_ALTERED : 0;
  426. }
  427. }
  428. EndWaitCursor(); // hourglass...
  429. if (!NT_SUCCESS(NtStatus))
  430. {
  431. AbortPageIfNecessary(); // display error...
  432. return FALSE;
  433. }
  434. return TRUE;
  435. }
  436. BOOL CMappingPropertyPageSettings::OnCommand(WPARAM wParam, LPARAM lParam)
  437. /*++
  438. Routine Description:
  439. Message handler for WM_COMMAND.
  440. Arguments:
  441. wParam - message specific.
  442. lParam - message specific.
  443. Return Values:
  444. Returns true if message processed.
  445. --*/
  446. {
  447. if (wParam == ID_INIT_CTRLS)
  448. {
  449. if (!m_bAreCtrlsInitialized)
  450. {
  451. InitCtrls();
  452. if (!RefreshCtrls())
  453. {
  454. AbortPageIfNecessary(); // display error...
  455. }
  456. }
  457. ::SafeEnableWindow(
  458. &m_delBtn,
  459. &m_userList,
  460. CDialog::GetFocus(),
  461. m_userList.GetItemCount()
  462. );
  463. ::LvResizeColumns(&m_userList, &g_userColumnInfo);
  464. return TRUE; // processed...
  465. }
  466. return CDialog::OnCommand(wParam, lParam);
  467. }
  468. void CMappingPropertyPageSettings::OnDeltaPosSpin(NMHDR* pNMHDR, LRESULT* pResult)
  469. /*++
  470. Routine Description:
  471. Notification handler for UDN_DELTAPOS.
  472. Arguments:
  473. pNMHDR - notification header.
  474. pResult - return code.
  475. Return Values:
  476. None.
  477. --*/
  478. {
  479. UpdateData(TRUE); // get data
  480. m_nLicenses += ((NM_UPDOWN*)pNMHDR)->iDelta;
  481. if (m_nLicenses < 0)
  482. {
  483. m_nLicenses = 0;
  484. ::MessageBeep(MB_OK);
  485. }
  486. else if (m_nLicenses > 999999)
  487. {
  488. m_nLicenses = 999999;
  489. ::MessageBeep(MB_OK);
  490. }
  491. UpdateData(FALSE); // set data
  492. *pResult = 1; // handle ourselves...
  493. }
  494. void CMappingPropertyPageSettings::OnUpdateQuantity()
  495. /*++
  496. Routine Description:
  497. Message handler for EN_UPDATE.
  498. Arguments:
  499. None.
  500. Return Values:
  501. None.
  502. --*/
  503. {
  504. long nLicensesOld = m_nLicenses;
  505. if (!IsQuantityValid())
  506. {
  507. m_nLicenses = nLicensesOld;
  508. UpdateData(FALSE);
  509. m_licEdit.SetFocus();
  510. m_licEdit.SetSel(0,-1);
  511. ::MessageBeep(MB_OK);
  512. }
  513. }
  514. BOOL CMappingPropertyPageSettings::IsQuantityValid()
  515. /*++
  516. Routine Description:
  517. Wrapper around UpdateData(TRUE).
  518. Arguments:
  519. None.
  520. Return Values:
  521. VT_BOOL.
  522. --*/
  523. {
  524. BOOL bIsValid;
  525. m_nLicensesMin = 1; // raise minimum...
  526. bIsValid = UpdateData(TRUE);
  527. m_nLicensesMin = 0; // reset minimum...
  528. return bIsValid;
  529. }
  530. void CMappingPropertyPageSettings::OnGetDispInfoUsers(NMHDR* pNMHDR, LRESULT* pResult)
  531. /*++
  532. Routine Description:
  533. Notification handler for LVN_GETDISPINFO.
  534. Arguments:
  535. pNMHDR - notification header.
  536. pResult - return code.
  537. Return Values:
  538. None.
  539. --*/
  540. {
  541. LV_ITEM* plvItem = &((LV_DISPINFO*)pNMHDR)->item;
  542. ASSERT(plvItem);
  543. ASSERT(plvItem->iSubItem == 0);
  544. CUser* pUser = (CUser*)plvItem->lParam;
  545. VALIDATE_OBJECT(pUser, CUser);
  546. plvItem->iImage = BMPI_USER;
  547. lstrcpyn(plvItem->pszText, pUser->m_strName, plvItem->cchTextMax);
  548. *pResult = 0;
  549. }