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.

877 lines
24 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: security.cxx
  7. //
  8. // Contents:
  9. //
  10. //--------------------------------------------------------------------------
  11. #include "act.hxx"
  12. // the constant generic mapping structure
  13. GENERIC_MAPPING sGenericMapping = {
  14. READ_CONTROL,
  15. READ_CONTROL,
  16. READ_CONTROL,
  17. READ_CONTROL};
  18. //-------------------------------------------------------------------------
  19. //
  20. // CheckForAccess
  21. //
  22. // Checks whether the given token has COM_RIGHTS_EXECUTE access in the
  23. // given security descriptor.
  24. //
  25. //-------------------------------------------------------------------------
  26. BOOL
  27. CheckForAccess(
  28. IN CToken * pToken,
  29. IN SECURITY_DESCRIPTOR * pSD
  30. )
  31. {
  32. // if we have an empty SD, deny everyone
  33. if ( ! pSD )
  34. return FALSE;
  35. //
  36. // pToken is NULL during an unsecure activation, in which case we check
  37. // if EVERYONE is granted access in the security descriptor.
  38. //
  39. if ( pToken )
  40. {
  41. HANDLE hToken = pToken->GetToken();
  42. BOOL fAccess = FALSE;
  43. BOOL fSuccess = FALSE;
  44. DWORD dwGrantedAccess;
  45. PRIVILEGE_SET sPrivilegeSet;
  46. DWORD dwSetLen = sizeof( sPrivilegeSet );
  47. sPrivilegeSet.PrivilegeCount = 1;
  48. sPrivilegeSet.Control = 0;
  49. fSuccess = AccessCheck( (PSECURITY_DESCRIPTOR) pSD,
  50. hToken,
  51. COM_RIGHTS_EXECUTE,
  52. &sGenericMapping,
  53. &sPrivilegeSet,
  54. &dwSetLen,
  55. &dwGrantedAccess,
  56. &fAccess );
  57. if ( fSuccess && fAccess )
  58. return TRUE;
  59. if ( !fSuccess )
  60. {
  61. CairoleDebugOut((DEB_ERROR, "Bad Security Descriptor 0x%08x, Access Check returned 0x%x\n", pSD, GetLastError() ));
  62. }
  63. return FALSE;
  64. }
  65. else
  66. {
  67. BOOL bStatus;
  68. BOOL bDaclPresent;
  69. BOOL bDaclDefaulted;
  70. DWORD Index;
  71. HRESULT hr;
  72. PACL pDacl;
  73. PACCESS_ALLOWED_ACE pAllowAce;
  74. SID SidEveryone = { SID_REVISION,
  75. 1,
  76. SECURITY_WORLD_SID_AUTHORITY,
  77. 0 };
  78. pDacl = 0;
  79. bStatus = GetSecurityDescriptorDacl(
  80. (void *)pSD,
  81. &bDaclPresent,
  82. &pDacl,
  83. &bDaclDefaulted );
  84. if ( ! bStatus )
  85. return FALSE;
  86. // Bug 95306: Can assume dacl exists only if both
  87. // bDaclPresent is TRUE and pDacl is not NULL
  88. if ( (!pDacl) || (!bDaclPresent) )
  89. return TRUE;
  90. bStatus = FALSE;
  91. for ( Index = 0; Index < pDacl->AceCount; Index++ )
  92. {
  93. if ( ! GetAce( pDacl, Index, (void **) &pAllowAce ) )
  94. break;
  95. if ( pAllowAce->Header.AceType != ACCESS_ALLOWED_ACE_TYPE )
  96. continue;
  97. if ( ! (pAllowAce->Mask & COM_RIGHTS_EXECUTE) )
  98. continue;
  99. if ( EqualSid( (PSID)(&pAllowAce->SidStart), &SidEveryone ) )
  100. {
  101. bStatus = TRUE;
  102. break;
  103. }
  104. }
  105. return bStatus;
  106. }
  107. }
  108. HANDLE
  109. GetRunAsToken(
  110. DWORD clsctx,
  111. WCHAR *pwszAppID,
  112. WCHAR *pwszRunAsDomainName,
  113. WCHAR *pwszRunAsUserName )
  114. {
  115. LSA_OBJECT_ATTRIBUTES sObjAttributes;
  116. HANDLE hPolicy = NULL;
  117. LSA_UNICODE_STRING sKey;
  118. WCHAR wszKey[CLSIDSTR_MAX+5];
  119. PLSA_UNICODE_STRING psPassword;
  120. HANDLE hToken;
  121. if ( !pwszAppID )
  122. {
  123. // if we have a RunAs, we'd better have an appid....
  124. return 0;
  125. }
  126. // formulate the access key
  127. lstrcpyW(wszKey, L"SCM:");
  128. lstrcatW(wszKey, pwszAppID );
  129. // UNICODE_STRING length fields are in bytes and include the NULL
  130. // terminator
  131. sKey.Length = (USHORT)((lstrlenW(wszKey) + 1) * sizeof(WCHAR));
  132. sKey.MaximumLength = (CLSIDSTR_MAX + 5) * sizeof(WCHAR);
  133. sKey.Buffer = wszKey;
  134. // Open the local security policy
  135. InitializeObjectAttributes(&sObjAttributes, NULL, 0L, NULL, NULL);
  136. if (!NT_SUCCESS(LsaOpenPolicy(NULL, &sObjAttributes,
  137. POLICY_GET_PRIVATE_INFORMATION, &hPolicy)))
  138. {
  139. return 0;
  140. }
  141. // Read the user's password
  142. if (!NT_SUCCESS(LsaRetrievePrivateData(hPolicy, &sKey, &psPassword)))
  143. {
  144. LsaClose(hPolicy);
  145. return 0;
  146. }
  147. // Close the policy handle, we're done with it now.
  148. LsaClose(hPolicy);
  149. // Possible for LsaRetrievePrivateData to return success but with a NULL
  150. // psPassword. If this happens we fail.
  151. if (!psPassword)
  152. {
  153. return 0;
  154. }
  155. // Log the specifed user on
  156. if (!LogonUserW(pwszRunAsUserName, pwszRunAsDomainName, psPassword->Buffer,
  157. LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &hToken))
  158. {
  159. memset(psPassword->Buffer, 0, psPassword->Length);
  160. LsaFreeMemory( psPassword );
  161. // a-sergiv (Sergei O. Ivanov), 6-17-99
  162. // Fix for com+ 9383/nt 272085
  163. // Apply event filters
  164. DWORD dwActLogLvl = GetActivationFailureLoggingLevel();
  165. if(dwActLogLvl == 2)
  166. return 0;
  167. if(dwActLogLvl != 1 && clsctx & CLSCTX_NO_FAILURE_LOG)
  168. return 0;
  169. // for this message,
  170. // %1 is the error number string
  171. // %2 is the domain name
  172. // %3 is the user name
  173. // %4 is the CLSID
  174. HANDLE LogHandle;
  175. LPWSTR Strings[4]; // array of message strings.
  176. WCHAR wszErrnum[20];
  177. WCHAR wszClsid[GUIDSTR_MAX];
  178. // Save the error number
  179. wsprintf(wszErrnum, L"%lu",GetLastError() );
  180. Strings[0] = wszErrnum;
  181. // Put in the RunAs identity
  182. Strings[1] = pwszRunAsDomainName;
  183. Strings[2] = pwszRunAsUserName;
  184. // Get the clsid
  185. Strings[3] = pwszAppID;
  186. // Get the log handle, then report then event.
  187. LogHandle = RegisterEventSource( NULL,
  188. SCM_EVENT_SOURCE );
  189. if ( LogHandle )
  190. {
  191. ReportEvent( LogHandle,
  192. EVENTLOG_ERROR_TYPE,
  193. 0, // event category
  194. EVENT_RPCSS_RUNAS_CANT_LOGIN,
  195. NULL, // SID
  196. 4, // 4 strings passed
  197. 0, // 0 bytes of binary
  198. (LPCTSTR *)Strings, // array of strings
  199. NULL ); // no raw data
  200. // clean up the event log handle
  201. DeregisterEventSource(LogHandle);
  202. }
  203. return 0;
  204. }
  205. // Clear the password
  206. memset(psPassword->Buffer, 0, psPassword->Length);
  207. LsaFreeMemory( psPassword );
  208. return hToken;
  209. }
  210. /***************************************************************************\
  211. * CreateAndSetProcessToken
  212. *
  213. * Set the primary token of the specified process
  214. * If the specified token is NULL, this routine does nothing.
  215. *
  216. * It assumed that the handles in ProcessInformation are the handles returned
  217. * on creation of the process and therefore have all access.
  218. *
  219. * Returns TRUE on success, FALSE on failure.
  220. *
  221. * 01-31-91 Davidc Created.
  222. * 31-Mar-94 AndyH Started from Winlogon; added SetToken
  223. \***************************************************************************/
  224. BOOL
  225. CreateAndSetProcessToken(
  226. PPROCESS_INFORMATION ProcessInformation,
  227. HANDLE hUserToken,
  228. PSID psidUserSid
  229. )
  230. {
  231. NTSTATUS NtStatus, NtAdjustStatus;
  232. PROCESS_ACCESS_TOKEN PrimaryTokenInfo;
  233. HANDLE hTokenToAssign;
  234. OBJECT_ATTRIBUTES ObjectAttributes;
  235. BOOLEAN fWasEnabled;
  236. PSECURITY_DESCRIPTOR psdNewProcessTokenSD;
  237. //
  238. // Check for a NULL token. (No need to do anything)
  239. // The process will run in the parent process's context and inherit
  240. // the default ACL from the parent process's token.
  241. //
  242. if (hUserToken == NULL) {
  243. return(TRUE);
  244. }
  245. //
  246. // Create the security descriptor that we want to put in the Token.
  247. // Need to destroy it before we leave this function.
  248. //
  249. CAccessInfo AccessInfo(psidUserSid);
  250. psdNewProcessTokenSD = AccessInfo.IdentifyAccess(
  251. FALSE,
  252. TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS |
  253. TOKEN_ADJUST_DEFAULT | TOKEN_QUERY |
  254. TOKEN_DUPLICATE | TOKEN_IMPERSONATE | READ_CONTROL,
  255. TOKEN_QUERY
  256. );
  257. if (psdNewProcessTokenSD == NULL)
  258. {
  259. CairoleDebugOut((DEB_ERROR, "Failed to create SD for process token\n"));
  260. return(FALSE);
  261. }
  262. //
  263. // A primary token can only be assigned to one process.
  264. // Duplicate the logon token so we can assign one to the new
  265. // process.
  266. //
  267. InitializeObjectAttributes(
  268. &ObjectAttributes,
  269. NULL,
  270. 0,
  271. NULL,
  272. psdNewProcessTokenSD
  273. );
  274. NtStatus = NtDuplicateToken(
  275. hUserToken, // Duplicate this token
  276. TOKEN_ASSIGN_PRIMARY, // Give me this access to the resulting token
  277. &ObjectAttributes,
  278. FALSE, // EffectiveOnly
  279. TokenPrimary, // TokenType
  280. &hTokenToAssign // Duplicate token handle stored here
  281. );
  282. if (!NT_SUCCESS(NtStatus)) {
  283. CairoleDebugOut((DEB_ERROR, "CreateAndSetProcessToken failed to duplicate primary token for new user process, status = 0x%lx\n", NtStatus));
  284. return(FALSE);
  285. }
  286. //
  287. // Set the process's primary token
  288. //
  289. //
  290. // Enable the required privilege
  291. //
  292. NtStatus = RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE,
  293. FALSE, &fWasEnabled);
  294. if (NT_SUCCESS(NtStatus)) {
  295. PrimaryTokenInfo.Token = hTokenToAssign;
  296. PrimaryTokenInfo.Thread = ProcessInformation->hThread;
  297. NtStatus = NtSetInformationProcess(
  298. ProcessInformation->hProcess,
  299. ProcessAccessToken,
  300. (PVOID)&PrimaryTokenInfo,
  301. (ULONG)sizeof(PROCESS_ACCESS_TOKEN)
  302. );
  303. //
  304. // if we just started the Shared WOW, the handle we get back
  305. // is really just a handle to an event.
  306. //
  307. if (STATUS_OBJECT_TYPE_MISMATCH == NtStatus)
  308. {
  309. HANDLE hRealProcess = OpenProcess(
  310. PROCESS_SET_INFORMATION | PROCESS_TERMINATE | SYNCHRONIZE,
  311. FALSE,
  312. ProcessInformation->dwProcessId);
  313. if (hRealProcess)
  314. {
  315. NtStatus = NtSetInformationProcess(
  316. hRealProcess,
  317. ProcessAccessToken,
  318. (PVOID)&PrimaryTokenInfo,
  319. (ULONG)sizeof(PROCESS_ACCESS_TOKEN)
  320. );
  321. CloseHandle(hRealProcess);
  322. }
  323. }
  324. //
  325. // Restore the privilege to its previous state
  326. //
  327. NtAdjustStatus = RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE,
  328. fWasEnabled, FALSE, &fWasEnabled);
  329. if (!NT_SUCCESS(NtAdjustStatus)) {
  330. CairoleDebugOut((DEB_ERROR, "failed to restore assign-primary-token privilege to previous enabled state\n"));
  331. }
  332. if (NT_SUCCESS(NtStatus)) {
  333. NtStatus = NtAdjustStatus;
  334. }
  335. } else {
  336. CairoleDebugOut((DEB_ERROR, "failed to enable assign-primary-token privilege\n"));
  337. }
  338. //
  339. // We're finished with the token handle and the SD
  340. //
  341. CloseHandle(hTokenToAssign);
  342. if (!NT_SUCCESS(NtStatus)) {
  343. CairoleDebugOut((DEB_ERROR, "CreateAndSetProcessToken failed to set primary token for new user process, Status = 0x%lx\n", NtStatus));
  344. }
  345. return (NT_SUCCESS(NtStatus));
  346. }
  347. BOOL
  348. DuplicateTokenForSessionUse(
  349. HANDLE hUserToken,
  350. HANDLE *hDuplicate
  351. )
  352. {
  353. OBJECT_ATTRIBUTES ObjectAttributes;
  354. PSECURITY_DESCRIPTOR psdNewProcessTokenSD;
  355. NTSTATUS NtStatus;
  356. if (hUserToken == NULL) {
  357. return(TRUE);
  358. }
  359. *hDuplicate = NULL;
  360. InitializeObjectAttributes(
  361. &ObjectAttributes,
  362. NULL,
  363. 0,
  364. NULL,
  365. NULL
  366. );
  367. NtStatus = NtDuplicateToken(
  368. hUserToken, // Duplicate this token
  369. TOKEN_ALL_ACCESS, //Give me this access to the resulting token
  370. &ObjectAttributes,
  371. FALSE, // EffectiveOnly
  372. TokenPrimary, // TokenType
  373. hDuplicate // Duplicate token handle stored here
  374. );
  375. if (!NT_SUCCESS(NtStatus)) {
  376. CairoleDebugOut((DEB_ERROR, "CreateAndSetProcessToken failed to duplicate primary token for new user process, status = 0x%lx\n", NtStatus));
  377. return(FALSE);
  378. }
  379. return TRUE;
  380. }
  381. /***************************************************************************\
  382. * GetUserSid
  383. *
  384. * Allocs space for the user sid, fills it in and returns a pointer.
  385. * The sid should be freed by calling DeleteUserSid.
  386. *
  387. * Note the sid returned is the user's real sid, not the per-logon sid.
  388. *
  389. * Returns pointer to sid or NULL on failure.
  390. *
  391. * History:
  392. * 26-Aug-92 Davidc Created.
  393. * 31-Mar-94 AndyH Copied from Winlogon, changed arg from pGlobals
  394. \***************************************************************************/
  395. PSID
  396. GetUserSid(
  397. HANDLE hUserToken
  398. )
  399. {
  400. BYTE achBuffer[100];
  401. PTOKEN_USER pUser = (PTOKEN_USER) &achBuffer;
  402. PSID pSid;
  403. DWORD dwBytesRequired;
  404. NTSTATUS NtStatus;
  405. BOOL fAllocatedBuffer = FALSE;
  406. NtStatus = NtQueryInformationToken(
  407. hUserToken, // Handle
  408. TokenUser, // TokenInformationClass
  409. pUser, // TokenInformation
  410. sizeof(achBuffer), // TokenInformationLength
  411. &dwBytesRequired // ReturnLength
  412. );
  413. if (!NT_SUCCESS(NtStatus))
  414. {
  415. if (NtStatus != STATUS_BUFFER_TOO_SMALL)
  416. {
  417. Win4Assert(NtStatus == STATUS_BUFFER_TOO_SMALL);
  418. return NULL;
  419. }
  420. //
  421. // Allocate space for the user info
  422. //
  423. pUser = (PTOKEN_USER) PrivMemAlloc(dwBytesRequired);
  424. if (pUser == NULL)
  425. {
  426. CairoleDebugOut((DEB_ERROR, "Failed to allocate %d bytes\n", dwBytesRequired));
  427. Win4Assert(pUser != NULL);
  428. return NULL;
  429. }
  430. fAllocatedBuffer = TRUE;
  431. //
  432. // Read in the UserInfo
  433. //
  434. NtStatus = NtQueryInformationToken(
  435. hUserToken, // Handle
  436. TokenUser, // TokenInformationClass
  437. pUser, // TokenInformation
  438. dwBytesRequired, // TokenInformationLength
  439. &dwBytesRequired // ReturnLength
  440. );
  441. if (!NT_SUCCESS(NtStatus))
  442. {
  443. CairoleDebugOut((DEB_ERROR, "Failed to query user info from user token, status = 0x%lx\n", NtStatus));
  444. Win4Assert(NtStatus == STATUS_SUCCESS);
  445. PrivMemFree((HANDLE)pUser);
  446. return NULL;
  447. }
  448. }
  449. // Alloc buffer for copy of SID
  450. dwBytesRequired = RtlLengthSid(pUser->User.Sid);
  451. pSid = (PSID) PrivMemAlloc(dwBytesRequired);
  452. if (pSid == NULL)
  453. {
  454. CairoleDebugOut((DEB_ERROR, "Failed to allocate %d bytes\n", dwBytesRequired));
  455. if (fAllocatedBuffer == TRUE)
  456. {
  457. PrivMemFree((HANDLE)pUser);
  458. }
  459. return NULL;
  460. }
  461. // Copy SID
  462. NtStatus = RtlCopySid(dwBytesRequired, pSid, pUser->User.Sid);
  463. if (fAllocatedBuffer == TRUE)
  464. {
  465. PrivMemFree((HANDLE)pUser);
  466. }
  467. if (!NT_SUCCESS(NtStatus))
  468. {
  469. CairoleDebugOut((DEB_ERROR, "RtlCopySid failed, status = 0x%lx\n", NtStatus));
  470. Win4Assert(NtStatus != STATUS_SUCCESS);
  471. PrivMemFree(pSid);
  472. pSid = NULL;
  473. }
  474. return pSid;
  475. }
  476. // Initialzed in InitializeSCM during boot.
  477. CRITICAL_SECTION ShellQueryCS;
  478. HANDLE GetShellProcessToken(
  479. ULONG ulSessionId
  480. )
  481. {
  482. NTSTATUS NtStatus;
  483. BOOL bStatus;
  484. HKEY hReg;
  485. LONG RegStatus;
  486. DWORD RegSize, RegType;
  487. WCHAR * pwszImageName;
  488. WCHAR * pwszSearch;
  489. WCHAR * pwszNext;
  490. WCHAR * pNull;
  491. DWORD Pid;
  492. DWORD n;
  493. BYTE StackInfoBuffer[4096];
  494. PBYTE pProcessInfoBuffer;
  495. ULONG ProcessInfoBufferSize;
  496. ULONG TotalOffset;
  497. HANDLE hProcess;
  498. HANDLE hToken;
  499. PSYSTEM_PROCESS_INFORMATION pProcessInfo;
  500. static HANDLE hShellProcess = 0;
  501. static HANDLE hShellProcessToken = 0;
  502. static WCHAR * pwszShellRegValue = 0;
  503. static WCHAR ** apwszShells = 0;
  504. static DWORD nShells = 0;
  505. EnterCriticalSection( &ShellQueryCS );
  506. if ( ! pwszShellRegValue )
  507. {
  508. nShells = 0;
  509. //
  510. // This code follows logic similar to userinit for finding the name of
  511. // the shell process.
  512. //
  513. RegStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  514. L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
  515. 0,
  516. KEY_READ,
  517. &hReg );
  518. if ( ERROR_SUCCESS == RegStatus )
  519. {
  520. RegStatus = ReadStringValue( hReg, L"Shell", &pwszShellRegValue );
  521. RegCloseKey( hReg );
  522. }
  523. if ( RegStatus != ERROR_SUCCESS )
  524. pwszShellRegValue = L"explorer.exe";
  525. pwszSearch = pwszShellRegValue;
  526. for ( ;; )
  527. {
  528. if ( ! FindExeComponent( pwszSearch, L" ,", &pNull, &pwszNext ) )
  529. break;
  530. nShells++;
  531. while ( *pwszNext && *pwszNext != L',' )
  532. pwszNext++;
  533. pwszSearch = pwszNext;
  534. }
  535. apwszShells = (WCHAR **) PrivMemAlloc( nShells * sizeof(WCHAR **) );
  536. if ( ! apwszShells )
  537. {
  538. LeaveCriticalSection( &ShellQueryCS );
  539. return NULL;
  540. }
  541. for ( pwszSearch = pwszShellRegValue, n = 0; n < nShells; n++ )
  542. {
  543. FindExeComponent( pwszSearch, L" ,", &apwszShells[n], &pwszNext );
  544. pNull = pwszNext;
  545. while ( *pwszNext && *pwszNext != L',' )
  546. pwszNext++;
  547. //
  548. // When using the const string L"explorer.exe" we can't
  549. // automatically write a null or we'll AV on the read only memory.
  550. //
  551. if ( *pNull )
  552. *pNull = 0;
  553. pwszSearch = pwszNext;
  554. }
  555. }
  556. //
  557. // Make sure the shell process is still alive before using its token.
  558. //
  559. if ( hShellProcess && !ulSessionId )
  560. {
  561. if ( WaitForSingleObject( hShellProcess, 0 ) == WAIT_TIMEOUT )
  562. {
  563. LeaveCriticalSection( &ShellQueryCS );
  564. return hShellProcessToken;
  565. }
  566. CloseHandle( hShellProcessToken );
  567. CloseHandle( hShellProcess );
  568. hShellProcessToken = 0;
  569. hShellProcess = 0;
  570. }
  571. Pid = 0;
  572. pProcessInfoBuffer = StackInfoBuffer;
  573. ProcessInfoBufferSize = sizeof(StackInfoBuffer);
  574. for (;;)
  575. {
  576. NtStatus = NtQuerySystemInformation( SystemProcessInformation,
  577. pProcessInfoBuffer,
  578. ProcessInfoBufferSize,
  579. NULL );
  580. if ( NtStatus == STATUS_INFO_LENGTH_MISMATCH )
  581. {
  582. ProcessInfoBufferSize += 4096;
  583. if ( pProcessInfoBuffer != StackInfoBuffer )
  584. PrivMemFree( pProcessInfoBuffer );
  585. pProcessInfoBuffer = (PBYTE) PrivMemAlloc( ProcessInfoBufferSize );
  586. if ( ! pProcessInfoBuffer )
  587. goto AllDone;
  588. continue;
  589. }
  590. if ( ! NT_SUCCESS(NtStatus) )
  591. goto AllDone;
  592. break;
  593. }
  594. pProcessInfo = (PSYSTEM_PROCESS_INFORMATION) pProcessInfoBuffer;
  595. TotalOffset = 0;
  596. for (;;)
  597. {
  598. if ( pProcessInfo->ImageName.Buffer &&
  599. ( pProcessInfo->SessionId == ulSessionId ) )
  600. {
  601. pwszImageName = &pProcessInfo->ImageName.Buffer[pProcessInfo->ImageName.Length / sizeof(WCHAR)];
  602. while ( (pwszImageName != pProcessInfo->ImageName.Buffer) &&
  603. (pwszImageName[-1] != '\\') )
  604. pwszImageName--;
  605. for ( n = 0; n < nShells; n++ )
  606. {
  607. if ( lstrcmpiW( apwszShells[n], pwszImageName ) == 0 )
  608. {
  609. Pid = PtrToUlong(pProcessInfo->UniqueProcessId);
  610. break;
  611. }
  612. }
  613. }
  614. if ( pProcessInfo->NextEntryOffset == 0 )
  615. break;
  616. TotalOffset += pProcessInfo->NextEntryOffset;
  617. pProcessInfo = (PSYSTEM_PROCESS_INFORMATION) &pProcessInfoBuffer[TotalOffset];
  618. }
  619. AllDone:
  620. if ( pProcessInfoBuffer != StackInfoBuffer )
  621. PrivMemFree( pProcessInfoBuffer );
  622. hProcess = 0;
  623. hToken = 0;
  624. if ( Pid != 0 )
  625. {
  626. hProcess = OpenProcess( PROCESS_ALL_ACCESS,
  627. FALSE,
  628. Pid );
  629. if ( hProcess )
  630. {
  631. bStatus = OpenProcessToken( hProcess,
  632. TOKEN_ALL_ACCESS,
  633. &hToken );
  634. if ( !bStatus ) {
  635. CloseHandle( hProcess );
  636. hProcess = 0;
  637. hToken = 0;
  638. }
  639. }
  640. }
  641. if ( ulSessionId )
  642. {
  643. if ( hProcess )
  644. CloseHandle( hProcess );
  645. LeaveCriticalSection( &ShellQueryCS );
  646. return hToken;
  647. }
  648. hShellProcess = hProcess;
  649. hShellProcessToken = hToken;
  650. LeaveCriticalSection( &ShellQueryCS );
  651. // Callers should not close this token unless they want to hose us!
  652. return hShellProcessToken;
  653. }
  654. // Global default launch permissions
  655. CSecDescriptor* gpDefaultLaunchPermissions;
  656. CSecDescriptor*
  657. GetDefaultLaunchPermissions()
  658. {
  659. CSecDescriptor* pSD = NULL;
  660. gpClientLock->LockShared();
  661. pSD = gpDefaultLaunchPermissions;
  662. if (pSD)
  663. pSD->IncRefCount();
  664. gpClientLock->UnlockShared();
  665. return pSD;
  666. }
  667. void
  668. SetDefaultLaunchPermissions(CSecDescriptor* pNewLaunchPerms)
  669. {
  670. CSecDescriptor* pOldSD = NULL;
  671. gpClientLock->LockExclusive();
  672. pOldSD = gpDefaultLaunchPermissions;
  673. gpDefaultLaunchPermissions = pNewLaunchPerms;
  674. if (gpDefaultLaunchPermissions)
  675. gpDefaultLaunchPermissions->IncRefCount();
  676. gpClientLock->UnlockExclusive();
  677. if (pOldSD)
  678. pOldSD->DecRefCount();
  679. return;
  680. }
  681. CSecDescriptor::CSecDescriptor(SECURITY_DESCRIPTOR* pSD) : _lRefs(1)
  682. {
  683. ASSERT(pSD);
  684. _pSD = pSD; // we own it now
  685. }
  686. CSecDescriptor::~CSecDescriptor()
  687. {
  688. ASSERT(_lRefs == 0);
  689. ASSERT(_pSD);
  690. PrivMemFree(_pSD);
  691. }
  692. void CSecDescriptor::IncRefCount()
  693. {
  694. ASSERT(_lRefs > 0);
  695. LONG lRefs = InterlockedIncrement(&_lRefs);
  696. }
  697. void CSecDescriptor::DecRefCount()
  698. {
  699. ASSERT(_lRefs > 0);
  700. LONG lRefs = InterlockedDecrement(&_lRefs);
  701. if (lRefs == 0)
  702. {
  703. delete this;
  704. }
  705. }
  706. SECURITY_DESCRIPTOR* CSecDescriptor::GetSD()
  707. {
  708. ASSERT(_pSD);
  709. ASSERT(_lRefs > 0);
  710. return _pSD;
  711. }