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.

1208 lines
32 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1998.
  5. //
  6. // File: N C A C S . C P P
  7. //
  8. // Contents: Installation support for ACS service
  9. //
  10. // Notes:
  11. //
  12. // Author: RameshPa 02/12/98
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "ncxbase.h"
  18. #include "ncerror.h"
  19. #include "ncreg.h"
  20. #include "ncacs.h"
  21. #include "ncsvc.h"
  22. #include "netoc.h"
  23. #include "ncnetcfg.h"
  24. #include "resource.h"
  25. #include <iphlpapi.h>
  26. #include <winsock2.h>
  27. #include <ntsecapi.h>
  28. extern const WCHAR c_szSvcRsvp[];
  29. static const WCHAR c_szTcpIp[] = L"TcpIp";
  30. static const WCHAR c_szAfd[] = L"Afd";
  31. static const WCHAR c_szAcsService[] = L"AcsService";
  32. static const WCHAR c_szRegKeyRsvpParams[] = L"System\\CurrentControlSet\\Services\\RSVP\\Parameters\\";
  33. static const WCHAR c_szRegKeyRsvpSubnet1[] = L"System\\CurrentControlSet\\Services\\RSVP\\Parameters\\Subnet\\Subnet1\\";
  34. static const WCHAR c_szRegKeyRsvpSubnet[] = L"System\\CurrentControlSet\\Services\\RSVP\\Parameters\\Subnet\\";
  35. static const WCHAR c_szRegKeyRsvpAdapters[]= L"System\\CurrentControlSet\\Services\\RSVP\\Parameters\\Adapters\\";
  36. static const WCHAR c_szRegKeyRsvpPcmConfig[]= L"System\\CurrentControlSet\\Services\\RSVP\\PCM Config\\";
  37. static const WCHAR c_szRegKeyRsvpMsidlpm[] = L"System\\CurrentControlSet\\Services\\RSVP\\MSIDLPM\\";
  38. //$ REVIEW : RameshPa : 02/13/98 : Is this defined anywhere?
  39. const DWORD dwKilo = 1024;
  40. const DWORD dwMega = (1024 * dwKilo);
  41. const DWORD dwGiga = (1024 * dwMega);
  42. static const WCHAR c_szIpHlpApiDllName[] = L"IpHlpApi";
  43. static const CHAR c_szaGetIpAddrTable[] = "GetIpAddrTable";
  44. typedef DWORD (*GETIPADDRTABLE)(
  45. OUT PMIB_IPADDRTABLE pIpAddrTable,
  46. IN OUT PDWORD pdwSize,
  47. IN BOOL bOrder);
  48. struct ACS_SUBNET_REG_DATA
  49. {
  50. DWORD dwSubnetIpAddress; // This is in host order
  51. DWORD dwDSBMPriority;
  52. DWORD dwMaxRSVPBandwidth;
  53. DWORD dwMaxTotalPeakRate;
  54. DWORD dwMaxTokenBucketRatePerFlow;
  55. DWORD dwMaxPeakRatePerFlow;
  56. DWORD dwIAmDsbmRefreshInterval;
  57. DWORD dwDSBMDeadInterval;
  58. BOOL fRunAsDSBM;
  59. };
  60. // Subnet registry keys
  61. //
  62. static const WCHAR c_szRunAsDSBM[] = L"Run as DSBM";
  63. static const WCHAR c_szSubnetIPAddress[] = L"Subnet IP Address";
  64. static const WCHAR c_szMaxPeakRate[] = L"Maximum peak rate per flow";
  65. static const WCHAR c_szMaxRSVPBandwidth[] = L"Maximum RSVP bandwidth";
  66. static const WCHAR c_szMaxTokenBucket[] = L"Maximum token bucket rate per flow";
  67. static const WCHAR c_szMaxTotalPeakRate[] = L"Maximum total peak rate";
  68. static const WCHAR c_szIAmDsbmRefresh[] = L"I_AM_DSBM Refresh Interval";
  69. static const WCHAR c_szDSBMDeadInterval[] = L"DSBM Dead Interval";
  70. static const WCHAR c_szDSBMPriority[] = L"DSBM Priority";
  71. // Default general property sheet values
  72. //
  73. const BOOL c_fRunAsDSBMDef = TRUE;
  74. // Default subnet values
  75. //
  76. const DWORD c_dwIpAddressDef = 0;
  77. static const WCHAR c_szIpAddressDef[] = L"0.0.0.0";
  78. const DWORD c_dwMaxPeakRateDef = 0xFFFFFFFF;
  79. const DWORD c_dwMaxRSVPBandwidthDef = 0;
  80. const DWORD c_dwMaxTokenBucketDef = 0xFFFFFFFF;
  81. const DWORD c_dwMaxTotalPeakRateDef = 0xFFFFFFFF;
  82. const DWORD c_dwIAmDsbmRefreshDef = 5;
  83. const DWORD c_dwDSBMDeadIntervalDef = 15;
  84. const DWORD c_dwDSBMPriorityDef = 4;
  85. // General values
  86. // 127.0.0.0, host order
  87. //
  88. const DWORD c_dwLocalSubnet = 0x7f000000;
  89. const DWORD c_dwNullSubnet = 0x00000000;
  90. static const VALUETABLE c_avtAcsSubnet[] =
  91. {
  92. {c_szSubnetIPAddress, REG_IP, offsetof(ACS_SUBNET_REG_DATA, dwSubnetIpAddress),
  93. (BYTE*)(&c_szIpAddressDef)},
  94. {c_szMaxPeakRate, REG_DWORD, offsetof(ACS_SUBNET_REG_DATA, dwMaxPeakRatePerFlow),
  95. (BYTE*)(&c_dwMaxPeakRateDef)},
  96. {c_szMaxRSVPBandwidth, REG_DWORD, offsetof(ACS_SUBNET_REG_DATA, dwMaxRSVPBandwidth),
  97. (BYTE*)(&c_dwMaxRSVPBandwidthDef)},
  98. {c_szMaxTokenBucket, REG_DWORD, offsetof(ACS_SUBNET_REG_DATA, dwMaxTokenBucketRatePerFlow),
  99. (BYTE*)(&c_dwMaxTokenBucketDef)},
  100. {c_szMaxTotalPeakRate, REG_DWORD, offsetof(ACS_SUBNET_REG_DATA, dwMaxTotalPeakRate),
  101. (BYTE*)(&c_dwMaxTotalPeakRateDef)},
  102. {c_szIAmDsbmRefresh, REG_DWORD, offsetof(ACS_SUBNET_REG_DATA, dwIAmDsbmRefreshInterval),
  103. (BYTE*)(&c_dwIAmDsbmRefreshDef)},
  104. {c_szDSBMDeadInterval, REG_DWORD, offsetof(ACS_SUBNET_REG_DATA, dwDSBMDeadInterval),
  105. (BYTE*)(&c_dwDSBMDeadIntervalDef)},
  106. {c_szDSBMPriority, REG_DWORD, offsetof(ACS_SUBNET_REG_DATA, dwDSBMPriority),
  107. (BYTE*)(&c_dwDSBMPriorityDef)},
  108. {c_szRunAsDSBM, REG_BOOL, offsetof(ACS_SUBNET_REG_DATA, fRunAsDSBM),
  109. (BYTE*) &c_fRunAsDSBMDef},
  110. };
  111. //+---------------------------------------------------------------------------
  112. //
  113. // Function: OpenPolicy
  114. //
  115. // Purpose: This routine opens the policy object on the local computer
  116. //
  117. // Arguments: PolicyHandle - Pointer to the opended handle
  118. //
  119. // Returns: ERROR_SUCCESS if successful, Win32 error otherwise.
  120. //
  121. // Notes: The retruned PolicyHandle must be closed by the caller
  122. //
  123. DWORD
  124. OpenPolicy( PLSA_HANDLE PolicyHandle )
  125. {
  126. NTSTATUS Status;
  127. DWORD Error;
  128. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  129. SECURITY_QUALITY_OF_SERVICE QualityOfService;
  130. QualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
  131. QualityOfService.ImpersonationLevel = SecurityImpersonation;
  132. QualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  133. QualityOfService.EffectiveOnly = FALSE;
  134. //
  135. // The two fields that must be set are length and the quality of service.
  136. //
  137. ObjectAttributes.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
  138. ObjectAttributes.RootDirectory = NULL;
  139. ObjectAttributes.ObjectName = NULL;
  140. ObjectAttributes.Attributes = 0;
  141. ObjectAttributes.SecurityDescriptor = NULL;
  142. ObjectAttributes.SecurityQualityOfService = &QualityOfService;
  143. //
  144. // Attempt to open the policy for all access on the local machine
  145. //
  146. Status = LsaOpenPolicy(
  147. NULL,
  148. &ObjectAttributes,
  149. POLICY_ALL_ACCESS,
  150. PolicyHandle );
  151. Error = LsaNtStatusToWinError(Status);
  152. return(Error);
  153. }
  154. //+---------------------------------------------------------------------------
  155. //
  156. // Function: InitLsaString
  157. //
  158. // Purpose: This routine intializes LSA_UNICODE_STRING given an UNICODE string0
  159. //
  160. // Arguments: LsaString
  161. // String
  162. //
  163. // Returns:
  164. //
  165. // Notes:
  166. //
  167. void
  168. InitLsaString(
  169. PLSA_UNICODE_STRING LsaString,
  170. PWSTR String )
  171. {
  172. DWORD StringLength;
  173. if (String == NULL)
  174. {
  175. LsaString->Buffer = NULL;
  176. LsaString->Length = 0;
  177. LsaString->MaximumLength = 0;
  178. return;
  179. }
  180. StringLength = wcslen(String);
  181. LsaString->Buffer = String;
  182. LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
  183. LsaString->MaximumLength = (USHORT) (StringLength + 1) * sizeof(WCHAR);
  184. }
  185. //+---------------------------------------------------------------------------
  186. //
  187. // Function: InitLsaString
  188. //
  189. // Purpose: This routine intializes LSA_UNICODE_STRING given an UNICODE string0
  190. //
  191. // Arguments: LsaString
  192. // String
  193. //
  194. // Returns:
  195. //
  196. // Notes:
  197. //
  198. PSID
  199. GetAccountSid(
  200. LSA_HANDLE PolicyHandle,
  201. PWSTR AccountName
  202. )
  203. {
  204. DWORD NewSidLength;
  205. DWORD SubAuthorityCount;
  206. PSID Sid;
  207. PSID DomainSid;
  208. NTSTATUS Status;
  209. PLSA_TRANSLATED_SID TranslatedSid;
  210. PLSA_REFERENCED_DOMAIN_LIST Domains;
  211. LSA_UNICODE_STRING AccountString;
  212. //
  213. // Convert the string to a LSA_UNICODE_STRING
  214. //
  215. InitLsaString(
  216. &AccountString,
  217. AccountName
  218. );
  219. //
  220. // Call the LSA to lookup the name
  221. //
  222. Status = LsaLookupNames(
  223. PolicyHandle,
  224. 1,
  225. &AccountString,
  226. &Domains,
  227. &TranslatedSid
  228. );
  229. if (!SUCCEEDED(Status))
  230. return(NULL);
  231. //
  232. // Build a SID from the Domain SID and account RID
  233. //
  234. DomainSid = Domains->Domains[TranslatedSid->DomainIndex].Sid;
  235. //
  236. // Compute the length of the new SID. This is the length required for the
  237. // number of subauthorities in the domain sid plus one for the user RID.
  238. //
  239. SubAuthorityCount = *GetSidSubAuthorityCount(DomainSid);
  240. NewSidLength = GetSidLengthRequired( (UCHAR) (SubAuthorityCount + 1) );
  241. Sid = LocalAlloc(0,NewSidLength);
  242. if (Sid == NULL)
  243. {
  244. LsaFreeMemory(Domains);
  245. LsaFreeMemory(TranslatedSid);
  246. return(NULL);
  247. }
  248. //
  249. // Build the SID by copying the domain SID and, increasing the sub-
  250. // authority count in the new sid by one, and setting the last
  251. // subauthority to be the relative id of the user.
  252. //
  253. CopySid(
  254. NewSidLength,
  255. Sid,
  256. DomainSid
  257. );
  258. *GetSidSubAuthorityCount(Sid) = (UCHAR) SubAuthorityCount + 1;
  259. *GetSidSubAuthority(Sid, SubAuthorityCount) = TranslatedSid->RelativeId;
  260. LsaFreeMemory(Domains);
  261. LsaFreeMemory(TranslatedSid);
  262. return(Sid);
  263. }
  264. //+---------------------------------------------------------------------------
  265. //
  266. // Function: AddUserRightToAccount
  267. //
  268. // Purpose: This routine grants the SE_TCB_NAME right to the specified user
  269. // account on the local machine
  270. //
  271. // Arguments: PolicyHandle
  272. // AccountName
  273. //
  274. // Returns: ERROR_SUCCESS if the right was granted successfully
  275. // Win32 error otherwise
  276. //
  277. // Notes:
  278. //
  279. DWORD
  280. AddUserRightToAccount(
  281. PWSTR AccountName )
  282. {
  283. DWORD Error;
  284. NTSTATUS Status;
  285. PSID AccountSid = NULL;
  286. LSA_HANDLE PolicyHandle;
  287. LSA_UNICODE_STRING UserRightString;
  288. // Get a LSA policy handle to manipulate user rights
  289. Error = OpenPolicy ( &PolicyHandle );
  290. if ( Error )
  291. return Error;
  292. // Get the SID for the account
  293. AccountSid = GetAccountSid(
  294. PolicyHandle,
  295. AccountName );
  296. if (AccountSid == NULL)
  297. {
  298. LsaClose ( &PolicyHandle );
  299. return(ERROR_NOT_ENOUGH_MEMORY);
  300. }
  301. //
  302. // Create a LSA_UNICODE_STRING for the right name
  303. //
  304. InitLsaString(
  305. &UserRightString,
  306. SE_TCB_NAME );
  307. // Grant the right
  308. Status = LsaAddAccountRights(
  309. PolicyHandle,
  310. AccountSid,
  311. &UserRightString,
  312. 1 );
  313. Error = LsaNtStatusToWinError(Status);
  314. LocalFree( AccountSid );
  315. LsaClose ( &PolicyHandle );
  316. return(Error);
  317. }
  318. //+---------------------------------------------------------------------------
  319. //
  320. // Function: AddUserRightToAccount
  321. //
  322. // Purpose: This routine removes the SE_TCB_NAME right to the specified user
  323. // account on the local machine
  324. //
  325. // Arguments: PolicyHandle
  326. // AccountName
  327. //
  328. // Returns: ERROR_SUCCESS if the right was rmoved successfully
  329. // Win32 error otherwise
  330. //
  331. // Notes:
  332. //
  333. DWORD
  334. RemoveUserRightFromAccount(
  335. PWSTR AccountName )
  336. {
  337. NTSTATUS Status;
  338. DWORD Error;
  339. PSID AccountSid;
  340. LSA_HANDLE PolicyHandle;
  341. LSA_UNICODE_STRING UserRightString;
  342. // Get a LSA policy handle to manipulate user rights
  343. Error = OpenPolicy ( &PolicyHandle );
  344. if ( Error )
  345. return Error;
  346. AccountSid = GetAccountSid(
  347. PolicyHandle,
  348. AccountName );
  349. if (AccountSid == NULL)
  350. {
  351. LsaClose ( &PolicyHandle );
  352. return(ERROR_NOT_ENOUGH_MEMORY);
  353. }
  354. //
  355. // Create a LSA_UNICODE_STRING for the right name
  356. //
  357. InitLsaString(
  358. &UserRightString,
  359. SE_TCB_NAME );
  360. Status = LsaRemoveAccountRights(
  361. PolicyHandle,
  362. AccountSid,
  363. FALSE, // don't remove all rights
  364. &UserRightString,
  365. 1 );
  366. Error = LsaNtStatusToWinError(Status);
  367. LocalFree(AccountSid);
  368. LsaClose ( &PolicyHandle );
  369. return(Error);
  370. }
  371. //+---------------------------------------------------------------------------
  372. //
  373. // Function: HrGetAcsServiceAccountName
  374. //
  375. // Purpose: This routine returns the AcsService account name in the
  376. // DomainName\UserName format. DomainName is obtained from
  377. // the current logon domain.
  378. //
  379. // Arguments: lpwNtAccountName - Buffer to return the account name.
  380. //
  381. // Returns: S_OK If the account name was generated
  382. // Win32 error otherwise
  383. //
  384. // Notes:
  385. //
  386. HRESULT HrGetAcsServiceAccountName (
  387. PWSTR lpwNtAccountName )
  388. {
  389. DWORD dwErr;
  390. HRESULT hr;
  391. PWSTR lpwDomain = NULL;
  392. PWSTR lpwDcName = NULL;
  393. LPBYTE lpbUserInfo = NULL;
  394. NETSETUP_JOIN_STATUS js;
  395. lpwNtAccountName[0] = 0;
  396. // Get the name of the DC for the logged on domain
  397. dwErr = NetGetDCName (
  398. NULL,
  399. NULL,
  400. (LPBYTE *) &lpwDcName );
  401. if ( dwErr ) {
  402. hr = HRESULT_FROM_WIN32(dwErr);
  403. goto Exit;
  404. }
  405. // Next get user info to verify that there is a user
  406. // account for AcsService
  407. dwErr = NetUserGetInfo (
  408. lpwDcName,
  409. c_szAcsService,
  410. 2,
  411. &lpbUserInfo );
  412. if ( dwErr ) {
  413. hr = HRESULT_FROM_WIN32(dwErr);
  414. goto Exit;
  415. }
  416. // Find out the name of the domain into which this compter
  417. // is currently logged on to
  418. dwErr = NetGetJoinInformation (
  419. NULL,
  420. &lpwDomain,
  421. &js );
  422. if ( dwErr ) {
  423. hr = HRESULT_FROM_WIN32(dwErr);
  424. goto Exit;
  425. }
  426. if ( js != NetSetupDomainName ) {
  427. hr = NETCFG_E_NOT_JOINED;
  428. goto Exit;
  429. }
  430. // Generate the account name by concatenating domain name and "AcsService"
  431. wcscpy ( lpwNtAccountName, lpwDomain );
  432. wcscat ( lpwNtAccountName, L"\\" );
  433. wcscat ( lpwNtAccountName, c_szAcsService );
  434. hr = S_OK;
  435. Exit:
  436. if ( lpwDcName )
  437. NetApiBufferFree ( lpwDcName );
  438. if ( lpbUserInfo )
  439. NetApiBufferFree ( lpbUserInfo );
  440. if ( lpwDomain )
  441. NetApiBufferFree ( lpwDomain );
  442. TraceError("HrGetAcsServiceAccountName", hr);
  443. return hr;
  444. }
  445. //+---------------------------------------------------------------------------
  446. //
  447. // Function: HrSetAcsServiceRights
  448. //
  449. // Purpose: This routine adds the AcsService account to the administrators group
  450. // on the local computer and grants SE_TCB_NAME right also
  451. //
  452. // Arguments:
  453. //
  454. // Returns: S_OK Success
  455. // Win32 error otherwise
  456. //
  457. // Notes:
  458. //
  459. HRESULT HrSetAcsServiceRights( )
  460. {
  461. DWORD dwErr;
  462. HRESULT hr;
  463. WCHAR szAcsUserName[UNLEN+GNLEN+2];
  464. PWSTR lpwAcsUserName;
  465. LOCALGROUP_MEMBERS_INFO_3 localgroup_members;
  466. // First get the user name of AcsService in the format
  467. // DomainName\UserName
  468. hr = ::HrGetAcsServiceAccountName ( szAcsUserName );
  469. if ( hr ) {
  470. hr = HRESULT_FROM_WIN32(ERROR_INVALID_ACCOUNT_NAME);
  471. goto Exit;
  472. }
  473. if ( !szAcsUserName[0] ) {
  474. hr = HRESULT_FROM_WIN32(ERROR_INVALID_ACCOUNT_NAME);
  475. goto Exit;
  476. }
  477. // Add AcsService account to be a local administrator
  478. localgroup_members.lgrmi3_domainandname = szAcsUserName;
  479. dwErr = NetLocalGroupAddMembers(
  480. NULL, // PDC name
  481. L"Administrators", // group name
  482. 3, // passing in name
  483. (LPBYTE)&localgroup_members, // Buffer
  484. 1 ); // count passed in
  485. if ( dwErr ) {
  486. if ( dwErr == ERROR_MEMBER_IN_ALIAS ) {
  487. hr = S_OK;
  488. dwErr = 0;
  489. }
  490. else {
  491. hr = HRESULT_FROM_WIN32(dwErr);
  492. goto Exit;
  493. }
  494. }
  495. // Grant SE_TCB_NAME "Act as part of Operating system" right to AcsService
  496. dwErr = AddUserRightToAccount(
  497. szAcsUserName );
  498. if ( dwErr ) {
  499. hr = HRESULT_FROM_WIN32( dwErr );
  500. goto Exit;
  501. }
  502. hr = S_OK;
  503. Exit:
  504. TraceError ( "HrSetAcsServiceRights", hr );
  505. return hr;
  506. }
  507. //+---------------------------------------------------------------------------
  508. //
  509. // Function: HrRemoveAcsServiceRights
  510. //
  511. // Purpose: This routine removes the AcsService account from the administrators group
  512. // on the local computer and removes SE_TCB_NAME right.
  513. //
  514. // Arguments:
  515. //
  516. // Returns: S_OK Success
  517. // Win32 error otherwise
  518. //
  519. // Notes:
  520. //
  521. HRESULT HrRemoveAcsServiceRights( )
  522. {
  523. DWORD dwErr;
  524. HRESULT hr;
  525. WCHAR szAcsUserName[UNLEN+GNLEN+2];
  526. LOCALGROUP_MEMBERS_INFO_3 localgroup_members;
  527. // First get the user name of AcsService in the format
  528. // DomainName\UserName
  529. hr = ::HrGetAcsServiceAccountName ( szAcsUserName );
  530. if ( hr ) {
  531. hr = HRESULT_FROM_WIN32(ERROR_INVALID_ACCOUNT_NAME);
  532. goto Exit;
  533. }
  534. if ( !szAcsUserName[0] ) {
  535. hr = HRESULT_FROM_WIN32(ERROR_INVALID_ACCOUNT_NAME);
  536. goto Exit;
  537. }
  538. // Remove AcsService account to be a local administrator
  539. localgroup_members.lgrmi3_domainandname = szAcsUserName;
  540. dwErr = NetLocalGroupDelMembers(
  541. NULL, // PDC name
  542. L"Administrators", // group name
  543. 3, // passing in name
  544. (LPBYTE)&localgroup_members, // Buffer
  545. 1 ); // count passed in
  546. if ( dwErr ) {
  547. if ( dwErr == ERROR_MEMBER_NOT_IN_ALIAS ) {
  548. hr = S_OK;
  549. dwErr = 0;
  550. }
  551. else {
  552. hr = HRESULT_FROM_WIN32(dwErr);
  553. goto Exit;
  554. }
  555. }
  556. // Grant "Act as part of Operating system" right to AcsService
  557. dwErr = RemoveUserRightFromAccount(
  558. szAcsUserName );
  559. if ( dwErr ) {
  560. hr = HRESULT_FROM_WIN32( dwErr );
  561. goto Exit;
  562. }
  563. hr = S_OK;
  564. Exit:
  565. TraceError ( "HrRemoveAcsServiceRights", hr );
  566. return hr;
  567. }
  568. //+---------------------------------------------------------------------------
  569. //
  570. // Function: HrGetIpAddrTable
  571. //
  572. // Purpose: Gets the address table of the subnets that machine can see
  573. //
  574. // Arguments: ppmiat - Where to return the allocated address table
  575. //
  576. // Returns: S_OK if successful, Win32 error otherwise.
  577. //
  578. // Notes: The result must be freed by the caller
  579. //
  580. HRESULT HrGetIpAddrTable(MIB_IPADDRTABLE** ppmiat)
  581. {
  582. HRESULT hr = S_OK;
  583. DWORD dwErr = NO_ERROR;
  584. HMODULE hIpHelpApi = NULL;
  585. GETIPADDRTABLE pfnGetIpAddrTable = NULL;
  586. AssertSz(ppmiat , "HrGetIpAddrTable doesn't have a ppmiat");
  587. // Make sure we have our function loaded
  588. //
  589. hr = ::HrLoadLibAndGetProc(
  590. c_szIpHlpApiDllName,
  591. c_szaGetIpAddrTable,
  592. &hIpHelpApi,
  593. (FARPROC*)&pfnGetIpAddrTable);
  594. if (SUCCEEDED(hr))
  595. {
  596. DWORD dwAddrCount = 0;
  597. AssertSz(pfnGetIpAddrTable, "We should have a pfnGetIpAddrTable");
  598. // Find out how big a buffer we need.
  599. //
  600. dwErr = pfnGetIpAddrTable(*ppmiat, &dwAddrCount, FALSE);
  601. hr = HRESULT_FROM_WIN32(dwErr);
  602. // Allocate the buffer of the correct size
  603. //
  604. if ((NO_ERROR == dwErr)
  605. || (ERROR_INSUFFICIENT_BUFFER == dwErr))
  606. {
  607. UINT cbTable = 0;
  608. // Create the buffer
  609. //
  610. cbTable = (sizeof(MIB_IPADDRTABLE)
  611. + (sizeof(MIB_IPADDRROW) * (dwAddrCount)));
  612. *ppmiat = reinterpret_cast<MIB_IPADDRTABLE*>(new BYTE [cbTable]);
  613. // Try a second time with the correct buffer
  614. //
  615. dwErr = pfnGetIpAddrTable(*ppmiat, &dwAddrCount, FALSE);
  616. hr = HRESULT_FROM_WIN32(dwErr);
  617. }
  618. // Unload the DLL
  619. //
  620. (VOID)::FreeLibrary(hIpHelpApi);
  621. }
  622. TraceErrorOptional("HrGetIpAddrTable", hr,
  623. (HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED) == hr));
  624. return hr;
  625. }
  626. //+---------------------------------------------------------------------------
  627. //
  628. // Function: HrFindFirstSubnet
  629. //
  630. // Purpose: Finds the first available subnet on the system to be used as
  631. // the default entry in the registry. If a subnet cannot be found
  632. // 000.000.000.000 is used.
  633. //
  634. // Arguments: pdwSubnet - Where to return the subnet
  635. //
  636. // Returns: Error code
  637. //
  638. // Notes:
  639. //
  640. HRESULT HrFindFirstSubnet(DWORD* pdwSubnet)
  641. {
  642. HRESULT hr = S_OK;
  643. MIB_IPADDRTABLE* ppmiat = NULL;
  644. // Get our list of address entries
  645. //
  646. hr = HrGetIpAddrTable(&ppmiat);
  647. if (SUCCEEDED(hr))
  648. {
  649. MIB_IPADDRROW* pmiarTemp = ppmiat->table;
  650. DWORD dwIpAddrCount = ppmiat->dwNumEntries;
  651. DWORD dwSubnet = 0x0;
  652. while (dwIpAddrCount--)
  653. {
  654. // Find out what the sub net is
  655. //
  656. dwSubnet = (pmiarTemp->dwAddr & pmiarTemp->dwMask);
  657. // The APIs return the value in network order, and we want to
  658. // store the data in host order, so we have to convert the
  659. // address
  660. //
  661. dwSubnet = ntohl(dwSubnet);
  662. // Don't add invalid subnets to the list
  663. //
  664. if ((c_dwLocalSubnet != dwSubnet)
  665. && (c_dwNullSubnet != dwSubnet))
  666. {
  667. // We found one!!
  668. //
  669. *pdwSubnet = dwSubnet;
  670. break;
  671. }
  672. // Look at the next entry
  673. //
  674. pmiarTemp++;
  675. }
  676. // Free the allocated memory
  677. //
  678. delete ppmiat;
  679. }
  680. TraceError("HrFindFirstSubnet", hr);
  681. return hr;
  682. }
  683. //+---------------------------------------------------------------------------
  684. //
  685. // Function: HrWriteAcsSubnetDataToReg
  686. //
  687. // Purpose: Writes out the subnet information to the registry
  688. //
  689. // Arguments: pasrdSubnet - The data that has to be written
  690. //
  691. // Returns: Error code
  692. //
  693. // Notes:
  694. //
  695. HRESULT HrWriteAcsSubnetDataToReg(ACS_SUBNET_REG_DATA* pasrdSubnet)
  696. {
  697. HRESULT hr = S_OK;
  698. HKEY hkeySubnet = NULL;
  699. DWORD dwDisposition = 0x0;
  700. hr = ::HrRegCreateKeyEx(
  701. HKEY_LOCAL_MACHINE,
  702. c_szRegKeyRsvpSubnet,
  703. REG_OPTION_NON_VOLATILE,
  704. KEY_ALL_ACCESS,
  705. NULL,
  706. &hkeySubnet,
  707. &dwDisposition);
  708. if (SUCCEEDED(hr))
  709. {
  710. // Write out the parameters
  711. //
  712. hr = ::HrRegWriteValueTable(
  713. hkeySubnet,
  714. celems(c_avtAcsSubnet),
  715. c_avtAcsSubnet,
  716. reinterpret_cast<BYTE*>(pasrdSubnet),
  717. REG_OPTION_NON_VOLATILE,
  718. KEY_ALL_ACCESS);
  719. ::RegSafeCloseKey(hkeySubnet);
  720. }
  721. TraceError("HrWriteAcsSubnetDataToReg", hr);
  722. return hr;
  723. }
  724. //+---------------------------------------------------------------------------
  725. //
  726. // Function: HrWriteAcsRegistryData
  727. //
  728. // Purpose: Writes to the registry all of ACS's default parameters
  729. //
  730. // Arguments: pnocd - The option component information that is
  731. // needed to get an INetCfg instance
  732. // pasrdSubnet - The subnet information
  733. // palrdLog - The logging information
  734. //
  735. // Returns: Error code
  736. //
  737. // Notes:
  738. //
  739. HRESULT HrWriteAcsRegistryData(
  740. PNETOCDATA pnocd )
  741. {
  742. HRESULT hr = S_OK;
  743. ACS_SUBNET_REG_DATA asrdSubnet = { 0 };
  744. // See if we can find a subnet
  745. //
  746. hr = ::HrFindFirstSubnet(&(asrdSubnet.dwSubnetIpAddress));
  747. if (SUCCEEDED(hr))
  748. {
  749. // Default subnet values
  750. //
  751. asrdSubnet.dwDSBMPriority = c_dwDSBMPriorityDef;
  752. asrdSubnet.dwMaxPeakRatePerFlow = c_dwMaxPeakRateDef;
  753. asrdSubnet.dwMaxRSVPBandwidth = c_dwMaxRSVPBandwidthDef;
  754. asrdSubnet.dwMaxTokenBucketRatePerFlow = c_dwMaxTokenBucketDef;
  755. asrdSubnet.dwMaxTotalPeakRate = c_dwMaxTotalPeakRateDef;
  756. asrdSubnet.dwIAmDsbmRefreshInterval = c_dwIAmDsbmRefreshDef;
  757. asrdSubnet.dwDSBMDeadInterval = c_dwDSBMDeadIntervalDef;
  758. asrdSubnet.fRunAsDSBM = c_fRunAsDSBMDef;
  759. hr = ::HrWriteAcsSubnetDataToReg(&asrdSubnet);
  760. if (SUCCEEDED(hr))
  761. {
  762. ::HrWriteAcsRegistryData(pnocd);
  763. }
  764. }
  765. TraceError("HrWriteAcsRegistryData", hr);
  766. return hr;
  767. }
  768. //+---------------------------------------------------------------------------
  769. //
  770. // Function: HrChangeRsvpService
  771. //
  772. // Purpose: Change some RSVP service parameters
  773. //
  774. // Arguments: szDisplayName - The new display name
  775. // dwStartType - The new start type
  776. // fStartService - If the service should be started
  777. //
  778. // Returns: Error code
  779. //
  780. // Notes:
  781. //
  782. HRESULT HrChangeRsvpService(
  783. const WCHAR* szDisplayName,
  784. DWORD dwStartType,
  785. BOOL fStartService)
  786. {
  787. HRESULT hr = S_OK;
  788. CServiceManager scm;
  789. CService svc;
  790. // Open the RSVP service with a lock on the service controller.
  791. //
  792. hr = scm.HrOpenService(&svc, c_szSvcRsvp, NO_LOCK);
  793. if (SUCCEEDED(hr))
  794. {
  795. hr = scm.HrAddServiceDependency ( c_szSvcRsvp, c_szTcpIp );
  796. if (SUCCEEDED(hr))
  797. {
  798. hr = scm.HrAddServiceDependency ( c_szSvcRsvp, c_szAfd );
  799. if (SUCCEEDED(hr))
  800. {
  801. // Set the new start type
  802. //
  803. hr = svc.HrSetStartType(dwStartType);
  804. if (SUCCEEDED(hr))
  805. {
  806. // Change the display name
  807. //
  808. hr = svc.HrSetDisplayName(szDisplayName);
  809. if (SUCCEEDED(hr) && fStartService)
  810. {
  811. // Unlock the Service Control Manager so that we can
  812. // start the service.
  813. //
  814. // scm.Unlock();
  815. // Start up the service
  816. //
  817. hr = scm.HrStartServiceNoWait(c_szSvcRsvp);
  818. }
  819. }
  820. }
  821. }
  822. }
  823. TraceError("HrChangeRsvpService", hr);
  824. return hr;
  825. }
  826. //+---------------------------------------------------------------------------
  827. //
  828. // Function: HrInstallACS
  829. //
  830. // Purpose: Called when ACS service is being installed. Handles all of the
  831. // additional installation for ACS beyond that of the INF file.
  832. //
  833. // Arguments:
  834. // pnocd [in] Pointer to NETOC data.
  835. //
  836. // Returns: S_OK if successful, Win32 error otherwise.
  837. //
  838. // Notes:
  839. //
  840. HRESULT HrInstallACS(PNETOCDATA pnocd)
  841. {
  842. HRESULT hr = S_OK;
  843. #ifdef NEVER
  844. // For NT 5.0 beta 2, setting rights for AcsService user name will not be done as this
  845. // is introducing significant delay.
  846. // Make AcsService to be local admin and grant SE_TCB_NAME right
  847. hr = ::HrSetAcsServiceRights();
  848. if (SUCCEEDED(hr)) {
  849. // Display a message box asking the user to change the logon name
  850. NcMsgBox( g_ocmData.hwnd,
  851. IDS_OC_CAPTION,
  852. IDS_OC_ACS_CHG_LOGON,
  853. MB_ICONSTOP | MB_OK);
  854. }
  855. #endif // NEVER
  856. // Ignoring any error from changing rights and continue with the
  857. // setup so that ACS will run in Resouce only mode.
  858. // Change the RSVP service parameters
  859. hr = ::HrChangeRsvpService(
  860. ::SzLoadIds(IDS_OC_ACS_SERVICE_NAME),
  861. SERVICE_AUTO_START,
  862. TRUE);
  863. TraceError("HrInstallACS", hr);
  864. return hr;
  865. }
  866. //+---------------------------------------------------------------------------
  867. //
  868. // Function: HrRemoveACS
  869. //
  870. // Purpose: Handles additional removal requirements for ACS Service
  871. // component.
  872. //
  873. // hwnd [in] Parent window for displaying UI.
  874. // poc [in] Pointer to optional component being installed.
  875. //
  876. // Returns: S_OK if successful, Win32 error otherwise.
  877. //
  878. // Notes:
  879. //
  880. HRESULT HrRemoveACS(PNETOCDATA pnocd)
  881. {
  882. HRESULT hr = S_OK;
  883. #ifdef NEVER
  884. // For NT 5.0 beta 2, Removing AcsService user right will not be done as this
  885. // is introducing significant delay.
  886. // Drop the membership from local admins and remove SE_TCB_NAME right
  887. (VOID)::HrRemoveAcsServiceRights ();
  888. #endif // NEVER
  889. //
  890. // Clean out the adapters and subnet reg keys (if present)
  891. //
  892. (VOID)::HrRegDeleteKeyTree(HKEY_LOCAL_MACHINE, c_szRegKeyRsvpAdapters);
  893. (VOID)::HrRegDeleteKeyTree(HKEY_LOCAL_MACHINE, c_szRegKeyRsvpSubnet1);
  894. (VOID)::HrRegDeleteKeyTree(HKEY_LOCAL_MACHINE, c_szRegKeyRsvpSubnet);
  895. // Put the name back the way it should be
  896. //
  897. (VOID)::HrChangeRsvpService(
  898. ::SzLoadIds(IDS_OC_RSVP_SERVICE_NAME),
  899. SERVICE_DEMAND_START,
  900. FALSE);
  901. TraceError("HrRemoveACS", hr);
  902. return hr;
  903. }
  904. //+---------------------------------------------------------------------------
  905. //
  906. // Function: HrOcExtACS
  907. //
  908. // Purpose: NetOC external message handler
  909. //
  910. // Arguments:
  911. // pnocd []
  912. // uMsg []
  913. // wParam []
  914. // lParam []
  915. //
  916. // Returns:
  917. //
  918. // Author: danielwe 17 Sep 1998
  919. //
  920. // Notes:
  921. //
  922. HRESULT HrOcExtACS(PNETOCDATA pnocd, UINT uMsg,
  923. WPARAM wParam, LPARAM lParam)
  924. {
  925. HRESULT hr = S_OK;
  926. Assert(pnocd);
  927. switch (uMsg)
  928. {
  929. case NETOCM_POST_INSTALL:
  930. hr = HrOcAcsOnInstall(pnocd);
  931. break;
  932. case NETOCM_QUERY_CHANGE_SEL_STATE:
  933. hr = HrOcAcsOnQueryChangeSelState(pnocd, static_cast<BOOL>(wParam));
  934. break;
  935. }
  936. TraceError("HrOcExtACS", hr);
  937. return hr;
  938. }
  939. //+---------------------------------------------------------------------------
  940. //
  941. // Function: HrOcAcsOnInstall
  942. //
  943. // Purpose: Called by optional components installer code to handle
  944. // additional installation requirements for ACS Server
  945. //
  946. // Arguments:
  947. // pnocd [in] Pointer to NETOC data
  948. //
  949. // Returns: S_OK if successful, Win32 error otherwise.
  950. //
  951. // Notes:
  952. //
  953. HRESULT HrOcAcsOnInstall(PNETOCDATA pnocd)
  954. {
  955. HRESULT hr = S_OK;
  956. if (IT_INSTALL == pnocd->eit)
  957. {
  958. hr = HrInstallACS(pnocd);
  959. }
  960. else if (IT_REMOVE == pnocd->eit)
  961. {
  962. hr = HrRemoveACS(pnocd);
  963. }
  964. TraceError("HrOcAcsOnInstall", hr);
  965. return hr;
  966. }
  967. //+---------------------------------------------------------------------------
  968. //
  969. // Function: HrOcAcsOnQueryChangeSelState
  970. //
  971. // Purpose: Handles the request of the OC framework of whether or not
  972. // the user should be allowed to install ACS on this host.
  973. //
  974. // Arguments:
  975. // pnocd [in] NetOC Data
  976. // fShowUi [in] TRUE if UI should be shown, FALSE if not
  977. //
  978. // Returns: S_OK if install is allowed, S_FALSE if not, Win32 error
  979. // otherwise
  980. //
  981. // Author: rameshpa 23 April 1998
  982. //
  983. // Notes:
  984. //
  985. HRESULT HrOcAcsOnQueryChangeSelState(PNETOCDATA pnocd, BOOL fShowUi)
  986. {
  987. HRESULT hr = S_OK;
  988. #ifdef NEVER
  989. // For NT 5.0 beta 2, checking for user name will not be done as this
  990. // is introducing significant delay.
  991. WCHAR szAcsUserName[UNLEN+GNLEN+2];
  992. Assert(pnocd);
  993. Assert(g_ocmData.hwnd);
  994. // See if AcsService account exists in this domain or not
  995. hr = HrGetAcsServiceAccountName(szAcsUserName);
  996. if ( FAILED(hr)
  997. || !szAcsUserName[0] )
  998. {
  999. if (fShowUi)
  1000. {
  1001. NcMsgBox( g_ocmData.hwnd,
  1002. IDS_OC_CAPTION,
  1003. IDS_OC_NO_ACS_USER_ACCOUNT,
  1004. MB_ICONSTOP | MB_OK);
  1005. }
  1006. // Allow ACS setup to continue, as ACS will default to
  1007. // Resource only
  1008. hr = S_FALSE;
  1009. }
  1010. TraceError("HrOcAcsOnQueryChangeSelState", hr);
  1011. #endif // NEVER
  1012. return hr;
  1013. }