Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1175 lines
25 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. pService = (CService*)m_serviceArray[iService];
  478. if (NULL != pService)
  479. {
  480. ASSERT(pService->IsKindOf(RUNTIME_CLASS(CService)));
  481. pService->InternalRelease();
  482. }
  483. }
  484. m_serviceArray.RemoveAll();
  485. m_bServicesRefreshed = FALSE;
  486. }
  487. BOOL CServer::InitializeIfNecessary()
  488. /*++
  489. Routine Description:
  490. Initialize registry keys if necessary.
  491. Arguments:
  492. None.
  493. Return Values:
  494. VT_BOOL.
  495. --*/
  496. {
  497. #ifdef CONFIG_THROUGH_REGISTRY
  498. LONG Status = ERROR_SUCCESS;
  499. if (!m_hkeyRoot)
  500. {
  501. Status = RegConnectRegistry(
  502. MKSTR(m_strName),
  503. HKEY_LOCAL_MACHINE,
  504. &m_hkeyRoot
  505. );
  506. LlsSetLastStatus(Status); // called api
  507. }
  508. if (!m_hkeyLicense && (Status == ERROR_SUCCESS))
  509. {
  510. ASSERT(m_hkeyRoot);
  511. Status = RegOpenKeyEx(
  512. m_hkeyRoot,
  513. REG_KEY_LICENSE,
  514. 0, // dwReserved
  515. KEY_ALL_ACCESS,
  516. &m_hkeyLicense
  517. );
  518. LlsSetLastStatus(Status); // called api
  519. }
  520. if (!m_hkeyReplication && (Status == ERROR_SUCCESS))
  521. {
  522. ASSERT(m_hkeyRoot);
  523. Status = RegOpenKeyEx(
  524. m_hkeyRoot,
  525. REG_KEY_SERVER_PARAMETERS,
  526. 0, // dwReserved
  527. KEY_ALL_ACCESS,
  528. &m_hkeyReplication
  529. );
  530. LlsSetLastStatus(Status); // called api
  531. }
  532. return (Status == ERROR_SUCCESS);
  533. #else
  534. return ConnectLls();
  535. #endif
  536. }
  537. BOOL CServer::IsReplicatingToDC()
  538. /*++
  539. Routine Description:
  540. Returns true if server replicating to domain controller.
  541. Arguments:
  542. None.
  543. Return Values:
  544. VT_BOOL.
  545. --*/
  546. {
  547. LONG Status;
  548. DWORD dwValue = 0;
  549. if (InitializeIfNecessary())
  550. {
  551. #ifdef CONFIG_THROUGH_REGISTRY
  552. DWORD dwType = REG_DWORD;
  553. DWORD dwSize = sizeof(DWORD);
  554. Status = RegQueryValueEx(
  555. m_hkeyReplication,
  556. REG_VALUE_USE_ENTERPRISE,
  557. 0,
  558. &dwType,
  559. (LPBYTE)&dwValue,
  560. &dwSize
  561. );
  562. #else
  563. PLLS_SERVICE_INFO_0 pConfig = NULL;
  564. Status = ::LlsServiceInfoGet( m_hLls, 0, (LPBYTE *) &pConfig );
  565. if ( NT_SUCCESS( Status ) )
  566. {
  567. dwValue = pConfig->UseEnterprise;
  568. ::LlsFreeMemory( pConfig->ReplicateTo );
  569. ::LlsFreeMemory( pConfig->EnterpriseServer );
  570. ::LlsFreeMemory( pConfig );
  571. }
  572. if ( IsConnectionDropped( Status ) )
  573. {
  574. DisconnectLls();
  575. }
  576. #endif
  577. LlsSetLastStatus(Status); // called api
  578. }
  579. return !((BOOL)dwValue);
  580. }
  581. BOOL CServer::IsReplicatingDaily()
  582. /*++
  583. Routine Description:
  584. Returns true if server replicating daily at certain time.
  585. Arguments:
  586. None.
  587. Return Values:
  588. VT_BOOL.
  589. --*/
  590. {
  591. LONG Status;
  592. DWORD dwValue = 0;
  593. if (InitializeIfNecessary())
  594. {
  595. #ifdef CONFIG_THROUGH_REGISTRY
  596. DWORD dwType = REG_DWORD;
  597. DWORD dwSize = sizeof(DWORD);
  598. Status = RegQueryValueEx(
  599. m_hkeyReplication,
  600. REG_VALUE_REPLICATION_TYPE,
  601. 0,
  602. &dwType,
  603. (LPBYTE)&dwValue,
  604. &dwSize
  605. );
  606. #else
  607. PLLS_SERVICE_INFO_0 pConfig = NULL;
  608. Status = ::LlsServiceInfoGet( m_hLls, 0, (LPBYTE *) &pConfig );
  609. if ( NT_SUCCESS( Status ) )
  610. {
  611. dwValue = pConfig->ReplicationType;
  612. ::LlsFreeMemory( pConfig->ReplicateTo );
  613. ::LlsFreeMemory( pConfig->EnterpriseServer );
  614. ::LlsFreeMemory( pConfig );
  615. }
  616. if ( IsConnectionDropped( Status ) )
  617. {
  618. DisconnectLls();
  619. }
  620. #endif
  621. LlsSetLastStatus(Status); // called api
  622. }
  623. return (dwValue == LLS_REPLICATION_TYPE_TIME);
  624. }
  625. long CServer::GetReplicationTime()
  626. /*++
  627. Routine Description:
  628. Returns time in seconds between replication or seconds
  629. from midnight if replicating daily.
  630. Arguments:
  631. None.
  632. Return Values:
  633. VT_I4.
  634. --*/
  635. {
  636. LONG Status;
  637. DWORD dwValue = 0;
  638. if (InitializeIfNecessary())
  639. {
  640. #ifdef CONFIG_THROUGH_REGISTRY
  641. DWORD dwType = REG_DWORD;
  642. DWORD dwSize = sizeof(DWORD);
  643. Status = RegQueryValueEx(
  644. m_hkeyReplication,
  645. REG_VALUE_REPLICATION_TIME,
  646. 0,
  647. &dwType,
  648. (LPBYTE)&dwValue,
  649. &dwSize
  650. );
  651. #else
  652. PLLS_SERVICE_INFO_0 pConfig = NULL;
  653. Status = ::LlsServiceInfoGet( m_hLls, 0, (LPBYTE *) &pConfig );
  654. if ( NT_SUCCESS( Status ) )
  655. {
  656. dwValue = pConfig->ReplicationTime;
  657. ::LlsFreeMemory( pConfig->ReplicateTo );
  658. ::LlsFreeMemory( pConfig->EnterpriseServer );
  659. ::LlsFreeMemory( pConfig );
  660. }
  661. if ( IsConnectionDropped( Status ) )
  662. {
  663. DisconnectLls();
  664. }
  665. #endif
  666. LlsSetLastStatus(Status); // called api
  667. }
  668. return dwValue;
  669. }
  670. BOOL CServer::ConnectLls()
  671. /*++
  672. Routine Description:
  673. Connects to license service on this server.
  674. Arguments:
  675. None.
  676. Return Values:
  677. VT_BOOL.
  678. --*/
  679. {
  680. NTSTATUS Status;
  681. if ( NULL == m_hLls )
  682. {
  683. CString strNetServerName = m_strName;
  684. if ( strNetServerName.Left(2).Compare( TEXT( "\\\\" ) ) )
  685. {
  686. strNetServerName = TEXT( "\\\\" ) + strNetServerName;
  687. }
  688. Status = LlsConnect( MKSTR(strNetServerName), &m_hLls );
  689. if ( STATUS_SUCCESS != Status )
  690. {
  691. m_hLls = NULL;
  692. }
  693. else if ( !HaveAdminAuthority() )
  694. {
  695. m_hLls = NULL;
  696. Status = ERROR_ACCESS_DENIED;
  697. }
  698. LlsSetLastStatus( Status );
  699. }
  700. return ( NULL != m_hLls );
  701. }
  702. void CServer::DisconnectLls()
  703. /*++
  704. Routine Description:
  705. Disconnects from license service on this server.
  706. Arguments:
  707. None.
  708. Return Values:
  709. None.
  710. --*/
  711. {
  712. if ( NULL != m_hLls )
  713. {
  714. LlsClose( m_hLls );
  715. m_hLls = NULL;
  716. }
  717. }
  718. BOOL CServer::HaveAdminAuthority()
  719. /*++
  720. Routine Description:
  721. Checks whether the current user has admin authority on the server.
  722. Arguments:
  723. None.
  724. Return Values:
  725. BOOL.
  726. --*/
  727. {
  728. BOOL bIsAdmin;
  729. CString strNetShareName;
  730. strNetShareName = m_strName + TEXT( "\\ADMIN$" );
  731. if ( strNetShareName.Left(2).Compare( TEXT( "\\\\" ) ) )
  732. {
  733. strNetShareName = TEXT( "\\\\" ) + strNetShareName;
  734. }
  735. #ifdef USE_WNET_API
  736. DWORD dwError;
  737. NETRESOURCE NetResource;
  738. ZeroMemory( &NetResource, sizeof( NetResource ) );
  739. NetResource.dwType = RESOURCETYPE_DISK;
  740. NetResource.lpLocalName = NULL;
  741. NetResource.lpRemoteName = MKSTR(strNetShareName);
  742. NetResource.lpProvider = NULL;
  743. dwError = WNetAddConnection2( &NetResource, NULL, NULL, 0 );
  744. bIsAdmin = ( NO_ERROR == dwError );
  745. if ( NO_ERROR != dwError )
  746. {
  747. bIsAdmin = FALSE;
  748. }
  749. else
  750. {
  751. bIsAdmin = TRUE;
  752. WNetCancelConnection2( MKSTR(strNetShareName), 0, FALSE );
  753. }
  754. #else
  755. NET_API_STATUS NetStatus;
  756. USE_INFO_1 UseInfo;
  757. DWORD dwErrorParm;
  758. ZeroMemory( &UseInfo, sizeof( UseInfo ) );
  759. UseInfo.ui1_remote = MKSTR( strNetShareName );
  760. NetStatus = NetUseAdd( NULL, 1, (LPBYTE) &UseInfo, &dwErrorParm );
  761. if ( NERR_Success != NetStatus )
  762. {
  763. bIsAdmin = FALSE;
  764. }
  765. else
  766. {
  767. bIsAdmin = TRUE;
  768. NetStatus = NetUseDel( NULL, MKSTR(strNetShareName), 0 );
  769. // ignore status
  770. }
  771. #endif
  772. return bIsAdmin;
  773. }
  774. BOOL CServer::IsWin2000()
  775. /*++
  776. Routine Description:
  777. Checks whether the current server is Windows 2000 or greater.
  778. Arguments:
  779. None.
  780. Return Values:
  781. BOOL.
  782. --*/
  783. {
  784. if ( m_IsWin2000 == uninitialized )
  785. {
  786. if ( GetName() != NULL )
  787. {
  788. NET_API_STATUS NetStatus;
  789. PWKSTA_INFO_100 pWkstaInfo100 = NULL;
  790. NetStatus = NetWkstaGetInfo(
  791. GetName(),
  792. 100,
  793. (LPBYTE*)&pWkstaInfo100
  794. );
  795. if (NetStatus == ERROR_SUCCESS)
  796. {
  797. if (pWkstaInfo100->wki100_ver_major < 5)
  798. {
  799. m_IsWin2000 = notwin2000;
  800. }
  801. else
  802. {
  803. m_IsWin2000 = win2000;
  804. }
  805. NetApiBufferFree(pWkstaInfo100);
  806. }
  807. }
  808. }
  809. // if still unitialized, assume win2000.
  810. return ( !(m_IsWin2000 == notwin2000) );
  811. }