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.

2175 lines
58 KiB

  1. //-------------------------------------------------------------------
  2. //
  3. // FILE: PriDlgs.cpp
  4. //
  5. // Summary;
  6. // This file contians the Primary Dialogs, functions and dialog procs
  7. //
  8. // Entry Points;
  9. //
  10. // History;
  11. // Nov-30-94 MikeMi Created
  12. // Mar-14-95 MikeMi Added F1 Message Filter and PWM_HELP message
  13. // Apr-26-95 MikeMi Added Computer name and remoting
  14. // Dec-15-95 JeffParh Added secure certificate support.
  15. //
  16. //-------------------------------------------------------------------
  17. #include <nt.h>
  18. #include <ntrtl.h>
  19. #include <nturtl.h>
  20. #include <windows.h>
  21. #include "resource.h"
  22. #include "CLicReg.hpp"
  23. #include <stdlib.h>
  24. #include <htmlhelp.h>
  25. #include "liccpa.hpp"
  26. #include "PriDlgs.hpp"
  27. #include "SecDlgs.hpp"
  28. #include <llsapi.h>
  29. extern "C"
  30. {
  31. INT_PTR CALLBACK dlgprocLICCPA( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
  32. INT_PTR CALLBACK dlgprocLICSETUP( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
  33. INT_PTR CALLBACK dlgprocPERSEATSETUP( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
  34. INT_PTR CALLBACK dlgprocLICCPACONFIG( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
  35. }
  36. // Perserver user count value limits and defaults
  37. //
  38. const int PERSERVER_LIMITDEFAULT = 0;
  39. const int PERSERVER_MAX = 999999;
  40. const int PERSERVER_MIN = 0;
  41. const int PERSERVER_PAGE = 10;
  42. const int cchEDITLIMIT = 6; // the number of chars to represent PERSERVER_MAX
  43. const UINT MB_VALUELIMIT = MB_OK; // beep when value limit is reached
  44. // Used for in memory storage of license mode state
  45. //
  46. typedef struct tagSERVICEENTRY
  47. {
  48. LPWSTR pszComputer;
  49. LPWSTR pszService;
  50. LPWSTR pszDisplayName;
  51. LPWSTR pszFamilyDisplayName;
  52. LICENSE_MODE lm;
  53. DWORD dwLimit;
  54. BOOL fIsNewProduct;
  55. } SERVICEENTRY, *PSERVICEENTRY;
  56. #pragma warning(push)
  57. #pragma warning(disable: 4296) // C4296: '<=' : expression is always true
  58. inline BOOL VALIDUSERCOUNT( UINT users )
  59. {
  60. return ((PERSERVER_MIN <= users) && (PERSERVER_MAX >= users));
  61. }
  62. #pragma warning(pop)
  63. static void UpdatePerServerLicenses( HWND hwndDlg, PSERVICEENTRY pServ );
  64. static int ServiceRegister( LPWSTR pszComputer,
  65. LPWSTR pszFamilyDisplayName,
  66. LPWSTR pszDisplayName );
  67. BOOL g_fWarned = FALSE;
  68. //-------------------------------------------------------------------
  69. //
  70. // Function: AccessOk
  71. //
  72. // Summary;
  73. // Checks access rights from reg call and raise dialog as needed
  74. //
  75. // Arguments;
  76. // hDlg [in] - Handle to working dialog to raise error dlgs with
  77. // lrc [in] - the return status from a reg call
  78. //
  79. // Returns:
  80. // local error mapping;
  81. // ERR_NONE
  82. // ERR_PERMISSIONDENIED
  83. // ERR_NOREMOTESERVER
  84. // ERR_REGISTRYCORRUPT
  85. //
  86. //
  87. // History;
  88. // Nov-30-94 MikeMi Created
  89. //
  90. //-------------------------------------------------------------------
  91. INT AccessOk( HWND hDlg, LONG lrc, BOOL fCPCall )
  92. {
  93. INT nrt = ERR_NONE;
  94. if (ERROR_SUCCESS != lrc)
  95. {
  96. WCHAR szText[TEMPSTR_SIZE];
  97. WCHAR szTitle[TEMPSTR_SIZE];
  98. UINT wId;
  99. UINT wIdTitle;
  100. switch (lrc)
  101. {
  102. case ERROR_ACCESS_DENIED:
  103. wId = IDS_NOACCESS;
  104. nrt = ERR_PERMISSIONDENIED;
  105. break;
  106. case RPC_S_SERVER_UNAVAILABLE:
  107. wId = IDS_NOSERVER;
  108. nrt = ERR_NOREMOTESERVER;
  109. break;
  110. default:
  111. wId = IDS_BADREG;
  112. nrt = ERR_REGISTRYCORRUPT;
  113. break;
  114. }
  115. if (fCPCall)
  116. {
  117. wIdTitle = IDS_CPCAPTION;
  118. }
  119. else
  120. {
  121. wIdTitle = IDS_SETUPCAPTION;
  122. }
  123. LoadString(g_hinst, wIdTitle, szTitle, TEMPSTR_SIZE);
  124. LoadString(g_hinst, wId, szText, TEMPSTR_SIZE);
  125. MessageBox (hDlg, szText, szTitle, MB_OK|MB_ICONSTOP);
  126. }
  127. return( nrt );
  128. }
  129. //-------------------------------------------------------------------
  130. //
  131. // Function: InitUserEdit
  132. //
  133. // Summary;
  134. // Initializes and defines user count edit control behaviour
  135. //
  136. // Arguments;
  137. // hwndDlg [in] - Parent dialog of user count edit dialog
  138. //
  139. // History;
  140. // Nov-30-94 MikeMi Created
  141. //
  142. //-------------------------------------------------------------------
  143. void InitUserEdit( HWND hwndDlg )
  144. {
  145. HWND hwndCount = GetDlgItem( hwndDlg, IDC_USERCOUNT);
  146. SendMessage( hwndCount, EM_LIMITTEXT, cchEDITLIMIT, 0 );
  147. }
  148. //-------------------------------------------------------------------
  149. //
  150. // Function: InitTitleText
  151. //
  152. // Summary;
  153. // Initialize title static text and mode definition static text
  154. //
  155. // Arguments;
  156. // hwndDlg [in] - Parent dialog of description static text
  157. // pServ [in] - Service definition to set static text
  158. //
  159. //
  160. // History;
  161. // Nov-30-94 MikeMi Created
  162. //
  163. //-------------------------------------------------------------------
  164. void InitTitleText( HWND hwndDlg, PSERVICEENTRY pServ )
  165. {
  166. InitStaticWithService( hwndDlg, IDC_STATICTITLE, pServ->pszDisplayName );
  167. InitStaticWithService( hwndDlg, IDC_STATICPERSEAT, pServ->pszDisplayName );
  168. }
  169. //-------------------------------------------------------------------
  170. //
  171. // Function: InitDialogForService
  172. //
  173. // Summary;
  174. // Initialize dialog controls to the service state
  175. //
  176. // Arguments;
  177. // hwndDlg [in] - Parent dialog to init controls in
  178. // pServ [in] - Service definition to set controls
  179. //
  180. // History;
  181. // Nov-30-94 MikeMi Created
  182. //
  183. //-------------------------------------------------------------------
  184. void InitDialogForService( HWND hwndDlg, PSERVICEENTRY pServ )
  185. {
  186. HWND hwndCount = GetDlgItem( hwndDlg, IDC_USERCOUNT );
  187. HWND hwndSpin = GetDlgItem( hwndDlg, IDC_USERCOUNTARROW );
  188. BOOL fIsPerServer = (LICMODE_PERSERVER==pServ->lm);
  189. // set radio button states
  190. CheckDlgButton( hwndDlg, IDC_PERSEAT, !fIsPerServer );
  191. CheckDlgButton( hwndDlg, IDC_PERSERVER, fIsPerServer );
  192. // set user count edit control
  193. if (fIsPerServer)
  194. {
  195. // add text back
  196. SetDlgItemInt( hwndDlg, IDC_USERCOUNT, pServ->dwLimit, FALSE );
  197. SetFocus( hwndCount );
  198. SendMessage( hwndCount, EM_SETSEL, 0, -1 );
  199. }
  200. else
  201. {
  202. // remove all text in item
  203. SetDlgItemText( hwndDlg, IDC_USERCOUNT, L"" );
  204. }
  205. // set state of edit control and arrows
  206. if ( NULL != hwndSpin )
  207. {
  208. EnableWindow( hwndCount, fIsPerServer );
  209. EnableWindow( hwndSpin, fIsPerServer );
  210. }
  211. else
  212. {
  213. UpdatePerServerLicenses( hwndDlg, pServ );
  214. EnableWindow( GetDlgItem( hwndDlg, IDC_ADD_LICENSES ), fIsPerServer );
  215. EnableWindow( GetDlgItem( hwndDlg, IDC_REMOVE_LICENSES ), fIsPerServer );
  216. }
  217. }
  218. //-------------------------------------------------------------------
  219. //
  220. // Function: FreeServiceEntry
  221. //
  222. // Summary;
  223. // Free all allocated memory when a service structure is created
  224. //
  225. // Aruments;
  226. // pServ [in] - The Service structure to free
  227. //
  228. // History;
  229. // Nov-30-94 MikeMi Created
  230. //
  231. //-------------------------------------------------------------------
  232. void FreeServiceEntry( PSERVICEENTRY pServ )
  233. {
  234. GlobalFree( pServ->pszService );
  235. GlobalFree( pServ->pszDisplayName );
  236. if ( NULL != pServ->pszComputer )
  237. {
  238. GlobalFree( pServ->pszComputer );
  239. }
  240. GlobalFree( pServ );
  241. }
  242. //-------------------------------------------------------------------
  243. //
  244. // Function: CreateServiceEntry
  245. //
  246. // Summary;
  247. // Using the Service registry key name, allocate a Service structure
  248. // and setup registry.
  249. //
  250. // Arguments;
  251. // pszComputer [in] - The name of the computer to use (maybe null)
  252. // pszService [in] - The name of the reg key to use to load or create
  253. // service from
  254. // pszDisplayName [in] - The name the user will see, this will only be
  255. // if the registry does not contain a displayname already
  256. //
  257. // Returns: NULL if Error, pointer to allocated Service Structure
  258. //
  259. // History;
  260. // Nov-30-94 MikeMi Created
  261. //
  262. //-------------------------------------------------------------------
  263. PSERVICEENTRY CreateServiceEntry( LPCWSTR pszComputer,
  264. LPCWSTR pszService,
  265. LPCWSTR pszFamilyDisplayName,
  266. LPCWSTR pszDisplayName )
  267. {
  268. CLicRegLicenseService cLicServKey;
  269. PSERVICEENTRY pServ = NULL;
  270. DWORD cchSize = 0;
  271. LONG lrt;
  272. pServ = (PSERVICEENTRY)GlobalAlloc( GPTR, sizeof( SERVICEENTRY ));
  273. if (pServ)
  274. {
  275. cLicServKey.SetService( pszService );
  276. cLicServKey.Open( pszComputer, TRUE );
  277. // load or set defaults
  278. //
  279. if (ERROR_SUCCESS != cLicServKey.GetMode( pServ->lm ))
  280. {
  281. pServ->lm = LICMODE_UNDEFINED;
  282. }
  283. if (ERROR_SUCCESS != cLicServKey.GetUserLimit( pServ->dwLimit ))
  284. {
  285. pServ->dwLimit = PERSERVER_LIMITDEFAULT;
  286. }
  287. //
  288. // get, set DisplayName
  289. //
  290. lrt = cLicServKey.GetDisplayName( NULL, cchSize );
  291. if (ERROR_SUCCESS == lrt)
  292. {
  293. pServ->pszDisplayName = (LPWSTR)GlobalAlloc( GPTR, cchSize * sizeof( WCHAR ) );
  294. if (pServ->pszDisplayName == NULL)
  295. {
  296. goto ErrorCleanup;
  297. }
  298. lrt = cLicServKey.GetDisplayName( pServ->pszDisplayName, cchSize );
  299. }
  300. // the GetDisplayName may fail in both the two cases above
  301. //
  302. if (ERROR_SUCCESS != lrt)
  303. {
  304. GlobalFree( (HGLOBAL)pServ->pszDisplayName );
  305. cchSize = lstrlen( pszDisplayName ) + 1;
  306. pServ->pszDisplayName = (LPWSTR)GlobalAlloc( GPTR, cchSize * sizeof( WCHAR ) );
  307. if (pServ->pszDisplayName == NULL)
  308. {
  309. goto ErrorCleanup;
  310. }
  311. lstrcpy( pServ->pszDisplayName, pszDisplayName );
  312. cLicServKey.SetDisplayName( pServ->pszDisplayName );
  313. pServ->fIsNewProduct = TRUE;
  314. }
  315. else
  316. {
  317. pServ->fIsNewProduct = FALSE;
  318. }
  319. //
  320. // get, set FamilyDisplayName
  321. //
  322. lrt = cLicServKey.GetFamilyDisplayName( NULL, cchSize );
  323. if (ERROR_SUCCESS == lrt)
  324. {
  325. pServ->pszFamilyDisplayName = (LPWSTR)GlobalAlloc( GPTR, cchSize * sizeof( WCHAR ) );
  326. if ( pServ->pszFamilyDisplayName == NULL )
  327. {
  328. goto ErrorCleanup;
  329. }
  330. lrt = cLicServKey.GetFamilyDisplayName( pServ->pszFamilyDisplayName, cchSize );
  331. }
  332. // the GetFamilyDisplayName may fail in both the two cases above
  333. //
  334. if (ERROR_SUCCESS != lrt)
  335. {
  336. GlobalFree( (HGLOBAL)pServ->pszFamilyDisplayName );
  337. cchSize = lstrlen( pszFamilyDisplayName ) + 1;
  338. pServ->pszFamilyDisplayName = (LPWSTR)GlobalAlloc( GPTR, cchSize * sizeof( WCHAR ) );
  339. if ( pServ->pszFamilyDisplayName == NULL )
  340. {
  341. goto ErrorCleanup;
  342. }
  343. lstrcpy( pServ->pszFamilyDisplayName, pszFamilyDisplayName );
  344. }
  345. cchSize = lstrlen( pszService ) + 1;
  346. pServ->pszService = (LPWSTR)GlobalAlloc( GPTR, cchSize * sizeof( WCHAR ) );
  347. if (pServ->pszService == NULL)
  348. {
  349. goto ErrorCleanup;
  350. }
  351. lstrcpy( pServ->pszService, pszService );
  352. cLicServKey.Close();
  353. if ( NULL == pszComputer )
  354. {
  355. pServ->pszComputer = NULL;
  356. }
  357. else
  358. {
  359. pServ->pszComputer = (LPWSTR)GlobalAlloc( GPTR, sizeof( WCHAR ) * ( 1 + lstrlen( pszComputer ) ) );
  360. if (pServ->pszComputer == NULL)
  361. {
  362. goto ErrorCleanup;
  363. }
  364. lstrcpy( pServ->pszComputer, pszComputer );
  365. }
  366. }
  367. return( pServ );
  368. ErrorCleanup:
  369. if (pServ) // JonN 5/15/00: PREFIX 112116-112119
  370. {
  371. if (pServ->pszDisplayName)
  372. GlobalFree( (HGLOBAL)pServ->pszDisplayName );
  373. if (pServ->pszFamilyDisplayName)
  374. GlobalFree( (HGLOBAL)pServ->pszFamilyDisplayName );
  375. if (pServ->pszService)
  376. GlobalFree( (HGLOBAL)pServ->pszService );
  377. if (pServ->pszComputer)
  378. GlobalFree( (HGLOBAL)pServ->pszComputer );
  379. GlobalFree( (HGLOBAL)pServ );
  380. }
  381. return ( (PSERVICEENTRY)NULL );
  382. }
  383. //-------------------------------------------------------------------
  384. //
  385. // Function: SaveServiceToReg
  386. //
  387. // Summary;
  388. // Save the given Service structure to the registry
  389. //
  390. // Arguments;
  391. // pServ [in] - Service structure to save
  392. //
  393. // History;
  394. // Nov-30-94 MikeMi Created
  395. //
  396. //-------------------------------------------------------------------
  397. void SaveServiceToReg( LPCWSTR pszComputer, PSERVICEENTRY pServ )
  398. {
  399. CLicRegLicenseService cLicServKey;
  400. LICENSE_MODE lm;
  401. cLicServKey.SetService( pServ->pszService );
  402. cLicServKey.Open( pszComputer );
  403. //
  404. // if no mode in the registry, set to current selected mode
  405. //
  406. if (ERROR_SUCCESS != cLicServKey.GetMode( lm ))
  407. {
  408. lm = pServ->lm;
  409. }
  410. //
  411. // if a mode change was made or perseat mode selected,
  412. // set the change flag so that user is warned on any change
  413. //
  414. if ((pServ->lm != lm) ||
  415. (LICMODE_PERSEAT == pServ->lm) )
  416. {
  417. cLicServKey.SetChangeFlag( TRUE );
  418. }
  419. else
  420. {
  421. // this will not modify change flag if it is
  422. // present, but will set it to false if it is not
  423. // present
  424. cLicServKey.CanChangeMode();
  425. }
  426. DWORD dwLimitInReg;
  427. // user limit should be set by CCFAPI32; set only if it's absent
  428. if ( ERROR_SUCCESS != cLicServKey.GetUserLimit( dwLimitInReg ) )
  429. {
  430. cLicServKey.SetUserLimit( pServ->dwLimit );
  431. }
  432. cLicServKey.SetDisplayName( pServ->pszDisplayName );
  433. cLicServKey.SetFamilyDisplayName( pServ->pszFamilyDisplayName );
  434. cLicServKey.SetMode( pServ->lm );
  435. cLicServKey.Close();
  436. }
  437. //-------------------------------------------------------------------
  438. //
  439. // Function: ServiceLicAgreement
  440. //
  441. // Summary;
  442. // Check the given Service structure for violation
  443. //
  444. // Arguments;
  445. // hwndDlg [in] - hwnd of dialog to use to raise legal voilation dialog
  446. // pServ [in] - Service structure to check
  447. // pszComputer [in] - computer to work with
  448. // pszHelpFile [in] - helpfile for dialogs help button
  449. // pszPerSeatHelpContext [in] - helpcontext for PerSeat dialog help button
  450. // pszPerServerHelpContext [in] - helpcontext for PerServer dialog help button
  451. //
  452. // Return: FALSE if agreement was not acceptable
  453. // TRUE if agreement was accepted
  454. //
  455. // History;
  456. // Nov-30-94 MikeMi Created
  457. //
  458. //-------------------------------------------------------------------
  459. BOOL ServiceLicAgreement( HWND hwndDlg,
  460. PSERVICEENTRY pServ,
  461. LPCWSTR pszComputer,
  462. LPCWSTR pszHelpFile,
  463. DWORD dwPerSeatHelpContext,
  464. DWORD dwPerServerHelpContext )
  465. {
  466. CLicRegLicenseService cLicServKey;
  467. LICENSE_MODE lm;
  468. DWORD dwLimit = pServ->dwLimit;
  469. BOOL frt = TRUE;
  470. BOOL fRaiseAgreement = TRUE;
  471. cLicServKey.SetService( pServ->pszService );
  472. if (ERROR_SUCCESS == cLicServKey.Open( pszComputer, FALSE ))
  473. {
  474. cLicServKey.GetMode( lm );
  475. cLicServKey.GetUserLimit( dwLimit );
  476. // check for changes
  477. if ( !( pServ->lm != lm ||
  478. (LICMODE_PERSERVER == pServ->lm &&
  479. dwLimit != pServ->dwLimit) ) )
  480. {
  481. fRaiseAgreement = FALSE;
  482. }
  483. cLicServKey.Close();
  484. }
  485. if (fRaiseAgreement)
  486. {
  487. if (LICMODE_PERSEAT == pServ->lm)
  488. {
  489. frt = PerSeatAgreementDialog( hwndDlg,
  490. pServ->pszDisplayName,
  491. pszHelpFile,
  492. dwPerSeatHelpContext );
  493. }
  494. else
  495. {
  496. // special case FilePrint and zero concurrent users
  497. //
  498. if ( 0 == lstrcmp( pServ->pszService, FILEPRINT_SERVICE_REG_KEY ) &&
  499. (0 == pServ->dwLimit))
  500. {
  501. frt = ServerAppAgreementDialog( hwndDlg,
  502. pszHelpFile,
  503. LICCPA_HELPCONTEXTSERVERAPP );
  504. }
  505. else
  506. {
  507. // find the limit has changed but was this invoked
  508. // by adding more licenses if so the user was already warned
  509. if( !g_fWarned )
  510. {
  511. frt = PerServerAgreementDialog( hwndDlg,
  512. pServ->pszDisplayName,
  513. dwLimit , //pServ->dwLimit,
  514. pszHelpFile,
  515. dwPerServerHelpContext );
  516. }
  517. }
  518. }
  519. }
  520. return( frt );
  521. }
  522. //-------------------------------------------------------------------
  523. //
  524. // Function: ServiceViolation
  525. //
  526. // Summary;
  527. // Check the given Service structure for violation
  528. //
  529. // Arguments;
  530. // hwndDlg [in] - hwnd of dialog to use to raise legal voilation dialog
  531. // pszComputer [in] - the name of the computer to work on
  532. // pServ [in] - Service structure to check
  533. //
  534. //
  535. // Return: FALSE if violation not made
  536. // TRUE if violation was made
  537. //
  538. // History;
  539. // Nov-30-94 MikeMi Created
  540. //
  541. //-------------------------------------------------------------------
  542. BOOL ServiceViolation( HWND hwndDlg, LPCWSTR pszComputer, PSERVICEENTRY pServ )
  543. {
  544. CLicRegLicenseService cLicServKey;
  545. LICENSE_MODE lm;
  546. DWORD dwLimit;
  547. BOOL frt = FALSE;
  548. cLicServKey.SetService( pServ->pszService );
  549. if (ERROR_SUCCESS == cLicServKey.Open( pszComputer, FALSE ))
  550. {
  551. cLicServKey.GetMode( lm );
  552. // check for changes
  553. if ( (pServ->lm != lm) && !cLicServKey.CanChangeMode() )
  554. {
  555. frt = LicViolationDialog( hwndDlg );
  556. }
  557. cLicServKey.Close();
  558. }
  559. return( frt );
  560. }
  561. //-------------------------------------------------------------------
  562. //
  563. // Function: EditInvalidDlg
  564. //
  565. // Summary;
  566. // Display Dialog when user count edit control value is invalid
  567. //
  568. // Arguments;
  569. // hwndDlg [in] - hwnd of dialog
  570. //
  571. // History;
  572. // Nov-30-94 MikeMi Created
  573. //
  574. //-------------------------------------------------------------------
  575. void EditInvalidDlg( HWND hwndDlg )
  576. {
  577. HWND hwndCount = GetDlgItem( hwndDlg, IDC_USERCOUNT);
  578. WCHAR szTitle[TEMPSTR_SIZE];
  579. WCHAR szText[LTEMPSTR_SIZE];
  580. WCHAR szTemp[LTEMPSTR_SIZE];
  581. MessageBeep( MB_VALUELIMIT );
  582. LoadString(g_hinst, IDS_CPCAPTION, szTitle, TEMPSTR_SIZE);
  583. LoadString(g_hinst, IDS_INVALIDUSERCOUNT, szTemp, LTEMPSTR_SIZE);
  584. wsprintf( szText, szTemp, PERSERVER_MIN, PERSERVER_MAX );
  585. MessageBox( hwndDlg, szText, szTitle, MB_OK | MB_ICONINFORMATION );
  586. // also set focus to edit and select all
  587. SetFocus( hwndCount );
  588. SendMessage( hwndCount, EM_SETSEL, 0, -1 );
  589. }
  590. //-------------------------------------------------------------------
  591. //
  592. // Function: EditValidate
  593. //
  594. // Summary;
  595. // Handle when the value within the user count edit control changes
  596. //
  597. // Arguments;
  598. // hwndDlg [in] - hwnd of dialog
  599. // pserv [in] - currently selected service
  600. //
  601. // Return: FALSE if Edit Value is not valid, TRUE if it is
  602. //
  603. // History;
  604. // Nov-30-94 MikeMi Created
  605. //
  606. //-------------------------------------------------------------------
  607. BOOL EditValidate( HWND hwndDlg, PSERVICEENTRY pServ )
  608. {
  609. BOOL fTranslated;
  610. UINT nValue;
  611. BOOL fValid = TRUE;
  612. // only do this if in PerServer mode
  613. //
  614. if (LICMODE_PERSERVER == pServ->lm)
  615. {
  616. fValid = FALSE;
  617. nValue = GetDlgItemInt( hwndDlg, IDC_USERCOUNT, &fTranslated, FALSE );
  618. if (fTranslated)
  619. {
  620. if (VALIDUSERCOUNT( nValue))
  621. {
  622. pServ->dwLimit = nValue;
  623. fValid = TRUE;
  624. }
  625. }
  626. }
  627. return( fValid );
  628. }
  629. //-------------------------------------------------------------------
  630. //
  631. // Function: OnEditChange
  632. //
  633. // Summary;
  634. // Handle when the value within the user count edit control changes
  635. //
  636. // Arguments;
  637. // hwndDlg [in] - hwnd of dialog
  638. // pserv [in] - currently selected service
  639. //
  640. // History;
  641. // Mar-06-94 MikeMi Created
  642. //
  643. //-------------------------------------------------------------------
  644. void OnEditChange( HWND hwndDlg, HWND hwndCount, PSERVICEENTRY pServ )
  645. {
  646. BOOL fTranslated;
  647. UINT nValue;
  648. BOOL fValid = TRUE;
  649. BOOL fModified = FALSE;
  650. // only do this if in PerServer mode
  651. //
  652. if (LICMODE_PERSERVER == pServ->lm)
  653. {
  654. fValid = FALSE;
  655. nValue = GetDlgItemInt( hwndDlg, IDC_USERCOUNT, &fTranslated, FALSE );
  656. if (fTranslated)
  657. {
  658. #pragma warning(push)
  659. #pragma warning(disable: 4296) // C4296: '>' : expression is always false
  660. if (PERSERVER_MIN > nValue)
  661. {
  662. nValue = PERSERVER_MIN;
  663. fModified = TRUE;
  664. }
  665. else if (PERSERVER_MAX < nValue)
  666. {
  667. nValue = PERSERVER_MAX;
  668. fModified = TRUE;
  669. }
  670. #pragma warning(pop)
  671. pServ->dwLimit = nValue;
  672. }
  673. else
  674. {
  675. // reset to last value
  676. nValue = pServ->dwLimit;
  677. fModified = TRUE;
  678. }
  679. if (fModified)
  680. {
  681. SetDlgItemInt( hwndDlg, IDC_USERCOUNT, nValue, FALSE );
  682. SetFocus( hwndCount );
  683. SendMessage( hwndCount, EM_SETSEL, 0, -1 );
  684. MessageBeep( MB_VALUELIMIT );
  685. }
  686. }
  687. }
  688. //-------------------------------------------------------------------
  689. //
  690. // Function: OnCpaClose
  691. //
  692. // Summary;
  693. // Do work needed when the Control Panel applet is closed.
  694. // Free all Service structures alloced and possible save.
  695. //
  696. // Arguments;
  697. // hwndDlg [in] - Dialog close was requested on
  698. // fSave [in] - Save Services to Registry
  699. //
  700. // History;
  701. // Nov-30-94 MikeMi Created
  702. //
  703. //-------------------------------------------------------------------
  704. void OnCpaClose( HWND hwndDlg, BOOL fSave )
  705. {
  706. WCHAR szText[TEMPSTR_SIZE];
  707. HWND hwndService = GetDlgItem( hwndDlg, IDC_SERVICES);
  708. LRESULT cItems = SendMessage( hwndService, CB_GETCOUNT, 0, 0 ) - 1;
  709. LONG_PTR iItem;
  710. PSERVICEENTRY pServ;
  711. LRESULT iSel;
  712. iSel = SendMessage( hwndService, CB_GETCURSEL, 0, 0 );
  713. pServ = (PSERVICEENTRY)SendMessage( hwndService, CB_GETITEMDATA, iSel, 0 );
  714. if ( fSave &&
  715. (pServ->lm == LICMODE_PERSERVER) &&
  716. !EditValidate( hwndDlg, pServ ) )
  717. {
  718. EditInvalidDlg( hwndDlg );
  719. }
  720. else
  721. {
  722. BOOL fCompleted = TRUE;
  723. // loop and check for agreement changes (only needed if saving)
  724. //
  725. if (fSave)
  726. {
  727. for (iItem = cItems; iItem >= 0; iItem--)
  728. {
  729. pServ = (PSERVICEENTRY)SendMessage( hwndService, CB_GETITEMDATA, iItem, 0 );
  730. if (ServiceLicAgreement( hwndDlg,
  731. pServ,
  732. NULL,
  733. LICCPA_HELPFILE,
  734. LICCPA_HELPCONTEXTPERSEAT,
  735. LICCPA_HELPCONTEXTPERSERVER ))
  736. {
  737. SaveServiceToReg( NULL, pServ );
  738. }
  739. else
  740. {
  741. fCompleted = FALSE;
  742. break;
  743. }
  744. }
  745. }
  746. if (fCompleted)
  747. {
  748. // loop and free service entries
  749. //
  750. for (iItem = cItems; iItem >= 0; iItem--)
  751. {
  752. pServ = (PSERVICEENTRY)SendMessage( hwndService, CB_GETITEMDATA, iItem, 0 );
  753. FreeServiceEntry( pServ );
  754. }
  755. EndDialog( hwndDlg, fSave );
  756. }
  757. else
  758. {
  759. // set combo box to last canceled entry
  760. SendMessage( hwndService, CB_SETCURSEL, iItem, 0 );
  761. }
  762. }
  763. }
  764. //-------------------------------------------------------------------
  765. //
  766. // Function: OnSetupClose
  767. //
  768. // Summary;
  769. // Do work needed when the Setup Dialog is closed.
  770. // Free the service structure and possible save it
  771. //
  772. // Arguments;
  773. // hwndDlg [in] - hwnd of dialog this close was requested on
  774. // fSave [in] - Save service to registry
  775. // pServ [in] - the service structure to work with
  776. // psdParams [in] - setup dlg params for help contexts and files
  777. //
  778. // History;
  779. // Nov-30-94 MikeMi Created
  780. //
  781. //-------------------------------------------------------------------
  782. void OnSetupClose( HWND hwndDlg,
  783. BOOL fSave,
  784. PSERVICEENTRY pServ,
  785. PSETUPDLGPARAM psdParams )
  786. {
  787. if ( fSave &&
  788. (pServ->lm == LICMODE_PERSERVER) &&
  789. !EditValidate( hwndDlg, pServ ) )
  790. {
  791. EditInvalidDlg( hwndDlg );
  792. }
  793. else
  794. {
  795. BOOL fCompleted = TRUE;
  796. if (fSave)
  797. {
  798. if (ServiceLicAgreement( hwndDlg,
  799. pServ,
  800. psdParams->pszComputer,
  801. psdParams->pszHelpFile,
  802. psdParams->dwHCPerSeat,
  803. psdParams->dwHCPerServer ))
  804. {
  805. SaveServiceToReg( psdParams->pszComputer, pServ );
  806. // register service at enterprise server
  807. ServiceRegister( psdParams->pszComputer,
  808. psdParams->pszFamilyDisplayName,
  809. psdParams->pszDisplayName );
  810. }
  811. else
  812. {
  813. fCompleted = FALSE;
  814. }
  815. }
  816. else if ( pServ->fIsNewProduct )
  817. {
  818. // new product, but we're aborting
  819. // make sure we don't leave any scraps behind
  820. DWORD winError;
  821. HKEY hkeyInfo;
  822. winError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  823. TEXT( "System\\CurrentControlSet\\Services\\LicenseInfo" ),
  824. 0,
  825. KEY_ALL_ACCESS,
  826. &hkeyInfo );
  827. if ( ERROR_SUCCESS == winError )
  828. {
  829. RegDeleteKey( hkeyInfo, pServ->pszService );
  830. RegCloseKey( hkeyInfo );
  831. }
  832. }
  833. if (fCompleted)
  834. {
  835. FreeServiceEntry( pServ );
  836. EndDialog( hwndDlg, fSave );
  837. }
  838. }
  839. }
  840. //-------------------------------------------------------------------
  841. //
  842. // Function: OnSetServiceMode
  843. //
  844. // Summary;
  845. // Handle the users request to change service mode
  846. //
  847. // Aruments;
  848. // hwndDlg [in] - hwnd of dialog
  849. // pszComputer [in] - compter to confirm mode change against
  850. // pServ [in] - The service the request was made agianst
  851. // idCtrl [in] - the control id that was pressed to make this request
  852. //
  853. // History;
  854. // Nov-30-94 MikeMi Created
  855. //
  856. //-------------------------------------------------------------------
  857. void OnSetServiceMode( HWND hwndDlg, LPCWSTR pszComputer, PSERVICEENTRY pServ, WORD idCtrl )
  858. {
  859. LICENSE_MODE lmOld = pServ->lm;
  860. BOOL fChanged = FALSE;
  861. if (idCtrl == IDC_PERSEAT)
  862. {
  863. fChanged = (pServ->lm != LICMODE_PERSEAT);
  864. pServ->lm = LICMODE_PERSEAT;
  865. }
  866. else
  867. {
  868. fChanged = (pServ->lm != LICMODE_PERSERVER);
  869. pServ->lm = LICMODE_PERSERVER;
  870. }
  871. //
  872. // only check for violation the first time the user switches
  873. //
  874. if (fChanged && ServiceViolation( hwndDlg, pszComputer, pServ ))
  875. {
  876. pServ->lm = lmOld;
  877. InitDialogForService( hwndDlg, pServ );
  878. }
  879. }
  880. //-------------------------------------------------------------------
  881. //
  882. // Function: OnSpinButton
  883. //
  884. // Summary;
  885. // Handle the events from user interactions with the spin control
  886. //
  887. // Arguments;
  888. // hwndDlg [in] - hwnd of dialog
  889. // wAction [in] - spin control event
  890. // pServ [in] - current service selected
  891. //
  892. // History;
  893. // Nov-30-94 MikeMi Created
  894. //
  895. //-------------------------------------------------------------------
  896. void OnSpinButton( HWND hwndDlg, WORD wAction, PSERVICEENTRY pServ )
  897. {
  898. HWND hwndCount = GetDlgItem( hwndDlg, IDC_USERCOUNT);
  899. INT nValue;
  900. BOOL fValidAction = TRUE;
  901. nValue = pServ->dwLimit;
  902. switch (wAction)
  903. {
  904. case SB_LINEUP:
  905. nValue++;
  906. break;
  907. case SB_LINEDOWN:
  908. nValue--;
  909. break;
  910. case SB_PAGEUP:
  911. nValue += PERSERVER_PAGE;
  912. break;
  913. case SB_PAGEDOWN:
  914. nValue -= PERSERVER_PAGE;
  915. break;
  916. case SB_TOP:
  917. nValue = PERSERVER_MAX;
  918. break;
  919. case SB_BOTTOM:
  920. nValue = PERSERVER_MIN;
  921. break;
  922. default:
  923. fValidAction = FALSE;
  924. break;
  925. }
  926. if (fValidAction)
  927. {
  928. nValue = max( PERSERVER_MIN, nValue );
  929. nValue = min( PERSERVER_MAX, nValue );
  930. if (pServ->dwLimit == (DWORD)nValue)
  931. {
  932. MessageBeep( MB_VALUELIMIT );
  933. }
  934. else
  935. {
  936. pServ->dwLimit = nValue;
  937. SetDlgItemInt( hwndDlg, IDC_USERCOUNT, pServ->dwLimit, FALSE );
  938. }
  939. SetFocus( hwndCount );
  940. SendMessage( hwndCount, EM_SETSEL, 0, -1 );
  941. }
  942. }
  943. //-------------------------------------------------------------------
  944. //
  945. // Function: UpdatePerServerLicenses
  946. //
  947. // Summary;
  948. // Update the number of per server licenses displayed in the
  949. // dialog with the proper value.
  950. //
  951. // Arguments;
  952. // hwndDlg [in] - hwnd of dialog
  953. // pServ [in] - current service selected
  954. //
  955. // History;
  956. // Dec-19-95 JeffParh Created
  957. //
  958. //-------------------------------------------------------------------
  959. static void UpdatePerServerLicenses( HWND hwndDlg, PSERVICEENTRY pServ )
  960. {
  961. LLS_HANDLE hLls;
  962. DWORD dwError;
  963. BOOL fIsSecure;
  964. BOOL fUseRegistry;
  965. fUseRegistry = TRUE;
  966. dwError = LlsConnect( pServ->pszComputer, &hLls );
  967. if ( ERROR_SUCCESS == dwError )
  968. {
  969. if ( pServ->fIsNewProduct )
  970. {
  971. dwError = LlsProductSecurityGet( hLls, pServ->pszDisplayName, &fIsSecure );
  972. if ( ( ERROR_SUCCESS == dwError )
  973. && fIsSecure )
  974. {
  975. dwError = LlsProductLicensesGet( hLls, pServ->pszDisplayName, LLS_LICENSE_MODE_PER_SERVER, &pServ->dwLimit );
  976. if ( ERROR_SUCCESS == dwError )
  977. {
  978. fUseRegistry = FALSE;
  979. }
  980. }
  981. }
  982. else
  983. {
  984. dwError = LlsProductLicensesGet( hLls, pServ->pszDisplayName, LLS_LICENSE_MODE_PER_SERVER, &pServ->dwLimit );
  985. if ( ERROR_SUCCESS == dwError )
  986. {
  987. fUseRegistry = FALSE;
  988. }
  989. }
  990. LlsClose( hLls );
  991. }
  992. if ( fUseRegistry )
  993. {
  994. CLicRegLicenseService cLicServKey;
  995. cLicServKey.SetService( pServ->pszService );
  996. cLicServKey.Open( NULL, FALSE );
  997. cLicServKey.GetUserLimit( pServ->dwLimit );
  998. cLicServKey.Close();
  999. }
  1000. SetDlgItemInt( hwndDlg, IDC_USERCOUNT, pServ->dwLimit, FALSE );
  1001. UpdateWindow( hwndDlg );
  1002. }
  1003. //-------------------------------------------------------------------
  1004. //
  1005. // Function: OnAddLicenses
  1006. //
  1007. // Summary;
  1008. // Handle the BN_CLICKED message from the Add Licenses button.
  1009. //
  1010. // Arguments;
  1011. // hwndDlg [in] - hwnd of dialog
  1012. // pServ [in] - current service selected
  1013. //
  1014. // History;
  1015. // Dec-19-95 JeffParh Created
  1016. //
  1017. //-------------------------------------------------------------------
  1018. void OnAddLicenses( HWND hwndDlg, PSERVICEENTRY pServ )
  1019. {
  1020. LPSTR pszAscProductName;
  1021. LPSTR pszAscServerName = NULL;
  1022. CHAR szAscServerName[ 3 + MAX_PATH ];
  1023. pszAscProductName = (LPSTR) LocalAlloc( LPTR, 1 + lstrlen(pServ->pszDisplayName) );
  1024. if ( NULL != pszAscProductName )
  1025. {
  1026. wsprintfA( pszAscProductName, "%ls", pServ->pszDisplayName );
  1027. if ( NULL != pServ->pszComputer )
  1028. {
  1029. wsprintfA( szAscServerName, "%ls", pServ->pszComputer );
  1030. pszAscServerName = szAscServerName;
  1031. }
  1032. CCFCertificateEnterUI( hwndDlg, pszAscServerName, pszAscProductName, "Microsoft", CCF_ENTER_FLAG_PER_SERVER_ONLY, NULL );
  1033. UpdatePerServerLicenses( hwndDlg, pServ );
  1034. LocalFree( pszAscProductName );
  1035. g_fWarned = TRUE;
  1036. }
  1037. }
  1038. //-------------------------------------------------------------------
  1039. //
  1040. // Function: OnRemoveLicenses
  1041. //
  1042. // Summary;
  1043. // Handle the BN_CLICKED message from the Remove Licenses button.
  1044. //
  1045. // Arguments;
  1046. // hwndDlg [in] - hwnd of dialog
  1047. // pServ [in] - current service selected
  1048. //
  1049. // History;
  1050. // Dec-19-95 JeffParh Created
  1051. //
  1052. //-------------------------------------------------------------------
  1053. void OnRemoveLicenses( HWND hwndDlg, PSERVICEENTRY pServ )
  1054. {
  1055. LPSTR pszAscProductName;
  1056. LPSTR pszAscServerName = NULL;
  1057. CHAR szAscServerName[ 3 + MAX_PATH ];
  1058. pszAscProductName = (LPSTR) LocalAlloc( LMEM_FIXED, 1 + lstrlen(pServ->pszDisplayName) );
  1059. if ( NULL != pszAscProductName )
  1060. {
  1061. wsprintfA( pszAscProductName, "%ls", pServ->pszDisplayName );
  1062. if ( NULL != pServ->pszComputer )
  1063. {
  1064. wsprintfA( szAscServerName, "%ls", pServ->pszComputer );
  1065. pszAscServerName = szAscServerName;
  1066. }
  1067. CCFCertificateRemoveUI( hwndDlg, pszAscServerName, pszAscProductName, "Microsoft", NULL, NULL );
  1068. UpdatePerServerLicenses( hwndDlg, pServ );
  1069. LocalFree( pszAscProductName );
  1070. }
  1071. }
  1072. //-------------------------------------------------------------------
  1073. //
  1074. // Function: OnSetupInitDialog
  1075. //
  1076. // Summary;
  1077. // Handle the initialization of the Setup Dialog
  1078. //
  1079. // Arguments;
  1080. // hwndDlg [in] - the dialog to initialize
  1081. // pszParams [in] - the dialog params to use to initialize
  1082. // pServ [out] - the current service
  1083. //
  1084. // Return;
  1085. // TRUE if succesful, otherwise false
  1086. //
  1087. // Notes;
  1088. //
  1089. // History;
  1090. // Nov-11-1994 MikeMi Created
  1091. //
  1092. //-------------------------------------------------------------------
  1093. BOOL OnSetupInitDialog( HWND hwndDlg,
  1094. PSETUPDLGPARAM psdParams,
  1095. PSERVICEENTRY& pServ )
  1096. {
  1097. BOOL frt = TRUE;
  1098. CLicRegLicense cLicKey;
  1099. LONG lrt;
  1100. INT nrt;
  1101. BOOL fNew;
  1102. do
  1103. {
  1104. CenterDialogToScreen( hwndDlg );
  1105. lrt = cLicKey.Open( fNew, psdParams->pszComputer );
  1106. nrt = AccessOk( hwndDlg, lrt, FALSE );
  1107. if (ERR_NONE != nrt)
  1108. {
  1109. EndDialog( hwndDlg, nrt );
  1110. frt = FALSE;
  1111. break;
  1112. }
  1113. pServ = CreateServiceEntry( psdParams->pszComputer,
  1114. psdParams->pszService,
  1115. psdParams->pszFamilyDisplayName,
  1116. psdParams->pszDisplayName );
  1117. if (pServ == NULL)
  1118. {
  1119. LowMemoryDlg();
  1120. EndDialog( hwndDlg, -2 );
  1121. break;
  1122. }
  1123. if (NULL == psdParams->pszHelpFile)
  1124. {
  1125. HWND hwndHelp = GetDlgItem( hwndDlg, IDC_BUTTONHELP );
  1126. // remove the help button
  1127. EnableWindow( hwndHelp, FALSE );
  1128. ShowWindow( hwndHelp, SW_HIDE );
  1129. }
  1130. if (psdParams->fNoExit)
  1131. {
  1132. HWND hwndExit = GetDlgItem( hwndDlg, IDCANCEL );
  1133. // remove the ExitSetup button
  1134. EnableWindow( hwndExit, FALSE );
  1135. ShowWindow( hwndExit, SW_HIDE );
  1136. }
  1137. // set char limit on edit box
  1138. InitUserEdit( hwndDlg );
  1139. // make sure title static text is set for this service
  1140. InitTitleText( hwndDlg, pServ );
  1141. // defaul to PerServer with Focus on edit
  1142. pServ->lm = LICMODE_PERSERVER;
  1143. // change default for setup only
  1144. // pServ->dwLimit = 1;
  1145. InitDialogForService( hwndDlg, pServ );
  1146. SetFocus( GetDlgItem( hwndDlg, IDC_PERSERVER ) );
  1147. } while (FALSE); // used to remove gotos
  1148. return( frt );
  1149. }
  1150. //-------------------------------------------------------------------
  1151. //
  1152. // Function: OnCpaInitDialog
  1153. //
  1154. // Summary;
  1155. // Handle the initialization of the Control Panel Applet Dialog
  1156. //
  1157. // Arguments;
  1158. // hwndDlg [in] - the dialog to initialize
  1159. // fEnableReplication [in] -
  1160. // iSel [out] - the current service selected
  1161. // pServ [out] - the current service
  1162. //
  1163. // Return;
  1164. // TRUE if succesful, otherwise false
  1165. //
  1166. // Notes;
  1167. //
  1168. // History;
  1169. // Nov-11-1994 MikeMi Created
  1170. // Mar-08-1995 MikeMi Added removal of Replication button
  1171. //
  1172. //-------------------------------------------------------------------
  1173. BOOL OnCpaInitDialog( HWND hwndDlg,
  1174. BOOL fEnableReplication,
  1175. LONG_PTR& iSel,
  1176. PSERVICEENTRY& pServ )
  1177. {
  1178. BOOL frt = FALSE;
  1179. CLicRegLicense cLicKey;
  1180. LONG lrt;
  1181. INT nrt;
  1182. BOOL fNew;
  1183. lrt = cLicKey.Open( fNew );
  1184. nrt = AccessOk( hwndDlg, lrt, TRUE );
  1185. if (ERR_NONE == nrt)
  1186. {
  1187. DWORD i = 0;
  1188. WCHAR szText[TEMPSTR_SIZE];
  1189. DWORD cchText = TEMPSTR_SIZE;
  1190. HWND hwndService = GetDlgItem( hwndDlg, IDC_SERVICES);
  1191. LONG_PTR lIndex;
  1192. CenterDialogToScreen( hwndDlg );
  1193. //
  1194. // remove replication button if product used on pre 3.51
  1195. //
  1196. if (!fEnableReplication)
  1197. {
  1198. HWND hwndRep = GetDlgItem( hwndDlg, IDC_CONFIGURE );
  1199. EnableWindow( hwndRep, FALSE );
  1200. ShowWindow( hwndRep, SW_HIDE );
  1201. }
  1202. // load the service names from the registry into combo box
  1203. // Create service local state structures as we go
  1204. //
  1205. while (ERROR_SUCCESS == cLicKey.EnumService(i, szText, cchText ))
  1206. {
  1207. pServ = CreateServiceEntry( NULL, szText, L"<unknown>", L"<undefined>" );
  1208. if (pServ == NULL)
  1209. {
  1210. LowMemoryDlg();
  1211. EndDialog( hwndDlg, -2 );
  1212. return( TRUE );
  1213. }
  1214. lIndex = SendMessage( hwndService, CB_ADDSTRING, 0, (LPARAM)pServ->pszDisplayName );
  1215. SendMessage( hwndService, CB_SETITEMDATA, lIndex, (LPARAM)pServ );
  1216. i++;
  1217. cchText = TEMPSTR_SIZE;
  1218. }
  1219. cLicKey.Close();
  1220. if (0 == i)
  1221. {
  1222. // no services installed
  1223. //
  1224. WCHAR szText[TEMPSTR_SIZE];
  1225. WCHAR szTitle[TEMPSTR_SIZE];
  1226. LoadString(g_hinst, IDS_CPCAPTION, szTitle, TEMPSTR_SIZE);
  1227. LoadString(g_hinst, IDS_NOSERVICES, szText, TEMPSTR_SIZE);
  1228. MessageBox(hwndDlg, szText, szTitle, MB_OK|MB_ICONINFORMATION);
  1229. frt = FALSE;
  1230. }
  1231. else
  1232. {
  1233. // make sure a service is selected and update dialog
  1234. iSel = SendMessage( hwndService, CB_GETCURSEL, 0, 0 );
  1235. if (CB_ERR == iSel)
  1236. {
  1237. iSel = 0;
  1238. SendMessage( hwndService, CB_SETCURSEL, iSel, 0 );
  1239. }
  1240. pServ = (PSERVICEENTRY)SendMessage( hwndService, CB_GETITEMDATA, iSel, 0 );
  1241. // Set edit text chars limit
  1242. InitUserEdit( hwndDlg );
  1243. InitDialogForService( hwndDlg, pServ );
  1244. frt = TRUE;
  1245. }
  1246. }
  1247. if (!frt)
  1248. {
  1249. EndDialog( hwndDlg, -1 );
  1250. }
  1251. return( frt );
  1252. }
  1253. //-------------------------------------------------------------------
  1254. //
  1255. // Function: dlgprocLICCPA
  1256. //
  1257. // Summary;
  1258. // The dialog procedure for the main Control Panel Applet Dialog
  1259. //
  1260. // Arguments;
  1261. // hwndDlg [in] - handle of Dialog window
  1262. // uMsg [in] - message
  1263. // lParam1 [in] - first message parameter
  1264. // lParam2 [in] - second message parameter
  1265. //
  1266. // Return;
  1267. // message dependant
  1268. //
  1269. // Notes;
  1270. //
  1271. // History;
  1272. // Nov-11-1994 MikeMi Created
  1273. // Mar-08-1995 MikeMi Added removal of Replication button
  1274. // from WM_INITDIALOG
  1275. // Mar-14-95 MikeMi Added F1 PWM_HELP message
  1276. //
  1277. //-------------------------------------------------------------------
  1278. INT_PTR CALLBACK dlgprocLICCPA( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  1279. {
  1280. BOOL frt = FALSE;
  1281. static PSERVICEENTRY pServ = NULL;
  1282. static LONG_PTR iSel = 0;
  1283. switch (uMsg)
  1284. {
  1285. case WM_INITDIALOG:
  1286. OnCpaInitDialog( hwndDlg, (BOOL)lParam , iSel, pServ );
  1287. return( TRUE ); // use default keyboard focus
  1288. break;
  1289. case WM_COMMAND:
  1290. switch (HIWORD( wParam ))
  1291. {
  1292. case BN_CLICKED:
  1293. switch (LOWORD( wParam ))
  1294. {
  1295. case IDOK:
  1296. frt = TRUE; // use as save flag
  1297. // intentional no break
  1298. case IDCANCEL:
  1299. OnCpaClose( hwndDlg, frt );
  1300. frt = FALSE;
  1301. break;
  1302. case IDC_PERSEAT:
  1303. case IDC_PERSERVER:
  1304. OnSetServiceMode( hwndDlg, NULL, pServ, LOWORD(wParam) );
  1305. break;
  1306. case IDC_CONFIGURE:
  1307. DialogBox(g_hinst,
  1308. MAKEINTRESOURCE(IDD_CPADLG_LCACONF),
  1309. hwndDlg,
  1310. (DLGPROC)dlgprocLICCPACONFIG );
  1311. break;
  1312. case IDC_BUTTONHELP:
  1313. PostMessage( hwndDlg, PWM_HELP, 0, 0 );
  1314. break;
  1315. case IDC_ADD_LICENSES:
  1316. OnAddLicenses( hwndDlg, pServ );
  1317. break;
  1318. case IDC_REMOVE_LICENSES:
  1319. OnRemoveLicenses( hwndDlg, pServ );
  1320. break;
  1321. default:
  1322. break;
  1323. }
  1324. break;
  1325. case CBN_SELENDOK:
  1326. if ((LICMODE_PERSERVER == pServ->lm) &&
  1327. !EditValidate( hwndDlg, pServ ))
  1328. {
  1329. // reset back to original
  1330. SendMessage( (HWND)lParam, CB_SETCURSEL, iSel, 0 );
  1331. EditInvalidDlg( hwndDlg );
  1332. }
  1333. else
  1334. {
  1335. iSel = SendMessage( (HWND)lParam, CB_GETCURSEL, 0, 0 );
  1336. pServ = (PSERVICEENTRY)SendMessage( (HWND)lParam, CB_GETITEMDATA, iSel, 0 );
  1337. InitDialogForService( hwndDlg, pServ );
  1338. }
  1339. break;
  1340. case EN_UPDATE:
  1341. if (IDC_USERCOUNT == LOWORD(wParam))
  1342. {
  1343. OnEditChange( hwndDlg, (HWND)(lParam), pServ );
  1344. }
  1345. break;
  1346. default:
  1347. break;
  1348. }
  1349. break;
  1350. case WM_VSCROLL:
  1351. OnSpinButton( hwndDlg, LOWORD( wParam ), pServ );
  1352. break;
  1353. default:
  1354. if (PWM_HELP == uMsg)
  1355. {
  1356. ::HtmlHelp( hwndDlg, LICCPA_HTMLHELPFILE, HH_DISPLAY_TOPIC,0);
  1357. }
  1358. break;
  1359. }
  1360. return( frt );
  1361. }
  1362. //-------------------------------------------------------------------
  1363. //
  1364. // Function: dlgprocLICSETUP
  1365. //
  1366. // Summary;
  1367. // The dialog procedure for the Setup entry point Dialog
  1368. //
  1369. // Arguments;
  1370. // hwndDlg [in] - handle of Dialog window
  1371. // uMsg [in] - message
  1372. // lParam1 [in] - first message parameter
  1373. // lParam2 [in] - second message parameter
  1374. //
  1375. // Return;
  1376. // message dependant
  1377. //
  1378. // Notes;
  1379. //
  1380. // History;
  1381. // Nov-11-1994 MikeMi Created
  1382. // Mar-14-95 MikeMi Added F1 PWM_HELP message
  1383. //
  1384. //-------------------------------------------------------------------
  1385. INT_PTR CALLBACK dlgprocLICSETUP( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  1386. {
  1387. BOOL frt = FALSE;
  1388. static PSERVICEENTRY pServ;
  1389. static PSETUPDLGPARAM psdParams;
  1390. switch (uMsg)
  1391. {
  1392. case WM_INITDIALOG:
  1393. psdParams = (PSETUPDLGPARAM)lParam;
  1394. OnSetupInitDialog( hwndDlg, psdParams, pServ );
  1395. frt = FALSE; // we set the focus
  1396. break;
  1397. case WM_COMMAND:
  1398. switch (HIWORD( wParam ))
  1399. {
  1400. case BN_CLICKED:
  1401. switch (LOWORD( wParam ))
  1402. {
  1403. case IDOK:
  1404. frt = TRUE; // use as save flag
  1405. // intentional no break
  1406. case IDCANCEL:
  1407. OnSetupClose( hwndDlg, frt, pServ, psdParams );
  1408. frt = FALSE;
  1409. break;
  1410. case IDC_PERSEAT:
  1411. case IDC_PERSERVER:
  1412. OnSetServiceMode( hwndDlg, psdParams->pszComputer, pServ, LOWORD(wParam) );
  1413. break;
  1414. case IDC_BUTTONHELP:
  1415. PostMessage( hwndDlg, PWM_HELP, 0, 0 );
  1416. break;
  1417. case IDC_ADD_LICENSES:
  1418. OnAddLicenses( hwndDlg, pServ );
  1419. break;
  1420. case IDC_REMOVE_LICENSES:
  1421. OnRemoveLicenses( hwndDlg, pServ );
  1422. break;
  1423. default:
  1424. break;
  1425. }
  1426. break;
  1427. case EN_UPDATE:
  1428. if (IDC_USERCOUNT == LOWORD(wParam))
  1429. {
  1430. OnEditChange( hwndDlg, (HWND)(lParam), pServ );
  1431. }
  1432. break;
  1433. default:
  1434. break;
  1435. }
  1436. break;
  1437. case WM_VSCROLL:
  1438. OnSpinButton( hwndDlg, LOWORD( wParam ), pServ );
  1439. break;
  1440. default:
  1441. if (PWM_HELP == uMsg)
  1442. {
  1443. ::HtmlHelp( hwndDlg, LICCPA_HTMLHELPFILE, HH_DISPLAY_TOPIC,0);
  1444. }
  1445. break;
  1446. }
  1447. return( frt );
  1448. }
  1449. //-------------------------------------------------------------------
  1450. //
  1451. // Function: OnPerSeatInitDialog
  1452. //
  1453. // Summary;
  1454. // Handle the initialization of the PerSeat only Setup Dialog
  1455. //
  1456. // Arguments;
  1457. // hwndDlg [in] - the dialog to initialize
  1458. // psdParams [in] - used for the displayname and service name
  1459. //
  1460. // Notes;
  1461. //
  1462. // History;
  1463. // Dec-08-1994 MikeMi Created
  1464. //
  1465. //-------------------------------------------------------------------
  1466. void OnPerSeatInitDialog( HWND hwndDlg, PSETUPDLGPARAM psdParams )
  1467. {
  1468. HWND hwndOK = GetDlgItem( hwndDlg, IDOK );
  1469. CLicRegLicense cLicKey;
  1470. BOOL fNew;
  1471. LONG lrt;
  1472. INT nrt;
  1473. lrt = cLicKey.Open( fNew, psdParams->pszComputer );
  1474. nrt = AccessOk( NULL, lrt, FALSE );
  1475. if (ERR_NONE == nrt)
  1476. {
  1477. CenterDialogToScreen( hwndDlg );
  1478. InitStaticWithService( hwndDlg, IDC_STATICTITLE, psdParams->pszDisplayName );
  1479. InitStaticWithService2( hwndDlg, IDC_STATICINFO, psdParams->pszDisplayName );
  1480. // disable OK button at start!
  1481. EnableWindow( hwndOK, FALSE );
  1482. // if help is not defined, remove the button
  1483. if (NULL == psdParams->pszHelpFile)
  1484. {
  1485. HWND hwndHelp = GetDlgItem( hwndDlg, IDC_BUTTONHELP );
  1486. EnableWindow( hwndHelp, FALSE );
  1487. ShowWindow( hwndHelp, SW_HIDE );
  1488. }
  1489. }
  1490. else
  1491. {
  1492. EndDialog( hwndDlg, nrt );
  1493. }
  1494. }
  1495. //-------------------------------------------------------------------
  1496. //
  1497. // Function: OnPerSeatSetupClose
  1498. //
  1499. // Summary;
  1500. // Do work needed when the Setup Dialog is closed.
  1501. // Save to Reg the Service entry.
  1502. //
  1503. // Arguments;
  1504. // hwndDlg [in] - hwnd of dialog this close was requested on
  1505. // fSave [in] - Save service to registry
  1506. // psdParams [in] - used for the service name and displayname
  1507. //
  1508. // History;
  1509. // Nov-30-94 MikeMi Created
  1510. //
  1511. //-------------------------------------------------------------------
  1512. void OnPerSeatSetupClose( HWND hwndDlg, BOOL fSave, PSETUPDLGPARAM psdParams )
  1513. {
  1514. int nrt = fSave;
  1515. if (fSave)
  1516. {
  1517. CLicRegLicenseService cLicServKey;
  1518. cLicServKey.SetService( psdParams->pszService );
  1519. cLicServKey.Open( psdParams->pszComputer );
  1520. // configure license rule of one change from PerServer to PerSeat
  1521. //
  1522. cLicServKey.SetChangeFlag( TRUE );
  1523. cLicServKey.SetUserLimit( 0 );
  1524. cLicServKey.SetDisplayName( psdParams->pszDisplayName );
  1525. cLicServKey.SetFamilyDisplayName( psdParams->pszFamilyDisplayName );
  1526. cLicServKey.SetMode( LICMODE_PERSEAT );
  1527. cLicServKey.Close();
  1528. // register service at enterprise server
  1529. ServiceRegister( psdParams->pszComputer,
  1530. psdParams->pszFamilyDisplayName,
  1531. psdParams->pszDisplayName );
  1532. }
  1533. EndDialog( hwndDlg, nrt );
  1534. }
  1535. //-------------------------------------------------------------------
  1536. //
  1537. // Function: OnPerSeatAgree
  1538. //
  1539. // Summary;
  1540. // Handle the user interaction with the Agree Check box
  1541. //
  1542. // Arguments;
  1543. // hwndDlg [in] - the dialog to initialize
  1544. //
  1545. // Return;
  1546. // TRUE if succesful, otherwise false
  1547. //
  1548. // Notes;
  1549. //
  1550. // History;
  1551. // Nov-11-1994 MikeMi Created
  1552. //
  1553. //-------------------------------------------------------------------
  1554. void OnPerSeatAgree( HWND hwndDlg )
  1555. {
  1556. HWND hwndOK = GetDlgItem( hwndDlg, IDOK );
  1557. BOOL fChecked = !IsDlgButtonChecked( hwndDlg, IDC_AGREE );
  1558. CheckDlgButton( hwndDlg, IDC_AGREE, fChecked );
  1559. EnableWindow( hwndOK, fChecked );
  1560. }
  1561. //-------------------------------------------------------------------
  1562. //
  1563. // Function: dlgprocPERSEATSETUP
  1564. //
  1565. // Summary;
  1566. // The dialog procedure for the PerSeat only Setup Dialog
  1567. //
  1568. // Arguments;
  1569. // hwndDlg [in] - handle of Dialog window
  1570. // uMsg [in] - message
  1571. // lParam1 [in] - first message parameter
  1572. // lParam2 [in] - second message parameter
  1573. //
  1574. // Return;
  1575. // message dependant
  1576. //
  1577. // Notes;
  1578. //
  1579. // History;
  1580. // Nov-11-1994 MikeMi Created
  1581. // Mar-14-95 MikeMi Added F1 PWM_HELP message
  1582. //
  1583. //-------------------------------------------------------------------
  1584. INT_PTR CALLBACK dlgprocPERSEATSETUP( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  1585. {
  1586. BOOL frt = FALSE;
  1587. static PSETUPDLGPARAM psdParams;
  1588. switch (uMsg)
  1589. {
  1590. case WM_INITDIALOG:
  1591. psdParams = (PSETUPDLGPARAM)lParam;
  1592. OnPerSeatInitDialog( hwndDlg, psdParams );
  1593. frt = TRUE; // we use the default focus
  1594. break;
  1595. case WM_COMMAND:
  1596. switch (HIWORD( wParam ))
  1597. {
  1598. case BN_CLICKED:
  1599. switch (LOWORD( wParam ))
  1600. {
  1601. case IDOK:
  1602. frt = TRUE; // use as save flag
  1603. // intentional no break
  1604. case IDCANCEL:
  1605. OnPerSeatSetupClose( hwndDlg, frt, psdParams );
  1606. frt = FALSE;
  1607. break;
  1608. case IDC_BUTTONHELP:
  1609. PostMessage( hwndDlg, PWM_HELP, 0, 0 );
  1610. break;
  1611. case IDC_AGREE:
  1612. OnPerSeatAgree( hwndDlg );
  1613. break;
  1614. default:
  1615. break;
  1616. }
  1617. break;
  1618. default:
  1619. break;
  1620. }
  1621. break;
  1622. default:
  1623. if (PWM_HELP == uMsg)
  1624. {
  1625. ::HtmlHelp( hwndDlg, LICCPA_HTMLHELPFILE, HH_DISPLAY_TOPIC,0);
  1626. }
  1627. break;
  1628. }
  1629. return( frt );
  1630. }
  1631. //-------------------------------------------------------------------
  1632. //
  1633. // Function: SetupDialog
  1634. //
  1635. // Summary;
  1636. // Init and raises main setup dialog.
  1637. //
  1638. // Arguments;
  1639. // hwndDlg [in] - handle of Dialog window
  1640. // dlgParem [in] - Setup params
  1641. //
  1642. // Return;
  1643. // 1 - OK button was used to exit
  1644. // 0 - Cancel button was used to exit
  1645. // -1 - General Dialog error
  1646. //
  1647. // Notes;
  1648. //
  1649. // History;
  1650. // Dec-05-1994 MikeMi Created
  1651. //
  1652. //-------------------------------------------------------------------
  1653. INT_PTR SetupDialog( HWND hwndParent, SETUPDLGPARAM& dlgParam )
  1654. {
  1655. INT_PTR nError;
  1656. nError = DialogBoxParam( g_hinst,
  1657. MAKEINTRESOURCE(IDD_SETUPDLG),
  1658. hwndParent,
  1659. (DLGPROC)dlgprocLICSETUP,
  1660. (LPARAM)&dlgParam );
  1661. return( nError );
  1662. }
  1663. //-------------------------------------------------------------------
  1664. //
  1665. // Function: PerSeatSetupDialog
  1666. //
  1667. // Summary;
  1668. // Init and raises Per Seat only setup dialog.
  1669. //
  1670. // Arguments;
  1671. // hwndDlg [in] - handle of Dialog window
  1672. // dlgParem [in] - Setup params
  1673. //
  1674. // Return;
  1675. // 1 - OK button was used to exit
  1676. // 0 - Cancel button was used to exit
  1677. // -1 - General Dialog error
  1678. //
  1679. // Notes;
  1680. //
  1681. // History;
  1682. // Dec-05-1994 MikeMi Created
  1683. //
  1684. //-------------------------------------------------------------------
  1685. INT_PTR PerSeatSetupDialog( HWND hwndParent, SETUPDLGPARAM& dlgParam )
  1686. {
  1687. return( DialogBoxParam( g_hinst,
  1688. MAKEINTRESOURCE(IDD_SETUP2DLG),
  1689. hwndParent,
  1690. (DLGPROC)dlgprocPERSEATSETUP,
  1691. (LPARAM)&dlgParam ) );
  1692. }
  1693. //-------------------------------------------------------------------
  1694. //
  1695. // Function: CpaDialog
  1696. //
  1697. // Summary;
  1698. // Init and Raise the main control panel applet dialog
  1699. //
  1700. // Arguments;
  1701. // hwndParent [in] - handle of parent window (CONTROL.EXE window)
  1702. //
  1703. // Return;
  1704. // 1 - OK button was used to exit
  1705. // 0 - Cancel button was used to exit
  1706. // -1 - General Dialog error
  1707. //
  1708. // Notes;
  1709. //
  1710. // History;
  1711. // Dec-05-1994 MikeMi Created
  1712. // Mar-08-1995 MikeMi Changed to only one Dialog Resource, Replication Button
  1713. //
  1714. //-------------------------------------------------------------------
  1715. INT_PTR CpaDialog( HWND hwndParent )
  1716. {
  1717. INT_PTR nError;
  1718. OSVERSIONINFO version;
  1719. version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  1720. GetVersionEx( &version );
  1721. BOOL fReplicationEnabled;
  1722. //
  1723. // Only allow Replication Button on 3.51 and above
  1724. //
  1725. fReplicationEnabled = ( (version.dwMajorVersion > 3)
  1726. || (version.dwMajorVersion == 3 && version.dwMinorVersion >= 51) );
  1727. nError = DialogBoxParam( g_hinst,
  1728. MAKEINTRESOURCE(IDD_CPADLG_CONFIGURE),
  1729. hwndParent,
  1730. (DLGPROC)dlgprocLICCPA,
  1731. (LPARAM)fReplicationEnabled );
  1732. return( nError );
  1733. }
  1734. //-------------------------------------------------------------------
  1735. //
  1736. // Function: UpdateReg
  1737. //
  1738. // Summary;
  1739. // This function is used in unatteneded setup modes, it will
  1740. // configure the registry with the values passed.
  1741. //
  1742. // Arguments;
  1743. // pszComputer [in] - computer name (maybe null for local)
  1744. // pszService [in] - service key name
  1745. // pszFamilyDisplayName [in] - family display name
  1746. // pszDisplayName [in] - displayname
  1747. // lm [in] - license mode
  1748. // dwUsers [in] - number of conncurrent users
  1749. //
  1750. // Return;
  1751. // ERR_NONE - Successful
  1752. // ERR_USERSPARAM - invalid users count
  1753. // ERR_PERMISSIONDENIED - invalid access rights
  1754. //
  1755. // Notes;
  1756. //
  1757. // History;
  1758. // Dec-09-1994 MikeMi Created
  1759. // Apr-26-95 MikeMi Added Computer name and remoting
  1760. //
  1761. //-------------------------------------------------------------------
  1762. int UpdateReg( LPCWSTR pszComputer,
  1763. LPCWSTR pszService,
  1764. LPCWSTR pszFamilyDisplayName,
  1765. LPCWSTR pszDisplayName,
  1766. LICENSE_MODE lm,
  1767. DWORD dwUsers )
  1768. {
  1769. int nrt = ERR_NONE;
  1770. if (VALIDUSERCOUNT( dwUsers ))
  1771. {
  1772. CLicRegLicense cLicKey;
  1773. LONG lrt;
  1774. BOOL fNew;
  1775. lrt = cLicKey.Open( fNew, pszComputer );
  1776. nrt = AccessOk( NULL, lrt, FALSE );
  1777. if (ERR_NONE == nrt)
  1778. {
  1779. CLicRegLicenseService cLicServKey;
  1780. cLicServKey.SetService( pszService );
  1781. cLicServKey.Open( pszComputer );
  1782. // configure license rule of one change from PerServer to PerSeat
  1783. //
  1784. cLicServKey.SetChangeFlag( (LICMODE_PERSEAT == lm ) );
  1785. cLicServKey.SetUserLimit( dwUsers );
  1786. cLicServKey.SetDisplayName( pszDisplayName );
  1787. cLicServKey.SetFamilyDisplayName( pszFamilyDisplayName );
  1788. cLicServKey.SetMode( lm );
  1789. cLicServKey.Close();
  1790. }
  1791. }
  1792. else
  1793. {
  1794. nrt = ERR_USERSPARAM;
  1795. }
  1796. return( nrt );
  1797. }
  1798. //-------------------------------------------------------------------
  1799. //
  1800. // Function: ServiceSecuritySet
  1801. //
  1802. // Summary;
  1803. // Set security on a given product such that it requires a
  1804. // secure certificate for license entry.
  1805. //
  1806. // Arguments;
  1807. // pszComputer [in] - computer on which the license server resides
  1808. // pszDisplayName [in] - display name for the service
  1809. //
  1810. // History;
  1811. // Dec-19-95 JeffParh Created
  1812. //
  1813. //-------------------------------------------------------------------
  1814. int ServiceSecuritySet( LPWSTR pszComputer, LPWSTR pszDisplayName )
  1815. {
  1816. int nError;
  1817. NTSTATUS nt;
  1818. LLS_HANDLE hLls;
  1819. // register the product as secure on the target server
  1820. nt = LlsConnect( pszComputer, &hLls );
  1821. if ( STATUS_SUCCESS != nt )
  1822. {
  1823. nError = ERR_NOREMOTESERVER;
  1824. }
  1825. else
  1826. {
  1827. if ( !LlsCapabilityIsSupported( hLls, LLS_CAPABILITY_SECURE_CERTIFICATES ) )
  1828. {
  1829. nError = ERR_DOWNLEVEL;
  1830. }
  1831. else
  1832. {
  1833. nt = LlsProductSecuritySetW( hLls, pszDisplayName );
  1834. if ( STATUS_SUCCESS != nt )
  1835. {
  1836. nError = ERR_CERTREQFAILED;
  1837. }
  1838. else
  1839. {
  1840. nError = ERR_NONE;
  1841. }
  1842. }
  1843. LlsClose( hLls );
  1844. }
  1845. // register the product as secure on the enterprise server
  1846. // it is acceptable for this to fail (the enterprise server may
  1847. // be downlevel)
  1848. if ( ERR_NONE == nError )
  1849. {
  1850. PLLS_CONNECT_INFO_0 pConnectInfo = NULL;
  1851. nt = LlsConnectEnterprise( pszComputer, &hLls, 0, (LPBYTE *) &pConnectInfo );
  1852. if ( STATUS_SUCCESS == nt )
  1853. {
  1854. LlsFreeMemory( pConnectInfo );
  1855. if ( LlsCapabilityIsSupported( hLls, LLS_CAPABILITY_SECURE_CERTIFICATES ) )
  1856. {
  1857. LlsProductSecuritySetW( hLls, pszDisplayName );
  1858. }
  1859. LlsClose( hLls );
  1860. }
  1861. }
  1862. return nError;
  1863. }
  1864. //-------------------------------------------------------------------
  1865. //
  1866. // Function: ServiceRegister
  1867. //
  1868. // Summary;
  1869. // Register a service at the enterprise server corresponding to
  1870. // the given server so that per seat licenses may be added
  1871. // immediately, rather than it taking up until the next
  1872. // replication cycle for the product to be listed.
  1873. //
  1874. // Arguments;
  1875. // pszComputer [in] - computer for which to register the service
  1876. // pszFamilyDisplayName [in] - family display name of the service
  1877. // pszDisplayName [in] - display name of the service
  1878. //
  1879. // History;
  1880. // Dec-19-95 JeffParh Created
  1881. //
  1882. //-------------------------------------------------------------------
  1883. static int ServiceRegister( LPWSTR pszComputer,
  1884. LPWSTR pszFamilyDisplayName,
  1885. LPWSTR pszDisplayName )
  1886. {
  1887. int nError;
  1888. NTSTATUS nt;
  1889. LLS_HANDLE hLls;
  1890. PLLS_CONNECT_INFO_0 pConnectInfo = NULL;
  1891. // register the product as secure on the enterprise server
  1892. nt = LlsConnectEnterprise( pszComputer, &hLls, 0, (LPBYTE *) &pConnectInfo );
  1893. if ( STATUS_SUCCESS != nt )
  1894. {
  1895. nError = ERR_NOREMOTESERVER;
  1896. }
  1897. else
  1898. {
  1899. LlsFreeMemory( pConnectInfo );
  1900. nt = LlsProductAdd( hLls, pszFamilyDisplayName, pszDisplayName, TEXT( "" ) );
  1901. LlsClose( hLls );
  1902. if ( STATUS_SUCCESS != nt )
  1903. {
  1904. nError = ERR_NOREMOTESERVER;
  1905. }
  1906. else
  1907. {
  1908. nError = ERR_NONE;
  1909. }
  1910. }
  1911. return nError;
  1912. }