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.

870 lines
24 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. service.c
  5. Abstract:
  6. This file provides access to the service control
  7. manager for starting, stopping, adding, and removing
  8. services.
  9. Environment:
  10. WIN32 User Mode
  11. Author:
  12. Wesley Witt (wesw) 17-Feb-1996
  13. --*/
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h>
  17. #include "faxocm.h"
  18. #include <ntsecapi.h>
  19. #include <lm.h>
  20. NTSTATUS
  21. OpenPolicy(
  22. LPWSTR ServerName, // machine to open policy on (Unicode)
  23. DWORD DesiredAccess, // desired access to policy
  24. PLSA_HANDLE PolicyHandle // resultant policy handle
  25. );
  26. BOOL
  27. GetAccountSid(
  28. LPWSTR SystemName, // where to lookup account
  29. LPWSTR AccountName, // account of interest
  30. PSID *Sid // resultant buffer containing SID
  31. );
  32. NTSTATUS
  33. SetPrivilegeOnAccount(
  34. LSA_HANDLE PolicyHandle, // open policy handle
  35. PSID AccountSid, // SID to grant privilege to
  36. LPWSTR PrivilegeName, // privilege to grant (Unicode)
  37. BOOL bEnable // enable or disable
  38. );
  39. void
  40. InitLsaString(
  41. PLSA_UNICODE_STRING LsaString, // destination
  42. LPWSTR String // source (Unicode)
  43. );
  44. void
  45. DisplayNtStatus(
  46. LPSTR szAPI, // pointer to function name (ANSI)
  47. NTSTATUS Status // NTSTATUS error value
  48. );
  49. void
  50. DisplayWinError(
  51. LPSTR szAPI, // pointer to function name (ANSI)
  52. DWORD WinError // DWORD WinError
  53. );
  54. #define RTN_OK 0
  55. #define RTN_USAGE 1
  56. #define RTN_ERROR 13
  57. //
  58. // If you have the ddk, include ntstatus.h.
  59. //
  60. #ifndef STATUS_SUCCESS
  61. #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
  62. #endif
  63. BOOL
  64. GetDefaultDomainName(
  65. LPWSTR DomainName
  66. )
  67. {
  68. OBJECT_ATTRIBUTES ObjectAttributes;
  69. NTSTATUS NtStatus;
  70. DWORD err = 0;
  71. LSA_HANDLE LsaPolicyHandle = NULL;
  72. PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo = NULL;
  73. //
  74. // Open a handle to the local machine's LSA policy object.
  75. //
  76. InitializeObjectAttributes( &ObjectAttributes, // object attributes
  77. NULL, // name
  78. 0L, // attributes
  79. NULL, // root directory
  80. NULL ); // security descriptor
  81. NtStatus = LsaOpenPolicy( NULL, // system name
  82. &ObjectAttributes, // object attributes
  83. POLICY_EXECUTE, // access mask
  84. &LsaPolicyHandle ); // policy handle
  85. if( !NT_SUCCESS( NtStatus ) )
  86. {
  87. return FALSE;
  88. }
  89. //
  90. // Query the domain information from the policy object.
  91. //
  92. NtStatus = LsaQueryInformationPolicy( LsaPolicyHandle,
  93. PolicyAccountDomainInformation,
  94. (PVOID *) &DomainInfo );
  95. if (!NT_SUCCESS(NtStatus))
  96. {
  97. LsaClose(LsaPolicyHandle);
  98. return FALSE;
  99. }
  100. (void) LsaClose(LsaPolicyHandle);
  101. //
  102. // Copy the domain name into our cache, and
  103. //
  104. CopyMemory( DomainName,
  105. DomainInfo->DomainName.Buffer,
  106. DomainInfo->DomainName.Length );
  107. //
  108. // Null terminate it appropriately
  109. //
  110. DomainName[DomainInfo->DomainName.Length / sizeof(WCHAR)] = L'\0';
  111. //
  112. // Clean up
  113. //
  114. LsaFreeMemory( (PVOID)DomainInfo );
  115. return TRUE;
  116. }
  117. LPWSTR
  118. GetMachineName(
  119. LPWSTR AccountName
  120. )
  121. {
  122. LSA_HANDLE PolicyHandle = NULL;
  123. WCHAR DomainName[128];
  124. WCHAR LocalComputerName[128];
  125. LPWSTR MachineName = NULL;
  126. LPWSTR p;
  127. LPWSTR DCName = NULL;
  128. NET_API_STATUS NetStatus;
  129. UNICODE_STRING NameStrings;
  130. PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains = NULL;
  131. PLSA_TRANSLATED_SID LsaSids = NULL;
  132. PUSER_MODALS_INFO_1 Modals = NULL;
  133. DWORD Size;
  134. NTSTATUS Status;
  135. //
  136. // get the domain name
  137. //
  138. p = wcschr( AccountName, L'\\' );
  139. if (p) {
  140. *p = 0;
  141. wcscpy( DomainName, AccountName );
  142. *p = L'\\';
  143. } else {
  144. wcscpy( DomainName, AccountName );
  145. }
  146. //
  147. // Open the policy on the target machine.
  148. //
  149. Status = OpenPolicy(
  150. NULL,
  151. POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
  152. &PolicyHandle
  153. );
  154. if (Status != STATUS_SUCCESS) {
  155. goto exit;
  156. }
  157. //
  158. // lookup the domain name for the account
  159. //
  160. InitLsaString( &NameStrings, AccountName );
  161. Status = LsaLookupNames(
  162. PolicyHandle,
  163. 1,
  164. &NameStrings,
  165. &ReferencedDomains,
  166. &LsaSids
  167. );
  168. if (Status != STATUS_SUCCESS) {
  169. goto exit;
  170. }
  171. //
  172. // get the local computer name
  173. //
  174. Size = sizeof(LocalComputerName);
  175. if (!GetComputerName( LocalComputerName, &Size )) {
  176. goto exit;
  177. }
  178. //
  179. // see if we are tring to set a local account
  180. //
  181. if (wcscmp( LocalComputerName, ReferencedDomains->Domains->Name.Buffer ) != 0) {
  182. //
  183. // see what part of the domain we are attempting to set
  184. //
  185. NetStatus = NetUserModalsGet( NULL, 1, (LPBYTE*) &Modals );
  186. if (NetStatus != NERR_Success) {
  187. goto exit;
  188. }
  189. if (Modals->usrmod1_role != UAS_ROLE_PRIMARY) {
  190. //
  191. // we know we are remote, so get the real dc name
  192. //
  193. NetStatus = NetGetDCName( NULL, DomainName, (LPBYTE*) &DCName );
  194. if (NetStatus != NERR_Success) {
  195. goto exit;
  196. }
  197. MachineName = StringDup( DCName );
  198. }
  199. }
  200. exit:
  201. if (Modals) {
  202. NetApiBufferFree( Modals );
  203. }
  204. if (DCName) {
  205. NetApiBufferFree( DCName );
  206. }
  207. if (ReferencedDomains) {
  208. LsaFreeMemory( ReferencedDomains );
  209. }
  210. if (LsaSids) {
  211. LsaFreeMemory( LsaSids );
  212. }
  213. if (PolicyHandle) {
  214. LsaClose( PolicyHandle );
  215. }
  216. return MachineName;
  217. }
  218. DWORD
  219. SetServiceSecurity(
  220. LPWSTR AccountName
  221. )
  222. {
  223. LSA_HANDLE PolicyHandle;
  224. PSID pSid;
  225. NTSTATUS Status;
  226. int iRetVal=RTN_ERROR;
  227. LPWSTR MachineName;
  228. WCHAR NewAccountName[512];
  229. if (AccountName[0] == L'.') {
  230. if (GetDefaultDomainName( NewAccountName )) {
  231. wcscat( NewAccountName, &AccountName[1] );
  232. AccountName = NewAccountName;
  233. }
  234. }
  235. //
  236. // try to get the correct machine name
  237. //
  238. MachineName = GetMachineName( AccountName );
  239. //
  240. // Open the policy on the target machine.
  241. //
  242. Status = OpenPolicy(
  243. MachineName,
  244. POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
  245. &PolicyHandle
  246. );
  247. if (Status != STATUS_SUCCESS) {
  248. return RTN_ERROR;
  249. }
  250. //
  251. // Obtain the SID of the user/group.
  252. // Note that we could target a specific machine, but we don't.
  253. // Specifying NULL for target machine searches for the SID in the
  254. // following order: well-known, Built-in and local, primary domain,
  255. // trusted domains.
  256. //
  257. if(GetAccountSid(
  258. MachineName, // target machine
  259. AccountName,// account to obtain SID
  260. &pSid // buffer to allocate to contain resultant SID
  261. )) {
  262. //
  263. // We only grant the privilege if we succeeded in obtaining the
  264. // SID. We can actually add SIDs which cannot be looked up, but
  265. // looking up the SID is a good sanity check which is suitable for
  266. // most cases.
  267. //
  268. // Grant the SeServiceLogonRight to users represented by pSid.
  269. //
  270. if((Status=SetPrivilegeOnAccount(
  271. PolicyHandle, // policy handle
  272. pSid, // SID to grant privilege
  273. L"SeServiceLogonRight", // Unicode privilege
  274. TRUE // enable the privilege
  275. )) == STATUS_SUCCESS) {
  276. iRetVal=RTN_OK;
  277. }
  278. }
  279. //
  280. // Close the policy handle.
  281. //
  282. LsaClose(PolicyHandle);
  283. //
  284. // Free memory allocated for SID.
  285. //
  286. if(pSid != NULL) MemFree(pSid);
  287. return iRetVal;
  288. }
  289. void
  290. InitLsaString(
  291. PLSA_UNICODE_STRING LsaString,
  292. LPWSTR String
  293. )
  294. {
  295. DWORD StringLength;
  296. if (String == NULL) {
  297. LsaString->Buffer = NULL;
  298. LsaString->Length = 0;
  299. LsaString->MaximumLength = 0;
  300. return;
  301. }
  302. StringLength = wcslen(String);
  303. LsaString->Buffer = String;
  304. LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
  305. LsaString->MaximumLength=(USHORT)(StringLength+1) * sizeof(WCHAR);
  306. }
  307. NTSTATUS
  308. OpenPolicy(
  309. LPWSTR ServerName,
  310. DWORD DesiredAccess,
  311. PLSA_HANDLE PolicyHandle
  312. )
  313. {
  314. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  315. LSA_UNICODE_STRING ServerString;
  316. PLSA_UNICODE_STRING Server = NULL;
  317. //
  318. // Always initialize the object attributes to all zeroes.
  319. //
  320. ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
  321. if (ServerName != NULL) {
  322. //
  323. // Make a LSA_UNICODE_STRING out of the LPWSTR passed in
  324. //
  325. InitLsaString(&ServerString, ServerName);
  326. Server = &ServerString;
  327. }
  328. //
  329. // Attempt to open the policy.
  330. //
  331. return LsaOpenPolicy(
  332. Server,
  333. &ObjectAttributes,
  334. DesiredAccess,
  335. PolicyHandle
  336. );
  337. }
  338. /*++
  339. This function attempts to obtain a SID representing the supplied
  340. account on the supplied system.
  341. If the function succeeds, the return value is TRUE. A buffer is
  342. allocated which contains the SID representing the supplied account.
  343. This buffer should be freed when it is no longer needed by calling
  344. HeapFree(GetProcessHeap(), 0, buffer)
  345. If the function fails, the return value is FALSE. Call GetLastError()
  346. to obtain extended error information.
  347. --*/
  348. BOOL
  349. GetAccountSid(
  350. LPWSTR SystemName,
  351. LPWSTR AccountName,
  352. PSID *Sid
  353. )
  354. {
  355. LPWSTR ReferencedDomain=NULL;
  356. DWORD cbSid=128; // initial allocation attempt
  357. DWORD cbReferencedDomain=32; // initial allocation size
  358. SID_NAME_USE peUse;
  359. BOOL bSuccess=FALSE; // assume this function will fail
  360. __try {
  361. //
  362. // initial memory allocations
  363. //
  364. if((*Sid=MemAlloc(cbSid)) == NULL) __leave;
  365. if((ReferencedDomain=(LPWSTR)MemAlloc(cbReferencedDomain)) == NULL) __leave;
  366. //
  367. // Obtain the SID of the specified account on the specified system.
  368. //
  369. while(!LookupAccountName(
  370. SystemName, // machine to lookup account on
  371. AccountName, // account to lookup
  372. *Sid, // SID of interest
  373. &cbSid, // size of SID
  374. ReferencedDomain, // domain account was found on
  375. &cbReferencedDomain,
  376. &peUse
  377. )) {
  378. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  379. //
  380. // reallocate memory
  381. //
  382. if((*Sid=HeapReAlloc(
  383. GetProcessHeap(),
  384. 0,
  385. *Sid,
  386. cbSid
  387. )) == NULL) __leave;
  388. if((ReferencedDomain=(LPWSTR)HeapReAlloc(
  389. GetProcessHeap(),
  390. 0,
  391. ReferencedDomain,
  392. cbReferencedDomain
  393. )) == NULL) __leave;
  394. }
  395. else __leave;
  396. }
  397. //
  398. // Indicate success.
  399. //
  400. bSuccess=TRUE;
  401. } // finally
  402. __finally {
  403. //
  404. // Cleanup and indicate failure, if appropriate.
  405. //
  406. MemFree(ReferencedDomain);
  407. if(!bSuccess) {
  408. if(*Sid != NULL) {
  409. MemFree(*Sid);
  410. *Sid = NULL;
  411. }
  412. }
  413. } // finally
  414. return bSuccess;
  415. }
  416. NTSTATUS
  417. SetPrivilegeOnAccount(
  418. LSA_HANDLE PolicyHandle, // open policy handle
  419. PSID AccountSid, // SID to grant privilege to
  420. LPWSTR PrivilegeName, // privilege to grant (Unicode)
  421. BOOL bEnable // enable or disable
  422. )
  423. {
  424. LSA_UNICODE_STRING PrivilegeString;
  425. //
  426. // Create a LSA_UNICODE_STRING for the privilege name.
  427. //
  428. InitLsaString(&PrivilegeString, PrivilegeName);
  429. //
  430. // grant or revoke the privilege, accordingly
  431. //
  432. if(bEnable) {
  433. return LsaAddAccountRights(
  434. PolicyHandle, // open policy handle
  435. AccountSid, // target SID
  436. &PrivilegeString, // privileges
  437. 1 // privilege count
  438. );
  439. }
  440. else {
  441. return LsaRemoveAccountRights(
  442. PolicyHandle, // open policy handle
  443. AccountSid, // target SID
  444. FALSE, // do not disable all rights
  445. &PrivilegeString, // privileges
  446. 1 // privilege count
  447. );
  448. }
  449. }
  450. PSID WorldSid = NULL;
  451. SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
  452. PACL gDacl = NULL,gSacl = NULL;
  453. PSID gGroup = NULL,gOwner = NULL;
  454. BOOL
  455. MakeAbsoluteCopyFromRelative(
  456. PSECURITY_DESCRIPTOR psdOriginal,
  457. PSECURITY_DESCRIPTOR* ppsdNew
  458. )
  459. {
  460. // we have to find out whether the original is already self-relative
  461. SECURITY_DESCRIPTOR_CONTROL sdc = 0;
  462. PSECURITY_DESCRIPTOR psdAbsoluteCopy = NULL;
  463. DWORD dwRevision = 0;
  464. DWORD cb = 0;
  465. PACL Dacl = NULL, Sacl = NULL;
  466. BOOL bDefaulted;
  467. PSID Owner = NULL, Group = NULL;
  468. DWORD dwDaclSize = 0;
  469. BOOL bDaclPresent = FALSE;
  470. DWORD dwSaclSize = 0;
  471. BOOL bSaclPresent = FALSE;
  472. DWORD dwOwnerSize = 0;
  473. DWORD dwPrimaryGroupSize = 0;
  474. if( !IsValidSecurityDescriptor( psdOriginal ) ) {
  475. return FALSE;
  476. }
  477. if( !GetSecurityDescriptorControl( psdOriginal, &sdc, &dwRevision ) ) {
  478. DWORD err = GetLastError();
  479. goto cleanup;
  480. }
  481. if( sdc & SE_SELF_RELATIVE ) {
  482. // the original is in self-relative format, build an absolute copy
  483. // get the dacl
  484. if( !GetSecurityDescriptorDacl(
  485. psdOriginal, // address of security descriptor
  486. &bDaclPresent, // address of flag for presence of disc. ACL
  487. &Dacl, // address of pointer to ACL
  488. &bDefaulted // address of flag for default disc. ACL
  489. )
  490. ) {
  491. goto cleanup;
  492. }
  493. // get the sacl
  494. if( !GetSecurityDescriptorSacl(
  495. psdOriginal, // address of security descriptor
  496. &bSaclPresent, // address of flag for presence of disc. ACL
  497. &Sacl, // address of pointer to ACL
  498. &bDefaulted // address of flag for default disc. ACL
  499. )
  500. ) {
  501. goto cleanup;
  502. }
  503. // get the owner
  504. if( !GetSecurityDescriptorOwner(
  505. psdOriginal, // address of security descriptor
  506. &Owner, // address of pointer to owner security
  507. // identifier (SID)
  508. &bDefaulted // address of flag for default
  509. )
  510. ) {
  511. goto cleanup;
  512. }
  513. // get the group
  514. if( !GetSecurityDescriptorGroup(
  515. psdOriginal, // address of security descriptor
  516. &Group, // address of pointer to owner security
  517. // identifier (SID)
  518. &bDefaulted // address of flag for default
  519. )
  520. ) {
  521. goto cleanup;
  522. }
  523. // get required buffer size
  524. cb = 0;
  525. MakeAbsoluteSD(
  526. psdOriginal, // address of self-relative SD
  527. psdAbsoluteCopy, // address of absolute SD
  528. &cb, // address of size of absolute SD
  529. NULL, // address of discretionary ACL
  530. &dwDaclSize, // address of size of discretionary ACL
  531. NULL, // address of system ACL
  532. &dwSaclSize, // address of size of system ACL
  533. NULL, // address of owner SID
  534. &dwOwnerSize, // address of size of owner SID
  535. NULL, // address of primary-group SID
  536. &dwPrimaryGroupSize // address of size of group SID
  537. );
  538. // alloc the memory
  539. psdAbsoluteCopy = (PSECURITY_DESCRIPTOR) MemAlloc( cb );
  540. Dacl = (PACL) MemAlloc( dwDaclSize );
  541. Sacl = (PACL) MemAlloc( dwSaclSize );
  542. Owner = (PSID) MemAlloc( dwOwnerSize );
  543. Group = (PSID) MemAlloc( dwPrimaryGroupSize );
  544. if(NULL == psdAbsoluteCopy ||
  545. NULL == Dacl ||
  546. NULL == Sacl ||
  547. NULL == Owner ||
  548. NULL == Group
  549. ) {
  550. goto cleanup;
  551. }
  552. // make the copy
  553. if( !MakeAbsoluteSD(
  554. psdOriginal, // address of self-relative SD
  555. psdAbsoluteCopy, // address of absolute SD
  556. &cb, // address of size of absolute SD
  557. Dacl, // address of discretionary ACL
  558. &dwDaclSize, // address of size of discretionary ACL
  559. Sacl, // address of system ACL
  560. &dwSaclSize, // address of size of system ACL
  561. Owner, // address of owner SID
  562. &dwOwnerSize, // address of size of owner SID
  563. Group, // address of primary-group SID
  564. &dwPrimaryGroupSize // address of size of group SID
  565. )
  566. ) {
  567. goto cleanup;
  568. }
  569. } else {
  570. // the original is in absolute format, fail
  571. goto cleanup;
  572. }
  573. *ppsdNew = psdAbsoluteCopy;
  574. // paranoia check
  575. if( !IsValidSecurityDescriptor( *ppsdNew ) ) {
  576. goto cleanup;
  577. }
  578. if( !IsValidSecurityDescriptor( psdOriginal ) ) {
  579. goto cleanup;
  580. }
  581. gDacl = Dacl;
  582. gSacl = Sacl;
  583. gOwner = Owner;
  584. gGroup = Group;
  585. return(TRUE);
  586. cleanup:
  587. if( Dacl != NULL && bDaclPresent == TRUE ) {
  588. MemFree((PVOID) Dacl );
  589. Dacl = NULL;
  590. }
  591. if( Sacl != NULL && bSaclPresent == TRUE ) {
  592. MemFree((PVOID) Sacl );
  593. Sacl = NULL;
  594. }
  595. if( Owner != NULL ) {
  596. MemFree((PVOID) Owner );
  597. Owner = NULL;
  598. }
  599. if( Group != NULL ) {
  600. MemFree((PVOID) Group );
  601. Group = NULL;
  602. }
  603. if( psdAbsoluteCopy != NULL ) {
  604. MemFree((PVOID) psdAbsoluteCopy );
  605. psdAbsoluteCopy = NULL;
  606. }
  607. return (FALSE);
  608. }
  609. BOOL
  610. SetServiceWorldAccessMask(
  611. SC_HANDLE hService,
  612. DWORD AccessMask
  613. )
  614. {
  615. BOOL Rval = FALSE;
  616. DWORD Size = 0;
  617. PSECURITY_DESCRIPTOR sd = NULL, sdnew = NULL;
  618. BOOL DaclPresent = FALSE;
  619. PACL Dacl = NULL;
  620. BOOL DaclDefaulted = FALSE;
  621. PACCESS_ALLOWED_ACE Ace = NULL;
  622. BOOL bEveryoneFound = FALSE;
  623. DWORD cbAcl, cbAce;
  624. PACL DaclNew = NULL;
  625. DWORD i;
  626. if (WorldSid == NULL) {
  627. if (!AllocateAndInitializeSid( &WorldAuthority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &WorldSid )) {
  628. goto exit;
  629. }
  630. }
  631. if (!QueryServiceObjectSecurity( hService, DACL_SECURITY_INFORMATION, &sd, 0, &Size ) &&
  632. GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
  633. (sd = (PSECURITY_DESCRIPTOR) MemAlloc( Size )) &&
  634. QueryServiceObjectSecurity( hService, DACL_SECURITY_INFORMATION, sd, Size, &Size ))
  635. {
  636. if (GetSecurityDescriptorDacl( sd, &DaclPresent, &Dacl, &DaclDefaulted )) {
  637. if (!IsValidSecurityDescriptor(sd)) {
  638. goto exit;
  639. }
  640. cbAcl = sizeof (ACL);
  641. for (i=0; i<Dacl->AceCount; i++) {
  642. if (GetAce( Dacl, i, (LPVOID*)&Ace )) {
  643. if (EqualSid( WorldSid, &(Ace->SidStart))) {
  644. Ace->Mask |= AccessMask;
  645. bEveryoneFound = TRUE;
  646. }
  647. cbAce = sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD); // add this ACE's SID length
  648. cbAce += GetLengthSid (Ace);
  649. // add the length of each ACE to the total ACL length
  650. cbAcl += cbAce;
  651. }
  652. }
  653. if (!MakeAbsoluteCopyFromRelative( sd, &sdnew )){
  654. goto exit;
  655. }
  656. if (!bEveryoneFound) {
  657. // subtract ACE.SidStart from the size
  658. cbAce = sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD); // add this ACE's SID length
  659. cbAce += GetLengthSid (WorldSid);
  660. // add the length of each ACE to the total ACL length
  661. cbAcl += cbAce;
  662. DaclNew = (PACL) MemAlloc( cbAcl *4 );
  663. if (!DaclNew) {
  664. goto exit;
  665. }
  666. if (!InitializeAcl(DaclNew, cbAcl*4, ACL_REVISION )) {
  667. goto exit;
  668. }
  669. if (!IsValidAcl(DaclNew)) {
  670. goto exit;
  671. }
  672. for (i = 0; i< Dacl->AceCount; i++) {
  673. if (GetAce( Dacl, i, (LPVOID*)&Ace )) {
  674. if (!AddAccessAllowedAce(
  675. DaclNew,
  676. ACL_REVISION,
  677. Ace->Mask,
  678. &(Ace->SidStart)
  679. )) {
  680. goto exit;
  681. }
  682. if (!IsValidAcl(DaclNew)) {
  683. goto exit;
  684. }
  685. } else {
  686. goto exit;
  687. }
  688. }
  689. if (!AddAccessAllowedAce(
  690. DaclNew, // pointer to access-control list
  691. ACL_REVISION, // ACL revision level
  692. SERVICE_QUERY_STATUS | AccessMask, // access mask
  693. WorldSid // pointer to security identifier);
  694. )) {
  695. goto exit;
  696. }
  697. if (!IsValidAcl(DaclNew) ||
  698. !IsValidSecurityDescriptor(sdnew) ||
  699. !SetSecurityDescriptorDacl(
  700. sdnew,
  701. TRUE,
  702. DaclNew,
  703. FALSE )) {
  704. goto exit;
  705. }
  706. }
  707. if (IsValidSecurityDescriptor( sdnew ) &&
  708. SetServiceObjectSecurity( hService, DACL_SECURITY_INFORMATION, sdnew )) {
  709. Rval = TRUE;
  710. }
  711. }
  712. }
  713. exit:
  714. MemFree( sd );
  715. MemFree( sdnew );
  716. MemFree( DaclNew );
  717. MemFree( gDacl );
  718. MemFree( gSacl );
  719. MemFree( gGroup );
  720. MemFree( gOwner );
  721. return Rval;
  722. }
  723.