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.

702 lines
18 KiB

  1. /**************************** Module Header ********************************\
  2. * Module Name: ex.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * Executive support routines
  7. *
  8. * History:
  9. * 03-04-95 JimA Created.
  10. \***************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. NTSTATUS
  14. OpenEffectiveToken(
  15. PHANDLE phToken)
  16. {
  17. NTSTATUS Status;
  18. /*
  19. * Open the client's token.
  20. */
  21. Status = ZwOpenThreadTokenEx(
  22. NtCurrentThread(),
  23. TOKEN_QUERY,
  24. (BOOLEAN)TRUE, // OpenAsSelf
  25. OBJ_KERNEL_HANDLE,
  26. phToken);
  27. if (Status == STATUS_NO_TOKEN) {
  28. /*
  29. * Client wasn't impersonating anyone. Open its process token.
  30. */
  31. Status = ZwOpenProcessTokenEx(
  32. NtCurrentProcess(),
  33. TOKEN_QUERY,
  34. OBJ_KERNEL_HANDLE,
  35. phToken);
  36. }
  37. if (!NT_SUCCESS(Status)) {
  38. RIPMSG1(RIP_WARNING, "Can't open client's token! - Status = %lx", Status);
  39. }
  40. return Status;
  41. }
  42. NTSTATUS
  43. GetProcessLuid(
  44. PETHREAD Thread,
  45. PLUID LuidProcess
  46. )
  47. {
  48. PACCESS_TOKEN UserToken = NULL;
  49. BOOLEAN fCopyOnOpen;
  50. BOOLEAN fEffectiveOnly;
  51. SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
  52. NTSTATUS Status;
  53. if (Thread == NULL)
  54. Thread = PsGetCurrentThread();
  55. //
  56. // Check for a thread token first
  57. //
  58. UserToken = PsReferenceImpersonationToken(Thread,
  59. &fCopyOnOpen, &fEffectiveOnly, &ImpersonationLevel);
  60. if (UserToken == NULL) {
  61. //
  62. // No thread token, go to the process
  63. //
  64. UserToken = PsReferencePrimaryToken(PsGetThreadProcess(Thread));
  65. if (UserToken == NULL)
  66. return STATUS_NO_TOKEN;
  67. }
  68. Status = SeQueryAuthenticationIdToken(UserToken, LuidProcess);
  69. //
  70. // We're finished with the token
  71. //
  72. ObDereferenceObject(UserToken);
  73. return Status;
  74. }
  75. BOOLEAN IsRestricted(
  76. PETHREAD Thread)
  77. {
  78. PACCESS_TOKEN UserToken;
  79. BOOLEAN fCopyOnOpen;
  80. BOOLEAN fEffectiveOnly;
  81. SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
  82. BOOLEAN fRestricted = FALSE;
  83. /*
  84. * Check for a thread token first.
  85. */
  86. UserToken = PsReferenceImpersonationToken(Thread,
  87. &fCopyOnOpen, &fEffectiveOnly, &ImpersonationLevel);
  88. /*
  89. * If no thread token, go to the process.
  90. */
  91. if (UserToken == NULL) {
  92. UserToken = PsReferencePrimaryToken(PsGetThreadProcess(Thread));
  93. }
  94. /*
  95. * If we got a token, is it restricted?
  96. */
  97. if (UserToken != NULL) {
  98. fRestricted = SeTokenIsRestricted(UserToken);
  99. ObDereferenceObject(UserToken);
  100. }
  101. return fRestricted;
  102. }
  103. NTSTATUS InitSystemThread(
  104. PUNICODE_STRING pstrThreadName)
  105. {
  106. PETHREAD pEThread;
  107. PEPROCESS Process;
  108. PTHREADINFO pti;
  109. NTSTATUS Status = STATUS_SUCCESS;
  110. CheckCritOut();
  111. pEThread = PsGetCurrentThread();
  112. Process = PsGetThreadProcess(pEThread);
  113. ValidateThreadSessionId(pEThread);
  114. /*
  115. * check to see if process is already set, if not, we
  116. * need to set it up as well
  117. */
  118. UserAssert(PsGetProcessWin32Process(Process));
  119. EnterCrit();
  120. /*
  121. * Flag this as a system thread
  122. */
  123. pti = PtiCurrentShared();
  124. /*
  125. * This is a CSRSS thread and we want to just convert it to a system thread,
  126. * Then changes the TIF flags and allocate a kernel side pClientInfo.
  127. */
  128. UserAssert((pti->TIF_flags & TIF_CSRSSTHREAD) && !(pti->TIF_flags & TIF_SYSTEMTHREAD));
  129. #if DBG
  130. try {
  131. UserAssert(pti->pClientInfo == ((PCLIENTINFO)((NtCurrentTeb())->Win32ClientInfo)));
  132. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  133. }
  134. #endif
  135. pti->pClientInfo = UserAllocPoolWithQuota(sizeof(CLIENTINFO),
  136. TAG_CLIENTTHREADINFO);
  137. if (pti->pClientInfo == NULL) {
  138. LeaveCrit();
  139. return STATUS_NO_MEMORY;
  140. }
  141. pti->TIF_flags &= ~TIF_CSRSSTHREAD;
  142. pti->TIF_flags |= TIF_SYSTEMTHREAD;
  143. INITCLIENTINFO(pti);
  144. if (pstrThreadName) {
  145. if (pti->pstrAppName != NULL)
  146. UserFreePool(pti->pstrAppName);
  147. pti->pstrAppName = UserAllocPoolWithQuota(sizeof(UNICODE_STRING) +
  148. pstrThreadName->Length + sizeof(WCHAR), TAG_TEXT);
  149. if (pti->pstrAppName != NULL) {
  150. pti->pstrAppName->Buffer = (PWCHAR)(pti->pstrAppName + 1);
  151. RtlCopyMemory(pti->pstrAppName->Buffer, pstrThreadName->Buffer,
  152. pstrThreadName->Length);
  153. pti->pstrAppName->Buffer[pstrThreadName->Length / sizeof(WCHAR)] = 0;
  154. pti->pstrAppName->MaximumLength = pstrThreadName->Length + sizeof(WCHAR);
  155. pti->pstrAppName->Length = pstrThreadName->Length;
  156. }
  157. }
  158. /*
  159. * Need to clear the W32PF_APPSTARTING bit so that windows created by
  160. * the RIT don't cause the cursor to change to the app starting cursor.
  161. */
  162. if (pti->ppi != NULL && (pti->ppi->W32PF_Flags & W32PF_APPSTARTING)) {
  163. ClearAppStarting(pti->ppi);
  164. }
  165. Error:
  166. LeaveCrit();
  167. return Status;
  168. }
  169. NTSTATUS CommitReadOnlyMemory(
  170. HANDLE hSection,
  171. PSIZE_T pCommitSize,
  172. DWORD dwCommitOffset,
  173. int* pdCommit)
  174. {
  175. SIZE_T ulViewSize;
  176. LARGE_INTEGER liOffset;
  177. PEPROCESS Process;
  178. PVOID pUserBase, pvt;
  179. NTSTATUS Status;
  180. ulViewSize = 0;
  181. pUserBase = NULL;
  182. liOffset.QuadPart = 0;
  183. Process = PsGetCurrentProcess();
  184. Status = MmMapViewOfSection(
  185. hSection,
  186. Process,
  187. &pUserBase,
  188. 0,
  189. PAGE_SIZE,
  190. &liOffset,
  191. &ulViewSize,
  192. ViewUnmap,
  193. SEC_NO_CHANGE,
  194. PAGE_EXECUTE_READ);
  195. if (NT_SUCCESS(Status)) {
  196. /*
  197. * Commit the memory
  198. */
  199. pUserBase = pvt = (PVOID)((PBYTE)pUserBase + dwCommitOffset);
  200. Status = ZwAllocateVirtualMemory(
  201. NtCurrentProcess(),
  202. &pUserBase,
  203. 0,
  204. pCommitSize,
  205. MEM_COMMIT,
  206. PAGE_EXECUTE_READ);
  207. if (pdCommit) {
  208. *pdCommit = (int)((PBYTE)pUserBase - (PBYTE)pvt);
  209. } else {
  210. UserAssert(pvt == pUserBase);
  211. }
  212. MmUnmapViewOfSection(Process, pUserBase);
  213. }
  214. return Status;
  215. }
  216. /***************************************************************************\
  217. * CreateKernelEvent
  218. *
  219. * Creates a kernel event. This is used when reference counted events
  220. * created by ZwCreateEvent are not needed.
  221. *
  222. * History:
  223. * 06-26-95 JimA Created.
  224. \***************************************************************************/
  225. PKEVENT CreateKernelEvent(
  226. IN EVENT_TYPE Type,
  227. IN BOOLEAN State)
  228. {
  229. PKEVENT pEvent;
  230. pEvent = UserAllocPoolNonPagedNS(sizeof(KEVENT), TAG_SYSTEM);
  231. if (pEvent != NULL) {
  232. KeInitializeEvent(pEvent, Type, State);
  233. }
  234. return pEvent;
  235. }
  236. /***************************************************************************\
  237. * LockObjectAssignment
  238. *
  239. * References an object into a data structure
  240. *
  241. * History:
  242. * 06-26-95 JimA Created.
  243. \***************************************************************************/
  244. VOID LockObjectAssignment(
  245. PVOID *pplock,
  246. PVOID pobject
  247. #ifdef LOGDESKTOPLOCKS
  248. ,DWORD tag,
  249. ULONG_PTR extra
  250. #endif
  251. )
  252. {
  253. PVOID pobjectOld;
  254. /*
  255. * Save old object to dereference AFTER the new object is referenced.
  256. * This will avoid problems with relocking the same object.
  257. */
  258. pobjectOld = *pplock;
  259. /*
  260. * Reference the new object.
  261. */
  262. if (pobject != NULL) {
  263. ObReferenceObject(pobject);
  264. #ifdef LOGDESKTOPLOCKS
  265. if (OBJECT_TO_OBJECT_HEADER(pobject)->Type == *ExDesktopObjectType) {
  266. LogDesktop(pobject, tag, TRUE, extra);
  267. }
  268. #endif
  269. }
  270. *pplock = pobject;
  271. /*
  272. * Dereference the old object.
  273. */
  274. if (pobjectOld != NULL) {
  275. #ifdef LOGDESKTOPLOCKS
  276. if (OBJECT_TO_OBJECT_HEADER(pobjectOld)->Type == *ExDesktopObjectType) {
  277. LogDesktop(pobjectOld, tag, FALSE, extra);
  278. }
  279. #endif
  280. ObDereferenceObject(pobjectOld);
  281. }
  282. }
  283. /***************************************************************************\
  284. * UnlockObjectAssignment
  285. *
  286. * Dereferences an object locked into a data structure
  287. *
  288. * History:
  289. * 06-26-95 JimA Created.
  290. \***************************************************************************/
  291. VOID UnlockObjectAssignment(
  292. PVOID *pplock
  293. #ifdef LOGDESKTOPLOCKS
  294. ,DWORD tag,
  295. ULONG_PTR extra
  296. #endif
  297. )
  298. {
  299. if (*pplock != NULL) {
  300. PVOID plock = *pplock;
  301. #ifdef LOGDESKTOPLOCKS
  302. if (OBJECT_TO_OBJECT_HEADER(*pplock)->Type == *ExDesktopObjectType) {
  303. LogDesktop(*pplock, tag, FALSE, extra);
  304. }
  305. #endif
  306. *pplock = NULL;
  307. ObDereferenceObject(plock);
  308. }
  309. }
  310. /***************************************************************************\
  311. * UserDereferenceObject
  312. *
  313. * We need this for thread locking stuff since ObDereferenceObject is a macro.
  314. *
  315. * 09-21-98 JerrySh Created.
  316. \***************************************************************************/
  317. VOID UserDereferenceObject(
  318. PVOID pobj)
  319. {
  320. ObDereferenceObject(pobj);
  321. }
  322. /***************************************************************************\
  323. * ProtectHandle
  324. *
  325. * This api is used set and clear close protection on handles used
  326. * by the kernel.
  327. *
  328. * 08-18-95 JimA Created.
  329. \***************************************************************************/
  330. NTSTATUS ProtectHandle(
  331. IN HANDLE Handle,
  332. IN POBJECT_TYPE pObjectType,
  333. IN BOOLEAN Protect)
  334. {
  335. OBJECT_HANDLE_INFORMATION HandleInfo;
  336. OBJECT_HANDLE_FLAG_INFORMATION HandleFlagInfo;
  337. NTSTATUS Status;
  338. PVOID pObject = NULL;
  339. Status = ObReferenceObjectByHandle(
  340. Handle,
  341. EVENT_ALL_ACCESS,
  342. pObjectType,
  343. UserMode,
  344. &pObject,
  345. &HandleInfo);
  346. if (NT_SUCCESS(Status)) {
  347. HandleFlagInfo.Inherit = (HandleInfo.HandleAttributes & OBJ_INHERIT) ? TRUE : FALSE;
  348. HandleFlagInfo.ProtectFromClose = Protect;
  349. Status = ObSetHandleAttributes(
  350. Handle,
  351. &HandleFlagInfo,
  352. UserMode);
  353. }
  354. if (pObject) {
  355. ObDereferenceObject(pObject);
  356. }
  357. return Status;
  358. }
  359. #ifdef LOGDESKTOPLOCKS
  360. #define LOG_DELTA 8
  361. PLogD GrowLogIfNecessary(
  362. PDESKTOP pdesk)
  363. {
  364. if (pdesk->nLogCrt < pdesk->nLogMax) {
  365. UserAssert(pdesk->pLog != NULL);
  366. return pdesk->pLog;
  367. }
  368. /*
  369. * Grow the buffer
  370. */
  371. if (pdesk->pLog == NULL) {
  372. UserAssert(pdesk->nLogMax == 0 && pdesk->nLogCrt == 0);
  373. pdesk->pLog = (PLogD)UserAllocPool(LOG_DELTA * sizeof(LogD), TAG_LOGDESKTOP);
  374. } else {
  375. pdesk->pLog = (PLogD)UserReAllocPool(pdesk->pLog,
  376. pdesk->nLogCrt * sizeof(LogD),
  377. (pdesk->nLogCrt + LOG_DELTA) * sizeof(LogD),
  378. TAG_LOGDESKTOP);
  379. }
  380. UserAssert(pdesk->pLog != NULL);
  381. pdesk->nLogMax += LOG_DELTA;
  382. return pdesk->pLog;
  383. }
  384. /***************************************************************************\
  385. * LogDesktop
  386. *
  387. * Log the lock/unlock calls for desktop objects
  388. *
  389. * Dec-2-97 clupu Created.
  390. \***************************************************************************/
  391. VOID LogDesktop(
  392. PDESKTOP pdesk,
  393. DWORD tag,
  394. BOOL bLock,
  395. ULONG_PTR extra)
  396. {
  397. DWORD tag1 = 0, tag2 = 0;
  398. PLogD pLog;
  399. if (pdesk == NULL) {
  400. return;
  401. }
  402. /*
  403. * The tag stored in LogD structure is actually a WORD.
  404. */
  405. UserAssert(HIWORD(tag) == 0);
  406. if (bLock) {
  407. (pdesk->nLockCount)++;
  408. growAndAdd:
  409. /*
  410. * grow the table if necessary and add the new
  411. * lock/unlock information to it
  412. */
  413. pLog = GrowLogIfNecessary(pdesk);
  414. pLog += pdesk->nLogCrt;
  415. pLog->tag = (WORD)tag;
  416. pLog->type = (WORD)bLock;
  417. pLog->extra = extra;
  418. RtlZeroMemory(pLog->trace, 6 * sizeof(PVOID));
  419. RtlWalkFrameChain(pLog->trace, 6, 0);
  420. (pdesk->nLogCrt)++;
  421. return;
  422. }
  423. /*
  424. * It's an unlock.
  425. * First search for a matching lock
  426. */
  427. UserAssert(pdesk->nLockCount > 0);
  428. switch (tag) {
  429. case LDU_CLS_DESKPARENT1:
  430. tag1 = LDL_CLS_DESKPARENT1;
  431. break;
  432. case LDU_CLS_DESKPARENT2:
  433. tag1 = LDL_CLS_DESKPARENT1;
  434. tag2 = LDL_CLS_DESKPARENT2;
  435. break;
  436. case LDU_FN_DESTROYCLASS:
  437. tag1 = LDL_FN_DESTROYCLASS;
  438. break;
  439. case LDU_FN_DESTROYMENU:
  440. tag1 = LDL_FN_DESTROYMENU;
  441. break;
  442. case LDU_FN_DESTROYTHREADINFO:
  443. tag1 = LDL_FN_DESTROYTHREADINFO;
  444. break;
  445. case LDU_FN_DESTROYWINDOWSTATION:
  446. tag1 = LDL_FN_DESTROYWINDOWSTATION;
  447. break;
  448. case LDU_DESKDISCONNECT:
  449. tag1 = LDL_DESKDISCONNECT;
  450. break;
  451. case LDU_DESK_DESKNEXT:
  452. tag1 = LDL_DESK_DESKNEXT1;
  453. break;
  454. case LDU_OBJ_DESK:
  455. tag1 = LDL_OBJ_DESK;
  456. tag2 = LDL_MOTHERDESK_DESK1;
  457. break;
  458. case LDL_PTI_DESK:
  459. tag1 = LDL_PTI_DESK;
  460. tag2 = LDL_DT_DESK;
  461. break;
  462. case LDU_PTI_DESK:
  463. tag1 = LDL_PTI_DESK;
  464. break;
  465. case LDU_PPI_DESKSTARTUP1:
  466. case LDU_PPI_DESKSTARTUP2:
  467. case LDU_PPI_DESKSTARTUP3:
  468. tag1 = LDL_PPI_DESKSTARTUP1;
  469. tag2 = LDL_PPI_DESKSTARTUP2;
  470. break;
  471. case LDU_DESKLOGON:
  472. tag1 = LDL_DESKLOGON;
  473. break;
  474. case LDUT_FN_FREEWINDOW:
  475. tag1 = LDLT_FN_FREEWINDOW;
  476. break;
  477. case LDUT_FN_DESKTOPTHREAD_DESK:
  478. tag1 = LDLT_FN_DESKTOPTHREAD_DESK;
  479. break;
  480. case LDUT_FN_DESKTOPTHREAD_DESKTEMP:
  481. tag1 = LDLT_FN_DESKTOPTHREAD_DESKTEMP;
  482. break;
  483. case LDUT_FN_SETDESKTOP:
  484. tag1 = LDLT_FN_SETDESKTOP;
  485. break;
  486. case LDUT_FN_NTUSERSWITCHDESKTOP:
  487. tag1 = LDLT_FN_NTUSERSWITCHDESKTOP;
  488. break;
  489. case LDUT_FN_SENDMESSAGEBSM1:
  490. case LDUT_FN_SENDMESSAGEBSM2:
  491. tag1 = LDLT_FN_SENDMESSAGEBSM;
  492. break;
  493. case LDUT_FN_SYSTEMBROADCASTMESSAGE:
  494. tag1 = LDLT_FN_SYSTEMBROADCASTMESSAGE;
  495. break;
  496. case LDUT_FN_CTXREDRAWSCREEN:
  497. tag1 = LDLT_FN_CTXREDRAWSCREEN;
  498. break;
  499. case LDUT_FN_CTXDISABLESCREEN:
  500. tag1 = LDLT_FN_CTXDISABLESCREEN;
  501. break;
  502. case LD_DEREF_FN_CREATEDESKTOP1:
  503. case LD_DEREF_FN_CREATEDESKTOP2:
  504. case LD_DEREF_FN_CREATEDESKTOP3:
  505. tag1 = LD_REF_FN_CREATEDESKTOP;
  506. break;
  507. case LD_DEREF_FN_OPENDESKTOP:
  508. tag1 = LD_REF_FN_OPENDESKTOP;
  509. break;
  510. case LD_DEREF_FN_SETDESKTOP:
  511. tag1 = LD_REF_FN_SETDESKTOP;
  512. break;
  513. case LD_DEREF_FN_GETTHREADDESKTOP:
  514. tag1 = LD_REF_FN_GETTHREADDESKTOP;
  515. break;
  516. case LD_DEREF_FN_CLOSEDESKTOP1:
  517. case LD_DEREF_FN_CLOSEDESKTOP2:
  518. tag1 = LD_REF_FN_CLOSEDESKTOP;
  519. break;
  520. case LD_DEREF_FN_RESOLVEDESKTOP:
  521. tag1 = LD_REF_FN_RESOLVEDESKTOP;
  522. break;
  523. case LD_DEREF_VALIDATE_HDESK1:
  524. case LD_DEREF_VALIDATE_HDESK2:
  525. case LD_DEREF_VALIDATE_HDESK3:
  526. case LD_DEREF_VALIDATE_HDESK4:
  527. tag1 = LDL_VALIDATE_HDESK;
  528. break;
  529. case LDUT_FN_CREATETHREADINFO1:
  530. case LDUT_FN_CREATETHREADINFO2:
  531. tag1 = LDLT_FN_CREATETHREADINFO;
  532. break;
  533. case LD_DEREF_FN_SETCSRSSTHREADDESKTOP1:
  534. case LD_DEREF_FN_SETCSRSSTHREADDESKTOP2:
  535. tag1 = LD_REF_FN_SETCSRSSTHREADDESKTOP;
  536. break;
  537. case LD_DEREF_FN_CONSOLECONTROL1:
  538. tag1 = LD_REF_FN_CONSOLECONTROL1;
  539. break;
  540. case LD_DEREF_FN_CONSOLECONTROL2:
  541. tag1 = LD_REF_FN_CONSOLECONTROL2;
  542. break;
  543. case LD_DEREF_FN_GETUSEROBJECTINFORMATION:
  544. tag1 = LD_REF_FN_GETUSEROBJECTINFORMATION;
  545. break;
  546. case LD_DEREF_FN_SETUSEROBJECTINFORMATION:
  547. tag1 = LD_REF_FN_SETUSEROBJECTINFORMATION;
  548. break;
  549. case LD_DEREF_FN_CREATEWINDOWSTATION:
  550. tag1 = LD_REF_FN_CREATEWINDOWSTATION;
  551. break;
  552. case LDL_TERM_DESKDESTROY1:
  553. tag1 = LDL_TERM_DESKDESTROY2;
  554. break;
  555. case LDL_MOTHERDESK_DESK1:
  556. tag1 = LDL_MOTHERDESK_DESK1;
  557. tag2 = LDL_MOTHERDESK_DESK2;
  558. break;
  559. case LDL_WINSTA_DESKLIST2:
  560. tag1 = LDL_WINSTA_DESKLIST1;
  561. break;
  562. case LDL_DESKRITINPUT:
  563. case LDU_DESKRITINPUT:
  564. tag1 = LDL_DESKRITINPUT;
  565. break;
  566. }
  567. if (tag1 != 0) {
  568. int ind;
  569. /*
  570. * this is an unlock we know about. Let's find the
  571. * matching lock in the table. We start searching
  572. * the table backwords.
  573. */
  574. for (ind = pdesk->nLogCrt - 1; ind >= 0; ind--) {
  575. pLog = pdesk->pLog + ind;
  576. if (pLog->type == 1 &&
  577. (pLog->tag == tag1 || pLog->tag == tag2) &&
  578. pLog->extra == extra) {
  579. /*
  580. * match found. remove the lock
  581. */
  582. RtlMoveMemory(pdesk->pLog + ind,
  583. pdesk->pLog + ind + 1,
  584. (pdesk->nLogCrt - ind - 1) * sizeof(LogD));
  585. (pdesk->nLogCrt)--;
  586. (pdesk->nLockCount)--;
  587. if (pdesk->nLockCount == 0) {
  588. RIPMSG1(RIP_VERBOSE, "Lock count 0 for pdesk %#p\n", pdesk);
  589. }
  590. return;
  591. }
  592. }
  593. /*
  594. * We didn't find the matching lock and we were supposed to.
  595. * Just add it to the table and we'll look at it.
  596. */
  597. RIPMSG3(RIP_WARNING, "Didn't find matching lock for pdesk %#p tag %d extra %lx\n",
  598. pdesk, tag, extra);
  599. }
  600. (pdesk->nLockCount)--;
  601. goto growAndAdd;
  602. }
  603. #endif