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.

977 lines
21 KiB

  1. /*++
  2. Copyright (c) 1994-95 Microsoft Corporation
  3. Module Name:
  4. lmoddlg.cpp
  5. Abstract:
  6. Licensing mode dialog.
  7. Author:
  8. Don Ryan (donryan) 28-Feb-1995
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. Jeff Parham (jeffparh) 16-Jan-1996
  13. o Ported to CCF API to add/remove licenses, incl. removing
  14. edit box for number of licenses and replacing with
  15. Add/Remove Licenses buttons.
  16. o Added warning of possible loss when switching license modes.
  17. --*/
  18. #include "stdafx.h"
  19. #include "llsmgr.h"
  20. #include "lmoddlg.h"
  21. #include "psrvdlg.h"
  22. #include "pseatdlg.h"
  23. #include "srvldlg.h"
  24. #include "lviodlg.h"
  25. static TCHAR szServerServiceNameNew[] = _T("Windows Server");
  26. static TCHAR szServerServiceNameOld2[] = _T("Windows NT Server");
  27. static TCHAR szServerServiceNameOld[] = _T("File and Print Service");
  28. #ifdef _DEBUG
  29. #undef THIS_FILE
  30. static char BASED_CODE THIS_FILE[] = __FILE__;
  31. #endif
  32. BEGIN_MESSAGE_MAP(CLicensingModeDialog, CDialog)
  33. //{{AFX_MSG_MAP(CLicensingModeDialog)
  34. ON_BN_CLICKED(IDC_MODE_RADIO_PER_SEAT, OnModePerSeat)
  35. ON_BN_CLICKED(IDC_MODE_RADIO_PER_SERVER, OnModePerServer)
  36. ON_EN_UPDATE(IDC_MODE_LICENSES, OnUpdateQuantity)
  37. ON_COMMAND(ID_HELP, OnHelp)
  38. //}}AFX_MSG_MAP
  39. ON_BN_CLICKED(IDC_MODE_ADD_PER_SERVER, OnAddPerServer)
  40. ON_BN_CLICKED(IDC_MODE_REMOVE_PER_SERVER, OnRemovePerServer)
  41. END_MESSAGE_MAP()
  42. CLicensingModeDialog::CLicensingModeDialog(CWnd* pParent /*=NULL*/)
  43. : CDialog(CLicensingModeDialog::IDD, pParent)
  44. /*++
  45. Routine Description:
  46. Constructor for dialog.
  47. Arguments:
  48. pParent - owner window.
  49. Return Values:
  50. None.
  51. --*/
  52. {
  53. //{{AFX_DATA_INIT(CLicensingModeDialog)
  54. m_nLicenses = 0;
  55. m_strPerSeatStatic = _T("");
  56. m_strSupportsStatic = _T("");
  57. //}}AFX_DATA_INIT
  58. m_pService = NULL;
  59. m_bAreCtrlsInitialized = FALSE;
  60. m_fUpdateHint = UPDATE_INFO_NONE;
  61. }
  62. void CLicensingModeDialog::DoDataExchange(CDataExchange* pDX)
  63. /*++
  64. Routine Description:
  65. Called by framework to exchange dialog data.
  66. Arguments:
  67. pDX - data exchange object.
  68. Return Values:
  69. None.
  70. --*/
  71. {
  72. CDialog::DoDataExchange(pDX);
  73. //{{AFX_DATA_MAP(CLicensingModeDialog)
  74. DDX_Control(pDX, IDOK, m_okBtn);
  75. DDX_Control(pDX, IDC_MODE_LICENSES, m_licEdit);
  76. DDX_Text(pDX, IDC_MODE_LICENSES, m_nLicenses);
  77. DDV_MinMaxDWord(pDX, m_nLicenses, 0, 999999);
  78. DDX_Text(pDX, IDC_MODE_STATIC_PER_SEAT, m_strPerSeatStatic);
  79. DDX_Text(pDX, IDC_MODE_STATIC_SUPPORTS, m_strSupportsStatic);
  80. DDX_Control(pDX, IDC_MODE_RADIO_PER_SEAT, m_perSeatBtn);
  81. DDX_Control(pDX, IDC_MODE_RADIO_PER_SERVER, m_perServerBtn);
  82. //}}AFX_DATA_MAP
  83. DDX_Control(pDX, IDC_MODE_ADD_PER_SERVER, m_addPerServerBtn);
  84. DDX_Control(pDX, IDC_MODE_REMOVE_PER_SERVER, m_removePerServerBtn);
  85. }
  86. void CLicensingModeDialog::InitDialog(CService* pService)
  87. /*++
  88. Routine Description:
  89. Initializes dialog.
  90. Arguments:
  91. pService - service object.
  92. Return Values:
  93. None.
  94. --*/
  95. {
  96. VALIDATE_OBJECT(pService, CService);
  97. m_pService = pService;
  98. BSTR bstrDisplayName = m_pService->GetDisplayName();
  99. m_strServiceName = bstrDisplayName;
  100. SysFreeString(bstrDisplayName);
  101. }
  102. void CLicensingModeDialog::InitCtrls()
  103. /*++
  104. Routine Description:
  105. Initializes dialog controls.
  106. Arguments:
  107. None.
  108. Return Values:
  109. None.
  110. --*/
  111. {
  112. m_licEdit.LimitText(6);
  113. if (m_pService->IsPerServer())
  114. {
  115. OnModePerServer();
  116. }
  117. else
  118. {
  119. OnModePerSeat();
  120. }
  121. m_bAreCtrlsInitialized = TRUE;
  122. }
  123. BOOL CLicensingModeDialog::OnInitDialog()
  124. /*++
  125. Routine Description:
  126. Message handler for WM_INITDIALOG.
  127. Arguments:
  128. None.
  129. Return Values:
  130. Returns false if focus set manually.
  131. --*/
  132. {
  133. AfxFormatString1(
  134. m_strPerSeatStatic,
  135. IDS_LICENSING_MODE_1,
  136. m_strServiceName
  137. );
  138. AfxFormatString1(
  139. m_strSupportsStatic,
  140. IDS_LICENSING_MODE_2,
  141. m_strServiceName
  142. );
  143. CDialog::OnInitDialog();
  144. PostMessage(WM_COMMAND, ID_INIT_CTRLS);
  145. return TRUE;
  146. }
  147. void CLicensingModeDialog::OnModePerSeat()
  148. /*++
  149. Routine Description:
  150. Changing mode to per seat.
  151. Arguments:
  152. None.
  153. Return Values:
  154. None.
  155. --*/
  156. {
  157. m_perSeatBtn.SetCheck(1);
  158. m_perServerBtn.SetCheck(0);
  159. ::SafeEnableWindow(&m_addPerServerBtn, &m_okBtn, CDialog::GetFocus(), FALSE);
  160. ::SafeEnableWindow(&m_removePerServerBtn, &m_okBtn, CDialog::GetFocus(), FALSE);
  161. m_licEdit.Clear();
  162. if (m_pService->IsPerServer())
  163. {
  164. if (m_pService->IsReadOnly())
  165. {
  166. CLicensingViolationDialog vioDlg;
  167. if (vioDlg.DoModal() != IDOK)
  168. {
  169. OnModePerServer();
  170. return; // bail...
  171. }
  172. }
  173. if ( ( 0 != GetDlgItemInt( IDC_MODE_LICENSES, NULL, FALSE ) )
  174. && ( IDYES != AfxMessageBox( IDP_CONFIRM_TO_PER_SEAT, MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2 ) ) )
  175. {
  176. OnModePerServer();
  177. return; // bail...
  178. }
  179. }
  180. }
  181. void CLicensingModeDialog::OnModePerServer()
  182. /*++
  183. Routine Description:
  184. Changing mode to per server.
  185. Arguments:
  186. None.
  187. Return Values:
  188. None.
  189. --*/
  190. {
  191. m_perSeatBtn.SetCheck(0);
  192. m_perServerBtn.SetCheck(1);
  193. ::SafeEnableWindow(&m_addPerServerBtn, &m_okBtn, CDialog::GetFocus(), TRUE);
  194. ::SafeEnableWindow(&m_removePerServerBtn, &m_okBtn, CDialog::GetFocus(), TRUE);
  195. UpdatePerServerLicenses();
  196. if (!m_pService->IsPerServer())
  197. {
  198. if (m_pService->IsReadOnly())
  199. {
  200. CLicensingViolationDialog vioDlg;
  201. if (vioDlg.DoModal() != IDOK)
  202. {
  203. OnModePerSeat();
  204. return; // bail...
  205. }
  206. }
  207. if ( IDYES != AfxMessageBox( IDP_CONFIRM_TO_PER_SERVER, MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2 ) )
  208. {
  209. OnModePerSeat();
  210. return; // bail...
  211. }
  212. }
  213. }
  214. void CLicensingModeDialog::OnOK()
  215. /*++
  216. Routine Description:
  217. Update registry.
  218. Arguments:
  219. None.
  220. Return Values:
  221. None.
  222. --*/
  223. {
  224. BOOL bUpdateRegistry = TRUE;
  225. if (m_perSeatBtn.GetCheck())
  226. {
  227. if (m_pService->IsPerServer())
  228. {
  229. CPerSeatLicensingDialog perSeatDlg;
  230. perSeatDlg.m_strProduct = m_strServiceName;
  231. if (perSeatDlg.DoModal() != IDOK)
  232. return; // bail...
  233. }
  234. else
  235. {
  236. bUpdateRegistry = FALSE;
  237. }
  238. }
  239. else if (m_perServerBtn.GetCheck())
  240. {
  241. if (!UpdateData(TRUE))
  242. return; // bail...
  243. if (!m_pService->IsPerServer())
  244. {
  245. if (!m_nLicenses &&
  246. (!m_strServiceName.CompareNoCase(szServerServiceNameNew) ||
  247. !m_strServiceName.CompareNoCase(szServerServiceNameOld2) ||
  248. !m_strServiceName.CompareNoCase(szServerServiceNameOld)))
  249. {
  250. CServerLicensingDialog srvlDlg;
  251. if (srvlDlg.DoModal() != IDOK)
  252. return; // bail...
  253. }
  254. else
  255. {
  256. CString strLicenses;
  257. CPerServerLicensingDialog perServerDlg;
  258. perServerDlg.m_strProduct = m_strServiceName;
  259. strLicenses.Format(_T("%ld"), m_nLicenses);
  260. perServerDlg.m_strLicenses = strLicenses;
  261. if (perServerDlg.DoModal() != IDOK)
  262. return; // bail...
  263. }
  264. }
  265. else
  266. {
  267. bUpdateRegistry = FALSE;
  268. }
  269. }
  270. if (bUpdateRegistry)
  271. {
  272. long Status;
  273. #ifdef CONFIG_THROUGH_REGISTRY
  274. DWORD dwValue;
  275. BOOL bIsRegistryUpdated = FALSE;
  276. HKEY hkeyService = m_pService->GetRegKey();
  277. dwValue = (m_perSeatBtn.GetCheck() || (m_perServerBtn.GetCheck() != m_pService->IsPerServer())) ? 0x1 : 0x0;
  278. Status = RegSetValueEx(
  279. hkeyService,
  280. REG_VALUE_FLIP,
  281. 0,
  282. REG_DWORD,
  283. (PBYTE)&dwValue,
  284. sizeof(DWORD)
  285. );
  286. if (Status == ERROR_SUCCESS)
  287. {
  288. m_fUpdateHint |= UPDATE_LICENSE_MODE; // update...
  289. m_pService->m_bIsReadOnly = (dwValue == 0x1); // update...
  290. dwValue = m_perSeatBtn.GetCheck() ? 0x0 : 0x1;
  291. Status = RegSetValueEx(
  292. hkeyService,
  293. REG_VALUE_MODE,
  294. 0,
  295. REG_DWORD,
  296. (PBYTE)&dwValue,
  297. sizeof(DWORD)
  298. );
  299. if (Status == ERROR_SUCCESS)
  300. {
  301. m_pService->m_bIsPerServer = (dwValue == 0x1); // update...
  302. bIsRegistryUpdated = TRUE;
  303. }
  304. }
  305. if (hkeyService)
  306. {
  307. RegCloseKey(hkeyService);
  308. }
  309. if (!bIsRegistryUpdated)
  310. {
  311. theApp.DisplayStatus(::GetLastError());
  312. return; // bail...
  313. }
  314. #else
  315. CServer* pServer = (CServer*)MKOBJ(m_pService->GetParent());
  316. if ( pServer && pServer->ConnectLls() ) // JonN 5/5/00 PREFIX 112122
  317. {
  318. BSTR pKeyName = m_pService->GetName();
  319. if ( NULL == pKeyName )
  320. {
  321. Status = STATUS_NO_MEMORY;
  322. }
  323. else
  324. {
  325. PLLS_LOCAL_SERVICE_INFO_0 pServiceInfo = NULL;
  326. Status = ::LlsLocalServiceInfoGet( pServer->GetLlsHandle(), pKeyName, 0, (LPBYTE *) &pServiceInfo );
  327. if ( NT_SUCCESS( Status ) )
  328. {
  329. pServiceInfo->FlipAllow = (m_perSeatBtn.GetCheck() || (m_perServerBtn.GetCheck() != m_pService->IsPerServer())) ? 0x1 : 0x0;
  330. pServiceInfo->Mode = m_perSeatBtn.GetCheck() ? 0x0 : 0x1;
  331. Status = ::LlsLocalServiceInfoSet( pServer->GetLlsHandle(), pKeyName, 0, (LPBYTE) pServiceInfo );
  332. if ( NT_SUCCESS( Status ) )
  333. {
  334. m_fUpdateHint |= UPDATE_LICENSE_MODE; // update...
  335. m_pService->m_bIsReadOnly = ( 0x1 == pServiceInfo->FlipAllow ); // update...
  336. m_pService->m_bIsPerServer = ( 0x1 == pServiceInfo->Mode ); // update...
  337. }
  338. ::LlsFreeMemory( pServiceInfo->KeyName );
  339. ::LlsFreeMemory( pServiceInfo->DisplayName );
  340. ::LlsFreeMemory( pServiceInfo->FamilyDisplayName );
  341. ::LlsFreeMemory( pServiceInfo );
  342. }
  343. if ( IsConnectionDropped( Status ) )
  344. {
  345. pServer->DisconnectLls();
  346. }
  347. SysFreeString( pKeyName );
  348. }
  349. }
  350. else
  351. {
  352. Status = LlsGetLastStatus();
  353. }
  354. LlsSetLastStatus( Status );
  355. if ( !NT_SUCCESS( Status ) )
  356. {
  357. theApp.DisplayStatus( Status );
  358. return; // bail...
  359. }
  360. #endif
  361. }
  362. EndDialog(IDOK);
  363. return;
  364. }
  365. void CLicensingModeDialog::OnCancel()
  366. /*++
  367. Routine Description:
  368. Update registry.
  369. Arguments:
  370. None.
  371. Return Values:
  372. None.
  373. --*/
  374. {
  375. if (m_nLicenses > (LONG) 999999)
  376. {
  377. UpdateData( TRUE );
  378. }
  379. else
  380. {
  381. EndDialog( 0 );
  382. }
  383. return;
  384. }
  385. BOOL CLicensingModeDialog::OnCommand(WPARAM wParam, LPARAM lParam)
  386. /*++
  387. Routine Description:
  388. Message handler for WM_COMMAND.
  389. Arguments:
  390. wParam - message specific.
  391. lParam - message specific.
  392. Return Values:
  393. Returns true if message processed.
  394. --*/
  395. {
  396. if (wParam == ID_INIT_CTRLS)
  397. {
  398. if (!m_bAreCtrlsInitialized)
  399. {
  400. InitCtrls();
  401. }
  402. return TRUE; // processed...
  403. }
  404. return CDialog::OnCommand(wParam, lParam);
  405. }
  406. void CLicensingModeDialog::OnDeltaPosSpin(NMHDR* pNMHDR, LRESULT* pResult)
  407. /*++
  408. Routine Description:
  409. Notification handler for UDN_DELTAPOS.
  410. Arguments:
  411. pNMHDR - notification header.
  412. pResult - return code.
  413. Return Values:
  414. None.
  415. --*/
  416. {
  417. UpdateData(TRUE); // get data
  418. m_nLicenses += ((NM_UPDOWN*)pNMHDR)->iDelta;
  419. if (m_nLicenses < 0)
  420. {
  421. m_nLicenses = 0;
  422. ::MessageBeep(MB_OK);
  423. }
  424. else if (m_nLicenses > 999999)
  425. {
  426. m_nLicenses = 999999;
  427. ::MessageBeep(MB_OK);
  428. }
  429. UpdateData(FALSE); // set data
  430. *pResult = 1; // handle ourselves...
  431. }
  432. void CLicensingModeDialog::OnUpdateQuantity()
  433. /*++
  434. Routine Description:
  435. Message handler for EN_UPDATE.
  436. Arguments:
  437. None.
  438. Return Values:
  439. None.
  440. --*/
  441. {
  442. if (m_licEdit.IsWindowEnabled())
  443. {
  444. long nLicensesOld = m_nLicenses;
  445. if (!UpdateData(TRUE))
  446. {
  447. m_nLicenses = nLicensesOld;
  448. UpdateData(FALSE);
  449. m_licEdit.SetFocus();
  450. m_licEdit.SetSel(0,-1);
  451. ::MessageBeep(MB_OK);
  452. }
  453. }
  454. }
  455. void CLicensingModeDialog::OnHelp()
  456. /*++
  457. Routine Description:
  458. Help button support.
  459. Arguments:
  460. None.
  461. Return Values:
  462. None.
  463. --*/
  464. {
  465. CDialog::OnCommandHelp(0, 0L);
  466. }
  467. void CLicensingModeDialog::OnAddPerServer()
  468. /*++
  469. Routine Description:
  470. Add per server licenses button support.
  471. Arguments:
  472. None.
  473. Return Values:
  474. None.
  475. --*/
  476. {
  477. CServer* pServer = (CServer*)MKOBJ(m_pService->GetParent());
  478. LPTSTR pszUniServerName = pServer->GetName();
  479. LPTSTR pszUniProductName = m_pService->GetDisplayName();
  480. if ( ( NULL == pszUniServerName ) || ( NULL == pszUniProductName ) )
  481. {
  482. theApp.DisplayStatus( STATUS_NO_MEMORY );
  483. }
  484. else
  485. {
  486. LPSTR pszAscServerName = (LPSTR) LocalAlloc( LMEM_FIXED, 1 + lstrlen( pszUniServerName ) );
  487. LPSTR pszAscProductName = (LPSTR) LocalAlloc( LMEM_FIXED, 1 + lstrlen( pszUniProductName ) );
  488. if ( ( NULL == pszAscServerName ) || ( NULL == pszAscProductName ) )
  489. {
  490. theApp.DisplayStatus( STATUS_NO_MEMORY );
  491. }
  492. else
  493. {
  494. wsprintfA( pszAscServerName, "%ls", pszUniServerName );
  495. wsprintfA( pszAscProductName, "%ls", pszUniProductName );
  496. DWORD dwError = CCFCertificateEnterUI( m_hWnd, pszAscServerName, pszAscProductName, "Microsoft", CCF_ENTER_FLAG_PER_SERVER_ONLY, NULL );
  497. if ( ERROR_SUCCESS == dwError )
  498. {
  499. m_fUpdateHint |= UPDATE_INFO_SERVICES | UPDATE_INFO_PRODUCTS; // update...
  500. UpdatePerServerLicenses();
  501. }
  502. }
  503. if ( NULL != pszAscServerName )
  504. {
  505. LocalFree( pszAscServerName );
  506. }
  507. if ( NULL != pszAscProductName )
  508. {
  509. LocalFree( pszAscProductName );
  510. }
  511. }
  512. if ( NULL != pszUniServerName )
  513. {
  514. SysFreeString( pszUniServerName );
  515. }
  516. if ( NULL != pszUniProductName )
  517. {
  518. SysFreeString( pszUniProductName );
  519. }
  520. }
  521. void CLicensingModeDialog::OnRemovePerServer()
  522. /*++
  523. Routine Description:
  524. Remove per server licenses button support.
  525. Arguments:
  526. None.
  527. Return Values:
  528. None.
  529. --*/
  530. {
  531. CServer* pServer = (CServer*)MKOBJ(m_pService->GetParent());
  532. LPTSTR pszUniServerName = pServer->GetName();
  533. LPTSTR pszUniProductName = m_pService->GetDisplayName();
  534. if ( ( NULL == pszUniServerName ) || ( NULL == pszUniProductName ) )
  535. {
  536. theApp.DisplayStatus( STATUS_NO_MEMORY );
  537. }
  538. else
  539. {
  540. LPSTR pszAscServerName = (LPSTR) LocalAlloc( LMEM_FIXED, 1 + lstrlen( pszUniServerName ) );
  541. LPSTR pszAscProductName = (LPSTR) LocalAlloc( LMEM_FIXED, 1 + lstrlen( pszUniProductName ) );
  542. if ( ( NULL == pszAscServerName ) || ( NULL == pszAscProductName ) )
  543. {
  544. theApp.DisplayStatus( STATUS_NO_MEMORY );
  545. }
  546. else
  547. {
  548. wsprintfA( pszAscServerName, "%ls", pszUniServerName );
  549. wsprintfA( pszAscProductName, "%ls", pszUniProductName );
  550. CCFCertificateRemoveUI( m_hWnd, pszAscServerName, pszAscProductName, "Microsoft", NULL, NULL );
  551. m_fUpdateHint |= UPDATE_INFO_SERVERS | UPDATE_INFO_SERVICES | UPDATE_LICENSE_DELETED; // update...
  552. UpdatePerServerLicenses();
  553. }
  554. if ( NULL != pszAscServerName ) LocalFree( pszAscServerName );
  555. if ( NULL != pszAscProductName ) LocalFree( pszAscProductName );
  556. }
  557. if ( NULL != pszUniServerName ) SysFreeString( pszUniServerName );
  558. if ( NULL != pszUniProductName ) SysFreeString( pszUniProductName );
  559. }
  560. void CLicensingModeDialog::UpdatePerServerLicenses()
  561. /*++
  562. Routine Description:
  563. Update the concurrent limit setting from the registry.
  564. Arguments:
  565. None.
  566. Return Values:
  567. None.
  568. --*/
  569. {
  570. BeginWaitCursor();
  571. CServer* pServer = (CServer*)MKOBJ(m_pService->GetParent());
  572. if ( pServer == NULL )
  573. {
  574. theApp.DisplayStatus( STATUS_NO_MEMORY );
  575. return;
  576. }
  577. LPTSTR pszUniServerName = pServer->GetName();
  578. LPTSTR pszUniProductName = m_pService->GetDisplayName();
  579. if ( ( NULL == pszUniServerName ) || ( NULL == pszUniProductName ) )
  580. {
  581. theApp.DisplayStatus( STATUS_NO_MEMORY );
  582. }
  583. else
  584. {
  585. LPTSTR pszUniNetServerName = (LPTSTR) LocalAlloc( LMEM_FIXED, sizeof( TCHAR) * ( 3 + lstrlen( pszUniServerName ) ) );
  586. if ( NULL == pszUniNetServerName )
  587. {
  588. theApp.DisplayStatus( STATUS_NO_MEMORY );
  589. }
  590. else
  591. {
  592. wsprintf( pszUniNetServerName, TEXT("%ls%ls"), (TEXT('\\') == *pszUniServerName) ? TEXT("") : TEXT("\\\\"), pszUniServerName );
  593. LLS_HANDLE hLls;
  594. DWORD dwError = LlsConnect( pszUniNetServerName, &hLls );
  595. if ( ERROR_SUCCESS == dwError )
  596. {
  597. DWORD dwConcurrentLimit;
  598. dwError = LlsProductLicensesGet( hLls, pszUniProductName, LLS_LICENSE_MODE_PER_SERVER, &dwConcurrentLimit );
  599. LlsClose( hLls );
  600. if ( ERROR_SUCCESS == dwError )
  601. {
  602. m_pService->m_lPerServerLimit = dwConcurrentLimit;
  603. }
  604. }
  605. if ( ERROR_SUCCESS != dwError )
  606. {
  607. #ifdef CONFIG_THROUGH_REGISTRY
  608. HKEY hkeyService = m_pService->GetRegKey();
  609. DWORD dwConcurrentLimit;
  610. DWORD dwType;
  611. DWORD cb = sizeof( dwConcurrentLimit );
  612. DWORD dwError = RegQueryValueEx( hkeyService, REG_VALUE_LIMIT, NULL, &dwType, (LPBYTE) &dwConcurrentLimit, &cb );
  613. ASSERT( ERROR_SUCCESS == dwError );
  614. if ( ERROR_SUCCESS == dwError )
  615. {
  616. m_pService->m_lPerServerLimit = dwConcurrentLimit;
  617. }
  618. RegCloseKey( hkeyService );
  619. #else
  620. NTSTATUS Status;
  621. if ( pServer->ConnectLls() )
  622. {
  623. BSTR pKeyName = m_pService->GetName();
  624. if ( NULL == pKeyName )
  625. {
  626. Status = STATUS_NO_MEMORY;
  627. }
  628. else
  629. {
  630. PLLS_LOCAL_SERVICE_INFO_0 pServiceInfo = NULL;
  631. Status = ::LlsLocalServiceInfoGet( pServer->GetLlsHandle(), pKeyName, 0, (LPBYTE *) &pServiceInfo );
  632. if ( NT_SUCCESS( Status ) )
  633. {
  634. m_pService->m_lPerServerLimit = pServiceInfo->ConcurrentLimit;
  635. ::LlsFreeMemory( pServiceInfo->KeyName );
  636. ::LlsFreeMemory( pServiceInfo->DisplayName );
  637. ::LlsFreeMemory( pServiceInfo->FamilyDisplayName );
  638. ::LlsFreeMemory( pServiceInfo );
  639. }
  640. if ( IsConnectionDropped( Status ) )
  641. {
  642. pServer->DisconnectLls();
  643. }
  644. SysFreeString( pKeyName );
  645. }
  646. }
  647. else
  648. {
  649. Status = LlsGetLastStatus();
  650. }
  651. LlsSetLastStatus( Status );
  652. if ( !NT_SUCCESS( Status ) )
  653. {
  654. theApp.DisplayStatus( Status );
  655. return; // bail...
  656. }
  657. #endif
  658. }
  659. }
  660. if ( NULL != pszUniNetServerName )
  661. {
  662. LocalFree( pszUniNetServerName );
  663. }
  664. }
  665. if ( NULL != pszUniServerName )
  666. {
  667. SysFreeString( pszUniServerName );
  668. }
  669. if ( NULL != pszUniProductName )
  670. {
  671. SysFreeString( pszUniProductName );
  672. }
  673. EndWaitCursor();
  674. m_nLicenses = m_pService->m_lPerServerLimit;
  675. UpdateData(FALSE);
  676. }