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.

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