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.

1174 lines
24 KiB

  1. /*++
  2. Copyright (c) 1994-95 Microsoft Corporation
  3. Module Name:
  4. srvobj.cpp
  5. Abstract:
  6. Server object implementation.
  7. Author:
  8. Don Ryan (donryan) 04-Jan-1995
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. Jeff Parham (jeffparh) 30-Jan-1996
  13. o Modified to use LlsProductLicensesGet() to avoid race conditions in
  14. getting the correct number of concurrent licenses with secure products.
  15. o Ported to LlsLocalService API to remove dependencies on configuration
  16. information being in the registry.
  17. --*/
  18. #include "stdafx.h"
  19. #include "llsmgr.h"
  20. #include <lm.h>
  21. #include <lmwksta.h>
  22. #ifdef _DEBUG
  23. #undef THIS_FILE
  24. static char BASED_CODE THIS_FILE[] = __FILE__;
  25. #endif
  26. IMPLEMENT_DYNCREATE(CServer, CCmdTarget)
  27. BEGIN_MESSAGE_MAP(CServer, CCmdTarget)
  28. //{{AFX_MSG_MAP(CServer)
  29. // NOTE - the ClassWizard will add and remove mapping macros here.
  30. //}}AFX_MSG_MAP
  31. END_MESSAGE_MAP()
  32. BEGIN_DISPATCH_MAP(CServer, CCmdTarget)
  33. //{{AFX_DISPATCH_MAP(CServer)
  34. DISP_PROPERTY_EX(CServer, "Application", GetApplication, SetNotSupported, VT_DISPATCH)
  35. DISP_PROPERTY_EX(CServer, "Name", GetName, SetNotSupported, VT_BSTR)
  36. DISP_PROPERTY_EX(CServer, "Parent", GetParent, SetNotSupported, VT_DISPATCH)
  37. DISP_PROPERTY_EX(CServer, "Controller", GetController, SetNotSupported, VT_BSTR)
  38. DISP_PROPERTY_EX(CServer, "IsLogging", IsLogging, SetNotSupported, VT_BOOL)
  39. DISP_PROPERTY_EX(CServer, "IsReplicatingToDC", IsReplicatingToDC, SetNotSupported, VT_BOOL)
  40. DISP_PROPERTY_EX(CServer, "IsReplicatingDaily", IsReplicatingDaily, SetNotSupported, VT_BOOL)
  41. DISP_PROPERTY_EX(CServer, "ReplicationTime", GetReplicationTime, SetNotSupported, VT_I4)
  42. DISP_PROPERTY_PARAM(CServer, "Services", GetServices, SetNotSupported, VT_DISPATCH, VTS_VARIANT)
  43. DISP_DEFVALUE(CServer, "Name")
  44. //}}AFX_DISPATCH_MAP
  45. END_DISPATCH_MAP()
  46. CServer::CServer(CCmdTarget* pParent, LPCTSTR pName)
  47. /*++
  48. Routine Description:
  49. Constructor for server object.
  50. Arguments:
  51. pParent - creator of object.
  52. pName - name of server.
  53. Return Values:
  54. None.
  55. --*/
  56. {
  57. EnableAutomation();
  58. #ifdef ENABLE_PARENT_CHECK
  59. ASSERT(pParent && pParent->IsKindOf(RUNTIME_CLASS(CDomain)));
  60. #endif // ENABLE_PARENT_CHECK
  61. m_pParent = pParent;
  62. ASSERT(pName && *pName);
  63. m_strName = pName;
  64. m_strController.Empty();
  65. m_pServices = NULL;
  66. m_serviceArray.RemoveAll();
  67. m_bServicesRefreshed = FALSE;
  68. m_hkeyRoot = (HKEY)0L;
  69. m_hkeyLicense = (HKEY)0L;
  70. m_hkeyReplication = (HKEY)0L;
  71. m_IsWin2000 = uninitialized;
  72. m_hLls = NULL;
  73. }
  74. CServer::~CServer()
  75. /*++
  76. Routine Description:
  77. Destructor for server object.
  78. Arguments:
  79. None.
  80. Return Values:
  81. None.
  82. --*/
  83. {
  84. if (m_pServices)
  85. m_pServices->InternalRelease();
  86. #ifdef CONFIG_THROUGH_REGISTRY
  87. if (m_hkeyReplication)
  88. RegCloseKey(m_hkeyReplication);
  89. if (m_hkeyLicense)
  90. RegCloseKey(m_hkeyLicense);
  91. if (m_hkeyRoot)
  92. RegCloseKey(m_hkeyRoot);
  93. #endif
  94. DisconnectLls();
  95. }
  96. void CServer::OnFinalRelease()
  97. /*++
  98. Routine Description:
  99. When the last reference for an automation object is released
  100. OnFinalRelease is called. This implementation deletes object.
  101. Arguments:
  102. None.
  103. Return Values:
  104. None.
  105. --*/
  106. {
  107. ResetServices();
  108. delete this;
  109. }
  110. LPDISPATCH CServer::GetApplication()
  111. /*++
  112. Routine Description:
  113. Returns the application object.
  114. Arguments:
  115. None.
  116. Return Values:
  117. VT_DISPATCH.
  118. --*/
  119. {
  120. return theApp.GetAppIDispatch();
  121. }
  122. BSTR CServer::GetController()
  123. /*++
  124. Routine Description:
  125. Returns license controller for server.
  126. Arguments:
  127. None.
  128. Return Values:
  129. VT_BSTR.
  130. --*/
  131. {
  132. LONG Status;
  133. CString strValue = _T("");
  134. if (InitializeIfNecessary())
  135. {
  136. #ifdef CONFIG_THROUGH_REGISTRY
  137. TCHAR szValue[256];
  138. DWORD dwType = REG_SZ;
  139. DWORD dwSize = sizeof(szValue);
  140. Status = RegQueryValueEx(
  141. m_hkeyReplication,
  142. REG_VALUE_ENTERPRISE_SERVER,
  143. 0,
  144. &dwType,
  145. (LPBYTE)szValue,
  146. &dwSize
  147. );
  148. LlsSetLastStatus(Status); // called api
  149. if (Status == ERROR_SUCCESS)
  150. strValue = szValue;
  151. #else
  152. PLLS_SERVICE_INFO_0 pConfig = NULL;
  153. Status = ::LlsServiceInfoGet( m_hLls, 0, (LPBYTE *) &pConfig );
  154. if ( NT_SUCCESS( Status ) )
  155. {
  156. strValue = pConfig->EnterpriseServer;
  157. ::LlsFreeMemory( pConfig->ReplicateTo );
  158. ::LlsFreeMemory( pConfig->EnterpriseServer );
  159. ::LlsFreeMemory( pConfig );
  160. }
  161. else if ( IsConnectionDropped( Status ) )
  162. {
  163. DisconnectLls();
  164. }
  165. #endif
  166. }
  167. return strValue.AllocSysString();
  168. }
  169. BSTR CServer::GetName()
  170. /*++
  171. Routine Description:
  172. Returns the name of the server.
  173. Arguments:
  174. None.
  175. Return Values:
  176. VT_BSTR.
  177. --*/
  178. {
  179. return m_strName.AllocSysString();
  180. }
  181. LPDISPATCH CServer::GetParent()
  182. /*++
  183. Routine Description:
  184. Returns the parent of the object.
  185. Arguments:
  186. None.
  187. Return Values:
  188. VT_DISPATCH.
  189. --*/
  190. {
  191. return m_pParent ? m_pParent->GetIDispatch(TRUE) : NULL;
  192. }
  193. LPDISPATCH CServer::GetServices(const VARIANT FAR& index)
  194. /*++
  195. Routine Description:
  196. Returns a collection object containing all of the
  197. services registered in the server's registry or returns
  198. an individual service described by an index into the
  199. collection.
  200. Arguments:
  201. index - optional argument that may be a string (VT_BSTR)
  202. indicating a service name or a number (VT_I4) indicating
  203. the position within collection.
  204. Return Values:
  205. VT_DISPATCH or VT_EMPTY.
  206. --*/
  207. {
  208. LPDISPATCH lpdispatch = NULL;
  209. if (!m_pServices)
  210. {
  211. m_pServices = new CServices(this, &m_serviceArray);
  212. }
  213. if (m_pServices)
  214. {
  215. if (V_ISVOID((VARIANT FAR*)&index))
  216. {
  217. if (RefreshServices())
  218. {
  219. lpdispatch = m_pServices->GetIDispatch(TRUE);
  220. }
  221. }
  222. else
  223. {
  224. if (m_bServicesRefreshed)
  225. {
  226. lpdispatch = m_pServices->GetItem(index);
  227. }
  228. else if (RefreshServices())
  229. {
  230. lpdispatch = m_pServices->GetItem(index);
  231. }
  232. }
  233. }
  234. else
  235. {
  236. LlsSetLastStatus(STATUS_NO_MEMORY);
  237. }
  238. return lpdispatch;
  239. }
  240. BOOL CServer::IsLogging()
  241. /*++
  242. Routine Description:
  243. Returns true if server replicating license information.
  244. Arguments:
  245. None.
  246. Return Values:
  247. VT_BOOL.
  248. --*/
  249. {
  250. return TRUE; // CODEWORK...
  251. }
  252. BOOL CServer::RefreshServices()
  253. /*++
  254. Routine Description:
  255. Refreshs service object list.
  256. Arguments:
  257. None.
  258. Return Values:
  259. VT_BOOL.
  260. --*/
  261. {
  262. ResetServices();
  263. LONG Status;
  264. if (InitializeIfNecessary())
  265. {
  266. #ifdef CONFIG_THROUGH_REGISTRY
  267. TCHAR szValue[260];
  268. DWORD cchValue = sizeof(szValue)/sizeof(TCHAR);
  269. DWORD dwValue;
  270. DWORD dwValueType;
  271. DWORD dwValueSize;
  272. FILETIME ftLastWritten;
  273. DWORD index = 0L;
  274. int iService = 0;
  275. HKEY hkeyService = NULL;
  276. CString strServiceName;
  277. CString strServiceDisplayName;
  278. BOOL bIsPerServer;
  279. BOOL bIsReadOnly;
  280. long lPerServerLimit;
  281. while ((Status = RegEnumKeyEx(
  282. m_hkeyLicense,
  283. index,
  284. szValue,
  285. &cchValue,
  286. NULL, // lpdwReserved
  287. NULL, // lpszClass
  288. NULL, // lpcchClass
  289. &ftLastWritten
  290. )) == ERROR_SUCCESS)
  291. {
  292. strServiceName = szValue; // store for ctor...
  293. Status = RegOpenKeyEx(
  294. m_hkeyLicense,
  295. MKSTR(strServiceName),
  296. 0, // dwReserved
  297. KEY_ALL_ACCESS,
  298. &hkeyService
  299. );
  300. if (Status != ERROR_SUCCESS)
  301. break; // abort...
  302. dwValueType = REG_SZ;
  303. dwValueSize = sizeof(szValue);
  304. Status = RegQueryValueEx(
  305. hkeyService,
  306. REG_VALUE_NAME,
  307. 0, // dwReserved
  308. &dwValueType,
  309. (LPBYTE)&szValue[0],
  310. &dwValueSize
  311. );
  312. if (Status != ERROR_SUCCESS)
  313. break; // abort...
  314. strServiceDisplayName = szValue;
  315. dwValueType = REG_DWORD;
  316. dwValueSize = sizeof(DWORD);
  317. Status = RegQueryValueEx(
  318. hkeyService,
  319. REG_VALUE_MODE,
  320. 0, // dwReserved
  321. &dwValueType,
  322. (LPBYTE)&dwValue,
  323. &dwValueSize
  324. );
  325. if (Status != ERROR_SUCCESS)
  326. break; // abort...
  327. //
  328. // 0x0 = per seat mode
  329. // 0x1 = per server mode
  330. //
  331. bIsPerServer = (dwValue == 0x1);
  332. dwValueType = REG_DWORD;
  333. dwValueSize = sizeof(DWORD);
  334. Status = RegQueryValueEx(
  335. hkeyService,
  336. REG_VALUE_FLIP,
  337. 0, // dwReserved
  338. &dwValueType,
  339. (LPBYTE)&dwValue,
  340. &dwValueSize
  341. );
  342. if (Status != ERROR_SUCCESS)
  343. break; // abort...
  344. //
  345. // 0x0 = can change mode
  346. // 0x1 = can't change mode
  347. //
  348. bIsReadOnly = (dwValue == 0x1);
  349. BOOL bGetLimitFromRegistry = TRUE;
  350. if ( ConnectLls() )
  351. {
  352. Status = LlsProductLicensesGet( m_hLls, MKSTR(strServiceDisplayName), LLS_LICENSE_MODE_PER_SERVER, &dwValue );
  353. if ( STATUS_SUCCESS == Status )
  354. {
  355. bGetLimitFromRegistry = FALSE;
  356. }
  357. }
  358. if ( bGetLimitFromRegistry )
  359. {
  360. dwValueType = REG_DWORD;
  361. dwValueSize = sizeof(DWORD);
  362. Status = RegQueryValueEx(
  363. hkeyService,
  364. REG_VALUE_LIMIT,
  365. 0, // dwReserved
  366. &dwValueType,
  367. (LPBYTE)&dwValue,
  368. &dwValueSize
  369. );
  370. }
  371. if (Status != ERROR_SUCCESS)
  372. break; // abort...
  373. lPerServerLimit = (long)dwValue;
  374. CService* pService = new CService(this,
  375. strServiceName,
  376. strServiceDisplayName,
  377. bIsPerServer,
  378. bIsReadOnly,
  379. lPerServerLimit
  380. );
  381. m_serviceArray.SetAtGrow(iService++, pService);
  382. index++;
  383. cchValue = sizeof(szValue)/sizeof(TCHAR);
  384. RegCloseKey(hkeyService); // no longer needed...
  385. hkeyService = NULL;
  386. }
  387. if (hkeyService)
  388. RegCloseKey(hkeyService);
  389. if (Status == ERROR_NO_MORE_ITEMS)
  390. Status = ERROR_SUCCESS;
  391. LlsSetLastStatus(Status); // called api
  392. if (Status == ERROR_SUCCESS)
  393. {
  394. m_bServicesRefreshed = TRUE;
  395. }
  396. else
  397. {
  398. ResetServices();
  399. }
  400. #else
  401. DWORD dwResumeHandle = 0;
  402. int iService = 0;
  403. do
  404. {
  405. PLLS_LOCAL_SERVICE_INFO_0 pServiceList = NULL;
  406. DWORD dwEntriesRead = 0;
  407. DWORD dwTotalEntries = 0;
  408. Status = ::LlsLocalServiceEnum( m_hLls,
  409. 0,
  410. (LPBYTE *) &pServiceList,
  411. LLS_PREFERRED_LENGTH,
  412. &dwEntriesRead,
  413. &dwTotalEntries,
  414. &dwResumeHandle );
  415. if ( NT_SUCCESS( Status ) )
  416. {
  417. DWORD i;
  418. for ( i=0; i < dwEntriesRead; i++ )
  419. {
  420. BOOL bIsPerServer = ( LLS_LICENSE_MODE_PER_SERVER == pServiceList[ i ].Mode );
  421. BOOL bIsReadOnly = ( 0 == pServiceList[ i ].FlipAllow );
  422. DWORD dwConcurrentLimit;
  423. // get number of per server license in case where product
  424. // is secure, and
  425. // ( is currently in per seat mode, or
  426. // new secure per server licenses have just been added and registry
  427. // has not been updated yet )
  428. if ( STATUS_SUCCESS != LlsProductLicensesGet( m_hLls, pServiceList[ i ].DisplayName, LLS_LICENSE_MODE_PER_SERVER, &dwConcurrentLimit ) )
  429. {
  430. dwConcurrentLimit = pServiceList[ i ].ConcurrentLimit;
  431. }
  432. CService* pService = new CService( this,
  433. pServiceList[ i ].KeyName,
  434. pServiceList[ i ].DisplayName,
  435. bIsPerServer,
  436. bIsReadOnly,
  437. dwConcurrentLimit );
  438. m_serviceArray.SetAtGrow(iService++, pService);
  439. ::LlsFreeMemory( pServiceList[ i ].KeyName );
  440. ::LlsFreeMemory( pServiceList[ i ].DisplayName );
  441. ::LlsFreeMemory( pServiceList[ i ].FamilyDisplayName );
  442. }
  443. ::LlsFreeMemory( pServiceList );
  444. }
  445. } while ( STATUS_MORE_ENTRIES == Status );
  446. LlsSetLastStatus( Status ); // called api
  447. if ( NT_SUCCESS( Status ) )
  448. {
  449. m_bServicesRefreshed = TRUE;
  450. }
  451. else
  452. {
  453. ResetServices();
  454. if ( IsConnectionDropped( Status ) )
  455. {
  456. DisconnectLls();
  457. }
  458. }
  459. #endif
  460. }
  461. return m_bServicesRefreshed;
  462. }
  463. void CServer::ResetServices()
  464. /*++
  465. Routine Description:
  466. Resets service object list.
  467. Arguments:
  468. None.
  469. Return Values:
  470. None.
  471. --*/
  472. {
  473. CService* pService;
  474. INT_PTR iService = m_serviceArray.GetSize();
  475. while (iService--)
  476. {
  477. if (pService = (CService*)m_serviceArray[iService])
  478. {
  479. ASSERT(pService->IsKindOf(RUNTIME_CLASS(CService)));
  480. pService->InternalRelease();
  481. }
  482. }
  483. m_serviceArray.RemoveAll();
  484. m_bServicesRefreshed = FALSE;
  485. }
  486. BOOL CServer::InitializeIfNecessary()
  487. /*++
  488. Routine Description:
  489. Initialize registry keys if necessary.
  490. Arguments:
  491. None.
  492. Return Values:
  493. VT_BOOL.
  494. --*/
  495. {
  496. #ifdef CONFIG_THROUGH_REGISTRY
  497. LONG Status = ERROR_SUCCESS;
  498. if (!m_hkeyRoot)
  499. {
  500. Status = RegConnectRegistry(
  501. MKSTR(m_strName),
  502. HKEY_LOCAL_MACHINE,
  503. &m_hkeyRoot
  504. );
  505. LlsSetLastStatus(Status); // called api
  506. }
  507. if (!m_hkeyLicense && (Status == ERROR_SUCCESS))
  508. {
  509. ASSERT(m_hkeyRoot);
  510. Status = RegOpenKeyEx(
  511. m_hkeyRoot,
  512. REG_KEY_LICENSE,
  513. 0, // dwReserved
  514. KEY_ALL_ACCESS,
  515. &m_hkeyLicense
  516. );
  517. LlsSetLastStatus(Status); // called api
  518. }
  519. if (!m_hkeyReplication && (Status == ERROR_SUCCESS))
  520. {
  521. ASSERT(m_hkeyRoot);
  522. Status = RegOpenKeyEx(
  523. m_hkeyRoot,
  524. REG_KEY_SERVER_PARAMETERS,
  525. 0, // dwReserved
  526. KEY_ALL_ACCESS,
  527. &m_hkeyReplication
  528. );
  529. LlsSetLastStatus(Status); // called api
  530. }
  531. return (Status == ERROR_SUCCESS);
  532. #else
  533. return ConnectLls();
  534. #endif
  535. }
  536. BOOL CServer::IsReplicatingToDC()
  537. /*++
  538. Routine Description:
  539. Returns true if server replicating to domain controller.
  540. Arguments:
  541. None.
  542. Return Values:
  543. VT_BOOL.
  544. --*/
  545. {
  546. LONG Status;
  547. DWORD dwValue = 0;
  548. if (InitializeIfNecessary())
  549. {
  550. #ifdef CONFIG_THROUGH_REGISTRY
  551. DWORD dwType = REG_DWORD;
  552. DWORD dwSize = sizeof(DWORD);
  553. Status = RegQueryValueEx(
  554. m_hkeyReplication,
  555. REG_VALUE_USE_ENTERPRISE,
  556. 0,
  557. &dwType,
  558. (LPBYTE)&dwValue,
  559. &dwSize
  560. );
  561. #else
  562. PLLS_SERVICE_INFO_0 pConfig = NULL;
  563. Status = ::LlsServiceInfoGet( m_hLls, 0, (LPBYTE *) &pConfig );
  564. if ( NT_SUCCESS( Status ) )
  565. {
  566. dwValue = pConfig->UseEnterprise;
  567. ::LlsFreeMemory( pConfig->ReplicateTo );
  568. ::LlsFreeMemory( pConfig->EnterpriseServer );
  569. ::LlsFreeMemory( pConfig );
  570. }
  571. if ( IsConnectionDropped( Status ) )
  572. {
  573. DisconnectLls();
  574. }
  575. #endif
  576. LlsSetLastStatus(Status); // called api
  577. }
  578. return !((BOOL)dwValue);
  579. }
  580. BOOL CServer::IsReplicatingDaily()
  581. /*++
  582. Routine Description:
  583. Returns true if server replicating daily at certain time.
  584. Arguments:
  585. None.
  586. Return Values:
  587. VT_BOOL.
  588. --*/
  589. {
  590. LONG Status;
  591. DWORD dwValue = 0;
  592. if (InitializeIfNecessary())
  593. {
  594. #ifdef CONFIG_THROUGH_REGISTRY
  595. DWORD dwType = REG_DWORD;
  596. DWORD dwSize = sizeof(DWORD);
  597. Status = RegQueryValueEx(
  598. m_hkeyReplication,
  599. REG_VALUE_REPLICATION_TYPE,
  600. 0,
  601. &dwType,
  602. (LPBYTE)&dwValue,
  603. &dwSize
  604. );
  605. #else
  606. PLLS_SERVICE_INFO_0 pConfig = NULL;
  607. Status = ::LlsServiceInfoGet( m_hLls, 0, (LPBYTE *) &pConfig );
  608. if ( NT_SUCCESS( Status ) )
  609. {
  610. dwValue = pConfig->ReplicationType;
  611. ::LlsFreeMemory( pConfig->ReplicateTo );
  612. ::LlsFreeMemory( pConfig->EnterpriseServer );
  613. ::LlsFreeMemory( pConfig );
  614. }
  615. if ( IsConnectionDropped( Status ) )
  616. {
  617. DisconnectLls();
  618. }
  619. #endif
  620. LlsSetLastStatus(Status); // called api
  621. }
  622. return (dwValue == LLS_REPLICATION_TYPE_TIME);
  623. }
  624. long CServer::GetReplicationTime()
  625. /*++
  626. Routine Description:
  627. Returns time in seconds between replication or seconds
  628. from midnight if replicating daily.
  629. Arguments:
  630. None.
  631. Return Values:
  632. VT_I4.
  633. --*/
  634. {
  635. LONG Status;
  636. DWORD dwValue = 0;
  637. if (InitializeIfNecessary())
  638. {
  639. #ifdef CONFIG_THROUGH_REGISTRY
  640. DWORD dwType = REG_DWORD;
  641. DWORD dwSize = sizeof(DWORD);
  642. Status = RegQueryValueEx(
  643. m_hkeyReplication,
  644. REG_VALUE_REPLICATION_TIME,
  645. 0,
  646. &dwType,
  647. (LPBYTE)&dwValue,
  648. &dwSize
  649. );
  650. #else
  651. PLLS_SERVICE_INFO_0 pConfig = NULL;
  652. Status = ::LlsServiceInfoGet( m_hLls, 0, (LPBYTE *) &pConfig );
  653. if ( NT_SUCCESS( Status ) )
  654. {
  655. dwValue = pConfig->ReplicationTime;
  656. ::LlsFreeMemory( pConfig->ReplicateTo );
  657. ::LlsFreeMemory( pConfig->EnterpriseServer );
  658. ::LlsFreeMemory( pConfig );
  659. }
  660. if ( IsConnectionDropped( Status ) )
  661. {
  662. DisconnectLls();
  663. }
  664. #endif
  665. LlsSetLastStatus(Status); // called api
  666. }
  667. return dwValue;
  668. }
  669. BOOL CServer::ConnectLls()
  670. /*++
  671. Routine Description:
  672. Connects to license service on this server.
  673. Arguments:
  674. None.
  675. Return Values:
  676. VT_BOOL.
  677. --*/
  678. {
  679. NTSTATUS Status;
  680. if ( NULL == m_hLls )
  681. {
  682. CString strNetServerName = m_strName;
  683. if ( strNetServerName.Left(2).Compare( TEXT( "\\\\" ) ) )
  684. {
  685. strNetServerName = TEXT( "\\\\" ) + strNetServerName;
  686. }
  687. Status = LlsConnect( MKSTR(strNetServerName), &m_hLls );
  688. if ( STATUS_SUCCESS != Status )
  689. {
  690. m_hLls = NULL;
  691. }
  692. else if ( !HaveAdminAuthority() )
  693. {
  694. m_hLls = NULL;
  695. Status = ERROR_ACCESS_DENIED;
  696. }
  697. LlsSetLastStatus( Status );
  698. }
  699. return ( NULL != m_hLls );
  700. }
  701. void CServer::DisconnectLls()
  702. /*++
  703. Routine Description:
  704. Disconnects from license service on this server.
  705. Arguments:
  706. None.
  707. Return Values:
  708. None.
  709. --*/
  710. {
  711. if ( NULL != m_hLls )
  712. {
  713. LlsClose( m_hLls );
  714. m_hLls = NULL;
  715. }
  716. }
  717. BOOL CServer::HaveAdminAuthority()
  718. /*++
  719. Routine Description:
  720. Checks whether the current user has admin authority on the server.
  721. Arguments:
  722. None.
  723. Return Values:
  724. BOOL.
  725. --*/
  726. {
  727. BOOL bIsAdmin;
  728. CString strNetShareName;
  729. strNetShareName = m_strName + TEXT( "\\ADMIN$" );
  730. if ( strNetShareName.Left(2).Compare( TEXT( "\\\\" ) ) )
  731. {
  732. strNetShareName = TEXT( "\\\\" ) + strNetShareName;
  733. }
  734. #ifdef USE_WNET_API
  735. DWORD dwError;
  736. NETRESOURCE NetResource;
  737. ZeroMemory( &NetResource, sizeof( NetResource ) );
  738. NetResource.dwType = RESOURCETYPE_DISK;
  739. NetResource.lpLocalName = NULL;
  740. NetResource.lpRemoteName = MKSTR(strNetShareName);
  741. NetResource.lpProvider = NULL;
  742. dwError = WNetAddConnection2( &NetResource, NULL, NULL, 0 );
  743. bIsAdmin = ( NO_ERROR == dwError );
  744. if ( NO_ERROR != dwError )
  745. {
  746. bIsAdmin = FALSE;
  747. }
  748. else
  749. {
  750. bIsAdmin = TRUE;
  751. WNetCancelConnection2( MKSTR(strNetShareName), 0, FALSE );
  752. }
  753. #else
  754. NET_API_STATUS NetStatus;
  755. USE_INFO_1 UseInfo;
  756. DWORD dwErrorParm;
  757. ZeroMemory( &UseInfo, sizeof( UseInfo ) );
  758. UseInfo.ui1_remote = MKSTR( strNetShareName );
  759. NetStatus = NetUseAdd( NULL, 1, (LPBYTE) &UseInfo, &dwErrorParm );
  760. if ( NERR_Success != NetStatus )
  761. {
  762. bIsAdmin = FALSE;
  763. }
  764. else
  765. {
  766. bIsAdmin = TRUE;
  767. NetStatus = NetUseDel( NULL, MKSTR(strNetShareName), 0 );
  768. // ignore status
  769. }
  770. #endif
  771. return bIsAdmin;
  772. }
  773. BOOL CServer::IsWin2000()
  774. /*++
  775. Routine Description:
  776. Checks whether the current server is Windows 2000 or greater.
  777. Arguments:
  778. None.
  779. Return Values:
  780. BOOL.
  781. --*/
  782. {
  783. if ( m_IsWin2000 == uninitialized )
  784. {
  785. if ( GetName() != NULL )
  786. {
  787. NET_API_STATUS NetStatus;
  788. PWKSTA_INFO_100 pWkstaInfo100 = NULL;
  789. NetStatus = NetWkstaGetInfo(
  790. GetName(),
  791. 100,
  792. (LPBYTE*)&pWkstaInfo100
  793. );
  794. if (NetStatus == ERROR_SUCCESS)
  795. {
  796. if (pWkstaInfo100->wki100_ver_major < 5)
  797. {
  798. m_IsWin2000 = notwin2000;
  799. }
  800. else
  801. {
  802. m_IsWin2000 = win2000;
  803. }
  804. NetApiBufferFree(pWkstaInfo100);
  805. }
  806. }
  807. }
  808. // if still unitialized, assume win2000.
  809. return ( !(m_IsWin2000 == notwin2000) );
  810. }