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.

274 lines
8.2 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: heap.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains kernel-mode heap management code.
  7. *
  8. * History:
  9. * 03-16-95 JimA Created.
  10. \***************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. NTSTATUS UserCommitDesktopMemory(
  14. PVOID pBase,
  15. PVOID *ppCommit,
  16. PSIZE_T pCommitSize)
  17. {
  18. PDESKTOPVIEW pdv;
  19. DWORD dwCommitOffset;
  20. PWINDOWSTATION pwinsta;
  21. PDESKTOP pdesk;
  22. int dCommit;
  23. NTSTATUS Status;
  24. PETHREAD Thread = PsGetCurrentThread();
  25. /*
  26. * If this is a system thread, we have no view of the desktop
  27. * and must map it in. Fortunately, this does not happen often.
  28. *
  29. * We use the Thread variable because PsIsSystemThread is a macro
  30. * that multiply resolves the parameter.
  31. */
  32. if (PsIsSystemThread(Thread)) {
  33. /*
  34. * Find the desktop that owns the section.
  35. */
  36. for (pwinsta = grpWinStaList; pwinsta; pwinsta = pwinsta->rpwinstaNext) {
  37. for (pdesk = pwinsta->rpdeskList; pdesk; pdesk = pdesk->rpdeskNext) {
  38. if (pdesk->pDeskInfo->pvDesktopBase == pBase)
  39. goto FoundIt;
  40. }
  41. }
  42. FoundIt:
  43. if (pwinsta == NULL) {
  44. RIPMSG3(RIP_ERROR, "UserCommitDesktopMemory failed: pBase %#p, ppCommit %#p, pCommitSize %d",
  45. pBase, ppCommit, *pCommitSize);
  46. return STATUS_NO_MEMORY;
  47. }
  48. /*
  49. * Map the section into the current process and commit the
  50. * first page of the section.
  51. */
  52. dwCommitOffset = (ULONG)((PBYTE)*ppCommit - (PBYTE)pBase);
  53. Status = CommitReadOnlyMemory(pdesk->hsectionDesktop, pCommitSize,
  54. dwCommitOffset, &dCommit);
  55. if (NT_SUCCESS(Status)) {
  56. *ppCommit = (PBYTE)*ppCommit + dCommit;
  57. }
  58. } else {
  59. /*
  60. * Find the current process' view of the desktop
  61. */
  62. for (pdv = PpiCurrent()->pdvList; pdv != NULL; pdv = pdv->pdvNext) {
  63. if (pdv->pdesk->pDeskInfo->pvDesktopBase == pBase)
  64. break;
  65. }
  66. /*
  67. * 254954: If we didn't find a desktop view then map the desktop view
  68. * to the current process.
  69. */
  70. if (pdv == NULL) {
  71. /*
  72. * Find the desktop that owns the section.
  73. */
  74. for (pwinsta = grpWinStaList; pwinsta; pwinsta = pwinsta->rpwinstaNext) {
  75. for (pdesk = pwinsta->rpdeskList; pdesk; pdesk = pdesk->rpdeskNext) {
  76. if (pdesk->pDeskInfo->pvDesktopBase == pBase)
  77. goto FoundTheDesktop;
  78. }
  79. }
  80. FoundTheDesktop:
  81. if (pwinsta == NULL) {
  82. RIPMSG3(RIP_ERROR, "UserCommitDesktopMemory failed: pBase %#p, ppCommit %#p, pCommitSize %d",
  83. pBase, ppCommit, *pCommitSize);
  84. return STATUS_NO_MEMORY;
  85. }
  86. UserAssert(pdesk != NULL);
  87. /*
  88. * Map the desktop into the current process
  89. */
  90. {
  91. WIN32_OPENMETHOD_PARAMETERS OpenParams;
  92. OpenParams.OpenReason = ObOpenHandle;
  93. OpenParams.Process = PsGetCurrentProcess();
  94. OpenParams.Object = pdesk;
  95. OpenParams.GrantedAccess = 0;
  96. OpenParams.HandleCount = 1;
  97. if (!NT_SUCCESS (MapDesktop(&OpenParams))) {
  98. RIPMSG2(RIP_WARNING, "UserCommitDesktopMemory: Could't map pdesk %#p in ppi %#p",
  99. pdesk, PpiCurrent());
  100. return STATUS_NO_MEMORY;
  101. }
  102. }
  103. pdv = GetDesktopView(PpiCurrent(), pdesk);
  104. if (pdv == NULL) {
  105. RIPMSG2(RIP_ERROR, "UserCommitDesktopMemory: GetDesktopView returns NULL for pdesk %#p in ppi %#p",
  106. pdesk, PpiCurrent());
  107. return STATUS_NO_MEMORY;
  108. }
  109. }
  110. /*
  111. * Commit the memory using the session view base so it doesn't matter
  112. * if the user destroys (and replaces) his usermode view.
  113. */
  114. Status = MmCommitSessionMappedView (*ppCommit, *pCommitSize);
  115. }
  116. return Status;
  117. }
  118. NTSTATUS UserCommitSharedMemory(
  119. PVOID pBase,
  120. PVOID *ppCommit,
  121. PSIZE_T pCommitSize)
  122. {
  123. ULONG_PTR ulClientDelta;
  124. DWORD dwCommitOffset;
  125. PBYTE pUserBase;
  126. NTSTATUS Status;
  127. PEPROCESS Process;
  128. int dCommit;
  129. PW32PROCESS pw32p;
  130. #if DBG
  131. if (pBase != Win32HeapGetHandle(gpvSharedAlloc)) {
  132. RIPMSG0(RIP_WARNING, "pBase != gpvSharedAlloc");
  133. }
  134. #else
  135. UNREFERENCED_PARAMETER(pBase);
  136. #endif
  137. Process = PsGetCurrentProcess();
  138. ValidateProcessSessionId(Process);
  139. pw32p = PsGetProcessWin32Process(Process);
  140. if (pw32p == NULL ||
  141. (((PPROCESSINFO)pw32p)->pClientBase == NULL)) {
  142. dwCommitOffset = (ULONG)((PBYTE)*ppCommit - (PBYTE)gpvSharedBase);
  143. Status = CommitReadOnlyMemory(
  144. ghSectionShared, pCommitSize, dwCommitOffset, &dCommit);
  145. if (NT_SUCCESS(Status)) {
  146. *ppCommit = (PBYTE) *ppCommit + dCommit;
  147. }
  148. } else {
  149. /*
  150. * Commit the memory
  151. */
  152. ulClientDelta = (ULONG_PTR)((PBYTE)gpvSharedBase - (PBYTE)(PpiCurrent()->pClientBase));
  153. pUserBase = (PVOID)((PBYTE)*ppCommit - ulClientDelta);
  154. Status = ZwAllocateVirtualMemory(
  155. NtCurrentProcess(),
  156. &pUserBase,
  157. 0,
  158. pCommitSize,
  159. MEM_COMMIT,
  160. PAGE_EXECUTE_READ);
  161. if (NT_SUCCESS(Status)) {
  162. *ppCommit = (PVOID)((PBYTE)pUserBase + ulClientDelta);
  163. }
  164. }
  165. return Status;
  166. }
  167. PWIN32HEAP UserCreateHeap(
  168. HANDLE hSection,
  169. ULONG ulViewOffset,
  170. PVOID pvBaseAddress,
  171. DWORD dwSize,
  172. PRTL_HEAP_COMMIT_ROUTINE pfnCommit)
  173. {
  174. PVOID pUserBase;
  175. SIZE_T ulViewSize;
  176. LARGE_INTEGER liOffset;
  177. PEPROCESS Process = PsGetCurrentProcess();
  178. RTL_HEAP_PARAMETERS HeapParams;
  179. NTSTATUS Status;
  180. ULONG HeapFlags;
  181. ULONG CommitSize;
  182. #if defined(_WIN64)
  183. CommitSize = 8192;
  184. #else
  185. CommitSize = 4096;
  186. #endif
  187. /*
  188. * Map the section into the current process and commit the
  189. * first page of the section.
  190. */
  191. ulViewSize = 0;
  192. liOffset.LowPart = ulViewOffset;
  193. liOffset.HighPart = 0;
  194. pUserBase = NULL;
  195. Status = MmMapViewOfSection(
  196. hSection,
  197. Process,
  198. &pUserBase,
  199. 0,
  200. CommitSize,
  201. &liOffset,
  202. &ulViewSize,
  203. ViewUnmap,
  204. SEC_NO_CHANGE,
  205. PAGE_EXECUTE_READ);
  206. if (!NT_SUCCESS(Status))
  207. return NULL;
  208. MmUnmapViewOfSection(Process, pUserBase);
  209. /*
  210. * We now have a committed page to create the heap in.
  211. */
  212. RtlZeroMemory(&HeapParams, sizeof(HeapParams));
  213. HeapParams.Length = sizeof(HeapParams);
  214. HeapParams.InitialCommit = CommitSize;
  215. HeapParams.InitialReserve = dwSize;
  216. HeapParams.CommitRoutine = pfnCommit;
  217. UserAssert(HeapParams.InitialCommit < dwSize);
  218. HeapFlags = HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY;
  219. #if DBG
  220. HeapFlags |= HEAP_TAIL_CHECKING_ENABLED;
  221. #endif // DBG
  222. return Win32HeapCreate("UH_HEAD",
  223. "UH_TAIL",
  224. HeapFlags,
  225. pvBaseAddress,
  226. dwSize,
  227. CommitSize,
  228. NULL,
  229. &HeapParams);
  230. }