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.

1393 lines
30 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. paper.cpp
  5. Abstract:
  6. Paper certificate dialog implementation.
  7. Author:
  8. Jeff Parham (jeffparh) 13-Dec-1995
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #include <stdlib.h>
  13. #include "resource.h"
  14. #include "ccfapi.h"
  15. #include "paper.h"
  16. #include "md4.h"
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char BASED_CODE THIS_FILE[] = __FILE__;
  20. #endif
  21. static void MD4UpdateDword( MD4_CTX * pCtx, DWORD dwValue );
  22. CPaperSourceDlg::CPaperSourceDlg(CWnd* pParent /*=NULL*/)
  23. : CDialog(CPaperSourceDlg::IDD, pParent)
  24. /*++
  25. Routine Description:
  26. Constructor for dialog.
  27. Arguments:
  28. pParent - owner window.
  29. Return Values:
  30. None.
  31. --*/
  32. {
  33. //{{AFX_DATA_INIT(CPaperSourceDlg)
  34. m_strActivationCode = _T("");
  35. m_strKeyCode = _T("");
  36. m_strSerialNumber = _T("");
  37. m_strVendor = _T("");
  38. m_strProductName = _T("");
  39. m_strComment = _T("");
  40. m_nDontInstallAllLicenses = -1;
  41. m_nLicenses = 0;
  42. m_nLicenseMode = -1;
  43. //}}AFX_DATA_INIT
  44. m_bProductListRetrieved = FALSE;
  45. m_hLls = NULL;
  46. m_hEnterpriseLls = NULL;
  47. m_dwEnterFlags = 0;
  48. m_nLicenses = 1;
  49. m_nDontInstallAllLicenses = 0;
  50. m_strServerName = _T("");
  51. }
  52. CPaperSourceDlg::~CPaperSourceDlg()
  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. if ( NULL != m_hEnterpriseLls )
  67. {
  68. LlsClose( m_hEnterpriseLls );
  69. }
  70. }
  71. void CPaperSourceDlg::DoDataExchange(CDataExchange* pDX)
  72. /*++
  73. Routine Description:
  74. Called by framework to exchange dialog data.
  75. Arguments:
  76. pDX - data exchange object.
  77. Return Values:
  78. None.
  79. --*/
  80. {
  81. CDialog::DoDataExchange(pDX);
  82. //{{AFX_DATA_MAP(CPaperSourceDlg)
  83. DDX_Control(pDX, IDC_SPIN_LICENSES, m_spinLicenses);
  84. DDX_Control(pDX, IDC_PRODUCT_NAME, m_cboxProductName);
  85. DDX_Text(pDX, IDC_ACTIVATION_CODE, m_strActivationCode);
  86. DDX_Text(pDX, IDC_KEY_CODE, m_strKeyCode);
  87. DDX_Text(pDX, IDC_SERIAL_NUMBER, m_strSerialNumber);
  88. DDX_Text(pDX, IDC_VENDOR, m_strVendor);
  89. DDX_CBString(pDX, IDC_PRODUCT_NAME, m_strProductName);
  90. DDX_Text(pDX, IDC_COMMENT, m_strComment);
  91. DDX_Radio(pDX, IDC_ALL_LICENSES, m_nDontInstallAllLicenses);
  92. DDX_Text(pDX, IDC_NUM_LICENSES, m_nLicenses);
  93. DDX_Radio(pDX, IDC_PER_SEAT, m_nLicenseMode);
  94. //}}AFX_DATA_MAP
  95. }
  96. BEGIN_MESSAGE_MAP(CPaperSourceDlg, CDialog)
  97. //{{AFX_MSG_MAP(CPaperSourceDlg)
  98. ON_EN_UPDATE(IDC_ACTIVATION_CODE, OnUpdateActivationCode)
  99. ON_EN_UPDATE(IDC_KEY_CODE, OnUpdateKeyCode)
  100. ON_EN_UPDATE(IDC_VENDOR, OnUpdateVendor)
  101. ON_EN_UPDATE(IDC_SERIAL_NUMBER, OnUpdateSerialNumber)
  102. ON_CBN_EDITUPDATE(IDC_PRODUCT_NAME, OnUpdateProductName)
  103. ON_CBN_DROPDOWN(IDC_PRODUCT_NAME, OnDropDownProductName)
  104. ON_BN_CLICKED(IDC_MY_HELP, OnHelp)
  105. ON_WM_DESTROY()
  106. ON_BN_CLICKED(IDC_ALL_LICENSES, OnAllLicenses)
  107. ON_BN_CLICKED(IDC_SOME_LICENSES, OnSomeLicenses)
  108. ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_LICENSES, OnDeltaPosSpinLicenses)
  109. //}}AFX_MSG_MAP
  110. END_MESSAGE_MAP()
  111. void CPaperSourceDlg::OnUpdateActivationCode()
  112. /*++
  113. Routine Description:
  114. Message handler for EN_UPDATE of activation code.
  115. Arguments:
  116. None.
  117. Return Values:
  118. None.
  119. --*/
  120. {
  121. EnableOrDisableOK();
  122. }
  123. void CPaperSourceDlg::OnUpdateKeyCode()
  124. /*++
  125. Routine Description:
  126. Message handler for EN_UPDATE of key code.
  127. Arguments:
  128. None.
  129. Return Values:
  130. None.
  131. --*/
  132. {
  133. EnableOrDisableOK();
  134. }
  135. void CPaperSourceDlg::OnUpdateProductName()
  136. /*++
  137. Routine Description:
  138. Message handler for EN_UPDATE of product name.
  139. Arguments:
  140. None.
  141. Return Values:
  142. None.
  143. --*/
  144. {
  145. EnableOrDisableOK();
  146. }
  147. void CPaperSourceDlg::OnUpdateSerialNumber()
  148. /*++
  149. Routine Description:
  150. Message handler for EN_UPDATE of serial number.
  151. Arguments:
  152. None.
  153. Return Values:
  154. None.
  155. --*/
  156. {
  157. EnableOrDisableOK();
  158. }
  159. void CPaperSourceDlg::OnUpdateVendor()
  160. /*++
  161. Routine Description:
  162. Message handler for EN_UPDATE of vendor.
  163. Arguments:
  164. None.
  165. Return Values:
  166. None.
  167. --*/
  168. {
  169. EnableOrDisableOK();
  170. }
  171. void CPaperSourceDlg::EnableOrDisableOK()
  172. /*++
  173. Routine Description:
  174. Enable or diable OK button depending upon whether all necessary dialog data
  175. has been supplied by the user.
  176. Arguments:
  177. None.
  178. Return Values:
  179. None.
  180. --*/
  181. {
  182. BOOL bEnableOK;
  183. UpdateData( TRUE );
  184. bEnableOK = !m_strActivationCode.IsEmpty()
  185. && !m_strKeyCode.IsEmpty()
  186. && !m_strProductName.IsEmpty()
  187. && !m_strSerialNumber.IsEmpty()
  188. && !m_strVendor.IsEmpty()
  189. && ( ( 0 == m_nLicenseMode )
  190. || ( 1 == m_nLicenseMode ) );
  191. GetDlgItem( IDOK )->EnableWindow( bEnableOK );
  192. }
  193. BOOL CPaperSourceDlg::OnInitDialog()
  194. /*++
  195. Routine Description:
  196. Handler for WM_INITDIALOG.
  197. Arguments:
  198. None.
  199. Return Values:
  200. Returns false if focus set manually.
  201. --*/
  202. {
  203. CDialog::OnInitDialog();
  204. EnableOrDisableOK();
  205. if ( m_nDontInstallAllLicenses )
  206. {
  207. OnSomeLicenses();
  208. }
  209. else
  210. {
  211. OnAllLicenses();
  212. }
  213. m_spinLicenses.SetRange( 1, MAX_NUM_LICENSES );
  214. // ghost out items that were passed to us from the application
  215. if ( !m_strProductName.IsEmpty() )
  216. GetDlgItem( IDC_PRODUCT_NAME )->EnableWindow( FALSE );
  217. if ( !m_strVendor.IsEmpty() )
  218. GetDlgItem( IDC_VENDOR )->EnableWindow( FALSE );
  219. // if license mode set by application, don't let user change it
  220. if ( m_dwEnterFlags & ( CCF_ENTER_FLAG_PER_SEAT_ONLY | CCF_ENTER_FLAG_PER_SERVER_ONLY ) )
  221. {
  222. m_nLicenseMode = ( m_dwEnterFlags & CCF_ENTER_FLAG_PER_SEAT_ONLY ) ? 0 : 1;
  223. GetDlgItem( IDC_PER_SERVER )->EnableWindow( FALSE );
  224. GetDlgItem( IDC_PER_SEAT )->EnableWindow( FALSE );
  225. UpdateData( FALSE );
  226. }
  227. return TRUE;
  228. }
  229. void CPaperSourceDlg::OnOK()
  230. /*++
  231. Routine Description:
  232. Creates a new license for product.
  233. Arguments:
  234. None.
  235. Return Values:
  236. None.
  237. --*/
  238. {
  239. NTSTATUS nt;
  240. if( UpdateData( TRUE ) )
  241. {
  242. // verify activation code
  243. DWORD nActivationCode = wcstoul( m_strActivationCode, NULL, 16 );
  244. if ( nActivationCode != ComputeActivationCode() )
  245. {
  246. AfxMessageBox( IDS_BAD_ACTIVATION_CODE, MB_ICONEXCLAMATION | MB_OK, 0 );
  247. }
  248. else if ( ( m_nLicenses < 1 ) || ( m_nLicenses > MAX_NUM_LICENSES ) )
  249. {
  250. AfxMessageBox( IDS_INVALID_NUM_LICENSES, MB_ICONEXCLAMATION | MB_OK, 0 );
  251. GetDlgItem( IDC_NUM_LICENSES )->SetActiveWindow();
  252. }
  253. else
  254. {
  255. DWORD dwKeyCode = KEY_CODE_MASK ^ wcstoul( m_strKeyCode, NULL, 10 );
  256. if ( m_nDontInstallAllLicenses
  257. && ( (DWORD)m_nLicenses > KeyCodeToNumLicenses( dwKeyCode ) ) )
  258. {
  259. // can't install more licenses than are in the certificate
  260. AfxMessageBox( IDS_NOT_ENOUGH_LICENSES_ON_CERTIFICATE, MB_ICONEXCLAMATION | MB_OK, 0 );
  261. GetDlgItem( IDC_NUM_LICENSES )->SetActiveWindow();
  262. }
  263. else if ( !( ( 1 << m_nLicenseMode ) & KeyCodeToModesAllowed( dwKeyCode ) ) )
  264. {
  265. // can't install certificate in a mode that's not allowed by the key code
  266. AfxMessageBox( IDS_LICENSE_MODE_NOT_ALLOWED, MB_ICONEXCLAMATION | MB_OK, 0 );
  267. GetDlgItem( IDC_PER_SEAT )->SetActiveWindow();
  268. }
  269. else
  270. {
  271. nt = AddLicense();
  272. if ( STATUS_SUCCESS == nt )
  273. {
  274. CDialog::OnOK();
  275. }
  276. else if ( ( ERROR_CANCELLED != nt ) && ( STATUS_CANCELLED != nt ) )
  277. {
  278. AbortDialogIfNecessary();
  279. }
  280. }
  281. }
  282. }
  283. }
  284. void CPaperSourceDlg::GetProductList()
  285. /*++
  286. Routine Description:
  287. Retrieves the list of installed product from the license server.
  288. Arguments:
  289. None.
  290. Return Values:
  291. None.
  292. --*/
  293. {
  294. if ( ConnectServer() )
  295. {
  296. // save edit selection
  297. UpdateData( TRUE );
  298. // get list of products from license server, inserting into listbox
  299. m_cboxProductName.ResetContent();
  300. DWORD dwResumeHandle = 0;
  301. DWORD dwTotalEntries;
  302. DWORD dwEntriesRead;
  303. NTSTATUS nt;
  304. do
  305. {
  306. LPBYTE pReturnBuffer = NULL;
  307. nt = ::LlsProductEnum( m_hLls,
  308. 0,
  309. &pReturnBuffer,
  310. LLS_PREFERRED_LENGTH,
  311. &dwEntriesRead,
  312. &dwTotalEntries,
  313. &dwResumeHandle );
  314. theApp.SetLastLlsError( nt );
  315. if ( ( STATUS_SUCCESS == nt ) || ( STATUS_MORE_ENTRIES == nt ) )
  316. {
  317. LLS_PRODUCT_INFO_0 * pProductInfo = (LLS_PRODUCT_INFO_0 *) pReturnBuffer;
  318. for ( DWORD i=0; i < dwEntriesRead; i++ )
  319. {
  320. m_cboxProductName.AddString( pProductInfo[i].Product );
  321. ::LlsFreeMemory( pProductInfo->Product );
  322. }
  323. ::LlsFreeMemory( pProductInfo );
  324. }
  325. } while ( STATUS_MORE_ENTRIES == nt );
  326. if ( STATUS_SUCCESS != nt )
  327. {
  328. // still connected?
  329. AbortDialogIfNecessary();
  330. }
  331. // restore previous edit selection
  332. UpdateData( FALSE );
  333. }
  334. }
  335. void CPaperSourceDlg::OnDropDownProductName()
  336. /*++
  337. Routine Description:
  338. Handler for CBN_DROPDOWN of product name combo box.
  339. Arguments:
  340. None.
  341. Return Values:
  342. None.
  343. --*/
  344. {
  345. if ( !m_bProductListRetrieved )
  346. {
  347. BeginWaitCursor();
  348. GetProductList();
  349. EndWaitCursor();
  350. m_bProductListRetrieved = TRUE;
  351. }
  352. }
  353. BOOL CPaperSourceDlg::ConnectServer()
  354. /*++
  355. Routine Description:
  356. Establish a connection to the license service on the target server.
  357. Arguments:
  358. None.
  359. Return Values:
  360. BOOL.
  361. --*/
  362. {
  363. if ( NULL == m_hLls )
  364. {
  365. ConnectTo( FALSE, m_strServerName, &m_hLls );
  366. if ( !LlsCapabilityIsSupported( m_hLls, LLS_CAPABILITY_SECURE_CERTIFICATES ) )
  367. {
  368. // we connected to the machine, but it doesn't support secure certificates
  369. // we should not get here under normal circumstances, since the select
  370. // source dialog should not allow the user to choose the paper source
  371. // under such circumstances
  372. LlsClose( m_hLls );
  373. m_hLls = NULL;
  374. theApp.SetLastLlsError( STATUS_INVALID_LEVEL );
  375. }
  376. if ( NULL == m_hLls )
  377. {
  378. theApp.DisplayLastError();
  379. EndDialog( IDABORT );
  380. }
  381. }
  382. return ( NULL != m_hLls );
  383. }
  384. BOOL CPaperSourceDlg::ConnectEnterprise()
  385. /*++
  386. Routine Description:
  387. Establish a connection to the license service on the enterprise server
  388. of the target server.
  389. Arguments:
  390. None.
  391. Return Values:
  392. BOOL.
  393. --*/
  394. {
  395. if ( NULL == m_hEnterpriseLls )
  396. {
  397. ConnectTo( !( m_dwEnterFlags & CCF_ENTER_FLAG_SERVER_IS_ES ), m_strServerName, &m_hEnterpriseLls );
  398. if ( NULL == m_hEnterpriseLls )
  399. {
  400. theApp.DisplayLastError();
  401. }
  402. }
  403. return ( NULL != m_hEnterpriseLls );
  404. }
  405. NTSTATUS CPaperSourceDlg::ConnectTo( BOOL bUseEnterprise, CString strServerName, PLLS_HANDLE phLls )
  406. /*++
  407. Routine Description:
  408. Establish a connection to the license service on the given server or that
  409. on the given server's enterprise server.
  410. Arguments:
  411. bUseEnterprise (BOOL)
  412. If TRUE, connect to the enterprise server of the target server, not to
  413. the target server itself.
  414. pszServerName (CString)
  415. The target server. An empty value indicates the local server.
  416. phLls (PLLS_HANDLE)
  417. On return, holds the handle to the standard LLS RPC.
  418. Return Values:
  419. STATUS_SUCCESS or NT status code.
  420. --*/
  421. {
  422. NTSTATUS nt = STATUS_SUCCESS;
  423. LPTSTR pszServerName = NULL;
  424. if ( !strServerName.IsEmpty() )
  425. {
  426. pszServerName = strServerName.GetBuffer(0);
  427. if ( NULL == pszServerName )
  428. {
  429. nt = ERROR_NOT_ENOUGH_MEMORY;
  430. }
  431. }
  432. if ( STATUS_SUCCESS == nt )
  433. {
  434. if ( !bUseEnterprise )
  435. {
  436. nt = ::LlsConnect( pszServerName, phLls );
  437. }
  438. else
  439. {
  440. PLLS_CONNECT_INFO_0 pConnect = NULL;
  441. nt = ::LlsConnectEnterprise( pszServerName, phLls, 0, (LPBYTE *) &pConnect );
  442. if ( STATUS_SUCCESS == nt )
  443. {
  444. ::LlsFreeMemory( pConnect );
  445. }
  446. }
  447. theApp.SetLastLlsError( nt );
  448. }
  449. if ( STATUS_SUCCESS != nt )
  450. {
  451. *phLls = NULL;
  452. }
  453. return nt;
  454. }
  455. void CPaperSourceDlg::OnHelp()
  456. /*++
  457. Routine Description:
  458. Handler for help button click.
  459. Arguments:
  460. None.
  461. Return Values:
  462. None.
  463. --*/
  464. {
  465. WinHelp( IDD, HELP_CONTEXT );
  466. }
  467. void CPaperSourceDlg::WinHelp(DWORD dwData, UINT nCmd)
  468. /*++
  469. Routine Description:
  470. Call WinHelp for this dialog.
  471. Arguments:
  472. dwData (DWORD)
  473. nCmd (UINT)
  474. Return Values:
  475. None.
  476. --*/
  477. {
  478. ::HtmlHelp(m_hWnd, L"liceconcepts.chm", HH_DISPLAY_TOPIC,0);
  479. /*
  480. BOOL ok = ::WinHelp( m_hWnd, theApp.GetHelpFileName(), nCmd, dwData );
  481. ASSERT( ok );
  482. */
  483. }
  484. void CPaperSourceDlg::OnDestroy()
  485. /*++
  486. Routine Description:
  487. Handler for WM_DESTROY.
  488. Arguments:
  489. None.
  490. Return Values:
  491. None.
  492. --*/
  493. {
  494. ::WinHelp( m_hWnd, theApp.GetHelpFileName(), HELP_QUIT, 0 );
  495. CDialog::OnDestroy();
  496. }
  497. void CPaperSourceDlg::AbortDialogIfNecessary()
  498. /*++
  499. Routine Description:
  500. Displays status and aborts if connection lost.
  501. Arguments:
  502. None.
  503. Return Values:
  504. None.
  505. --*/
  506. {
  507. theApp.DisplayLastError();
  508. if ( theApp.IsConnectionDropped() )
  509. {
  510. EndDialog( IDABORT );
  511. }
  512. }
  513. DWORD CPaperSourceDlg::ComputeActivationCode()
  514. /*++
  515. Routine Description:
  516. Return the computed activation code corresponding to the entered
  517. certificate.
  518. Arguments:
  519. None.
  520. Return Values:
  521. DWORD.
  522. --*/
  523. {
  524. MD4_CTX ctx;
  525. DWORD dw;
  526. UCHAR digest[ 16 ];
  527. DWORD adwCodeSeg[ sizeof( digest ) / sizeof( DWORD ) ];
  528. int nCodeSeg;
  529. int nCodeSegByte;
  530. DWORD dwActivationCode ;
  531. CHAR szAnsiName[ 128 ];
  532. MD4Init( &ctx );
  533. ZeroMemory( szAnsiName, sizeof( szAnsiName ) );
  534. wcstombs( szAnsiName, m_strProductName, sizeof( szAnsiName ) - 1 );
  535. MD4Update( &ctx, (LPBYTE)szAnsiName, strlen( szAnsiName ) );
  536. ZeroMemory( szAnsiName, sizeof( szAnsiName ) );
  537. wcstombs( szAnsiName, m_strVendor, sizeof( szAnsiName ) - 1 );
  538. MD4Update( &ctx, (LPBYTE)szAnsiName, strlen( szAnsiName ) );
  539. MD4UpdateDword( &ctx, 14721776 );
  540. MD4UpdateDword( &ctx, wcstoul( m_strSerialNumber, NULL, 10 ) );
  541. MD4UpdateDword( &ctx, 19721995 );
  542. MD4UpdateDword( &ctx, KEY_CODE_MASK ^ wcstoul( m_strKeyCode, NULL, 10 ) );
  543. MD4Final( &ctx );
  544. CopyMemory( digest, ctx.digest, sizeof(digest) );
  545. // convert digest into platform-independent array of DWORDs
  546. for ( nCodeSeg=0; nCodeSeg < sizeof( adwCodeSeg ) / sizeof( *adwCodeSeg ); nCodeSeg++ )
  547. {
  548. adwCodeSeg[ nCodeSeg ] = 0;
  549. for ( nCodeSegByte=0; nCodeSegByte < sizeof( *adwCodeSeg ); nCodeSegByte++ )
  550. {
  551. adwCodeSeg[ nCodeSeg ] <<= 8;
  552. adwCodeSeg[ nCodeSeg ] |= digest[ nCodeSeg * sizeof( *adwCodeSeg ) + nCodeSegByte ];
  553. }
  554. }
  555. dwActivationCode = ( adwCodeSeg[ 0 ] + adwCodeSeg[ 1 ] ) ^ ( adwCodeSeg[ 2 ] - adwCodeSeg[ 3 ] );
  556. return dwActivationCode;
  557. }
  558. NTSTATUS CPaperSourceDlg::AddLicense()
  559. /*++
  560. Routine Description:
  561. Enter a new license into the system.
  562. Arguments:
  563. None.
  564. Return Values:
  565. STATUS_SUCCESS
  566. ERROR_NOT_ENOUGH_MEMORY
  567. ERROR_CANCELLED
  568. NT status code
  569. Win error
  570. --*/
  571. {
  572. NTSTATUS nt;
  573. if ( !ConnectServer() )
  574. {
  575. nt = ERROR_CANCELLED;
  576. }
  577. else
  578. {
  579. LPTSTR pszProductName = m_strProductName.GetBuffer(0);
  580. LPTSTR pszServerName = m_strServerName.GetBuffer(0);
  581. LPTSTR pszComment = m_strComment.GetBuffer(0);
  582. LPTSTR pszVendor = m_strVendor.GetBuffer(0);
  583. if ( ( NULL == pszProductName ) || ( NULL == pszServerName ) || ( NULL == pszComment ) || ( NULL == pszVendor ) )
  584. {
  585. nt = ERROR_NOT_ENOUGH_MEMORY;
  586. }
  587. else
  588. {
  589. // handles for LLS on machine to receive licenses
  590. // (if per seat, these will be changed to correspond to the enterprise server)
  591. LLS_HANDLE hLls = NULL;
  592. if ( 0 == m_nLicenseMode )
  593. {
  594. // per seat mode; install on enterprise server
  595. BeginWaitCursor();
  596. BOOL ok = ConnectEnterprise();
  597. EndWaitCursor();
  598. if ( !ok )
  599. {
  600. // can't connect to enterprise server
  601. nt = ERROR_CANCELLED;
  602. }
  603. else if ( !LlsCapabilityIsSupported( m_hEnterpriseLls, LLS_CAPABILITY_SECURE_CERTIFICATES ) )
  604. {
  605. // enterprise server doesn't support secure certificates
  606. AfxMessageBox( IDS_ENTERPRISE_SERVER_BACKLEVEL_CANT_ADD_CERT, MB_ICONSTOP | MB_OK, 0 );
  607. nt = ERROR_CANCELLED;
  608. }
  609. else
  610. {
  611. hLls = m_hEnterpriseLls;
  612. nt = STATUS_SUCCESS;
  613. }
  614. }
  615. else
  616. {
  617. // per server mode; install on target server
  618. hLls = m_hLls;
  619. nt = STATUS_SUCCESS;
  620. }
  621. if ( STATUS_SUCCESS == nt )
  622. {
  623. TCHAR szUserName[ 64 ];
  624. DWORD cchUserName;
  625. BOOL ok;
  626. cchUserName = sizeof( szUserName ) / sizeof( *szUserName );
  627. ok = GetUserName( szUserName, &cchUserName );
  628. if ( !ok )
  629. {
  630. nt = GetLastError();
  631. }
  632. else
  633. {
  634. // enter certificate into system
  635. DWORD nKeyCode = KEY_CODE_MASK ^ wcstoul( m_strKeyCode, NULL, 10 );
  636. // --------- fill in certificate info ---------
  637. LLS_LICENSE_INFO_1 lic;
  638. ZeroMemory( &lic, sizeof( lic ) );
  639. lic.Product = pszProductName;
  640. lic.Vendor = pszVendor;
  641. lic.Comment = pszComment;
  642. lic.Admin = szUserName;
  643. lic.Quantity = m_nDontInstallAllLicenses ? m_nLicenses : KeyCodeToNumLicenses( nKeyCode );
  644. lic.Date = 0;
  645. lic.AllowedModes = 1 << m_nLicenseMode;
  646. lic.CertificateID = wcstoul( m_strSerialNumber, NULL, 10 );
  647. lic.Source = TEXT("Paper");
  648. lic.ExpirationDate = KeyCodeToExpirationDate( nKeyCode );
  649. lic.MaxQuantity = KeyCodeToNumLicenses( nKeyCode );
  650. BeginWaitCursor();
  651. nt = ::LlsLicenseAdd( hLls, 1, (LPBYTE) &lic );
  652. theApp.SetLastLlsError( nt );
  653. EndWaitCursor();
  654. if ( ( STATUS_OBJECT_NAME_EXISTS == nt )
  655. || ( STATUS_ALREADY_COMMITTED == nt ) )
  656. {
  657. LLS_HANDLE hLlsForTargets = NULL;
  658. // too many licenses of this certificate
  659. if ( STATUS_OBJECT_NAME_EXISTS == nt )
  660. {
  661. // denied by target's local database
  662. hLlsForTargets = hLls;
  663. }
  664. else if ( ConnectEnterprise() )
  665. {
  666. // denied by target's enterprise server; we're connected!
  667. hLlsForTargets = m_hEnterpriseLls;
  668. }
  669. if ( NULL == hLlsForTargets )
  670. {
  671. // denied by enterprise server, and can't connect to it (?!)
  672. AfxMessageBox( IDS_NET_LICENSES_ALREADY_INSTALLED, MB_ICONSTOP | MB_OK, 0 );
  673. }
  674. else
  675. {
  676. // too many licenses of this certificate exist in the enterprise
  677. LPBYTE ReturnBuffer = NULL;
  678. DWORD dwNumTargets = 0;
  679. // get list of machines on which licenses from this certificate have been installed
  680. nt = ::LlsCertificateClaimEnum( hLlsForTargets, 1, (LPBYTE) &lic, 0, &ReturnBuffer, &dwNumTargets );
  681. if ( ( STATUS_SUCCESS == nt ) && ( dwNumTargets > 0 ) )
  682. {
  683. PLLS_CERTIFICATE_CLAIM_INFO_0 pTarget = (PLLS_CERTIFICATE_CLAIM_INFO_0) ReturnBuffer;
  684. CString strLicenses;
  685. CString strTarget;
  686. CString strTargetList;
  687. while ( dwNumTargets-- )
  688. {
  689. strLicenses.Format( TEXT("%d"), pTarget->Quantity );
  690. AfxFormatString2( strTarget, IDS_NET_CERTIFICATE_TARGET_ENTRY, pTarget->ServerName, strLicenses );
  691. strTargetList = strTargetList.IsEmpty() ? strTarget : ( TEXT("\n") + strTarget );
  692. pTarget++;
  693. }
  694. CString strMessage;
  695. AfxFormatString1( strMessage, IDS_NET_LICENSES_ALREADY_INSTALLED_ON, strTargetList );
  696. AfxMessageBox( strMessage, MB_ICONSTOP | MB_OK );
  697. }
  698. else
  699. {
  700. AfxMessageBox( IDS_NET_LICENSES_ALREADY_INSTALLED, MB_ICONSTOP | MB_OK, 0 );
  701. }
  702. if ( STATUS_SUCCESS == nt )
  703. {
  704. ::LlsFreeMemory( ReturnBuffer );
  705. }
  706. }
  707. nt = ERROR_CANCELLED;
  708. }
  709. }
  710. }
  711. }
  712. // don't set if !ConnectServer() -- otherwise we'll clobber the LLS error
  713. theApp.SetLastError( nt );
  714. if ( NULL != pszProductName )
  715. m_strProductName.ReleaseBuffer();
  716. if ( NULL != pszServerName )
  717. m_strServerName.ReleaseBuffer();
  718. if ( NULL != pszComment )
  719. m_strComment.ReleaseBuffer();
  720. if ( NULL != pszVendor )
  721. m_strVendor.ReleaseBuffer();
  722. }
  723. return nt;
  724. }
  725. DWORD CPaperSourceDlg::KeyCodeToExpirationDate( DWORD dwKeyCode )
  726. /*++
  727. Routine Description:
  728. Derive the license expiration date from the key code.
  729. Arguments:
  730. dwKeyCode (DWORD)
  731. Return Values:
  732. DWORD.
  733. --*/
  734. {
  735. DWORD dwExpirationDate = 0;
  736. USHORT usWinDate = (USHORT)( ( dwKeyCode >> 12 ) & 0x0000FFFF );
  737. if ( 0 != usWinDate )
  738. {
  739. TIME_FIELDS tf;
  740. LARGE_INTEGER li;
  741. ZeroMemory( &tf, sizeof( tf ) );
  742. tf.Year = 1980 + ( usWinDate & 0x7F );
  743. tf.Month = ( ( usWinDate >> 7 ) & 0x0F );
  744. tf.Day = ( usWinDate >> 11 );
  745. tf.Hour = 23;
  746. tf.Minute = 59;
  747. tf.Second = 59;
  748. BOOL ok;
  749. ok = RtlTimeFieldsToTime( &tf, &li );
  750. ASSERT( ok );
  751. if ( ok )
  752. {
  753. ok = RtlTimeToSecondsSince1980( &li, &dwExpirationDate );
  754. ASSERT( ok );
  755. }
  756. }
  757. return dwExpirationDate;
  758. }
  759. void CPaperSourceDlg::OnAllLicenses()
  760. /*++
  761. Routine Description:
  762. Handler for BN_CLICKED of "install all licenses".
  763. Arguments:
  764. None.
  765. Return Values:
  766. None.
  767. --*/
  768. {
  769. GetDlgItem( IDC_NUM_LICENSES )->EnableWindow( FALSE );
  770. GetDlgItem( IDC_SPIN_LICENSES )->EnableWindow( FALSE );
  771. }
  772. void CPaperSourceDlg::OnSomeLicenses()
  773. /*++
  774. Routine Description:
  775. Handler for BN_CLICKED of "install only x licenses".
  776. Arguments:
  777. None.
  778. Return Values:
  779. None.
  780. --*/
  781. {
  782. GetDlgItem( IDC_NUM_LICENSES )->EnableWindow( TRUE );
  783. GetDlgItem( IDC_SPIN_LICENSES )->EnableWindow( TRUE );
  784. }
  785. void CPaperSourceDlg::OnDeltaPosSpinLicenses(NMHDR* pNMHDR, LRESULT* pResult)
  786. /*++
  787. Routine Description:
  788. Handler for UDN_DELTAPOS of number of licenses.
  789. Arguments:
  790. pNMHDR (NMHDR*)
  791. pResult (LRESULT*)
  792. Return Values:
  793. None.
  794. --*/
  795. {
  796. if ( UpdateData(TRUE) ) // get data
  797. {
  798. m_nLicenses += ((NM_UPDOWN*)pNMHDR)->iDelta;
  799. if (m_nLicenses < 1)
  800. {
  801. m_nLicenses = 1;
  802. ::MessageBeep(MB_OK);
  803. }
  804. else if (m_nLicenses > MAX_NUM_LICENSES )
  805. {
  806. m_nLicenses = MAX_NUM_LICENSES;
  807. ::MessageBeep(MB_OK);
  808. }
  809. UpdateData(FALSE); // set data
  810. }
  811. *pResult = 1; // handle ourselves...
  812. }
  813. DWORD CPaperSourceDlg::CertificateEnter( LPCSTR pszServerName, LPCSTR pszProductName, LPCSTR pszVendor, DWORD dwFlags )
  814. /*++
  815. Routine Description:
  816. Display a dialog allowing the user to enter a license certificate
  817. into the system with a paper certificate.
  818. Arguments:
  819. pszServerName (LPCSTR)
  820. Name of the server for which licenses are to be installed. Note that
  821. this may not be the same as the server on which licenses are actually
  822. installed, as, for example, per seat licenses are always installed on
  823. the enterprise server. A NULL value indicates the local server.
  824. pszProductName (LPCSTR)
  825. Product for which licenses are to be installed. A NULL value indicates
  826. that the user should be allowed to choose.
  827. pszVendor (LPCSTR)
  828. Name of the vendor of the product. This value should be NULL if
  829. pszProductName is NULL, and should be non-NULL if pszProductName is
  830. non-NULL.
  831. dwFlags (DWORD)
  832. A bitfield containing one or more of the following:
  833. CCF_ENTER_FLAG_PER_SEAT_ONLY
  834. Allow the user to enter only per seat licenses. Not valid in
  835. combination with CCF_ENTER_FLAG_PER_SERVER_ONLY.
  836. CCF_ENTER_FLAG_PER_SERVER_ONLY
  837. Allow the user to enter only per server licenses. Not valid in
  838. combination with CCF_ENTER_FLAG_PER_SEAT_ONLY.
  839. Return Value:
  840. ERROR_SUCCESS (A certificate was successfully entered into the system.)
  841. ERROR_CANCELLED (The user cancelled without installing a certificate.)
  842. other Win error
  843. --*/
  844. {
  845. DWORD dwError;
  846. m_strServerName = pszServerName ? pszServerName : "";
  847. m_strProductName = pszProductName ? pszProductName : "";
  848. m_strVendor = pszVendor ? pszVendor : "";
  849. m_dwEnterFlags = dwFlags;
  850. if ( IDOK == DoModal() )
  851. {
  852. dwError = ERROR_SUCCESS;
  853. }
  854. else
  855. {
  856. dwError = ERROR_CANCELLED;
  857. }
  858. return dwError;
  859. }
  860. DWORD CPaperSourceDlg::CertificateRemove( LPCSTR pszServerName, DWORD dwFlags, PLLS_LICENSE_INFO_1 pLicenseInfo )
  861. /*++
  862. Routine Description:
  863. Remove licenses previously installed via PaperCertificateEnter().
  864. Arguments:
  865. hWndParent (HWND)
  866. HWND to the client's main window, for use as the parent window to any
  867. opened dialogs. May be NULL.
  868. pszServerName (LPCSTR)
  869. Name of the server on which licenses are to be removed. A NULL value
  870. indicates the local server.
  871. dwFlags (DWORD)
  872. Certificate removal options. As of this writing, no flags are
  873. supported.
  874. dwLicenseLevel (DWORD)
  875. Level of the LLS_LICENSE_INFO_X structure pointed to by pvLicenseInfo.
  876. pvLicenseInfo (LPVOID)
  877. Points to a LLS_LICENSE_INFO_X (where X is determined by dwLicenseLevel)
  878. describing the licenses to be removed.
  879. Return Value:
  880. ERROR_SUCCESS
  881. Win error
  882. --*/
  883. {
  884. DWORD dwError;
  885. // dwFlags unused
  886. m_strServerName = pszServerName ? pszServerName : "";
  887. m_strProductName = pLicenseInfo->Product;
  888. if ( !ConnectServer() )
  889. {
  890. dwError = theApp.GetLastError();
  891. // error message already displayed
  892. }
  893. else
  894. {
  895. CString strComment;
  896. strComment.LoadString( IDS_PAPER_REMOVE_COMMENT );
  897. LPTSTR pszComment = strComment.GetBuffer(0);
  898. if ( NULL == pszComment )
  899. {
  900. dwError = ERROR_NOT_ENOUGH_MEMORY;
  901. }
  902. else
  903. {
  904. TCHAR szUserName[ 256 ];
  905. DWORD cchUserName = sizeof( szUserName ) / sizeof( *szUserName );
  906. BOOL ok = GetUserName( szUserName, &cchUserName );
  907. if ( !ok )
  908. {
  909. dwError = GetLastError();
  910. }
  911. else
  912. {
  913. NTSTATUS nt;
  914. LLS_LICENSE_INFO_1 lic;
  915. memcpy( &lic, pLicenseInfo, sizeof( lic ) );
  916. lic.Admin = szUserName;
  917. lic.Comment = pszComment;
  918. lic.Date = 0;
  919. lic.Quantity = -pLicenseInfo->Quantity;
  920. BeginWaitCursor();
  921. nt = ::LlsLicenseAdd( m_hLls, 1, (LPBYTE) &lic );
  922. theApp.SetLastLlsError( nt );
  923. EndWaitCursor();
  924. dwError = (DWORD) nt;
  925. }
  926. }
  927. strComment.ReleaseBuffer();
  928. if ( ( ERROR_SUCCESS != dwError ) && ( ERROR_CANCELLED != dwError ) )
  929. {
  930. theApp.SetLastError( dwError );
  931. theApp.DisplayLastError();
  932. }
  933. }
  934. return dwError;
  935. }
  936. // MD4Update on a DWORD that is platform-independent
  937. static void MD4UpdateDword( MD4_CTX * pCtx, DWORD dwValue )
  938. {
  939. BYTE b;
  940. b = (BYTE) ( ( dwValue & 0xFF000000 ) >> 24 );
  941. MD4Update( pCtx, &b, 1 );
  942. b = (BYTE) ( ( dwValue & 0x00FF0000 ) >> 16 );
  943. MD4Update( pCtx, &b, 1 );
  944. b = (BYTE) ( ( dwValue & 0x0000FF00 ) >> 8 );
  945. MD4Update( pCtx, &b, 1 );
  946. b = (BYTE) ( ( dwValue & 0x000000FF ) );
  947. MD4Update( pCtx, &b, 1 );
  948. }