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.

1404 lines
33 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. remdlg.cpp
  5. Abstract:
  6. Remove licenses dialog implementation.
  7. Author:
  8. Jeff Parham (jeffparh) 13-Dec-1995
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #include "ccfapi.h"
  13. #include "remdlg.h"
  14. #include "utils.h"
  15. #include "licobj.h"
  16. #include "imagelst.h"
  17. #include "nlicdlg.h"
  18. #include <htmlhelp.h>
  19. #ifdef _DEBUG
  20. #define new DEBUG_NEW
  21. #undef THIS_FILE
  22. static char THIS_FILE[] = __FILE__;
  23. #endif
  24. // describes the list view layout
  25. static LV_COLUMN_INFO g_removeColumnInfo =
  26. {
  27. 0, 1, LVID_REMOVE_TOTAL_COLUMNS,
  28. {{LVID_REMOVE_SERIAL_NUMBER, IDS_SERIAL_NUMBER, LVCX_REMOVE_SERIAL_NUMBER },
  29. {LVID_REMOVE_PRODUCT_NAME, IDS_PRODUCT_NAME, LVCX_REMOVE_PRODUCT_NAME },
  30. {LVID_REMOVE_LICENSE_MODE, IDS_LICENSE_MODE, LVCX_REMOVE_LICENSE_MODE },
  31. {LVID_REMOVE_NUM_LICENSES, IDS_QUANTITY, LVCX_REMOVE_NUM_LICENSES },
  32. {LVID_REMOVE_SOURCE, IDS_SOURCE, LVCX_REMOVE_SOURCE }},
  33. };
  34. CCertRemoveSelectDlg::CCertRemoveSelectDlg(CWnd* pParent /*=NULL*/)
  35. : CDialog(CCertRemoveSelectDlg::IDD, pParent)
  36. /*++
  37. Routine Description:
  38. Constructor for dialog.
  39. Arguments:
  40. pParent - owner window.
  41. Return Values:
  42. None.
  43. --*/
  44. {
  45. //{{AFX_DATA_INIT(CCertRemoveSelectDlg)
  46. m_nLicenses = 0;
  47. //}}AFX_DATA_INIT
  48. m_hLls = NULL;
  49. m_bLicensesRefreshed = FALSE;
  50. m_dwRemoveFlags = 0;
  51. }
  52. CCertRemoveSelectDlg::~CCertRemoveSelectDlg()
  53. /*++
  54. Routine Description:
  55. Destructor for dialog.
  56. Arguments:
  57. None.
  58. Return Values:
  59. None.
  60. --*/
  61. {
  62. if ( NULL != m_hLls )
  63. {
  64. LlsClose( m_hLls );
  65. }
  66. }
  67. void CCertRemoveSelectDlg::DoDataExchange(CDataExchange* pDX)
  68. /*++
  69. Routine Description:
  70. Called by framework to exchange dialog data.
  71. Arguments:
  72. pDX - data exchange object.
  73. Return Values:
  74. None.
  75. --*/
  76. {
  77. CDialog::DoDataExchange(pDX);
  78. //{{AFX_DATA_MAP(CCertRemoveSelectDlg)
  79. DDX_Control(pDX, IDC_SPIN_LICENSES, m_spinLicenses);
  80. DDX_Control(pDX, IDC_CERTIFICATE_LIST, m_listCertificates);
  81. DDX_Text(pDX, IDC_NUM_LICENSES, m_nLicenses);
  82. //}}AFX_DATA_MAP
  83. }
  84. BEGIN_MESSAGE_MAP(CCertRemoveSelectDlg, CDialog)
  85. //{{AFX_MSG_MAP(CCertRemoveSelectDlg)
  86. ON_BN_CLICKED(IDC_MY_HELP, OnHelp)
  87. ON_NOTIFY(LVN_COLUMNCLICK, IDC_CERTIFICATE_LIST, OnColumnClickCertificateList)
  88. ON_NOTIFY(LVN_GETDISPINFO, IDC_CERTIFICATE_LIST, OnGetDispInfoCertificateList)
  89. ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_LICENSES, OnDeltaPosSpinLicenses)
  90. ON_NOTIFY(NM_DBLCLK, IDC_CERTIFICATE_LIST, OnDblClkCertificateList)
  91. ON_NOTIFY(NM_RETURN, IDC_CERTIFICATE_LIST, OnReturnCertificateList)
  92. ON_WM_DESTROY()
  93. ON_NOTIFY(NM_CLICK, IDC_CERTIFICATE_LIST, OnClickCertificateList)
  94. ON_NOTIFY(LVN_KEYDOWN, IDC_CERTIFICATE_LIST, OnKeyDownCertificateList)
  95. ON_BN_CLICKED(IDC_REFRESH, OnRefresh)
  96. ON_MESSAGE( WM_HELP , OnHelpCmd )
  97. //}}AFX_MSG_MAP
  98. END_MESSAGE_MAP()
  99. BOOL CCertRemoveSelectDlg::OnInitDialog()
  100. /*++
  101. Routine Description:
  102. Handler for WM_INITDIALOG.
  103. Arguments:
  104. None.
  105. Return Values:
  106. Returns false if focus set manually.
  107. --*/
  108. {
  109. CDialog::OnInitDialog();
  110. LoadImages();
  111. m_listCertificates.SetImageList( &m_smallImages, LVSIL_SMALL );
  112. ::LvInitColumns( &m_listCertificates, &g_removeColumnInfo );
  113. RefreshLicenses();
  114. RefreshCertificateList();
  115. UpdateSpinControlRange();
  116. return TRUE; // return TRUE unless you set the focus to a control
  117. // EXCEPTION: OCX Property Pages should return FALSE
  118. }
  119. void CCertRemoveSelectDlg::OnOK()
  120. /*++
  121. Routine Description:
  122. Handler for BN_CLICKED of OK.
  123. Arguments:
  124. None.
  125. Return Values:
  126. None.
  127. --*/
  128. {
  129. RemoveSelectedCertificate();
  130. }
  131. /*++
  132. Routine Description:
  133. Handler for pressing F1.
  134. Arguments:
  135. None.
  136. Return Values:
  137. Nothing significant.
  138. --*/
  139. LRESULT CCertRemoveSelectDlg::OnHelpCmd( WPARAM , LPARAM )
  140. {
  141. OnHelp();
  142. return 0;
  143. }
  144. void CCertRemoveSelectDlg::OnHelp()
  145. /*++
  146. Routine Description:
  147. Handler for help button click.
  148. Arguments:
  149. None.
  150. Return Values:
  151. None.
  152. --*/
  153. {
  154. WinHelp( IDD, HELP_CONTEXT );
  155. }
  156. void CCertRemoveSelectDlg::WinHelp(DWORD dwData, UINT nCmd)
  157. /*++
  158. Routine Description:
  159. Call WinHelp for this dialog.
  160. Arguments:
  161. dwData (DWORD)
  162. nCmd (UINT)
  163. Return Values:
  164. None.
  165. --*/
  166. {
  167. ::HtmlHelp(m_hWnd, L"liceconcepts.chm", HH_DISPLAY_TOPIC,0);
  168. /*
  169. BOOL ok = ::WinHelp( m_hWnd, theApp.GetHelpFileName(), nCmd, dwData );
  170. ASSERT( ok );
  171. */
  172. }
  173. void CCertRemoveSelectDlg::OnDestroy()
  174. /*++
  175. Routine Description:
  176. Handler for WM_DESTROY.
  177. Arguments:
  178. None.
  179. Return Values:
  180. None.
  181. --*/
  182. {
  183. ResetLicenses();
  184. /*
  185. ::WinHelp( m_hWnd, theApp.GetHelpFileName(), HELP_QUIT, 0 );
  186. */
  187. CDialog::OnDestroy();
  188. }
  189. void CCertRemoveSelectDlg::OnColumnClickCertificateList(NMHDR* pNMHDR, LRESULT* pResult)
  190. /*++
  191. Routine Description:
  192. Handler for LVN_COLUMNCLICK of certificate list view.
  193. Arguments:
  194. pNMHDR (NMHDR*)
  195. pResult (LRESULT*)
  196. Return Values:
  197. None.
  198. --*/
  199. {
  200. g_removeColumnInfo.bSortOrder = GetKeyState(VK_CONTROL) < 0;
  201. g_removeColumnInfo.nSortedItem = ((NM_LISTVIEW*)pNMHDR)->iSubItem;
  202. m_listCertificates.SortItems( CompareLicenses, 0 ); // use column info
  203. *pResult = 0;
  204. }
  205. void CCertRemoveSelectDlg::OnGetDispInfoCertificateList(NMHDR* pNMHDR, LRESULT* pResult)
  206. /*++
  207. Routine Description:
  208. Handler for LVN_GETDISPINFO of certificate list view.
  209. Arguments:
  210. pNMHDR (NMHDR*)
  211. pResult (LRESULT*)
  212. Return Values:
  213. None.
  214. --*/
  215. {
  216. LV_ITEM* plvItem = &((LV_DISPINFO*)pNMHDR)->item;
  217. ASSERT(plvItem);
  218. CLicense* pLicense = (CLicense*)plvItem->lParam;
  219. VALIDATE_OBJECT(pLicense, CLicense);
  220. switch (plvItem->iSubItem)
  221. {
  222. case LVID_REMOVE_SERIAL_NUMBER:
  223. plvItem->iImage = BMPI_CERTIFICATE;
  224. {
  225. CString strSerialNumber;
  226. strSerialNumber.Format( TEXT("%ld"), (LONG) ( pLicense->m_dwCertificateID ) );
  227. lstrcpyn( plvItem->pszText, strSerialNumber, plvItem->cchTextMax );
  228. }
  229. break;
  230. case LVID_REMOVE_PRODUCT_NAME:
  231. lstrcpyn( plvItem->pszText, pLicense->m_strProduct, plvItem->cchTextMax );
  232. break;
  233. case LVID_REMOVE_LICENSE_MODE:
  234. lstrcpyn( plvItem->pszText, pLicense->GetAllowedModesString(), plvItem->cchTextMax );
  235. break;
  236. case LVID_REMOVE_NUM_LICENSES:
  237. {
  238. CString strLicenses;
  239. strLicenses.Format( TEXT("%ld"), (LONG) ( pLicense->m_lQuantity ) );
  240. lstrcpyn( plvItem->pszText, strLicenses, plvItem->cchTextMax );
  241. }
  242. break;
  243. case LVID_REMOVE_SOURCE:
  244. lstrcpyn( plvItem->pszText, pLicense->GetSourceDisplayName(), plvItem->cchTextMax );
  245. break;
  246. default:
  247. ASSERT( FALSE );
  248. break;
  249. }
  250. *pResult = 0;
  251. }
  252. void CCertRemoveSelectDlg::OnDeltaPosSpinLicenses(NMHDR* pNMHDR, LRESULT* pResult)
  253. /*++
  254. Routine Description:
  255. Handler for UDN_DELTAPOS of number of licenses.
  256. Arguments:
  257. pNMHDR (NMHDR*)
  258. pResult (LRESULT*)
  259. Return Values:
  260. None.
  261. --*/
  262. {
  263. if ( UpdateData(TRUE) ) // get data
  264. {
  265. m_nLicenses += ((NM_UPDOWN*)pNMHDR)->iDelta;
  266. int nLow;
  267. int nHigh;
  268. m_spinLicenses.GetRange( nLow, nHigh );
  269. if (m_nLicenses < nLow)
  270. {
  271. m_nLicenses = nLow;
  272. ::MessageBeep(MB_OK);
  273. }
  274. else if (m_nLicenses > nHigh )
  275. {
  276. m_nLicenses = nHigh;
  277. ::MessageBeep(MB_OK);
  278. }
  279. UpdateData(FALSE); // set data
  280. }
  281. *pResult = 1; // handle ourselves...
  282. }
  283. void CCertRemoveSelectDlg::OnDblClkCertificateList(NMHDR* pNMHDR, LRESULT* pResult)
  284. /*++
  285. Routine Description:
  286. Handler for NM_DBLCLK of certificate list view.
  287. Arguments:
  288. pNMHDR (NMHDR*)
  289. pResult (LRESULT*)
  290. Return Values:
  291. None.
  292. --*/
  293. {
  294. RemoveSelectedCertificate();
  295. *pResult = 0;
  296. }
  297. void CCertRemoveSelectDlg::OnReturnCertificateList(NMHDR* pNMHDR, LRESULT* pResult)
  298. /*++
  299. Routine Description:
  300. Handler for NM_RETURN of certificate list view.
  301. Arguments:
  302. None.
  303. Return Values:
  304. None.
  305. --*/
  306. {
  307. RemoveSelectedCertificate();
  308. *pResult = 0;
  309. }
  310. void CCertRemoveSelectDlg::ResetLicenses()
  311. /*++
  312. Routine Description:
  313. Remove all licenses from internal list.
  314. Arguments:
  315. None.
  316. Return Values:
  317. None.
  318. --*/
  319. {
  320. CLicense* pLicense;
  321. int iLicense = (int)m_licenseArray.GetSize();
  322. while (iLicense--)
  323. {
  324. if (pLicense = (CLicense*)m_licenseArray[iLicense])
  325. {
  326. ASSERT(pLicense->IsKindOf(RUNTIME_CLASS(CLicense)));
  327. delete pLicense;
  328. }
  329. }
  330. m_licenseArray.RemoveAll();
  331. m_listCertificates.DeleteAllItems();
  332. m_bLicensesRefreshed = FALSE;
  333. }
  334. BOOL CCertRemoveSelectDlg::RefreshLicenses()
  335. /*++
  336. Routine Description:
  337. Refresh internal license list with data from license server.
  338. Arguments:
  339. None.
  340. Return Values:
  341. BOOL.
  342. --*/
  343. {
  344. ResetLicenses();
  345. if ( ConnectServer() )
  346. {
  347. NTSTATUS NtStatus;
  348. DWORD ResumeHandle = 0L;
  349. int iLicense = 0;
  350. do
  351. {
  352. DWORD EntriesRead;
  353. DWORD TotalEntries;
  354. LPBYTE ReturnBuffer = NULL;
  355. DWORD Level = LlsCapabilityIsSupported( m_hLls, LLS_CAPABILITY_SECURE_CERTIFICATES ) ? 1 : 0;
  356. BeginWaitCursor();
  357. NtStatus = ::LlsLicenseEnum( m_hLls,
  358. Level,
  359. &ReturnBuffer,
  360. LLS_PREFERRED_LENGTH,
  361. &EntriesRead,
  362. &TotalEntries,
  363. &ResumeHandle );
  364. EndWaitCursor();
  365. if ( ( STATUS_SUCCESS == NtStatus )
  366. || ( STATUS_MORE_ENTRIES == NtStatus ) )
  367. {
  368. CLicense* pLicense;
  369. PLLS_LICENSE_INFO_0 pLicenseInfo0;
  370. PLLS_LICENSE_INFO_1 pLicenseInfo1;
  371. pLicenseInfo0 = (PLLS_LICENSE_INFO_0)ReturnBuffer;
  372. pLicenseInfo1 = (PLLS_LICENSE_INFO_1)ReturnBuffer;
  373. while (EntriesRead--)
  374. {
  375. if ( ( m_strProductName.IsEmpty() || !m_strProductName.CompareNoCase( Level ? pLicenseInfo1->Product : pLicenseInfo0->Product ) )
  376. && ( m_strSourceToUse.IsEmpty() || !m_strSourceToUse.CompareNoCase( Level ? pLicenseInfo1->Source : TEXT("None") ) ) )
  377. {
  378. // we want to list this license
  379. // have we seen this certificate yet?
  380. for ( int i=0; i < m_licenseArray.GetSize(); i++ )
  381. {
  382. pLicense = (CLicense*) m_licenseArray[ i ];
  383. VALIDATE_OBJECT( pLicense, CLicense );
  384. if ( ( ( 1 == Level )
  385. && ( pLicense->m_dwCertificateID == pLicenseInfo1->CertificateID )
  386. && ( pLicense->m_dwAllowedModes == pLicenseInfo1->AllowedModes )
  387. && ( pLicense->m_dwMaxQuantity == pLicenseInfo1->MaxQuantity )
  388. && ( !pLicense->m_strSource.CompareNoCase( pLicenseInfo1->Source ) )
  389. && ( !pLicense->m_strProduct.CompareNoCase( pLicenseInfo1->Product ) )
  390. && ( !memcmp( pLicense->m_adwSecrets,
  391. pLicenseInfo1->Secrets,
  392. sizeof( pLicense->m_adwSecrets ) ) ) )
  393. || ( ( 0 == Level )
  394. && ( !pLicense->m_strProduct.CompareNoCase( pLicenseInfo0->Product ) ) ) )
  395. {
  396. // we've seen this certificate before; update the tally
  397. pLicense->m_lQuantity += ( Level ? pLicenseInfo1->Quantity : pLicenseInfo0->Quantity );
  398. break;
  399. }
  400. }
  401. if ( i >= m_licenseArray.GetSize() )
  402. {
  403. // we haven't seen this certificate yet; create a new license for it
  404. if ( 1 == Level )
  405. {
  406. pLicense = new CLicense( pLicenseInfo1->Product,
  407. pLicenseInfo1->Vendor,
  408. pLicenseInfo1->Admin,
  409. pLicenseInfo1->Date,
  410. pLicenseInfo1->Quantity,
  411. pLicenseInfo1->Comment,
  412. pLicenseInfo1->AllowedModes,
  413. pLicenseInfo1->CertificateID,
  414. pLicenseInfo1->Source,
  415. pLicenseInfo1->ExpirationDate,
  416. pLicenseInfo1->MaxQuantity,
  417. pLicenseInfo1->Secrets );
  418. ::LlsFreeMemory( pLicenseInfo1->Product );
  419. ::LlsFreeMemory( pLicenseInfo1->Admin );
  420. ::LlsFreeMemory( pLicenseInfo1->Comment );
  421. ::LlsFreeMemory( pLicenseInfo1->Source );
  422. }
  423. else
  424. {
  425. ASSERT( 0 == Level );
  426. pLicense = new CLicense( pLicenseInfo0->Product,
  427. TEXT( "Microsoft" ),
  428. pLicenseInfo0->Admin,
  429. pLicenseInfo0->Date,
  430. pLicenseInfo0->Quantity,
  431. pLicenseInfo0->Comment );
  432. ::LlsFreeMemory( pLicenseInfo0->Product );
  433. ::LlsFreeMemory( pLicenseInfo0->Admin );
  434. ::LlsFreeMemory( pLicenseInfo0->Comment );
  435. }
  436. if ( NULL == pLicense )
  437. {
  438. NtStatus = ERROR_OUTOFMEMORY;
  439. break;
  440. }
  441. m_licenseArray.Add( pLicense );
  442. }
  443. }
  444. pLicenseInfo1++;
  445. pLicenseInfo0++;
  446. }
  447. ::LlsFreeMemory(ReturnBuffer);
  448. }
  449. } while ( STATUS_MORE_ENTRIES == NtStatus );
  450. theApp.SetLastLlsError( NtStatus ); // called api
  451. if ( STATUS_SUCCESS == NtStatus )
  452. {
  453. // add per server entries
  454. LPTSTR pszServerName = m_strServerName.GetBuffer(0);
  455. if ( NULL != pszServerName )
  456. {
  457. BeginWaitCursor();
  458. HKEY hKeyLocalMachine;
  459. NtStatus = RegConnectRegistry( pszServerName, HKEY_LOCAL_MACHINE, &hKeyLocalMachine );
  460. if ( ERROR_SUCCESS != NtStatus )
  461. {
  462. theApp.SetLastError( NtStatus );
  463. }
  464. else
  465. {
  466. HKEY hKeyLicenseInfo;
  467. NtStatus = RegOpenKeyEx( hKeyLocalMachine, TEXT( "SYSTEM\\CurrentControlSet\\Services\\LicenseInfo" ), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_SET_VALUE, &hKeyLicenseInfo );
  468. if ( ERROR_SUCCESS != NtStatus )
  469. {
  470. theApp.SetLastError( NtStatus );
  471. }
  472. else
  473. {
  474. NTSTATUS ntEnum;
  475. BOOL bFoundKey = FALSE;
  476. DWORD iSubKey = 0;
  477. // if the service is 3.51-style per server, add it to the list
  478. do
  479. {
  480. TCHAR szKeyName[ 128 ];
  481. DWORD cchKeyName = sizeof( szKeyName ) / sizeof( *szKeyName );
  482. ntEnum = RegEnumKeyEx( hKeyLicenseInfo, iSubKey++, szKeyName, &cchKeyName, NULL, NULL, NULL, NULL );
  483. if ( ERROR_SUCCESS == ntEnum )
  484. {
  485. HKEY hKeyProduct;
  486. NtStatus = RegOpenKeyEx( hKeyLicenseInfo, szKeyName, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hKeyProduct );
  487. if ( ERROR_SUCCESS == NtStatus )
  488. {
  489. DWORD dwType;
  490. TCHAR szDisplayName[ 128 ];
  491. DWORD cbDisplayName = sizeof( szDisplayName );
  492. NtStatus = RegQueryValueEx( hKeyProduct, TEXT( "DisplayName" ), NULL, &dwType, (LPBYTE) szDisplayName, &cbDisplayName );
  493. if ( ERROR_SUCCESS == NtStatus )
  494. {
  495. // is this product secure?
  496. BOOL bIsSecure = FALSE;
  497. if ( LlsCapabilityIsSupported( m_hLls, LLS_CAPABILITY_SECURE_CERTIFICATES ) )
  498. {
  499. NtStatus = ::LlsProductSecurityGet( m_hLls, szDisplayName, &bIsSecure );
  500. theApp.SetLastLlsError( NtStatus );
  501. if ( STATUS_SUCCESS != NtStatus )
  502. {
  503. bIsSecure = FALSE;
  504. }
  505. }
  506. if ( !bIsSecure )
  507. {
  508. #ifdef REMOVE_CONCURRENT_ONLY_IF_PER_SERVER_MODE
  509. // not secure; is it in per server mode?
  510. DWORD dwMode;
  511. DWORD cbMode = sizeof( dwMode );
  512. NtStatus = RegQueryValueEx( hKeyProduct, TEXT( "Mode" ), NULL, &dwType, (LPBYTE) &dwMode, &cbMode );
  513. if ( ( ERROR_SUCCESS == NtStatus ) && dwMode )
  514. {
  515. // per server mode; add to list
  516. #endif
  517. DWORD dwConcurrentLimit;
  518. DWORD cbConcurrentLimit = sizeof( dwConcurrentLimit );
  519. NtStatus = RegQueryValueEx( hKeyProduct, TEXT( "ConcurrentLimit" ), NULL, &dwType, (LPBYTE) &dwConcurrentLimit, &cbConcurrentLimit );
  520. if ( ( ERROR_SUCCESS == NtStatus )
  521. && ( 0 < dwConcurrentLimit )
  522. && ( m_strProductName.IsEmpty() || !m_strProductName.CompareNoCase( szDisplayName ) )
  523. && ( m_strSourceToUse.IsEmpty() || !m_strSourceToUse.CompareNoCase( TEXT("None") ) ) )
  524. {
  525. CLicense * pLicense = new CLicense( szDisplayName,
  526. TEXT(""),
  527. TEXT(""),
  528. 0,
  529. dwConcurrentLimit,
  530. TEXT(""),
  531. LLS_LICENSE_MODE_ALLOW_PER_SERVER );
  532. if ( NULL != pLicense )
  533. {
  534. m_licenseArray.Add( pLicense );
  535. }
  536. }
  537. }
  538. #ifdef REMOVE_CONCURRENT_ONLY_IF_PER_SERVER_MODE
  539. }
  540. #endif
  541. }
  542. RegCloseKey( hKeyProduct );
  543. }
  544. }
  545. } while ( ERROR_SUCCESS == ntEnum );
  546. RegCloseKey( hKeyLicenseInfo );
  547. }
  548. RegCloseKey( hKeyLocalMachine );
  549. }
  550. m_strServerName.ReleaseBuffer();
  551. }
  552. EndWaitCursor();
  553. m_bLicensesRefreshed = TRUE;
  554. // remove any entries from the list that aren't removable
  555. for ( int i=0; i < m_licenseArray.GetSize(); )
  556. {
  557. CLicense* pLicense = (CLicense*) m_licenseArray[ i ];
  558. VALIDATE_OBJECT( pLicense, CLicense );
  559. if ( pLicense->m_lQuantity <= 0 )
  560. {
  561. delete pLicense;
  562. m_licenseArray.RemoveAt( i );
  563. }
  564. else
  565. {
  566. i++;
  567. }
  568. }
  569. }
  570. else
  571. {
  572. theApp.DisplayLastError();
  573. ResetLicenses();
  574. }
  575. }
  576. return m_bLicensesRefreshed;
  577. }
  578. BOOL CCertRemoveSelectDlg::RefreshCertificateList()
  579. /*++
  580. Routine Description:
  581. Refresh certificate list view from internal license list.
  582. Arguments:
  583. None.
  584. Return Values:
  585. BOOL.
  586. --*/
  587. {
  588. BeginWaitCursor();
  589. BOOL ok = ::LvRefreshObArray( &m_listCertificates, &g_removeColumnInfo, &m_licenseArray );
  590. EndWaitCursor();
  591. return ok;
  592. }
  593. int CALLBACK CompareLicenses(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  594. /*++
  595. Routine Description:
  596. Notification handler for LVM_SORTITEMS.
  597. Arguments:
  598. lParam1 - object to sort.
  599. lParam2 - object to sort.
  600. lParamSort - sort criteria.
  601. Return Values:
  602. Same as lstrcmp.
  603. --*/
  604. {
  605. CLicense * pLic1 = (CLicense *) lParam1;
  606. CLicense * pLic2 = (CLicense *) lParam2;
  607. VALIDATE_OBJECT( pLic1, CLicense );
  608. VALIDATE_OBJECT( pLic2, CLicense );
  609. int iResult;
  610. switch (g_removeColumnInfo.nSortedItem)
  611. {
  612. case LVID_REMOVE_SERIAL_NUMBER:
  613. iResult = pLic1->m_dwCertificateID - pLic2->m_dwCertificateID;
  614. break;
  615. case LVID_REMOVE_PRODUCT_NAME:
  616. iResult = pLic1->m_strProduct.CompareNoCase( pLic2->m_strProduct );
  617. break;
  618. case LVID_REMOVE_NUM_LICENSES:
  619. iResult = pLic1->m_lQuantity - pLic2->m_lQuantity;
  620. break;
  621. case LVID_REMOVE_SOURCE:
  622. iResult = pLic1->GetSourceDisplayName().CompareNoCase( pLic2->GetSourceDisplayName() );
  623. break;
  624. default:
  625. iResult = 0;
  626. break;
  627. }
  628. return g_removeColumnInfo.bSortOrder ? -iResult : iResult;
  629. }
  630. void CCertRemoveSelectDlg::UpdateSpinControlRange()
  631. /*++
  632. Routine Description:
  633. Update range of spin control for number of licenses.
  634. Arguments:
  635. None.
  636. Return Values:
  637. None.
  638. --*/
  639. {
  640. CLicense * pLicense;
  641. UpdateData( TRUE );
  642. if ( pLicense = (CLicense*)::LvGetSelObj( &m_listCertificates ) )
  643. {
  644. m_spinLicenses.SetRange( 1, pLicense->m_lQuantity );
  645. m_nLicenses = pLicense->m_lQuantity;
  646. GetDlgItem( IDOK )->EnableWindow( TRUE );
  647. }
  648. else
  649. {
  650. m_spinLicenses.SetRange( 0, 0 );
  651. m_nLicenses = 0;
  652. GetDlgItem( IDOK )->EnableWindow( FALSE );
  653. }
  654. UpdateData( FALSE );
  655. }
  656. DWORD CCertRemoveSelectDlg::RemoveSelectedCertificate()
  657. /*++
  658. Routine Description:
  659. Remove the given number of licenses from the selected certificate.
  660. Arguments:
  661. None.
  662. Return Values:
  663. ERROR_SUCCESS
  664. NT status code
  665. Win error
  666. --*/
  667. {
  668. NTSTATUS nt = STATUS_SUCCESS;
  669. if ( UpdateData( TRUE ) )
  670. {
  671. BOOL bDisplayError = TRUE;
  672. CLicense * pLicense;
  673. if ( !( pLicense = (CLicense*)::LvGetSelObj( &m_listCertificates ) ) )
  674. {
  675. // no certificate selected
  676. bDisplayError = FALSE;
  677. }
  678. else if ( ( m_nLicenses < 1 ) || ( m_nLicenses > pLicense->m_lQuantity ) )
  679. {
  680. // invalid number of licenses to remove
  681. AfxMessageBox( IDS_REMOVE_INVALID_NUM_LICENSES, MB_ICONEXCLAMATION | MB_OK, 0 );
  682. nt = ERROR_CANCELLED;
  683. bDisplayError = FALSE;
  684. }
  685. else
  686. {
  687. CString strLicenses;
  688. CString strConfirm;
  689. strLicenses.Format( TEXT("%d"), m_nLicenses );
  690. AfxFormatString2( strConfirm, IDS_REMOVE_CERTIFICATE_CONFIRM, strLicenses, pLicense->m_strProduct );
  691. int nResponse = AfxMessageBox( strConfirm, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2 );
  692. if ( IDYES != nResponse )
  693. {
  694. nt = ERROR_CANCELLED;
  695. bDisplayError = FALSE;
  696. }
  697. else
  698. {
  699. // delete certificate
  700. LPSTR pszAscServerName = (LPSTR) LocalAlloc( LMEM_FIXED, 1 + m_strServerName.GetLength() );
  701. LPSTR pszAscProductName = (LPSTR) LocalAlloc( LMEM_FIXED, 1 + pLicense->m_strProduct.GetLength() );
  702. LPSTR pszAscVendor = (LPSTR) LocalAlloc( LMEM_FIXED, 1 + m_strVendor.GetLength() );
  703. CString cstrClose;
  704. cstrClose.LoadString( IDS_CLOSETEXT );
  705. CWnd *pWnd = GetDlgItem( IDCANCEL );
  706. if( pWnd != NULL )
  707. {
  708. pWnd->SetWindowText( cstrClose );
  709. }
  710. if ( ( NULL == pszAscServerName ) || ( NULL == pszAscProductName ) || ( NULL == pszAscVendor ) )
  711. {
  712. nt = ERROR_NOT_ENOUGH_MEMORY;
  713. }
  714. else
  715. {
  716. wsprintfA( pszAscServerName, "%ls", (LPCWSTR) m_strServerName );
  717. wsprintfA( pszAscProductName, "%ls", (LPCWSTR) pLicense->m_strProduct );
  718. wsprintfA( pszAscVendor, "%ls", (LPCWSTR) m_strVendor );
  719. LLS_LICENSE_INFO_1 lic;
  720. nt = pLicense->CreateLicenseInfo( &lic );
  721. if ( STATUS_SUCCESS == nt )
  722. {
  723. // only remove as many licenses as requested
  724. lic.Quantity = m_nLicenses;
  725. if ( !pLicense->m_strSource.CompareNoCase( TEXT( "None" ) ) )
  726. {
  727. nt = NoCertificateRemove( m_hWnd, pszAscServerName, m_dwRemoveFlags, 1, &lic );
  728. bDisplayError = FALSE;
  729. }
  730. else
  731. {
  732. // get certificate source DLL path
  733. CString strKeyName = TEXT( "Software\\LSAPI\\Microsoft\\CertificateSources\\" )
  734. + pLicense->m_strSource;
  735. HKEY hKeySource;
  736. nt = RegOpenKeyEx( HKEY_LOCAL_MACHINE, strKeyName, 0, KEY_READ, &hKeySource );
  737. if ( ( ERROR_PATH_NOT_FOUND == nt ) || ( ERROR_FILE_NOT_FOUND == nt ) )
  738. {
  739. AfxMessageBox( IDS_CERT_SOURCE_NOT_AVAILABLE, MB_ICONSTOP | MB_OK, 0 );
  740. nt = ERROR_CANCELLED;
  741. bDisplayError = FALSE;
  742. }
  743. else if ( ERROR_SUCCESS == nt )
  744. {
  745. TCHAR szImagePath[ 1 + _MAX_PATH ];
  746. DWORD cbImagePath = sizeof( szImagePath );
  747. DWORD dwType;
  748. nt = RegQueryValueEx( hKeySource, TEXT( "ImagePath" ), NULL, &dwType, (LPBYTE) szImagePath, &cbImagePath );
  749. if ( ERROR_SUCCESS == nt )
  750. {
  751. TCHAR szExpandedImagePath[ 1 + _MAX_PATH ];
  752. BOOL ok = ExpandEnvironmentStrings( szImagePath, szExpandedImagePath, sizeof( szExpandedImagePath ) / sizeof( *szExpandedImagePath ) );
  753. if ( !ok )
  754. {
  755. nt = GetLastError();
  756. }
  757. else
  758. {
  759. // load certificate source DLL
  760. HINSTANCE hDll = ::LoadLibrary( szExpandedImagePath );
  761. if ( NULL == hDll )
  762. {
  763. nt = GetLastError();
  764. }
  765. else
  766. {
  767. // get certificate remove function
  768. CHAR szExportName[ 256 ];
  769. PCCF_REMOVE_API pRemoveFn;
  770. wsprintfA( szExportName, "%lsCertificateRemove", (LPCWSTR) pLicense->m_strSource );
  771. pRemoveFn = (PCCF_REMOVE_API) GetProcAddress( hDll, szExportName );
  772. if ( NULL == pRemoveFn )
  773. {
  774. nt = GetLastError();
  775. }
  776. else
  777. {
  778. // remove certificate
  779. nt = (*pRemoveFn)( m_hWnd, pszAscServerName, m_dwRemoveFlags, 1, &lic );
  780. bDisplayError = FALSE;
  781. }
  782. ::FreeLibrary( hDll );
  783. }
  784. }
  785. }
  786. RegCloseKey( hKeySource );
  787. }
  788. }
  789. pLicense->DestroyLicenseInfo( &lic );
  790. }
  791. }
  792. if ( NULL != pszAscServerName ) LocalFree( pszAscServerName );
  793. if ( NULL != pszAscProductName ) LocalFree( pszAscProductName );
  794. if ( NULL != pszAscVendor ) LocalFree( pszAscVendor );
  795. RefreshLicenses();
  796. RefreshCertificateList();
  797. UpdateSpinControlRange();
  798. }
  799. }
  800. if ( bDisplayError && ( ERROR_SUCCESS != nt ) )
  801. {
  802. theApp.SetLastError( nt );
  803. theApp.DisplayLastError();
  804. }
  805. }
  806. return nt;
  807. }
  808. BOOL CCertRemoveSelectDlg::ConnectServer()
  809. /*++
  810. Routine Description:
  811. Establish a connection to the license service on the target server.
  812. Arguments:
  813. None.
  814. Return Values:
  815. BOOL.
  816. --*/
  817. {
  818. if ( NULL == m_hLls )
  819. {
  820. LPTSTR pszServerName;
  821. if ( m_strServerName.IsEmpty() )
  822. {
  823. pszServerName = NULL;
  824. }
  825. else
  826. {
  827. pszServerName = m_strServerName.GetBuffer( 0 );
  828. }
  829. ConnectTo( pszServerName, &m_hLls );
  830. if ( NULL != pszServerName )
  831. {
  832. m_strServerName.ReleaseBuffer();
  833. }
  834. }
  835. if ( NULL == m_hLls )
  836. {
  837. theApp.DisplayLastError();
  838. if ( ( NULL != m_hWnd ) && IsWindow( m_hWnd ) )
  839. {
  840. EndDialog( IDABORT );
  841. }
  842. }
  843. return ( NULL != m_hLls );
  844. }
  845. NTSTATUS CCertRemoveSelectDlg::ConnectTo( LPTSTR pszServerName, PLLS_HANDLE phLls )
  846. /*++
  847. Routine Description:
  848. Establish a connection to the license service on the given server.
  849. Arguments:
  850. pszServerName (CString)
  851. The target server. An empty value indicates the local server.
  852. phLls (PLLS_HANDLE)
  853. On return, holds the handle to the standard LLS RPC.
  854. Return Values:
  855. STATUS_SUCCESS or NT status code.
  856. --*/
  857. {
  858. NTSTATUS nt;
  859. nt = ::LlsConnect( pszServerName, phLls );
  860. theApp.SetLastLlsError( nt );
  861. if ( STATUS_SUCCESS != nt )
  862. {
  863. *phLls = NULL;
  864. }
  865. return nt;
  866. }
  867. void CCertRemoveSelectDlg::OnClickCertificateList(NMHDR* pNMHDR, LRESULT* pResult)
  868. /*++
  869. Routine Description:
  870. Handler for NM_CLICK of certificate list view.
  871. Arguments:
  872. pNMHDR (NMHDR*)
  873. pResult (LRESULT*)
  874. Return Values:
  875. None.
  876. --*/
  877. {
  878. UpdateSpinControlRange();
  879. *pResult = 1; // not handled...
  880. }
  881. void CCertRemoveSelectDlg::OnKeyDownCertificateList(NMHDR* pNMHDR, LRESULT* pResult)
  882. /*++
  883. Routine Description:
  884. Handler for LVN_KEYDOWN of certificate list view.
  885. Arguments:
  886. pNMHDR (NMHDR*)
  887. pResult (LRESULT*)
  888. Return Values:
  889. None.
  890. --*/
  891. {
  892. UpdateSpinControlRange();
  893. *pResult = 1; // not handled...
  894. }
  895. BOOL CCertRemoveSelectDlg::LoadImages()
  896. /*++
  897. Routine Description:
  898. Load icons for the list view.
  899. Arguments:
  900. None.
  901. Return Values:
  902. BOOL.
  903. --*/
  904. {
  905. BOOL bImagesLoaded = m_smallImages.Create( IDB_SMALL_ICONS, BMPI_SMALL_SIZE, 0, BMPI_RGB_BKGND );
  906. ASSERT( bImagesLoaded );
  907. return bImagesLoaded;
  908. }
  909. void CCertRemoveSelectDlg::OnRefresh()
  910. /*++
  911. Routine Description:
  912. Handler for BN_CLICK of refresh button.
  913. Arguments:
  914. None.
  915. Return Values:
  916. None.
  917. --*/
  918. {
  919. RefreshLicenses();
  920. RefreshCertificateList();
  921. UpdateSpinControlRange();
  922. }
  923. DWORD CCertRemoveSelectDlg::CertificateRemove( LPCSTR pszServerName, LPCSTR pszProductName, LPCSTR pszVendor, DWORD dwFlags, LPCSTR pszSourceToUse )
  924. /*++
  925. Routine Description:
  926. Display a dialog allowing the user to remove one or more license
  927. certificates from the system.
  928. Arguments:
  929. pszServerName (LPCSTR)
  930. Name of the server on which licenses are to be removed. A NULL value
  931. indicates the local server.
  932. pszProductName (LPCSTR)
  933. Product for which licenses are to be removed. A NULL value indicates
  934. that the user should be allowed to remove licenses from any product.
  935. pszVendor (LPCSTR)
  936. Name of the vendor of the product. This value should be NULL if
  937. pszProductName is NULL, and should be non-NULL if pszProductName is
  938. non-NULL.
  939. dwFlags (DWORD)
  940. Certificate removal options. As of this writing, no flags are
  941. supported.
  942. pszSourceToUse (LPCSTR)
  943. Name of the secure certificate source by which licenses are to be
  944. removed, e.g., "Paper". A NULL value indicates that the user should
  945. be allowed to remove licenses that were installed with any source.
  946. Return Value:
  947. ERROR_SUCCESS
  948. Win error
  949. --*/
  950. {
  951. m_strServerName = pszServerName ? pszServerName : "";
  952. m_strProductName = pszProductName ? pszProductName : "";
  953. m_strVendor = pszVendor ? pszVendor : "";
  954. m_dwRemoveFlags = dwFlags;
  955. m_strSourceToUse = pszSourceToUse ? pszSourceToUse : "";
  956. DoModal();
  957. return ERROR_SUCCESS;
  958. }