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.

1119 lines
23 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. /*++
  4. Copyright (c) 1990 Microsoft Corporation
  5. Module Name:
  6. security.c
  7. Abstract:
  8. Security related functions in the setupdll
  9. Detect Routines:
  10. 1. GetUserAccounts. Lists down all the user accounts in the system
  11. 2. GetComputerName. Finds the computer name.
  12. Install Routines Workers:
  13. 1. CheckPrivilegeExistsWorker.
  14. 2. EnablePrivilegeWorker.
  15. General Subroutines:
  16. 1. AdjustPrivilege.
  17. 2. RestorePrivilege.
  18. Author:
  19. Sunil Pai (sunilp) April 1992
  20. --*/
  21. //
  22. // Routines which are used to force deletion of a file by taking ownership
  23. // of the file
  24. //
  25. BOOL
  26. AssertTakeOwnership(
  27. HANDLE TokenHandle,
  28. PTOKEN_PRIVILEGES OldPrivs
  29. );
  30. BOOL
  31. GetTokenHandle(
  32. PHANDLE TokenHandle
  33. );
  34. VOID
  35. RestoreTakeOwnership(
  36. HANDLE TokenHandle,
  37. PTOKEN_PRIVILEGES OldPrivs
  38. );
  39. BOOL
  40. FForceDeleteFile(
  41. LPSTR szPath
  42. );
  43. //======================
  44. // DETECT ROUTINES
  45. //=======================
  46. //
  47. // Get current users account name
  48. //
  49. CB
  50. GetMyUserName(
  51. IN RGSZ Args,
  52. IN USHORT cArgs,
  53. OUT SZ ReturnBuffer,
  54. IN CB cbReturnBuffer
  55. )
  56. /*++
  57. Routine Description:
  58. DetectRoutine for GetUserName. This finds out the username of
  59. the logged in account.
  60. Arguments:
  61. Args - C argument list to this detect routine (None exist)
  62. cArgs - Number of arguments.
  63. ReturnBuffer - Buffer in which detected value is returned.
  64. cbReturnBuffer - Buffer Size.
  65. Return value:
  66. Returns length of detected value.
  67. --*/
  68. {
  69. CHAR UserName[MAX_PATH];
  70. CHAR DomainName[MAX_PATH];
  71. DWORD cbUserName = MAX_PATH;
  72. DWORD cbDomainName = MAX_PATH;
  73. SID_NAME_USE peUse;
  74. BOOL bStatus = FALSE;
  75. HANDLE hToken = NULL;
  76. TOKEN_USER *ptu = NULL;
  77. DWORD cbTokenBuffer = 0;
  78. CB Length;
  79. #define DEFAULT_USERNAME ""
  80. Unused(Args);
  81. Unused(cArgs);
  82. Unused(cbReturnBuffer);
  83. if( !OpenProcessToken( GetCurrentProcess(), TOKEN_READ, &hToken ) ) {
  84. goto err;
  85. }
  86. //
  87. // Get space needed for process token information
  88. //
  89. if( !GetTokenInformation( hToken, TokenUser, (LPVOID)NULL, 0, &cbTokenBuffer) ) {
  90. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  91. goto err;
  92. }
  93. }
  94. //
  95. // Allocate space for token user information
  96. //
  97. if ( (ptu = (TOKEN_USER *)SAlloc(cbTokenBuffer)) == NULL ) {
  98. goto err;
  99. }
  100. //
  101. // Query token user information again
  102. //
  103. if( !GetTokenInformation( hToken, TokenUser, (LPVOID)ptu, cbTokenBuffer, &cbTokenBuffer) ) {
  104. goto err;
  105. }
  106. //
  107. // Query the user name and return it
  108. //
  109. if( LookupAccountSid( NULL, ptu->User.Sid, UserName, &cbUserName , DomainName, &cbDomainName, &peUse) ) {
  110. lstrcpy( ReturnBuffer, DomainName );
  111. lstrcat( ReturnBuffer, "\\" );
  112. lstrcat( ReturnBuffer, UserName );
  113. Length = lstrlen( ReturnBuffer ) + 1;
  114. bStatus = TRUE;
  115. }
  116. err:
  117. if( !bStatus ) {
  118. lstrcpy( ReturnBuffer, DEFAULT_USERNAME );
  119. Length = lstrlen( DEFAULT_USERNAME ) + 1;
  120. }
  121. if( hToken != NULL ) {
  122. CloseHandle( hToken );
  123. }
  124. if( ptu ) {
  125. SFree( ptu );
  126. }
  127. return( Length );
  128. }
  129. //
  130. // Get User Accounts
  131. //
  132. CB
  133. GetUserAccounts(
  134. IN RGSZ Args,
  135. IN USHORT cArgs,
  136. OUT SZ ReturnBuffer,
  137. IN CB cbReturnBuffer
  138. )
  139. /*++
  140. Routine Description:
  141. DetectRoutine for UserAccounts. This routine enumerates all the
  142. user accounts under HKEY_USERS and returns the <sid-string key, username>
  143. tuplet for every user found. The detected value will have the
  144. following form:
  145. { {sid-string1, user-name1}, {sid-string2, user-name2} ... }
  146. Arguments:
  147. Args - C argument list to this detect routine (None exist)
  148. cArgs - Number of arguments.
  149. ReturnBuffer - Buffer in which detected value is returned.
  150. cbReturnBuffer - Buffer Size.
  151. Return value:
  152. Returns length of detected value.
  153. --*/
  154. {
  155. HKEY hProfile, hSubKey;
  156. CHAR SubKeyName[MAX_PATH];
  157. CHAR UserName[MAX_PATH];
  158. CHAR DomainName[MAX_PATH];
  159. CHAR ProfilePath[MAX_PATH];
  160. CHAR Class[MAX_PATH];
  161. DWORD cbSubKeyName;
  162. DWORD cbUserName;
  163. DWORD cbDomainName;
  164. DWORD cbProfilePath;
  165. DWORD cbClass;
  166. FILETIME FileTime;
  167. UINT Index;
  168. LONG Status;
  169. BOOL bStatus;
  170. RGSZ rgszUsers, rgszCurrent;
  171. SZ sz;
  172. CB Length;
  173. CHAR UnknownUser[MAX_PATH];
  174. DWORD UnknownUserNum;
  175. CHAR UnknownUserChar[10];
  176. PSID pSid;
  177. SID_NAME_USE peUse;
  178. Unused(Args);
  179. Unused(cArgs);
  180. Unused(cbReturnBuffer);
  181. #define NO_ACCOUNTS "{}"
  182. //
  183. // Load the string to use as the unknown user string. We will append
  184. // it with numbers
  185. //
  186. LoadString( MyDllModuleHandle, IDS_STRING_UNKNOWN_USER, UnknownUser, MAX_PATH );
  187. UnknownUserNum = 1;
  188. //
  189. // Enumerate keys under HKEY_USERS, for each user see if it is a
  190. // a .Default (reject this), get the sid value and convert the
  191. // sid to a user name. Add the subkey (this is a sid-string) and
  192. // the username as an account.
  193. //
  194. //
  195. // Intialise users list to no users
  196. //
  197. rgszUsers = RgszAlloc(1);
  198. //
  199. // open the key to the profile tree
  200. //
  201. Status = RegOpenKeyEx(
  202. HKEY_LOCAL_MACHINE,
  203. "Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
  204. 0,
  205. KEY_READ,
  206. &hProfile
  207. );
  208. if (Status == ERROR_SUCCESS) {
  209. //
  210. // Profile key exists, enumerate the profiles under this key
  211. //
  212. for ( Index = 0 ; ; Index++ ) {
  213. //
  214. // Get the current sub-key
  215. //
  216. cbSubKeyName = MAX_PATH;
  217. cbClass = MAX_PATH;
  218. cbUserName = MAX_PATH;
  219. cbDomainName = MAX_PATH;
  220. cbProfilePath = MAX_PATH;
  221. Status = RegEnumKeyEx(
  222. hProfile,
  223. Index,
  224. SubKeyName,
  225. &cbSubKeyName,
  226. NULL,
  227. Class,
  228. &cbClass,
  229. &FileTime
  230. );
  231. if ( Status != ERROR_SUCCESS ) {
  232. break;
  233. }
  234. //
  235. // Open the subkey
  236. //
  237. Status = RegOpenKeyEx(
  238. hProfile,
  239. SubKeyName,
  240. 0,
  241. KEY_READ,
  242. &hSubKey
  243. );
  244. if ( Status != ERROR_SUCCESS) {
  245. continue;
  246. }
  247. if( !lstrcmpi( SubKeyName, "THE_USER" ) ) {
  248. lstrcpy( UserName, "THE_USER" );
  249. goto skip_1;
  250. }
  251. //
  252. // Get the User name for this profile, by looking up the sid
  253. // value in the user key and then looking up the sid.
  254. //
  255. pSid = (PSID)GetValueEntry(
  256. hSubKey,
  257. "Sid"
  258. );
  259. if (!pSid) {
  260. RegCloseKey( hSubKey );
  261. continue;
  262. }
  263. //
  264. // Convert the Sid into Username
  265. //
  266. bStatus = LookupAccountSid(
  267. NULL,
  268. pSid,
  269. UserName,
  270. &cbUserName,
  271. DomainName,
  272. &cbDomainName,
  273. &peUse
  274. );
  275. SFree( pSid );
  276. if( !bStatus ) {
  277. RegCloseKey( hSubKey );
  278. continue;
  279. }
  280. lstrcat( DomainName, "\\" );
  281. if(!lstrcmpi(UserName, "")) {
  282. lstrcat(DomainName, UnknownUser);
  283. _ultoa( UnknownUserNum, UnknownUserChar, 10 );
  284. lstrcat(DomainName, UnknownUserChar);
  285. UnknownUserNum++;
  286. }
  287. else {
  288. lstrcat(DomainName, UserName);
  289. }
  290. skip_1:
  291. //
  292. // Get the profilepath for this subkey, check to see if profilepath
  293. // exists
  294. //
  295. bStatus = HUserKeyToProfilePath(
  296. hSubKey,
  297. ProfilePath,
  298. &cbProfilePath
  299. );
  300. if( !bStatus ) {
  301. RegCloseKey( hSubKey );
  302. continue;
  303. }
  304. RegCloseKey( hSubKey );
  305. //
  306. // Form the list entry for this user
  307. //
  308. rgszCurrent = RgszAlloc(4);
  309. rgszCurrent[0] = SzDup ( SubKeyName );
  310. rgszCurrent[1] = SzDup ( DomainName );
  311. rgszCurrent[2] = SzDup ( ProfilePath );
  312. rgszCurrent[3] = NULL;
  313. //
  314. // Add this user to the list of users
  315. //
  316. sz = SzListValueFromRgsz( rgszCurrent );
  317. if ( sz ) {
  318. if( !RgszAdd ( &rgszUsers, sz ) ) {
  319. SFree( sz );
  320. }
  321. }
  322. RgszFree ( rgszCurrent );
  323. }
  324. RegCloseKey( hProfile );
  325. }
  326. sz = SzListValueFromRgsz( rgszUsers );
  327. RgszFree( rgszUsers );
  328. if ( sz ) {
  329. lstrcpy( ReturnBuffer, sz );
  330. Length = lstrlen( sz ) + 1;
  331. SFree ( sz );
  332. }
  333. else {
  334. lstrcpy( ReturnBuffer, NO_ACCOUNTS );
  335. Length = lstrlen( NO_ACCOUNTS ) + 1;
  336. }
  337. return ( Length );
  338. }
  339. //========================
  340. // INSTALL ROUTINE WORKERS
  341. //========================
  342. BOOL
  343. CheckPrivilegeExistsWorker(
  344. IN LPSTR PrivilegeType
  345. )
  346. /*++
  347. Routine Description:
  348. Routine to determine whether we have a particular privilege
  349. Arguments:
  350. PrivilegeType - Name of the privilege to enable / disable
  351. Return value:
  352. TRUE if CheckTakeOwnerPrivilege succeeds, FALSE otherwise.
  353. If TRUE: ReturnTextBuffer has "YES" if privilege exists, "NO" otherwise.
  354. If FALSE: ReturnTextBuffer has error text.
  355. --*/
  356. {
  357. LONG Privilege;
  358. TOKEN_PRIVILEGES PrevState;
  359. ULONG ReturnLength = sizeof( TOKEN_PRIVILEGES );
  360. if ( !lstrcmpi( PrivilegeType, "SeTakeOwnershipPrivilege" ) ) {
  361. Privilege = SE_TAKE_OWNERSHIP_PRIVILEGE;
  362. }
  363. else if ( !lstrcmpi( PrivilegeType, "SeSystemEnvironmentPrivilege" ) ) {
  364. Privilege = SE_SYSTEM_ENVIRONMENT_PRIVILEGE;
  365. }
  366. else {
  367. SetErrorText(IDS_ERROR_UNSUPPORTEDPRIV);
  368. return ( FALSE );
  369. }
  370. if ( AdjustPrivilege(
  371. Privilege,
  372. ENABLE_PRIVILEGE,
  373. &PrevState,
  374. &ReturnLength
  375. )
  376. ) {
  377. SetReturnText( "YES" );
  378. RestorePrivilege( &PrevState );
  379. return ( TRUE );
  380. }
  381. else {
  382. SetReturnText( "NO" );
  383. return ( TRUE );
  384. }
  385. }
  386. BOOL
  387. EnablePrivilegeWorker(
  388. LPSTR PrivilegeType,
  389. LPSTR Action
  390. )
  391. /*++
  392. Routine Description:
  393. Install routine to enable / disable the SE_SYSTEM_ENVIRONMENT_PRIVILEGE
  394. Arguments:
  395. PrivilegeType - Name of the privilege to enable / disable
  396. Action - Whether to enable / disable
  397. Return value:
  398. TRUE if Enable / Disable succeeds, FALSE otherwise. ReturnTextBuffer
  399. gets initialised to error text if FALSE.
  400. --*/
  401. {
  402. ULONG Privilege;
  403. INT AdjustAction;
  404. if ( !lstrcmpi( PrivilegeType, "SeTakeOwnershipPrivilege" ) ) {
  405. Privilege = SE_TAKE_OWNERSHIP_PRIVILEGE;
  406. }
  407. else if ( !lstrcmpi( PrivilegeType, "SeSystemEnvironmentPrivilege" ) ) {
  408. Privilege = SE_SYSTEM_ENVIRONMENT_PRIVILEGE;
  409. }
  410. else {
  411. SetErrorText(IDS_ERROR_UNSUPPORTEDPRIV);
  412. return ( FALSE );
  413. }
  414. //
  415. // Check Arg[1] .. Whether to enable / disable
  416. //
  417. if (!lstrcmpi(Action, "ENABLE")) {
  418. AdjustAction = ENABLE_PRIVILEGE;
  419. }
  420. else if (!lstrcmpi(Action, "DISABLE")) {
  421. AdjustAction = DISABLE_PRIVILEGE;
  422. }
  423. else {
  424. SetErrorText(IDS_ERROR_BADARGS);
  425. return(FALSE);
  426. }
  427. if ( !AdjustPrivilege(
  428. Privilege,
  429. AdjustAction,
  430. NULL,
  431. NULL
  432. )
  433. ) {
  434. SetErrorText(IDS_ERROR_ADJUSTPRIVILEGE);
  435. return ( FALSE );
  436. }
  437. else {
  438. return ( TRUE );
  439. }
  440. }
  441. //======================================================================
  442. // General security subroutines
  443. //======================================================================
  444. BOOL
  445. AdjustPrivilege(
  446. IN LONG PrivilegeType,
  447. IN INT Action,
  448. IN PTOKEN_PRIVILEGES PrevState, OPTIONAL
  449. IN PULONG ReturnLength OPTIONAL
  450. )
  451. /*++
  452. Routine Description:
  453. Routine to enable or disable a particular privilege
  454. Arguments:
  455. PrivilegeType - Name of the privilege to enable / disable
  456. Action - ENABLE_PRIVILEGE | DISABLE_PRIVILEGE
  457. PrevState - Optional pointer to TOKEN_PRIVILEGES structure
  458. to receive the previous state of privilege.
  459. ReturnLength - Optional pointer to a ULONG to receive the length
  460. of the PrevState returned.
  461. Return value:
  462. TRUE if succeeded, FALSE otherwise.
  463. --*/
  464. {
  465. NTSTATUS NtStatus;
  466. HANDLE Token;
  467. LUID Privilege;
  468. TOKEN_PRIVILEGES NewState;
  469. ULONG BufferLength = 0;
  470. //
  471. // Get Privilege LUID
  472. //
  473. Privilege = RtlConvertLongToLuid(PrivilegeType);
  474. NewState.PrivilegeCount = 1;
  475. NewState.Privileges[0].Luid = Privilege;
  476. //
  477. // Look at action and determine the attributes
  478. //
  479. switch( Action ) {
  480. case ENABLE_PRIVILEGE:
  481. NewState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  482. break;
  483. case DISABLE_PRIVILEGE:
  484. NewState.Privileges[0].Attributes = 0;
  485. break;
  486. default:
  487. return ( FALSE );
  488. }
  489. //
  490. // Open our own token
  491. //
  492. NtStatus = NtOpenProcessToken(
  493. NtCurrentProcess(),
  494. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  495. &Token
  496. );
  497. if (!NT_SUCCESS(NtStatus)) {
  498. return( FALSE );
  499. }
  500. //
  501. // See if return buffer is present and accordingly set the parameter
  502. // of buffer length
  503. //
  504. if ( PrevState && ReturnLength ) {
  505. BufferLength = *ReturnLength;
  506. }
  507. //
  508. // Set the state of the privilege
  509. //
  510. NtStatus = NtAdjustPrivilegesToken(
  511. Token, // TokenHandle
  512. FALSE, // DisableAllPrivileges
  513. &NewState, // NewState
  514. BufferLength, // BufferLength
  515. PrevState, // PreviousState (OPTIONAL)
  516. ReturnLength // ReturnLength (OPTIONAL)
  517. );
  518. if ( NT_SUCCESS( NtStatus ) ) {
  519. NtClose( Token );
  520. return( TRUE );
  521. }
  522. else {
  523. NtClose( Token );
  524. return( FALSE );
  525. }
  526. }
  527. BOOL
  528. RestorePrivilege(
  529. IN PTOKEN_PRIVILEGES PrevState
  530. )
  531. /*++
  532. Routine Description:
  533. To restore a privilege to its previous state
  534. Arguments:
  535. PrevState - Pointer to token privileges returned from an earlier
  536. AdjustPrivileges call.
  537. Return value:
  538. TRUE on success, FALSE otherwise
  539. --*/
  540. {
  541. NTSTATUS NtStatus;
  542. HANDLE Token;
  543. //
  544. // Parameter checking
  545. //
  546. if ( !PrevState ) {
  547. return ( FALSE );
  548. }
  549. //
  550. // Open our own token
  551. //
  552. NtStatus = NtOpenProcessToken(
  553. NtCurrentProcess(),
  554. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  555. &Token
  556. );
  557. if (!NT_SUCCESS(NtStatus)) {
  558. return( FALSE );
  559. }
  560. //
  561. // Set the state of the privilege
  562. //
  563. NtStatus = NtAdjustPrivilegesToken(
  564. Token, // TokenHandle
  565. FALSE, // DisableAllPrivileges
  566. PrevState, // NewState
  567. 0, // BufferLength
  568. NULL, // PreviousState (OPTIONAL)
  569. NULL // ReturnLength (OPTIONAL)
  570. );
  571. if ( NT_SUCCESS( NtStatus ) ) {
  572. NtClose( Token );
  573. return( TRUE );
  574. }
  575. else {
  576. NtClose( Token );
  577. return( FALSE );
  578. }
  579. }
  580. BOOL
  581. HUserKeyToProfilePath(
  582. IN HKEY hUserKey,
  583. OUT LPSTR lpProfilePath,
  584. IN OUT LPDWORD lpcbProfilePath
  585. )
  586. /*++
  587. Routine Description:
  588. This finds out the ProfilePath corresponding to a user account key handle
  589. sees if the file exists and then returns the path to the profile.
  590. Arguments:
  591. hUserKey - Handle to a user account profile key
  592. lpProfilePath - Pointer to a profile path buffer which will receive the
  593. queried path.
  594. lpcbProfilePath - Pointer to the size of the profile path buffer. Input
  595. value is the size of the name buffer. Output value is the
  596. actual size of the username queried
  597. Return value:
  598. Returns TRUE for success, FALSE for failure. If TRUE lpProfilePath and
  599. lpcbProfilePath are initialized.
  600. --*/
  601. {
  602. LONG Status;
  603. CHAR szValue[ MAX_PATH ];
  604. DWORD dwSize = MAX_PATH;
  605. //
  606. // Get the profile path value
  607. //
  608. Status = RegQueryValueEx(
  609. hUserKey,
  610. "ProfileImagePath",
  611. NULL,
  612. NULL,
  613. szValue,
  614. &dwSize
  615. );
  616. if( Status != ERROR_SUCCESS ) {
  617. return( FALSE );
  618. }
  619. *lpcbProfilePath = ExpandEnvironmentStrings(
  620. (LPCSTR)szValue,
  621. lpProfilePath,
  622. *lpcbProfilePath
  623. );
  624. //
  625. // Check if profile path exists
  626. //
  627. if ( FFileExist( lpProfilePath ) ) {
  628. return( TRUE );
  629. }
  630. else {
  631. return( FALSE );
  632. }
  633. }
  634. BOOL
  635. FForceDeleteFile(
  636. LPSTR szPath
  637. )
  638. {
  639. BOOL Result;
  640. SECURITY_DESCRIPTOR SecurityDescriptor;
  641. HANDLE TokenHandle;
  642. TOKEN_PRIVILEGES OldPrivs;
  643. PSID AliasAdminsSid = NULL;
  644. SID_IDENTIFIER_AUTHORITY SepNtAuthority = SECURITY_NT_AUTHORITY;
  645. Result = AllocateAndInitializeSid(
  646. &SepNtAuthority,
  647. 2,
  648. SECURITY_BUILTIN_DOMAIN_RID,
  649. DOMAIN_ALIAS_RID_ADMINS,
  650. 0,
  651. 0,
  652. 0,
  653. 0,
  654. 0,
  655. 0,
  656. &AliasAdminsSid
  657. );
  658. if ( !Result ) {
  659. return( FALSE );
  660. }
  661. Result = GetTokenHandle( &TokenHandle );
  662. if ( !Result ) {
  663. return( FALSE );
  664. }
  665. //
  666. // Create the security descritor with NULL DACL and Administrator as owner
  667. //
  668. InitializeSecurityDescriptor( &SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
  669. Result = SetSecurityDescriptorDacl (
  670. &SecurityDescriptor,
  671. TRUE,
  672. NULL,
  673. FALSE
  674. );
  675. if ( !Result ) {
  676. CloseHandle( TokenHandle );
  677. return( FALSE );
  678. }
  679. Result = SetSecurityDescriptorOwner (
  680. &SecurityDescriptor,
  681. AliasAdminsSid,
  682. FALSE
  683. );
  684. if ( !Result ) {
  685. CloseHandle( TokenHandle );
  686. return FALSE;
  687. }
  688. //
  689. // Assert TakeOwnership privilege.
  690. //
  691. Result = AssertTakeOwnership( TokenHandle, &OldPrivs );
  692. if ( !Result ) {
  693. CloseHandle( TokenHandle );
  694. return FALSE;
  695. }
  696. //
  697. // Make Administrator the owner of the file.
  698. //
  699. Result = SetFileSecurity(
  700. szPath,
  701. OWNER_SECURITY_INFORMATION,
  702. &SecurityDescriptor
  703. );
  704. RestoreTakeOwnership( TokenHandle, &OldPrivs );
  705. if ( !Result ) {
  706. CloseHandle( TokenHandle );
  707. return( FALSE );
  708. }
  709. //
  710. // We are now the owner, put a benign DACL onto the file
  711. //
  712. Result = SetFileSecurity(
  713. szPath,
  714. DACL_SECURITY_INFORMATION,
  715. &SecurityDescriptor
  716. );
  717. if ( !Result ) {
  718. CloseHandle( TokenHandle );
  719. return( FALSE );
  720. }
  721. return( TRUE );
  722. }
  723. BOOL
  724. GetTokenHandle(
  725. PHANDLE TokenHandle
  726. )
  727. //
  728. // This routine will open the current process and return
  729. // a handle to its token.
  730. //
  731. // These handles will be closed for us when the process
  732. // exits.
  733. //
  734. {
  735. HANDLE ProcessHandle;
  736. BOOL Result;
  737. ProcessHandle = OpenProcess(
  738. PROCESS_QUERY_INFORMATION,
  739. FALSE,
  740. GetCurrentProcessId()
  741. );
  742. if ( ProcessHandle == NULL ) {
  743. //
  744. // This should not happen
  745. //
  746. return( FALSE );
  747. }
  748. Result = OpenProcessToken (
  749. ProcessHandle,
  750. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  751. TokenHandle
  752. );
  753. if ( !Result ) {
  754. //
  755. // This should not happen
  756. //
  757. return( FALSE );
  758. }
  759. return( TRUE );
  760. }
  761. BOOL
  762. AssertTakeOwnership(
  763. HANDLE TokenHandle,
  764. PTOKEN_PRIVILEGES OldPrivs
  765. )
  766. //
  767. // This routine turns on SeTakeOwnershipPrivilege in the current
  768. // token. Once that has been accomplished, we can open the file
  769. // for WRITE_OWNER even if we are denied that access by the ACL
  770. // on the file.
  771. {
  772. LUID TakeOwnershipValue;
  773. BOOL Result;
  774. TOKEN_PRIVILEGES TokenPrivileges;
  775. DWORD ReturnLength;
  776. //
  777. // First, find out the value of TakeOwnershipPrivilege
  778. //
  779. Result = LookupPrivilegeValue(
  780. NULL,
  781. "SeTakeOwnershipPrivilege",
  782. &TakeOwnershipValue
  783. );
  784. if ( !Result ) {
  785. //
  786. // This should not happen
  787. //
  788. return FALSE;
  789. }
  790. //
  791. // Set up the privilege set we will need
  792. //
  793. TokenPrivileges.PrivilegeCount = 1;
  794. TokenPrivileges.Privileges[0].Luid = TakeOwnershipValue;
  795. TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  796. ReturnLength = sizeof( TOKEN_PRIVILEGES );
  797. (VOID) AdjustTokenPrivileges (
  798. TokenHandle,
  799. FALSE,
  800. &TokenPrivileges,
  801. sizeof( TOKEN_PRIVILEGES ),
  802. OldPrivs,
  803. &ReturnLength
  804. );
  805. if ( GetLastError() != NO_ERROR ) {
  806. return( FALSE );
  807. } else {
  808. return( TRUE );
  809. }
  810. }
  811. VOID
  812. RestoreTakeOwnership(
  813. HANDLE TokenHandle,
  814. PTOKEN_PRIVILEGES OldPrivs
  815. )
  816. {
  817. (VOID) AdjustTokenPrivileges (
  818. TokenHandle,
  819. FALSE,
  820. OldPrivs,
  821. sizeof( TOKEN_PRIVILEGES ),
  822. NULL,
  823. NULL
  824. );
  825. }