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.

1010 lines
24 KiB

  1. /*++
  2. Copyright (c) 1996, 1997 Microsoft Corporation
  3. Module Name:
  4. secmisc.c
  5. Abstract:
  6. This module contains miscellaneous security routines for the Protected
  7. Storage.
  8. Author:
  9. Scott Field (sfield) 25-Mar-97
  10. --*/
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <windows.h>
  15. #include "secmisc.h"
  16. #include "unicode5.h"
  17. #include "debug.h"
  18. BOOL
  19. GetUserHKEYEx(
  20. IN LPCWSTR szUser,
  21. IN DWORD dwDesiredAccess,
  22. IN OUT HKEY *hKeyUser,
  23. IN BOOL fCheckDefault // check .Default registry hive when user's not available?
  24. )
  25. {
  26. HKEY hKey = NULL;
  27. LONG lRet;
  28. //
  29. // first, try HKEY_USERS\szUser
  30. // note on WinNT, szUser is an textual sid of the form S-1-5-21-xxx ...
  31. // on Win95, szUser is the username associated with the logged on user
  32. //
  33. //
  34. // unfortunately, if szUser is null or empty, the RegOpenKeyEx below will
  35. // succeed, which is not correct behavior for us. Check for this case
  36. // and retry with default on if fCheckDefault is TRUE.
  37. //
  38. if(szUser == NULL || szUser[0] == L'\0') {
  39. // invalid szUser specified.
  40. lRet = ERROR_FILE_NOT_FOUND;
  41. } else {
  42. lRet = RegOpenKeyExU(
  43. HKEY_USERS,
  44. szUser,
  45. 0, // dwOptions
  46. dwDesiredAccess,
  47. &hKey
  48. );
  49. }
  50. if( lRet != ERROR_SUCCESS && fCheckDefault ) {
  51. //
  52. // if that failed, try HKEY_USERS\.Default (for services on NT).
  53. // TODO (lookat), for now, don't fall back to HKEY_USERS\.Default on Win95
  54. // because that is shared across users when profiles are disabled.
  55. //
  56. lRet = RegOpenKeyExU(
  57. HKEY_USERS,
  58. L".Default",
  59. 0, // dwOptions
  60. dwDesiredAccess,
  61. &hKey
  62. );
  63. }
  64. if(lRet != ERROR_SUCCESS) {
  65. SetLastError( (DWORD)lRet );
  66. return FALSE;
  67. }
  68. *hKeyUser = hKey;
  69. return TRUE;
  70. }
  71. BOOL
  72. GetUserHKEY(
  73. IN LPCWSTR szUser,
  74. IN DWORD dwDesiredAccess,
  75. IN OUT HKEY *hKeyUser
  76. )
  77. {
  78. //
  79. // winnt: try HKEY_USERS\.Default
  80. // win95: don't go to HKEY_USERS\.Default when profiles disabled.
  81. //
  82. BOOL fRet = GetUserHKEYEx(szUser, dwDesiredAccess, hKeyUser, FALSE);
  83. if(!fRet)
  84. {
  85. //
  86. // see if local system. If so, retry against .Default
  87. //
  88. static const WCHAR szTextualSidSystem[] = TEXTUAL_SID_LOCAL_SYSTEM;
  89. if( memcmp(szUser, szTextualSidSystem, sizeof(szTextualSidSystem)) == 0 )
  90. fRet = GetUserHKEYEx(szUser, dwDesiredAccess, hKeyUser, TRUE);
  91. }
  92. return fRet;
  93. }
  94. BOOL
  95. GetUserTextualSid(
  96. IN HANDLE hUserToken, // optional
  97. IN OUT LPWSTR lpBuffer,
  98. IN OUT LPDWORD nSize
  99. )
  100. {
  101. HANDLE hToken;
  102. PSID pSidUser = NULL;
  103. BOOL fSuccess = FALSE;
  104. if(hUserToken == NULL)
  105. {
  106. if(!OpenThreadToken(
  107. GetCurrentThread(),
  108. TOKEN_QUERY,
  109. TRUE,
  110. &hToken
  111. ))
  112. {
  113. return FALSE;
  114. }
  115. }
  116. else
  117. {
  118. hToken = hUserToken;
  119. }
  120. fSuccess = GetTokenUserSid(hToken, &pSidUser);
  121. if(fSuccess)
  122. {
  123. //
  124. // obtain the textual representaion of the Sid
  125. //
  126. fSuccess = GetTextualSid(
  127. pSidUser, // user binary Sid
  128. lpBuffer, // buffer for TextualSid
  129. nSize // required/result buffer size in chars (including NULL)
  130. );
  131. }
  132. if(pSidUser)
  133. SSFree(pSidUser);
  134. if(hToken != hUserToken)
  135. {
  136. CloseHandle(hToken);
  137. }
  138. return fSuccess;
  139. }
  140. BOOL
  141. GetTextualSid(
  142. IN PSID pSid, // binary Sid
  143. IN OUT LPWSTR TextualSid, // buffer for Textual representaion of Sid
  144. IN OUT LPDWORD dwBufferLen // required/provided TextualSid buffersize
  145. )
  146. {
  147. PSID_IDENTIFIER_AUTHORITY psia;
  148. DWORD dwSubAuthorities;
  149. DWORD dwCounter;
  150. DWORD dwSidSize;
  151. if(!IsValidSid(pSid)) return FALSE;
  152. // obtain SidIdentifierAuthority
  153. psia = GetSidIdentifierAuthority(pSid);
  154. // obtain sidsubauthority count
  155. dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
  156. //
  157. // compute buffer length (conservative guess)
  158. // S-SID_REVISION- + identifierauthority- + subauthorities- + NULL
  159. //
  160. dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(WCHAR);
  161. //
  162. // check provided buffer length.
  163. // If not large enough, indicate proper size and setlasterror
  164. //
  165. if(*dwBufferLen < dwSidSize) {
  166. *dwBufferLen = dwSidSize;
  167. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  168. return FALSE;
  169. }
  170. //
  171. // prepare S-SID_REVISION-
  172. //
  173. dwSidSize = wsprintfW(TextualSid, L"S-%lu-", SID_REVISION );
  174. //
  175. // prepare SidIdentifierAuthority
  176. //
  177. if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) ) {
  178. dwSidSize += wsprintfW(TextualSid + dwSidSize,
  179. L"0x%02hx%02hx%02hx%02hx%02hx%02hx",
  180. (USHORT)psia->Value[0],
  181. (USHORT)psia->Value[1],
  182. (USHORT)psia->Value[2],
  183. (USHORT)psia->Value[3],
  184. (USHORT)psia->Value[4],
  185. (USHORT)psia->Value[5]);
  186. } else {
  187. dwSidSize += wsprintfW(TextualSid + dwSidSize,
  188. L"%lu",
  189. (ULONG)(psia->Value[5] ) +
  190. (ULONG)(psia->Value[4] << 8) +
  191. (ULONG)(psia->Value[3] << 16) +
  192. (ULONG)(psia->Value[2] << 24) );
  193. }
  194. //
  195. // loop through SidSubAuthorities
  196. //
  197. for (dwCounter = 0 ; dwCounter < dwSubAuthorities ; dwCounter++) {
  198. dwSidSize += wsprintfW(TextualSid + dwSidSize,
  199. L"-%lu", *GetSidSubAuthority(pSid, dwCounter) );
  200. }
  201. *dwBufferLen = dwSidSize + 1; // tell caller how many chars (include NULL)
  202. return TRUE;
  203. }
  204. BOOL
  205. GetThreadAuthenticationId(
  206. IN HANDLE hThread,
  207. IN OUT PLUID AuthenticationId
  208. )
  209. /*++
  210. This function retrieves the authentication Id (LUID) from the access token
  211. specified by the calling thread.
  212. The thread specified by hThread must be impersonating a client.
  213. --*/
  214. {
  215. HANDLE hToken;
  216. TOKEN_STATISTICS TokenInfo;
  217. DWORD dwReturnLen;
  218. BOOL bSuccess;
  219. if(!OpenThreadToken(
  220. hThread,
  221. TOKEN_QUERY,
  222. TRUE,
  223. &hToken
  224. )) return FALSE;
  225. bSuccess = GetTokenInformation(
  226. hToken,
  227. TokenStatistics,
  228. &TokenInfo,
  229. sizeof(TokenInfo),
  230. &dwReturnLen
  231. );
  232. CloseHandle(hToken);
  233. if(!bSuccess) return FALSE;
  234. memcpy(AuthenticationId, &(TokenInfo.AuthenticationId), sizeof(LUID));
  235. return TRUE;
  236. }
  237. BOOL
  238. GetTokenAuthenticationId(
  239. IN HANDLE hUserToken,
  240. IN OUT PLUID AuthenticationId
  241. )
  242. /*++
  243. This function retrieves the authentication Id (LUID) from the specified
  244. access token.
  245. --*/
  246. {
  247. TOKEN_STATISTICS TokenInfo;
  248. DWORD dwReturnLen;
  249. BOOL bSuccess;
  250. HANDLE hToken = NULL;
  251. if(hUserToken == NULL)
  252. {
  253. if(!OpenThreadToken(
  254. GetCurrentThread(),
  255. TOKEN_QUERY,
  256. TRUE,
  257. &hToken
  258. ))
  259. {
  260. return FALSE;
  261. }
  262. }
  263. else
  264. {
  265. hToken = hUserToken;
  266. }
  267. bSuccess = GetTokenInformation(
  268. hToken,
  269. TokenStatistics,
  270. &TokenInfo,
  271. sizeof(TokenInfo),
  272. &dwReturnLen
  273. );
  274. if(hToken != hUserToken)
  275. {
  276. CloseHandle(hToken);
  277. }
  278. if(!bSuccess) return FALSE;
  279. memcpy(AuthenticationId, &(TokenInfo.AuthenticationId), sizeof(LUID));
  280. return TRUE;
  281. }
  282. BOOL
  283. GetTokenUserSid(
  284. IN HANDLE hUserToken, // token to query
  285. IN OUT PSID *ppUserSid // resultant user sid
  286. )
  287. /*++
  288. This function queries the access token specified by the
  289. hToken parameter, and returns an allocated copy of the
  290. TokenUser information on success.
  291. The access token specified by hToken must be opened for
  292. TOKEN_QUERY access.
  293. On success, the return value is TRUE. The caller is
  294. responsible for freeing the resultant UserSid via a call
  295. to SSFree().
  296. On failure, the return value is FALSE. The caller does
  297. not need to free any buffer.
  298. --*/
  299. {
  300. BYTE FastBuffer[256];
  301. LPBYTE SlowBuffer = NULL;
  302. PTOKEN_USER ptgUser;
  303. DWORD cbBuffer;
  304. BOOL fSuccess = FALSE;
  305. HANDLE hToken = NULL;
  306. *ppUserSid = NULL;
  307. if(hUserToken == NULL)
  308. {
  309. if(!OpenThreadToken(
  310. GetCurrentThread(),
  311. TOKEN_QUERY,
  312. TRUE,
  313. &hToken
  314. ))
  315. {
  316. return FALSE;
  317. }
  318. }
  319. else
  320. {
  321. hToken = hUserToken;
  322. }
  323. //
  324. // try querying based on a fast stack based buffer first.
  325. //
  326. ptgUser = (PTOKEN_USER)FastBuffer;
  327. cbBuffer = sizeof(FastBuffer);
  328. fSuccess = GetTokenInformation(
  329. hToken, // identifies access token
  330. TokenUser, // TokenUser info type
  331. ptgUser, // retrieved info buffer
  332. cbBuffer, // size of buffer passed-in
  333. &cbBuffer // required buffer size
  334. );
  335. if(!fSuccess) {
  336. if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  337. //
  338. // try again with the specified buffer size
  339. //
  340. SlowBuffer = (LPBYTE)SSAlloc(cbBuffer);
  341. if(SlowBuffer != NULL) {
  342. ptgUser = (PTOKEN_USER)SlowBuffer;
  343. fSuccess = GetTokenInformation(
  344. hToken, // identifies access token
  345. TokenUser, // TokenUser info type
  346. ptgUser, // retrieved info buffer
  347. cbBuffer, // size of buffer passed-in
  348. &cbBuffer // required buffer size
  349. );
  350. }
  351. }
  352. }
  353. //
  354. // if we got the token info successfully, copy the
  355. // relevant element for the caller.
  356. //
  357. if(fSuccess) {
  358. DWORD cbSid;
  359. // reset to assume failure
  360. fSuccess = FALSE;
  361. cbSid = GetLengthSid(ptgUser->User.Sid);
  362. *ppUserSid = SSAlloc( cbSid );
  363. if(*ppUserSid != NULL) {
  364. fSuccess = CopySid(cbSid, *ppUserSid, ptgUser->User.Sid);
  365. }
  366. else
  367. {
  368. fSuccess = FALSE;
  369. }
  370. }
  371. if(!fSuccess) {
  372. if(*ppUserSid) {
  373. SSFree(*ppUserSid);
  374. *ppUserSid = NULL;
  375. }
  376. }
  377. if(SlowBuffer)
  378. SSFree(SlowBuffer);
  379. if(hToken != hUserToken)
  380. {
  381. CloseHandle(hToken);
  382. }
  383. return fSuccess;
  384. }
  385. BOOL
  386. SetRegistrySecurity(
  387. IN HKEY hKey
  388. )
  389. /*++
  390. The function applies security to the specifed registry key such that only
  391. Local System has Full Control to the registry key. Note that the owner
  392. is not set, which results in a default owner of Administrators.
  393. The specified hKey must to opened for WRITE_DAC access.
  394. --*/
  395. {
  396. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
  397. PSID pLocalSystemSid = NULL;
  398. SECURITY_DESCRIPTOR sd;
  399. PACL pDacl = NULL;
  400. PACCESS_ALLOWED_ACE pAce;
  401. DWORD dwAclSize;
  402. LONG lRetCode;
  403. BOOL bSuccess = FALSE; // assume this function fails
  404. //
  405. // prepare a Sid representing the Local System account
  406. //
  407. if(!AllocateAndInitializeSid(
  408. &sia,
  409. 1,
  410. SECURITY_LOCAL_SYSTEM_RID,
  411. 0, 0, 0, 0, 0, 0, 0,
  412. &pLocalSystemSid
  413. )) goto cleanup;
  414. //
  415. // compute size of new acl
  416. //
  417. dwAclSize = sizeof(ACL) +
  418. 1 * ( sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) ) +
  419. GetLengthSid(pLocalSystemSid) ;
  420. //
  421. // allocate storage for Acl
  422. //
  423. pDacl = (PACL)SSAlloc(dwAclSize);
  424. if(pDacl == NULL) goto cleanup;
  425. if(!InitializeAcl(pDacl, dwAclSize, ACL_REVISION))
  426. goto cleanup;
  427. if(!AddAccessAllowedAce(
  428. pDacl,
  429. ACL_REVISION,
  430. KEY_ALL_ACCESS,
  431. pLocalSystemSid
  432. )) goto cleanup;
  433. //
  434. // make it container inherit.
  435. //
  436. if(!GetAce(pDacl, 0, &pAce))
  437. goto cleanup;
  438. pAce->Header.AceFlags = CONTAINER_INHERIT_ACE;
  439. if(!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
  440. goto cleanup;
  441. if(!SetSecurityDescriptorDacl(&sd, TRUE, pDacl, FALSE)) {
  442. goto cleanup;
  443. }
  444. //
  445. // apply the security descriptor to the registry key
  446. //
  447. lRetCode = RegSetKeySecurity(
  448. hKey,
  449. (SECURITY_INFORMATION)DACL_SECURITY_INFORMATION,
  450. &sd
  451. );
  452. if(lRetCode != ERROR_SUCCESS) {
  453. goto cleanup;
  454. }
  455. bSuccess = TRUE; // indicate success
  456. cleanup:
  457. //
  458. // free allocated resources
  459. //
  460. if(pDacl != NULL)
  461. SSFree(pDacl);
  462. if(pLocalSystemSid != NULL)
  463. FreeSid(pLocalSystemSid);
  464. return bSuccess;
  465. }
  466. BOOL
  467. SetPrivilege(
  468. HANDLE hToken, // token handle
  469. LPCWSTR Privilege, // Privilege to enable/disable
  470. BOOL bEnablePrivilege // to enable or disable privilege
  471. )
  472. {
  473. TOKEN_PRIVILEGES tp;
  474. LUID luid;
  475. TOKEN_PRIVILEGES tpPrevious;
  476. DWORD cbPrevious=sizeof(TOKEN_PRIVILEGES);
  477. if(!LookupPrivilegeValueW( NULL, Privilege, &luid )) return FALSE;
  478. //
  479. // first pass. get current privilege setting
  480. //
  481. tp.PrivilegeCount = 1;
  482. tp.Privileges[0].Luid = luid;
  483. tp.Privileges[0].Attributes = 0;
  484. AdjustTokenPrivileges(
  485. hToken,
  486. FALSE,
  487. &tp,
  488. sizeof(TOKEN_PRIVILEGES),
  489. &tpPrevious,
  490. &cbPrevious
  491. );
  492. if (GetLastError() != ERROR_SUCCESS) return FALSE;
  493. //
  494. // second pass. set privilege based on previous setting
  495. //
  496. tpPrevious.PrivilegeCount = 1;
  497. tpPrevious.Privileges[0].Luid = luid;
  498. if(bEnablePrivilege) {
  499. tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
  500. }
  501. else {
  502. tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED &
  503. tpPrevious.Privileges[0].Attributes);
  504. }
  505. AdjustTokenPrivileges(
  506. hToken,
  507. FALSE,
  508. &tpPrevious,
  509. cbPrevious,
  510. NULL,
  511. NULL
  512. );
  513. if (GetLastError() != ERROR_SUCCESS) return FALSE;
  514. return TRUE;
  515. }
  516. BOOL
  517. SetCurrentPrivilege(
  518. LPCWSTR Privilege, // Privilege to enable/disable
  519. BOOL bEnablePrivilege // to enable or disable privilege
  520. )
  521. {
  522. BOOL bSuccess=FALSE; // assume failure
  523. HANDLE hToken;
  524. if(OpenProcessToken(
  525. GetCurrentProcess(),
  526. TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
  527. &hToken
  528. ))
  529. {
  530. if(SetPrivilege(hToken, Privilege, bEnablePrivilege)) bSuccess=TRUE;
  531. CloseHandle(hToken);
  532. }
  533. return bSuccess;
  534. }
  535. #if 0
  536. BOOL
  537. IsDelegating(
  538. IN HANDLE hToken // token to query, open for at least TOKEN_QUERY access
  539. )
  540. /*++
  541. This function determines if the specified access token represents an
  542. impersonation at the delegation impersonate level.
  543. The access token specified by the hToken parameter must be opened for
  544. at least TOKEN_QUERY access.
  545. If the return value is TRUE, the specified hToken is impersonating at
  546. delegation level.
  547. If the return value is FALSE, hToken does not represent delegation level
  548. impersonation.
  549. --*/
  550. {
  551. DWORD dwImpersonationLevel;
  552. DWORD cbTokenInfo;
  553. if( GetTokenInformation(
  554. hToken,
  555. TokenImpersonationLevel,
  556. &dwImpersonationLevel,
  557. sizeof(dwImpersonationLevel),
  558. &cbTokenInfo
  559. ) && dwImpersonationLevel == SecurityDelegation ) {
  560. return TRUE;
  561. }
  562. return FALSE;
  563. }
  564. #endif
  565. BOOL
  566. IsUserSidInDomain(
  567. IN PSID pSidDomain, // domain Sid
  568. IN PSID pSidUser // user Sid
  569. )
  570. /*++
  571. This function determines if the user associated with the
  572. pSidUser parameter exists in the domain specified by pSidDomain.
  573. If the user is in the specified domain, the return value is TRUE.
  574. Otherwise, the return value is FALSE.
  575. --*/
  576. {
  577. DWORD dwSubauthorityCount;
  578. DWORD dwSubauthIndex;
  579. //
  580. // pickup count of subauthorities in domain sid. The domain Sid
  581. // is the prefix associated with user sids, so use that count
  582. // as the basis for our comparison.
  583. //
  584. dwSubauthorityCount = (DWORD)*GetSidSubAuthorityCount( pSidDomain );
  585. if( dwSubauthorityCount >= (DWORD)*GetSidSubAuthorityCount( pSidUser ) )
  586. return FALSE;
  587. //
  588. // compare identifier authority values.
  589. //
  590. if(memcmp( GetSidIdentifierAuthority(pSidDomain),
  591. GetSidIdentifierAuthority(pSidUser),
  592. sizeof(SID_IDENTIFIER_AUTHORITY) ) != 0)
  593. return FALSE;
  594. //
  595. // loop through subauthorities comparing equality.
  596. //
  597. for(dwSubauthIndex = 0 ;
  598. dwSubauthIndex < dwSubauthorityCount ;
  599. dwSubauthIndex++) {
  600. if( *GetSidSubAuthority(pSidDomain, dwSubauthIndex) !=
  601. *GetSidSubAuthority(pSidUser, dwSubauthIndex) )
  602. return FALSE;
  603. }
  604. return TRUE;
  605. }
  606. #if 0
  607. BOOL
  608. IsAdministrator(
  609. VOID
  610. )
  611. /*++
  612. This function determines if the calling user is an Administrator.
  613. On Windows 95, this function always returns TRUE, as there is
  614. no difference between users on that platform.
  615. On Windows NT, the caller of this function must be impersonating
  616. the user which is to be queried. If the caller is not impersonating,
  617. this function will always return FALSE.
  618. --*/
  619. {
  620. HANDLE hAccessToken;
  621. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  622. PSID psidAdministrators = NULL;
  623. BOOL bSuccess;
  624. if(!OpenThreadToken(
  625. GetCurrentThread(),
  626. TOKEN_QUERY,
  627. TRUE,
  628. &hAccessToken
  629. )) return FALSE;
  630. bSuccess = AllocateAndInitializeSid(
  631. &siaNtAuthority,
  632. 2,
  633. SECURITY_BUILTIN_DOMAIN_RID,
  634. DOMAIN_ALIAS_RID_ADMINS,
  635. 0, 0, 0, 0, 0, 0,
  636. &psidAdministrators
  637. );
  638. if( bSuccess ) {
  639. BOOL fIsMember = FALSE;
  640. bSuccess = CheckTokenMembership( hAccessToken, psidAdministrators, &fIsMember );
  641. if( bSuccess && !fIsMember )
  642. bSuccess = FALSE;
  643. }
  644. CloseHandle( hAccessToken );
  645. if(psidAdministrators)
  646. FreeSid(psidAdministrators);
  647. return bSuccess;
  648. }
  649. #endif
  650. BOOL
  651. IsLocal(
  652. VOID
  653. )
  654. /*++
  655. This function determines if the calling user is logged on locally
  656. On Windows NT, the caller of this function must be impersonating
  657. the user which is to be queried. If the caller is not impersonating,
  658. this function will always return FALSE.
  659. --*/
  660. {
  661. HANDLE hAccessToken;
  662. SID_IDENTIFIER_AUTHORITY siaLocalAuthority = SECURITY_LOCAL_SID_AUTHORITY;
  663. PSID psidLocal = NULL;
  664. BOOL bSuccess;
  665. if(!OpenThreadToken(
  666. GetCurrentThread(),
  667. TOKEN_QUERY,
  668. TRUE,
  669. &hAccessToken
  670. )) return FALSE;
  671. bSuccess = AllocateAndInitializeSid(
  672. &siaLocalAuthority,
  673. 1,
  674. SECURITY_LOCAL_RID,
  675. 0, 0, 0, 0, 0, 0, 0,
  676. &psidLocal
  677. );
  678. if( bSuccess ) {
  679. BOOL fIsMember = FALSE;
  680. bSuccess = CheckTokenMembership( hAccessToken, psidLocal, &fIsMember );
  681. if( bSuccess && !fIsMember )
  682. bSuccess = FALSE;
  683. }
  684. CloseHandle( hAccessToken );
  685. if(psidLocal)
  686. FreeSid(psidLocal);
  687. return bSuccess;
  688. }
  689. BOOL
  690. IsDomainController(
  691. VOID
  692. )
  693. /*++
  694. This function returns TRUE if the current machine is a Windows NT
  695. domain controller.
  696. The function returns FALSE if the current machine is not a Windows NT
  697. domain controller.
  698. --*/
  699. {
  700. HMODULE hNtDll;
  701. typedef BOOLEAN (NTAPI *RTLGETNTPRODUCTTYPE)(
  702. OUT PNT_PRODUCT_TYPE NtProductType
  703. );
  704. RTLGETNTPRODUCTTYPE _RtlGetNtProductType;
  705. NT_PRODUCT_TYPE NtProductType;
  706. hNtDll = GetModuleHandleW(L"ntdll.dll");
  707. if( hNtDll == NULL )
  708. return FALSE;
  709. _RtlGetNtProductType = (RTLGETNTPRODUCTTYPE)GetProcAddress( hNtDll, "RtlGetNtProductType" );
  710. if( _RtlGetNtProductType == NULL )
  711. return FALSE;
  712. if(_RtlGetNtProductType( &NtProductType )) {
  713. if( NtProductType == NtProductLanManNt )
  714. return TRUE;
  715. }
  716. return FALSE;
  717. }
  718. #if 0
  719. LONG
  720. SecureRegDeleteValueU(
  721. IN HKEY hKey, // handle of key
  722. IN LPCWSTR lpValueName // address of value name
  723. )
  724. /*++
  725. This function securely deletes a value from the registry. This approach
  726. avoids leaving a copy of the old data in the registry backing file after
  727. the delete has occurred.
  728. The specified registry handle hKey must be opened for
  729. REG_QUERY_VALUE | REG_SET_VALUE | DELETE access.
  730. On success, the return value is ERROR_SUCCESS.
  731. On error, the return value is a Win32 error code.
  732. --*/
  733. {
  734. DWORD dwType;
  735. DWORD cbData;
  736. BYTE FastBuffer[ 256 ];
  737. LPBYTE lpData;
  738. LPBYTE SlowBuffer = NULL;
  739. LONG lRet;
  740. cbData = 0; // query size of value data.
  741. //
  742. // query the current size of the registry data.
  743. // zero the current registry data of current size.
  744. // delete the registry data.
  745. // flush the change to disk.
  746. // If errors occur, just do a regular delete.
  747. //
  748. lRet = RegQueryValueExU(
  749. hKey,
  750. lpValueName,
  751. NULL,
  752. &dwType,
  753. NULL,
  754. &cbData
  755. );
  756. if( lRet == ERROR_MORE_DATA ) {
  757. BOOL fSet = TRUE; // assume ok to set
  758. //
  759. // select fast buffer if large enough. otherwise, allocate a buffer
  760. //
  761. if(cbData <= sizeof(FastBuffer)) {
  762. lpData = FastBuffer;
  763. } else {
  764. SlowBuffer = (LPBYTE)SSAlloc( cbData );
  765. if(SlowBuffer == NULL) {
  766. fSet = FALSE; // failure.
  767. } else {
  768. lpData = SlowBuffer;
  769. }
  770. }
  771. if( fSet ) {
  772. ZeroMemory( lpData, cbData );
  773. RegSetValueExU(
  774. hKey,
  775. lpValueName,
  776. 0,
  777. dwType,
  778. lpData,
  779. cbData
  780. );
  781. }
  782. }
  783. lRet = RegDeleteValueU( hKey, lpValueName );
  784. RegFlushKey( hKey );
  785. if( SlowBuffer )
  786. SSFree( SlowBuffer );
  787. return lRet;
  788. }
  789. #endif