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.

926 lines
16 KiB

  1. /*++
  2. Copyright (c) 1994-95 Microsoft Corporation
  3. Module Name:
  4. usrppgp.cpp
  5. Abstract:
  6. User property page (products) implementation.
  7. Author:
  8. Don Ryan (donryan) 05-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 "usrppgp.h"
  20. #include "prdpsht.h"
  21. #define LVID_PRODUCT 0
  22. #define LVID_LAST_USED 1
  23. #define LVID_TOTAL_USED 2
  24. #define LVCX_PRODUCT 40
  25. #define LVCX_LAST_USED 30
  26. #define LVCX_TOTAL_USED -1
  27. static LV_COLUMN_INFO g_productColumnInfo = {
  28. 0, 0, 3,
  29. {{LVID_PRODUCT, IDS_PRODUCT, 0, LVCX_PRODUCT },
  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(CUserPropertyPageProducts, CPropertyPage)
  38. BEGIN_MESSAGE_MAP(CUserPropertyPageProducts, CPropertyPage)
  39. //{{AFX_MSG_MAP(CUserPropertyPageProducts)
  40. ON_BN_CLICKED(IDC_PP_USER_PRODUCTS_DELETE, OnDelete)
  41. ON_BN_CLICKED(IDC_PP_USER_PRODUCTS_BACKOFFICE, OnBackOfficeUpgrade)
  42. ON_NOTIFY(NM_DBLCLK, IDC_PP_USER_PRODUCTS_PRODUCTS, OnDblClkProducts)
  43. ON_NOTIFY(NM_RETURN, IDC_PP_USER_PRODUCTS_PRODUCTS, OnReturnProducts)
  44. ON_NOTIFY(NM_SETFOCUS, IDC_PP_USER_PRODUCTS_PRODUCTS, OnSetFocusProducts)
  45. ON_NOTIFY(NM_KILLFOCUS, IDC_PP_USER_PRODUCTS_PRODUCTS, OnKillFocusProducts)
  46. ON_NOTIFY(LVN_COLUMNCLICK, IDC_PP_USER_PRODUCTS_PRODUCTS, OnColumnClickProducts)
  47. ON_NOTIFY(LVN_GETDISPINFO, IDC_PP_USER_PRODUCTS_PRODUCTS, OnGetDispInfoProducts)
  48. ON_WM_DESTROY()
  49. //}}AFX_MSG_MAP
  50. END_MESSAGE_MAP()
  51. CUserPropertyPageProducts::CUserPropertyPageProducts()
  52. : CPropertyPage(CUserPropertyPageProducts::IDD)
  53. /*++
  54. Routine Description:
  55. Constructor for user property page (products).
  56. Arguments:
  57. None.
  58. Return Values:
  59. None.
  60. --*/
  61. {
  62. //{{AFX_DATA_INIT(CUserPropertyPageProducts)
  63. m_bUseBackOffice = FALSE;
  64. //}}AFX_DATA_INIT
  65. m_pUser = NULL;
  66. m_pUpdateHint = NULL;
  67. m_bProductProperties = TRUE;
  68. m_bAreCtrlsInitialized = FALSE;
  69. }
  70. CUserPropertyPageProducts::~CUserPropertyPageProducts()
  71. /*++
  72. Routine Description:
  73. Destructor for user property page (products).
  74. Arguments:
  75. None.
  76. Return Values:
  77. None.
  78. --*/
  79. {
  80. //
  81. // Nothing to do here...
  82. //
  83. }
  84. void CUserPropertyPageProducts::DoDataExchange(CDataExchange* pDX)
  85. /*++
  86. Routine Description:
  87. Called by framework to exchange dialog data.
  88. Arguments:
  89. pDX - data exchange object.
  90. Return Values:
  91. None.
  92. --*/
  93. {
  94. CPropertyPage::DoDataExchange(pDX);
  95. //{{AFX_DATA_MAP(CUserPropertyPageProducts)
  96. DDX_Control(pDX, IDC_PP_USER_PRODUCTS_BACKOFFICE, m_upgBtn);
  97. DDX_Control(pDX, IDC_PP_USER_PRODUCTS_DELETE, m_delBtn);
  98. DDX_Control(pDX, IDC_PP_USER_PRODUCTS_PRODUCTS, m_productList);
  99. DDX_Check(pDX, IDC_PP_USER_PRODUCTS_BACKOFFICE, m_bUseBackOffice);
  100. //}}AFX_DATA_MAP
  101. }
  102. void CUserPropertyPageProducts::InitCtrls()
  103. /*++
  104. Routine Description:
  105. Initializes property page controls.
  106. Arguments:
  107. None.
  108. Return Values:
  109. None.
  110. --*/
  111. {
  112. m_upgBtn.SetCheck(0);
  113. m_delBtn.EnableWindow(FALSE);
  114. m_productList.SetFocus();
  115. m_bAreCtrlsInitialized = TRUE;
  116. ::LvInitColumns(&m_productList, &g_productColumnInfo);
  117. }
  118. void CUserPropertyPageProducts::InitPage(CUser* pUser, DWORD* pUpdateHint, BOOL bProductProperties)
  119. /*++
  120. Routine Description:
  121. Initializes property page.
  122. Arguments:
  123. pUser - user object.
  124. pUpdateHint - update hint.
  125. bProductProperties - to recurse or not
  126. Return Values:
  127. None.
  128. --*/
  129. {
  130. ASSERT(pUpdateHint);
  131. VALIDATE_OBJECT(pUser, CUser);
  132. m_pUser = pUser;
  133. m_pUpdateHint = pUpdateHint;
  134. m_bProductProperties = bProductProperties;
  135. }
  136. void CUserPropertyPageProducts::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 CUserPropertyPageProducts::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 CUserPropertyPageProducts::OnInitDialog()
  166. /*++
  167. Routine Description:
  168. Message handler for WM_INITDIALOG.
  169. Arguments:
  170. None.
  171. Return Values:
  172. Return false if focus set manually.
  173. --*/
  174. {
  175. CPropertyPage::OnInitDialog();
  176. PostMessage(WM_COMMAND, ID_INIT_CTRLS);
  177. return TRUE;
  178. }
  179. void CUserPropertyPageProducts::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_productList); // release now...
  190. CPropertyPage::OnDestroy();
  191. }
  192. BOOL CUserPropertyPageProducts::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 (IsProductInfoUpdated(*m_pUpdateHint) && !RefreshCtrls())
  206. {
  207. AbortPageIfNecessary(); // display error...
  208. }
  209. }
  210. return bIsActivated;
  211. }
  212. BOOL CUserPropertyPageProducts::RefreshCtrls()
  213. /*++
  214. Routine Description:
  215. Refreshs property page controls.
  216. Arguments:
  217. None.
  218. Return Values:
  219. Returns true if controls refreshed.
  220. --*/
  221. {
  222. VALIDATE_OBJECT(m_pUser, CUser);
  223. BOOL bIsRefreshed = FALSE;
  224. VARIANT va;
  225. VariantInit(&va);
  226. BeginWaitCursor(); // hourglass...
  227. CStatistics* pStatistics = (CStatistics*)MKOBJ(m_pUser->GetStatistics(va));
  228. if (pStatistics)
  229. {
  230. VALIDATE_OBJECT(pStatistics, CStatistics);
  231. bIsRefreshed = ::LvRefreshObArray(
  232. &m_productList,
  233. &g_productColumnInfo,
  234. pStatistics->m_pObArray
  235. );
  236. pStatistics->InternalRelease(); // add ref'd individually...
  237. }
  238. if (!bIsRefreshed)
  239. {
  240. ::LvReleaseObArray(&m_productList); // reset list now...
  241. }
  242. EndWaitCursor(); // hourglass...
  243. PostMessage(WM_COMMAND, ID_INIT_CTRLS);
  244. return bIsRefreshed;
  245. }
  246. void CUserPropertyPageProducts::OnDelete()
  247. /*++
  248. Routine Description:
  249. Revokes license from user.
  250. Arguments:
  251. None.
  252. Return Values:
  253. None.
  254. --*/
  255. {
  256. CStatistic* pStatistic;
  257. if (pStatistic = (CStatistic*)::LvGetSelObj(&m_productList))
  258. {
  259. VALIDATE_OBJECT(pStatistic, CStatistic);
  260. CString strConfirm;
  261. AfxFormatString2(
  262. strConfirm,
  263. IDP_CONFIRM_REVOKE_LICENSE,
  264. m_pUser->m_strName,
  265. pStatistic->m_strEntry
  266. );
  267. if (AfxMessageBox(strConfirm, MB_YESNO) == IDYES)
  268. {
  269. NTSTATUS NtStatus;
  270. BeginWaitCursor(); // hourglass...
  271. NtStatus = ::LlsUserProductDelete(
  272. LlsGetActiveHandle(),
  273. MKSTR(m_pUser->m_strName),
  274. MKSTR(pStatistic->m_strEntry)
  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. BOOL CUserPropertyPageProducts::OnKillActive()
  296. /*++
  297. Routine Description:
  298. Processes backoffice upgrade.
  299. Arguments:
  300. None.
  301. Return Values:
  302. Returns true if upgrade processed successfully.
  303. --*/
  304. {
  305. if (m_pUser->m_bIsBackOffice != m_upgBtn.GetCheck())
  306. {
  307. NTSTATUS NtStatus;
  308. LLS_USER_INFO_1 UserInfo1;
  309. UserInfo1.Name = MKSTR(m_pUser->m_strName);
  310. UserInfo1.Group = MKSTR(m_pUser->m_strMapping);
  311. UserInfo1.Licensed = m_pUser->m_lInUse;
  312. UserInfo1.UnLicensed = m_pUser->m_lUnlicensed;
  313. UserInfo1.Flags = m_upgBtn.GetCheck() ? LLS_FLAG_SUITE_USE : 0;
  314. BeginWaitCursor(); // hourglass...
  315. NtStatus = ::LlsUserInfoSet(
  316. LlsGetActiveHandle(),
  317. MKSTR(m_pUser->m_strName),
  318. 1,
  319. (LPBYTE)&UserInfo1
  320. );
  321. EndWaitCursor(); // hourglass...
  322. LlsSetLastStatus(NtStatus); // called api...
  323. if (NT_SUCCESS(NtStatus))
  324. {
  325. m_pUser->m_bIsBackOffice = m_upgBtn.GetCheck() ? TRUE : FALSE;
  326. *m_pUpdateHint |= UPDATE_LICENSE_UPGRADED;
  327. SetModified(FALSE);
  328. if (!RefreshCtrls())
  329. {
  330. AbortPageIfNecessary(); // display error...
  331. return FALSE;
  332. }
  333. }
  334. else
  335. {
  336. AbortPageIfNecessary(); // display error...
  337. return FALSE;
  338. }
  339. }
  340. return TRUE;
  341. }
  342. void CUserPropertyPageProducts::OnBackOfficeUpgrade()
  343. /*++
  344. Routine Description:
  345. Enables Apply Now button.
  346. Arguments:
  347. None.
  348. Return Values:
  349. None.
  350. --*/
  351. {
  352. SetModified(m_pUser->m_bIsBackOffice != m_upgBtn.GetCheck());
  353. }
  354. void CUserPropertyPageProducts::OnDblClkProducts(NMHDR* pNMHDR, LRESULT* pResult)
  355. /*++
  356. Routine Description:
  357. Notification handler for NM_DBLCLK.
  358. Arguments:
  359. pNMHDR - notification header.
  360. pResult - return code.
  361. Return Values:
  362. None.
  363. --*/
  364. {
  365. ViewProductProperties();
  366. *pResult = 0;
  367. }
  368. void CUserPropertyPageProducts::OnReturnProducts(NMHDR* pNMHDR, LRESULT* pResult)
  369. /*++
  370. Routine Description:
  371. Notification handler for NM_RETURN.
  372. Arguments:
  373. pNMHDR - notification header.
  374. pResult - return code.
  375. Return Values:
  376. None.
  377. --*/
  378. {
  379. ViewProductProperties();
  380. *pResult = 0;
  381. }
  382. void CUserPropertyPageProducts::OnSetFocusProducts(NMHDR* pNMHDR, LRESULT* pResult)
  383. /*++
  384. Routine Description:
  385. Notification handler for NM_SETFOCUS.
  386. Arguments:
  387. pNMHDR - notification header.
  388. pResult - return code.
  389. Return Values:
  390. None.
  391. --*/
  392. {
  393. PostMessage(WM_COMMAND, ID_INIT_CTRLS);
  394. *pResult = 0;
  395. }
  396. void CUserPropertyPageProducts::OnKillFocusProducts(NMHDR* pNMHDR, LRESULT* pResult)
  397. /*++
  398. Routine Description:
  399. Notification handler for NM_KILLFOCUS.
  400. Arguments:
  401. pNMHDR - notification header.
  402. pResult - return code.
  403. Return Values:
  404. None.
  405. --*/
  406. {
  407. ::LvSelObjIfNecessary(&m_productList); // ensure selection...
  408. PostMessage(WM_COMMAND, ID_INIT_CTRLS);
  409. *pResult = 0;
  410. }
  411. BOOL CUserPropertyPageProducts::OnCommand(WPARAM wParam, LPARAM lParam)
  412. /*++
  413. Routine Description:
  414. Message handler for WM_COMMAND.
  415. Arguments:
  416. wParam - message specific.
  417. lParam - message specific.
  418. Return Values:
  419. Returns true if message processed.
  420. --*/
  421. {
  422. if (wParam == ID_INIT_CTRLS)
  423. {
  424. if (!m_bAreCtrlsInitialized)
  425. {
  426. InitCtrls();
  427. if (!RefreshCtrls())
  428. {
  429. AbortPageIfNecessary(); // display error...
  430. }
  431. }
  432. m_upgBtn.SetCheck(m_pUser->m_bIsBackOffice);
  433. ::SafeEnableWindow(
  434. &m_delBtn,
  435. &m_productList,
  436. CDialog::GetFocus(),
  437. m_productList.GetItemCount()
  438. );
  439. return TRUE; // processed...
  440. }
  441. return CDialog::OnCommand(wParam, lParam);
  442. }
  443. void CUserPropertyPageProducts::OnColumnClickProducts(NMHDR* pNMHDR, LRESULT* pResult)
  444. /*++
  445. Routine Description:
  446. Notification handler for LVN_COLUMNCLICK.
  447. Arguments:
  448. pNMHDR - notification header.
  449. pResult - return code.
  450. Return Values:
  451. None.
  452. --*/
  453. {
  454. g_productColumnInfo.bSortOrder = GetKeyState(VK_CONTROL) < 0;
  455. g_productColumnInfo.nSortedItem = ((NM_LISTVIEW*)pNMHDR)->iSubItem;
  456. m_productList.SortItems(CompareUserProducts, 0); // use column info
  457. *pResult = 0;
  458. }
  459. void CUserPropertyPageProducts::ViewProductProperties()
  460. /*++
  461. Routine Description:
  462. Recurse into product property page.
  463. Arguments:
  464. None.
  465. Return Values:
  466. None.
  467. --*/
  468. {
  469. CStatistic* pStatistic;
  470. if (!m_bProductProperties)
  471. {
  472. ::MessageBeep(MB_OK);
  473. return; // bail...
  474. }
  475. if (pStatistic = (CStatistic*)::LvGetSelObj(&m_productList))
  476. {
  477. VALIDATE_OBJECT(pStatistic, CStatistic);
  478. CProduct* pProduct = new CProduct(NULL, pStatistic->m_strEntry);
  479. if (pProduct)
  480. {
  481. CString strTitle;
  482. AfxFormatString1(strTitle, IDS_PROPERTIES_OF, pProduct->m_strName);
  483. CProductPropertySheet productProperties(strTitle);
  484. productProperties.InitPages(pProduct, FALSE);
  485. productProperties.DoModal();
  486. *m_pUpdateHint |= productProperties.m_fUpdateHint;
  487. if (IsUpdateAborted(productProperties.m_fUpdateHint))
  488. {
  489. AbortPage(); // don't display error...
  490. }
  491. else if (IsProductInfoUpdated(productProperties.m_fUpdateHint) && !RefreshCtrls())
  492. {
  493. AbortPageIfNecessary(); // display error...
  494. }
  495. }
  496. else
  497. {
  498. AbortPageIfNecessary(); // display error...
  499. }
  500. if (pProduct)
  501. pProduct->InternalRelease(); // delete object...
  502. }
  503. }
  504. void CUserPropertyPageProducts::OnGetDispInfoProducts(NMHDR* pNMHDR, LRESULT* pResult)
  505. /*++
  506. Routine Description:
  507. Notification handler for LVN_GETDISPINFO.
  508. Arguments:
  509. pNMHDR - notification header.
  510. pResult - return code.
  511. Return Values:
  512. None.
  513. --*/
  514. {
  515. LV_ITEM* plvItem = &((LV_DISPINFO*)pNMHDR)->item;
  516. ASSERT(plvItem);
  517. CStatistic* pStatistic = (CStatistic*)plvItem->lParam;
  518. VALIDATE_OBJECT(pStatistic, CStatistic);
  519. switch (plvItem->iSubItem)
  520. {
  521. case LVID_PRODUCT:
  522. plvItem->iImage = pStatistic->m_bIsValid ? BMPI_PRODUCT_PER_SEAT : BMPI_VIOLATION;
  523. lstrcpyn(plvItem->pszText, pStatistic->m_strEntry, plvItem->cchTextMax);
  524. break;
  525. case LVID_LAST_USED:
  526. {
  527. BSTR bstrDateLastUsed = pStatistic->GetLastUsedString();
  528. if( bstrDateLastUsed != NULL )
  529. {
  530. lstrcpyn(plvItem->pszText, bstrDateLastUsed, plvItem->cchTextMax);
  531. SysFreeString(bstrDateLastUsed);
  532. }
  533. else
  534. {
  535. lstrcpy(plvItem->pszText, L"");
  536. }
  537. }
  538. break;
  539. case LVID_TOTAL_USED:
  540. {
  541. CString strLabel;
  542. strLabel.Format(_T("%ld"), pStatistic->GetTotalUsed());
  543. lstrcpyn(plvItem->pszText, strLabel, plvItem->cchTextMax);
  544. }
  545. break;
  546. }
  547. *pResult = 0;
  548. }
  549. int CALLBACK CompareUserProducts(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  550. /*++
  551. Routine Description:
  552. Notification handler for LVM_SORTITEMS.
  553. Arguments:
  554. lParam1 - object to sort.
  555. lParam2 - object to sort.
  556. lParamSort - sort criteria.
  557. Return Values:
  558. Same as lstrcmp.
  559. --*/
  560. {
  561. #define pStatistic1 ((CStatistic*)lParam1)
  562. #define pStatistic2 ((CStatistic*)lParam2)
  563. VALIDATE_OBJECT(pStatistic1, CStatistic);
  564. VALIDATE_OBJECT(pStatistic2, CStatistic);
  565. int iResult;
  566. switch (g_productColumnInfo.nSortedItem)
  567. {
  568. case LVID_PRODUCT:
  569. iResult = pStatistic1->m_strEntry.CompareNoCase(pStatistic2->m_strEntry);
  570. break;
  571. case LVID_LAST_USED:
  572. iResult = pStatistic1->m_lLastUsed - pStatistic2->m_lLastUsed;
  573. break;
  574. case LVID_TOTAL_USED:
  575. iResult = pStatistic1->GetTotalUsed() - pStatistic2->GetTotalUsed();
  576. break;
  577. default:
  578. iResult = 0;
  579. break;
  580. }
  581. return g_productColumnInfo.bSortOrder ? -iResult : iResult;
  582. }