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.

833 lines
14 KiB

  1. /*++
  2. Copyright (c) 1994-95 Microsoft Corporation
  3. Module Name:
  4. prdppgu.cpp
  5. Abstract:
  6. Product property page (users) 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 "prdppgu.h"
  20. #include "usrpsht.h"
  21. #define LVID_USER 0
  22. #define LVID_LAST_USED 1
  23. #define LVID_TOTAL_USED 2
  24. #define LVCX_USER 40
  25. #define LVCX_LAST_USED 30
  26. #define LVCX_TOTAL_USED -1
  27. static LV_COLUMN_INFO g_userColumnInfo = {
  28. 0, 0, 3,
  29. {{LVID_USER, IDS_USER, 0, LVCX_USER },
  30. {LVID_LAST_USED, IDS_LAST_DATE_USED, 0, LVCX_LAST_USED },
  31. {LVID_TOTAL_USED, IDS_USAGE_COUNT, 0, LVCX_TOTAL_USED}},
  32. };
  33. #ifdef _DEBUG
  34. #undef THIS_FILE
  35. static char BASED_CODE THIS_FILE[] = __FILE__;
  36. #endif
  37. IMPLEMENT_DYNCREATE(CProductPropertyPageUsers, CPropertyPage)
  38. BEGIN_MESSAGE_MAP(CProductPropertyPageUsers, CPropertyPage)
  39. //{{AFX_MSG_MAP(CProductPropertyPageUsers)
  40. ON_BN_CLICKED(IDC_PP_PRODUCT_USERS_DELETE, OnDelete)
  41. ON_NOTIFY(NM_DBLCLK, IDC_PP_PRODUCT_USERS_USERS, OnDblClkUsers)
  42. ON_NOTIFY(NM_RETURN, IDC_PP_PRODUCT_USERS_USERS, OnReturnUsers)
  43. ON_NOTIFY(NM_SETFOCUS, IDC_PP_PRODUCT_USERS_USERS, OnSetFocusUsers)
  44. ON_NOTIFY(NM_KILLFOCUS, IDC_PP_PRODUCT_USERS_USERS, OnKillFocusUsers)
  45. ON_NOTIFY(LVN_COLUMNCLICK, IDC_PP_PRODUCT_USERS_USERS, OnColumnClickUsers)
  46. ON_NOTIFY(LVN_GETDISPINFO, IDC_PP_PRODUCT_USERS_USERS, OnGetDispInfoUsers)
  47. ON_WM_DESTROY()
  48. //}}AFX_MSG_MAP
  49. END_MESSAGE_MAP()
  50. CProductPropertyPageUsers::CProductPropertyPageUsers()
  51. : CPropertyPage(CProductPropertyPageUsers::IDD)
  52. /*++
  53. Routine Description:
  54. Constructor for product property page (users).
  55. Arguments:
  56. None.
  57. Return Values:
  58. None.
  59. --*/
  60. {
  61. //{{AFX_DATA_INIT(CProductPropertyPageUsers)
  62. //}}AFX_DATA_INIT
  63. m_pProduct = NULL;
  64. m_pUpdateHint = NULL;
  65. m_bUserProperties = FALSE;
  66. m_bAreCtrlsInitialized = FALSE;
  67. }
  68. CProductPropertyPageUsers::~CProductPropertyPageUsers()
  69. /*++
  70. Routine Description:
  71. Destructor for product property page (users).
  72. Arguments:
  73. None.
  74. Return Values:
  75. None.
  76. --*/
  77. {
  78. //
  79. // Nothing to do here.
  80. //
  81. }
  82. void CProductPropertyPageUsers::DoDataExchange(CDataExchange* pDX)
  83. /*++
  84. Routine Description:
  85. Called by framework to exchange dialog data.
  86. Arguments:
  87. pDX - data exchange object.
  88. Return Values:
  89. None.
  90. --*/
  91. {
  92. CPropertyPage::DoDataExchange(pDX);
  93. //{{AFX_DATA_MAP(CProductPropertyPageUsers)
  94. DDX_Control(pDX, IDC_PP_PRODUCT_USERS_DELETE, m_delBtn);
  95. DDX_Control(pDX, IDC_PP_PRODUCT_USERS_USERS, m_userList);
  96. //}}AFX_DATA_MAP
  97. }
  98. void CProductPropertyPageUsers::InitCtrls()
  99. /*++
  100. Routine Description:
  101. Initializes property page controls.
  102. Arguments:
  103. None.
  104. Return Values:
  105. None.
  106. --*/
  107. {
  108. m_userList.SetFocus();
  109. m_delBtn.EnableWindow(FALSE);
  110. m_bAreCtrlsInitialized = TRUE;
  111. ::LvInitColumns(&m_userList, &g_userColumnInfo);
  112. }
  113. void
  114. CProductPropertyPageUsers::InitPage(
  115. CProduct* pProduct,
  116. DWORD* pUpdateHint,
  117. BOOL bUserProperties
  118. )
  119. /*++
  120. Routine Description:
  121. Initializes property page.
  122. Arguments:
  123. pProduct - product object.
  124. pUpdateHint - update hint.
  125. bUserProperties - to recurse or not.
  126. Return Values:
  127. None.
  128. --*/
  129. {
  130. ASSERT(pUpdateHint);
  131. VALIDATE_OBJECT(pProduct, CProduct);
  132. m_pProduct = pProduct;
  133. m_pUpdateHint = pUpdateHint;
  134. m_bUserProperties = bUserProperties;
  135. }
  136. void CProductPropertyPageUsers::AbortPageIfNecessary()
  137. /*++
  138. Routine Description:
  139. Displays status and aborts if connection lost.
  140. Arguments:
  141. None.
  142. Return Values:
  143. None.
  144. --*/
  145. {
  146. theApp.DisplayLastStatus();
  147. if (IsConnectionDropped(LlsGetLastStatus()))
  148. {
  149. AbortPage(); // bail...
  150. }
  151. }
  152. void CProductPropertyPageUsers::AbortPage()
  153. /*++
  154. Routine Description:
  155. Aborts property page.
  156. Arguments:
  157. None.
  158. Return Values:
  159. None.
  160. --*/
  161. {
  162. *m_pUpdateHint = UPDATE_INFO_ABORT;
  163. GetParent()->PostMessage(WM_COMMAND, IDCANCEL);
  164. }
  165. BOOL CProductPropertyPageUsers::OnInitDialog()
  166. /*++
  167. Routine Description:
  168. Message handler for WM_INITDIALOG.
  169. Arguments:
  170. None.
  171. Return Values:
  172. Returns false if focus set to control manually.
  173. --*/
  174. {
  175. CPropertyPage::OnInitDialog();
  176. PostMessage(WM_COMMAND, ID_INIT_CTRLS);
  177. return TRUE;
  178. }
  179. void CProductPropertyPageUsers::OnDestroy()
  180. /*++
  181. Routine Description:
  182. Message handler for WM_DESTROY.
  183. Arguments:
  184. None.
  185. Return Values:
  186. None.
  187. --*/
  188. {
  189. ::LvReleaseObArray(&m_userList); // release now...
  190. CPropertyPage::OnDestroy();
  191. }
  192. BOOL CProductPropertyPageUsers::OnSetActive()
  193. /*++
  194. Routine Description:
  195. Activates property page.
  196. Arguments:
  197. None.
  198. Return Values:
  199. Returns true if focus accepted.
  200. --*/
  201. {
  202. BOOL bIsActivated;
  203. if (bIsActivated = CPropertyPage::OnSetActive())
  204. {
  205. if (IsUserInfoUpdated(*m_pUpdateHint) && !RefreshCtrls())
  206. {
  207. AbortPageIfNecessary(); // display error...
  208. }
  209. }
  210. return bIsActivated;
  211. }
  212. BOOL CProductPropertyPageUsers::RefreshCtrls()
  213. /*++
  214. Routine Description:
  215. Refreshs property page controls.
  216. Arguments:
  217. None.
  218. Return Values:
  219. Returns true if controls refreshed successfully.
  220. --*/
  221. {
  222. VALIDATE_OBJECT(m_pProduct, CProduct);
  223. BOOL bIsRefreshed = FALSE;
  224. VARIANT va;
  225. VariantInit(&va);
  226. BeginWaitCursor(); // hourglass...
  227. CStatistics* pStatistics = (CStatistics*)MKOBJ(m_pProduct->GetStatistics(va));
  228. if (pStatistics)
  229. {
  230. VALIDATE_OBJECT(pStatistics, CStatistics);
  231. bIsRefreshed = ::LvRefreshObArray(
  232. &m_userList,
  233. &g_userColumnInfo,
  234. pStatistics->m_pObArray
  235. );
  236. pStatistics->InternalRelease(); // add ref'd individually...
  237. }
  238. if (!bIsRefreshed)
  239. {
  240. ::LvReleaseObArray(&m_userList); // reset list now...
  241. }
  242. EndWaitCursor(); // hourglass...
  243. PostMessage(WM_COMMAND, ID_INIT_CTRLS);
  244. return bIsRefreshed;
  245. }
  246. void CProductPropertyPageUsers::OnDelete()
  247. /*++
  248. Routine Description:
  249. Revokes licenses from user.
  250. Arguments:
  251. None.
  252. Return Values:
  253. None.
  254. --*/
  255. {
  256. CStatistic* pStatistic;
  257. if (pStatistic = (CStatistic*)::LvGetSelObj(&m_userList))
  258. {
  259. VALIDATE_OBJECT(pStatistic, CStatistic);
  260. CString strConfirm;
  261. AfxFormatString2(
  262. strConfirm,
  263. IDP_CONFIRM_REVOKE_LICENSE,
  264. pStatistic->m_strEntry,
  265. m_pProduct->m_strName
  266. );
  267. if (AfxMessageBox(strConfirm, MB_YESNO) == IDYES)
  268. {
  269. NTSTATUS NtStatus;
  270. BeginWaitCursor(); // hourglass...
  271. NtStatus = ::LlsUserProductDelete(
  272. LlsGetActiveHandle(),
  273. MKSTR(pStatistic->m_strEntry),
  274. MKSTR(m_pProduct->m_strName)
  275. );
  276. EndWaitCursor(); // hourglass...
  277. if (NtStatus == STATUS_OBJECT_NAME_NOT_FOUND)
  278. NtStatus = STATUS_SUCCESS;
  279. LlsSetLastStatus(NtStatus); // called api...
  280. if (NT_SUCCESS(NtStatus))
  281. {
  282. *m_pUpdateHint |= UPDATE_LICENSE_REVOKED;
  283. if (!RefreshCtrls())
  284. {
  285. AbortPageIfNecessary(); // display error...
  286. }
  287. }
  288. else
  289. {
  290. AbortPageIfNecessary(); // display error...
  291. }
  292. }
  293. }
  294. }
  295. void CProductPropertyPageUsers::OnDblClkUsers(NMHDR* pNMHDR, LRESULT* pResult)
  296. /*++
  297. Routine Description:
  298. Notification handler for NM_DBLCLK.
  299. Arguments:
  300. pNMHDR - notification header.
  301. pResult - return code.
  302. Return Values:
  303. None.
  304. --*/
  305. {
  306. ViewUserProperties();
  307. *pResult = 0;
  308. }
  309. void CProductPropertyPageUsers::OnReturnUsers(NMHDR* pNMHDR, LRESULT* pResult)
  310. /*++
  311. Routine Description:
  312. Notification handler for NM_RETURN.
  313. Arguments:
  314. pNMHDR - notification header.
  315. pResult - return code.
  316. Return Values:
  317. None.
  318. --*/
  319. {
  320. ViewUserProperties();
  321. *pResult = 0;
  322. }
  323. void CProductPropertyPageUsers::OnSetFocusUsers(NMHDR* pNMHDR, LRESULT* pResult)
  324. /*++
  325. Routine Description:
  326. Notification handler for NM_SETFOCUS.
  327. Arguments:
  328. pNMHDR - notification header.
  329. pResult - return code.
  330. Return Values:
  331. None.
  332. --*/
  333. {
  334. PostMessage(WM_COMMAND, ID_INIT_CTRLS);
  335. *pResult = 0;
  336. }
  337. void CProductPropertyPageUsers::OnKillFocusUsers(NMHDR* pNMHDR, LRESULT* pResult)
  338. /*++
  339. Routine Description:
  340. Notification handler for NM_KILLFOCUS.
  341. Arguments:
  342. pNMHDR - notification header.
  343. pResult - return code.
  344. Return Values:
  345. None.
  346. --*/
  347. {
  348. ::LvSelObjIfNecessary(&m_userList); // ensure selection...
  349. PostMessage(WM_COMMAND, ID_INIT_CTRLS);
  350. *pResult = 0;
  351. }
  352. BOOL CProductPropertyPageUsers::OnCommand(WPARAM wParam, LPARAM lParam)
  353. /*++
  354. Routine Description:
  355. Message handler for WM_COMMAND.
  356. Arguments:
  357. wParam - message specific.
  358. lParam - message specific.
  359. Return Values:
  360. Returns true if message processed.
  361. --*/
  362. {
  363. if (wParam == ID_INIT_CTRLS)
  364. {
  365. if (!m_bAreCtrlsInitialized)
  366. {
  367. InitCtrls();
  368. if (!RefreshCtrls())
  369. {
  370. AbortPageIfNecessary(); // display error...
  371. }
  372. }
  373. ::SafeEnableWindow(
  374. &m_delBtn,
  375. &m_userList,
  376. CDialog::GetFocus(),
  377. m_userList.GetItemCount()
  378. );
  379. return TRUE; // processed...
  380. }
  381. return CDialog::OnCommand(wParam, lParam);
  382. }
  383. void CProductPropertyPageUsers::OnColumnClickUsers(NMHDR* pNMHDR, LRESULT* pResult)
  384. /*++
  385. Routine Description:
  386. Notification handler for LVN_COLUMNCLICK.
  387. Arguments:
  388. pNMHDR - notification header.
  389. pResult - return code.
  390. Return Values:
  391. None.
  392. --*/
  393. {
  394. g_userColumnInfo.bSortOrder = GetKeyState(VK_CONTROL) < 0;
  395. g_userColumnInfo.nSortedItem = ((NM_LISTVIEW*)pNMHDR)->iSubItem;
  396. m_userList.SortItems(CompareProductUsers, 0); // use column info
  397. *pResult = 0;
  398. }
  399. void CProductPropertyPageUsers::ViewUserProperties()
  400. /*++
  401. Routine Description:
  402. Recurse into user property page.
  403. Arguments:
  404. None.
  405. Return Values:
  406. None.
  407. --*/
  408. {
  409. CStatistic* pStatistic;
  410. if (!m_bUserProperties)
  411. {
  412. ::MessageBeep(MB_OK);
  413. return; // bail if recursion disabled...
  414. }
  415. if (pStatistic = (CStatistic*)::LvGetSelObj(&m_userList))
  416. {
  417. VALIDATE_OBJECT(pStatistic, CStatistic);
  418. CUser* pUser = new CUser(NULL, pStatistic->m_strEntry);
  419. if (pUser && pUser->Refresh())
  420. {
  421. CString strTitle;
  422. AfxFormatString1(strTitle, IDS_PROPERTIES_OF, pUser->m_strName);
  423. CUserPropertySheet userProperties(strTitle);
  424. userProperties.InitPages(pUser, FALSE);
  425. userProperties.DoModal();
  426. *m_pUpdateHint |= userProperties.m_fUpdateHint;
  427. if (IsUpdateAborted(userProperties.m_fUpdateHint))
  428. {
  429. AbortPage(); // don't display error...
  430. }
  431. else if (IsUserInfoUpdated(userProperties.m_fUpdateHint) && !RefreshCtrls())
  432. {
  433. AbortPageIfNecessary(); // display error...
  434. }
  435. }
  436. else
  437. {
  438. AbortPageIfNecessary(); // display error...
  439. }
  440. if (pUser)
  441. pUser->InternalRelease(); // delete object...
  442. }
  443. }
  444. void CProductPropertyPageUsers::OnGetDispInfoUsers(NMHDR* pNMHDR, LRESULT* pResult)
  445. /*++
  446. Routine Description:
  447. Notification handler for LVN_GETDISPINFO.
  448. Arguments:
  449. pNMHDR - notification header.
  450. pResult - return code.
  451. Return Values:
  452. None.
  453. --*/
  454. {
  455. LV_ITEM* plvItem = &((LV_DISPINFO*)pNMHDR)->item;
  456. ASSERT(plvItem);
  457. CStatistic* pStatistic = (CStatistic*)plvItem->lParam;
  458. VALIDATE_OBJECT(pStatistic, CStatistic);
  459. switch (plvItem->iSubItem)
  460. {
  461. case LVID_USER:
  462. plvItem->iImage = pStatistic->m_bIsValid ? BMPI_USER : BMPI_VIOLATION;
  463. lstrcpyn(plvItem->pszText, pStatistic->m_strEntry, plvItem->cchTextMax);
  464. break;
  465. case LVID_LAST_USED:
  466. {
  467. BSTR bstrDateLastUsed = pStatistic->GetLastUsedString();
  468. if( bstrDateLastUsed != NULL )
  469. {
  470. lstrcpyn(plvItem->pszText, bstrDateLastUsed, plvItem->cchTextMax);
  471. SysFreeString(bstrDateLastUsed);
  472. }
  473. else
  474. {
  475. lstrcpy(plvItem->pszText, L"");
  476. }
  477. }
  478. break;
  479. case LVID_TOTAL_USED:
  480. {
  481. CString strLabel;
  482. strLabel.Format(_T("%ld"), pStatistic->GetTotalUsed());
  483. lstrcpyn(plvItem->pszText, strLabel, plvItem->cchTextMax);
  484. }
  485. break;
  486. }
  487. *pResult = 0;
  488. }
  489. int CALLBACK CompareProductUsers(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  490. /*++
  491. Routine Description:
  492. Notification handler for LVM_SORTITEMS.
  493. Arguments:
  494. lParam1 - object to sort.
  495. lParam2 - object to sort.
  496. lParamSort - sort criteria.
  497. Return Values:
  498. Same as lstrcmp.
  499. --*/
  500. {
  501. #define pStatistic1 ((CStatistic*)lParam1)
  502. #define pStatistic2 ((CStatistic*)lParam2)
  503. VALIDATE_OBJECT(pStatistic1, CStatistic);
  504. VALIDATE_OBJECT(pStatistic2, CStatistic);
  505. int iResult;
  506. switch (g_userColumnInfo.nSortedItem)
  507. {
  508. case LVID_USER:
  509. iResult = pStatistic1->m_strEntry.CompareNoCase(pStatistic2->m_strEntry);
  510. break;
  511. case LVID_LAST_USED:
  512. iResult = pStatistic1->m_lLastUsed - pStatistic2->m_lLastUsed;
  513. break;
  514. case LVID_TOTAL_USED:
  515. iResult = pStatistic1->GetTotalUsed() - pStatistic2->GetTotalUsed();
  516. break;
  517. default:
  518. iResult = 0;
  519. break;
  520. }
  521. return g_userColumnInfo.bSortOrder ? -iResult : iResult;
  522. }