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.

946 lines
18 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. bIsActivated = CPropertyPage::OnSetActive();
  204. if (FALSE != bIsActivated)
  205. {
  206. if (IsProductInfoUpdated(*m_pUpdateHint) && !RefreshCtrls())
  207. {
  208. AbortPageIfNecessary(); // display error...
  209. }
  210. }
  211. return bIsActivated;
  212. }
  213. BOOL CUserPropertyPageProducts::RefreshCtrls()
  214. /*++
  215. Routine Description:
  216. Refreshs property page controls.
  217. Arguments:
  218. None.
  219. Return Values:
  220. Returns true if controls refreshed.
  221. --*/
  222. {
  223. VALIDATE_OBJECT(m_pUser, CUser);
  224. BOOL bIsRefreshed = FALSE;
  225. VARIANT va;
  226. VariantInit(&va);
  227. BeginWaitCursor(); // hourglass...
  228. CStatistics* pStatistics = (CStatistics*)MKOBJ(m_pUser->GetStatistics(va));
  229. if (pStatistics)
  230. {
  231. VALIDATE_OBJECT(pStatistics, CStatistics);
  232. bIsRefreshed = ::LvRefreshObArray(
  233. &m_productList,
  234. &g_productColumnInfo,
  235. pStatistics->m_pObArray
  236. );
  237. pStatistics->InternalRelease(); // add ref'd individually...
  238. }
  239. if (!bIsRefreshed)
  240. {
  241. ::LvReleaseObArray(&m_productList); // reset list now...
  242. }
  243. EndWaitCursor(); // hourglass...
  244. PostMessage(WM_COMMAND, ID_INIT_CTRLS);
  245. return bIsRefreshed;
  246. }
  247. void CUserPropertyPageProducts::OnDelete()
  248. /*++
  249. Routine Description:
  250. Revokes license from user.
  251. Arguments:
  252. None.
  253. Return Values:
  254. None.
  255. --*/
  256. {
  257. CStatistic* pStatistic;
  258. pStatistic = (CStatistic*)::LvGetSelObj(&m_productList);
  259. if (NULL != pStatistic)
  260. {
  261. VALIDATE_OBJECT(pStatistic, CStatistic);
  262. CString strConfirm;
  263. AfxFormatString2(
  264. strConfirm,
  265. IDP_CONFIRM_REVOKE_LICENSE,
  266. m_pUser->m_strName,
  267. pStatistic->m_strEntry
  268. );
  269. if (AfxMessageBox(strConfirm, MB_YESNO) == IDYES)
  270. {
  271. NTSTATUS NtStatus;
  272. BeginWaitCursor(); // hourglass...
  273. NtStatus = ::LlsUserProductDelete(
  274. LlsGetActiveHandle(),
  275. MKSTR(m_pUser->m_strName),
  276. MKSTR(pStatistic->m_strEntry)
  277. );
  278. EndWaitCursor(); // hourglass...
  279. if (NtStatus == STATUS_OBJECT_NAME_NOT_FOUND)
  280. NtStatus = STATUS_SUCCESS;
  281. LlsSetLastStatus(NtStatus); // called api...
  282. if (NT_SUCCESS(NtStatus))
  283. {
  284. *m_pUpdateHint |= UPDATE_LICENSE_REVOKED;
  285. if (!RefreshCtrls())
  286. {
  287. AbortPageIfNecessary(); // display error...
  288. }
  289. }
  290. else
  291. {
  292. AbortPageIfNecessary(); // display error...
  293. }
  294. }
  295. }
  296. }
  297. BOOL CUserPropertyPageProducts::OnKillActive()
  298. /*++
  299. Routine Description:
  300. Processes backoffice upgrade.
  301. Arguments:
  302. None.
  303. Return Values:
  304. Returns true if upgrade processed successfully.
  305. --*/
  306. {
  307. if (m_pUser->m_bIsBackOffice != m_upgBtn.GetCheck())
  308. {
  309. NTSTATUS NtStatus;
  310. LLS_USER_INFO_1 UserInfo1;
  311. UserInfo1.Name = MKSTR(m_pUser->m_strName);
  312. UserInfo1.Group = MKSTR(m_pUser->m_strMapping);
  313. UserInfo1.Licensed = m_pUser->m_lInUse;
  314. UserInfo1.UnLicensed = m_pUser->m_lUnlicensed;
  315. UserInfo1.Flags = m_upgBtn.GetCheck() ? LLS_FLAG_SUITE_USE : 0;
  316. BeginWaitCursor(); // hourglass...
  317. NtStatus = ::LlsUserInfoSet(
  318. LlsGetActiveHandle(),
  319. MKSTR(m_pUser->m_strName),
  320. 1,
  321. (LPBYTE)&UserInfo1
  322. );
  323. EndWaitCursor(); // hourglass...
  324. LlsSetLastStatus(NtStatus); // called api...
  325. if (NT_SUCCESS(NtStatus))
  326. {
  327. m_pUser->m_bIsBackOffice = m_upgBtn.GetCheck() ? TRUE : FALSE;
  328. *m_pUpdateHint |= UPDATE_LICENSE_UPGRADED;
  329. SetModified(FALSE);
  330. if (!RefreshCtrls())
  331. {
  332. AbortPageIfNecessary(); // display error...
  333. return FALSE;
  334. }
  335. }
  336. else
  337. {
  338. AbortPageIfNecessary(); // display error...
  339. return FALSE;
  340. }
  341. }
  342. return TRUE;
  343. }
  344. void CUserPropertyPageProducts::OnBackOfficeUpgrade()
  345. /*++
  346. Routine Description:
  347. Enables Apply Now button.
  348. Arguments:
  349. None.
  350. Return Values:
  351. None.
  352. --*/
  353. {
  354. SetModified(m_pUser->m_bIsBackOffice != m_upgBtn.GetCheck());
  355. }
  356. void CUserPropertyPageProducts::OnDblClkProducts(NMHDR* pNMHDR, LRESULT* pResult)
  357. /*++
  358. Routine Description:
  359. Notification handler for NM_DBLCLK.
  360. Arguments:
  361. pNMHDR - notification header.
  362. pResult - return code.
  363. Return Values:
  364. None.
  365. --*/
  366. {
  367. UNREFERENCED_PARAMETER(pNMHDR);
  368. ViewProductProperties();
  369. *pResult = 0;
  370. }
  371. void CUserPropertyPageProducts::OnReturnProducts(NMHDR* pNMHDR, LRESULT* pResult)
  372. /*++
  373. Routine Description:
  374. Notification handler for NM_RETURN.
  375. Arguments:
  376. pNMHDR - notification header.
  377. pResult - return code.
  378. Return Values:
  379. None.
  380. --*/
  381. {
  382. UNREFERENCED_PARAMETER(pNMHDR);
  383. ViewProductProperties();
  384. ASSERT(NULL != pResult);
  385. *pResult = 0;
  386. }
  387. void CUserPropertyPageProducts::OnSetFocusProducts(NMHDR* pNMHDR, LRESULT* pResult)
  388. /*++
  389. Routine Description:
  390. Notification handler for NM_SETFOCUS.
  391. Arguments:
  392. pNMHDR - notification header.
  393. pResult - return code.
  394. Return Values:
  395. None.
  396. --*/
  397. {
  398. UNREFERENCED_PARAMETER(pNMHDR);
  399. PostMessage(WM_COMMAND, ID_INIT_CTRLS);
  400. ASSERT(NULL != pResult);
  401. *pResult = 0;
  402. }
  403. void CUserPropertyPageProducts::OnKillFocusProducts(NMHDR* pNMHDR, LRESULT* pResult)
  404. /*++
  405. Routine Description:
  406. Notification handler for NM_KILLFOCUS.
  407. Arguments:
  408. pNMHDR - notification header.
  409. pResult - return code.
  410. Return Values:
  411. None.
  412. --*/
  413. {
  414. UNREFERENCED_PARAMETER(pNMHDR);
  415. ::LvSelObjIfNecessary(&m_productList); // ensure selection...
  416. PostMessage(WM_COMMAND, ID_INIT_CTRLS);
  417. ASSERT(NULL != pResult);
  418. *pResult = 0;
  419. }
  420. BOOL CUserPropertyPageProducts::OnCommand(WPARAM wParam, LPARAM lParam)
  421. /*++
  422. Routine Description:
  423. Message handler for WM_COMMAND.
  424. Arguments:
  425. wParam - message specific.
  426. lParam - message specific.
  427. Return Values:
  428. Returns true if message processed.
  429. --*/
  430. {
  431. if (wParam == ID_INIT_CTRLS)
  432. {
  433. if (!m_bAreCtrlsInitialized)
  434. {
  435. InitCtrls();
  436. if (!RefreshCtrls())
  437. {
  438. AbortPageIfNecessary(); // display error...
  439. }
  440. }
  441. m_upgBtn.SetCheck(m_pUser->m_bIsBackOffice);
  442. ::SafeEnableWindow(
  443. &m_delBtn,
  444. &m_productList,
  445. CDialog::GetFocus(),
  446. m_productList.GetItemCount()
  447. );
  448. return TRUE; // processed...
  449. }
  450. return CDialog::OnCommand(wParam, lParam);
  451. }
  452. void CUserPropertyPageProducts::OnColumnClickProducts(NMHDR* pNMHDR, LRESULT* pResult)
  453. /*++
  454. Routine Description:
  455. Notification handler for LVN_COLUMNCLICK.
  456. Arguments:
  457. pNMHDR - notification header.
  458. pResult - return code.
  459. Return Values:
  460. None.
  461. --*/
  462. {
  463. g_productColumnInfo.bSortOrder = GetKeyState(VK_CONTROL) < 0;
  464. ASSERT(NULL != pNMHDR);
  465. g_productColumnInfo.nSortedItem = ((NM_LISTVIEW*)pNMHDR)->iSubItem;
  466. m_productList.SortItems(CompareUserProducts, 0); // use column info
  467. ASSERT(NULL != pResult);
  468. *pResult = 0;
  469. }
  470. void CUserPropertyPageProducts::ViewProductProperties()
  471. /*++
  472. Routine Description:
  473. Recurse into product property page.
  474. Arguments:
  475. None.
  476. Return Values:
  477. None.
  478. --*/
  479. {
  480. CStatistic* pStatistic;
  481. if (!m_bProductProperties)
  482. {
  483. ::MessageBeep(MB_OK);
  484. return; // bail...
  485. }
  486. pStatistic = (CStatistic*)::LvGetSelObj(&m_productList);
  487. if (NULL != pStatistic)
  488. {
  489. VALIDATE_OBJECT(pStatistic, CStatistic);
  490. CProduct* pProduct = new CProduct(NULL, pStatistic->m_strEntry);
  491. if (pProduct)
  492. {
  493. CString strTitle;
  494. AfxFormatString1(strTitle, IDS_PROPERTIES_OF, pProduct->m_strName);
  495. CProductPropertySheet productProperties(strTitle);
  496. productProperties.InitPages(pProduct, FALSE);
  497. productProperties.DoModal();
  498. *m_pUpdateHint |= productProperties.m_fUpdateHint;
  499. if (IsUpdateAborted(productProperties.m_fUpdateHint))
  500. {
  501. AbortPage(); // don't display error...
  502. }
  503. else if (IsProductInfoUpdated(productProperties.m_fUpdateHint) && !RefreshCtrls())
  504. {
  505. AbortPageIfNecessary(); // display error...
  506. }
  507. }
  508. else
  509. {
  510. AbortPageIfNecessary(); // display error...
  511. }
  512. if (pProduct)
  513. pProduct->InternalRelease(); // delete object...
  514. }
  515. }
  516. void CUserPropertyPageProducts::OnGetDispInfoProducts(NMHDR* pNMHDR, LRESULT* pResult)
  517. /*++
  518. Routine Description:
  519. Notification handler for LVN_GETDISPINFO.
  520. Arguments:
  521. pNMHDR - notification header.
  522. pResult - return code.
  523. Return Values:
  524. None.
  525. --*/
  526. {
  527. ASSERT(NULL != pNMHDR);
  528. LV_ITEM* plvItem = &((LV_DISPINFO*)pNMHDR)->item;
  529. ASSERT(plvItem);
  530. CStatistic* pStatistic = (CStatistic*)plvItem->lParam;
  531. VALIDATE_OBJECT(pStatistic, CStatistic);
  532. switch (plvItem->iSubItem)
  533. {
  534. case LVID_PRODUCT:
  535. plvItem->iImage = pStatistic->m_bIsValid ? BMPI_PRODUCT_PER_SEAT : BMPI_VIOLATION;
  536. lstrcpyn(plvItem->pszText, pStatistic->m_strEntry, plvItem->cchTextMax);
  537. break;
  538. case LVID_LAST_USED:
  539. {
  540. BSTR bstrDateLastUsed = pStatistic->GetLastUsedString();
  541. if( bstrDateLastUsed != NULL )
  542. {
  543. lstrcpyn(plvItem->pszText, bstrDateLastUsed, plvItem->cchTextMax);
  544. SysFreeString(bstrDateLastUsed);
  545. }
  546. else
  547. {
  548. plvItem->pszText[0] = L'\0';
  549. }
  550. }
  551. break;
  552. case LVID_TOTAL_USED:
  553. {
  554. CString strLabel;
  555. strLabel.Format(_T("%ld"), pStatistic->GetTotalUsed());
  556. lstrcpyn(plvItem->pszText, strLabel, plvItem->cchTextMax);
  557. }
  558. break;
  559. }
  560. ASSERT(NULL != pResult);
  561. *pResult = 0;
  562. }
  563. int CALLBACK CompareUserProducts(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  564. /*++
  565. Routine Description:
  566. Notification handler for LVM_SORTITEMS.
  567. Arguments:
  568. lParam1 - object to sort.
  569. lParam2 - object to sort.
  570. lParamSort - sort criteria.
  571. Return Values:
  572. Same as lstrcmp.
  573. --*/
  574. {
  575. UNREFERENCED_PARAMETER(lParamSort);
  576. #define pStatistic1 ((CStatistic*)lParam1)
  577. #define pStatistic2 ((CStatistic*)lParam2)
  578. VALIDATE_OBJECT(pStatistic1, CStatistic);
  579. VALIDATE_OBJECT(pStatistic2, CStatistic);
  580. int iResult;
  581. switch (g_productColumnInfo.nSortedItem)
  582. {
  583. case LVID_PRODUCT:
  584. iResult = pStatistic1->m_strEntry.CompareNoCase(pStatistic2->m_strEntry);
  585. break;
  586. case LVID_LAST_USED:
  587. iResult = pStatistic1->m_lLastUsed - pStatistic2->m_lLastUsed;
  588. break;
  589. case LVID_TOTAL_USED:
  590. iResult = pStatistic1->GetTotalUsed() - pStatistic2->GetTotalUsed();
  591. break;
  592. default:
  593. iResult = 0;
  594. break;
  595. }
  596. return g_productColumnInfo.bSortOrder ? -iResult : iResult;
  597. }