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

/****************************** Module Header ******************************\
* Module Name: heap.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* This module contains kernel-mode heap management code.
*
* History:
* 03-16-95 JimA Created.
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
NTSTATUS UserCommitDesktopMemory(
PVOID pBase,
PVOID *ppCommit,
PSIZE_T pCommitSize)
{
PDESKTOPVIEW pdv;
DWORD dwCommitOffset;
PWINDOWSTATION pwinsta;
PDESKTOP pdesk;
int dCommit;
NTSTATUS Status;
PETHREAD Thread = PsGetCurrentThread();
/*
* If this is a system thread, we have no view of the desktop
* and must map it in. Fortunately, this does not happen often.
*
* We use the Thread variable because PsIsSystemThread is a macro
* that multiply resolves the parameter.
*/
if (PsIsSystemThread(Thread)) {
/*
* Find the desktop that owns the section.
*/
for (pwinsta = grpWinStaList; pwinsta; pwinsta = pwinsta->rpwinstaNext) {
for (pdesk = pwinsta->rpdeskList; pdesk; pdesk = pdesk->rpdeskNext) {
if (pdesk->pDeskInfo->pvDesktopBase == pBase)
goto FoundIt;
}
}
FoundIt:
if (pwinsta == NULL) {
RIPMSG3(RIP_ERROR, "UserCommitDesktopMemory failed: pBase %#p, ppCommit %#p, pCommitSize %d",
pBase, ppCommit, *pCommitSize);
return STATUS_NO_MEMORY;
}
/*
* Map the section into the current process and commit the
* first page of the section.
*/
dwCommitOffset = (ULONG)((PBYTE)*ppCommit - (PBYTE)pBase);
Status = CommitReadOnlyMemory(pdesk->hsectionDesktop, pCommitSize,
dwCommitOffset, &dCommit);
if (NT_SUCCESS(Status)) {
*ppCommit = (PBYTE)*ppCommit + dCommit;
}
} else {
/*
* Find the current process' view of the desktop
*/
for (pdv = PpiCurrent()->pdvList; pdv != NULL; pdv = pdv->pdvNext) {
if (pdv->pdesk->pDeskInfo->pvDesktopBase == pBase)
break;
}
/*
* 254954: If we didn't find a desktop view then map the desktop view
* to the current process.
*/
if (pdv == NULL) {
/*
* Find the desktop that owns the section.
*/
for (pwinsta = grpWinStaList; pwinsta; pwinsta = pwinsta->rpwinstaNext) {
for (pdesk = pwinsta->rpdeskList; pdesk; pdesk = pdesk->rpdeskNext) {
if (pdesk->pDeskInfo->pvDesktopBase == pBase)
goto FoundTheDesktop;
}
}
FoundTheDesktop:
if (pwinsta == NULL) {
RIPMSG3(RIP_ERROR, "UserCommitDesktopMemory failed: pBase %#p, ppCommit %#p, pCommitSize %d",
pBase, ppCommit, *pCommitSize);
return STATUS_NO_MEMORY;
}
UserAssert(pdesk != NULL);
/*
* Map the desktop into the current process
*/
{
WIN32_OPENMETHOD_PARAMETERS OpenParams;
OpenParams.OpenReason = ObOpenHandle;
OpenParams.Process = PsGetCurrentProcess();
OpenParams.Object = pdesk;
OpenParams.GrantedAccess = 0;
OpenParams.HandleCount = 1;
if (!NT_SUCCESS (MapDesktop(&OpenParams))) {
RIPMSG2(RIP_WARNING, "UserCommitDesktopMemory: Could't map pdesk %#p in ppi %#p",
pdesk, PpiCurrent());
return STATUS_NO_MEMORY;
}
}
pdv = GetDesktopView(PpiCurrent(), pdesk);
if (pdv == NULL) {
RIPMSG2(RIP_ERROR, "UserCommitDesktopMemory: GetDesktopView returns NULL for pdesk %#p in ppi %#p",
pdesk, PpiCurrent());
return STATUS_NO_MEMORY;
}
}
/*
* Commit the memory using the session view base so it doesn't matter
* if the user destroys (and replaces) his usermode view.
*/
Status = MmCommitSessionMappedView (*ppCommit, *pCommitSize);
}
return Status;
}
NTSTATUS UserCommitSharedMemory(
PVOID pBase,
PVOID *ppCommit,
PSIZE_T pCommitSize)
{
ULONG_PTR ulClientDelta;
DWORD dwCommitOffset;
PBYTE pUserBase;
NTSTATUS Status;
PEPROCESS Process;
int dCommit;
PW32PROCESS pw32p;
#if DBG
if (pBase != Win32HeapGetHandle(gpvSharedAlloc)) {
RIPMSG0(RIP_WARNING, "pBase != gpvSharedAlloc");
}
#else
UNREFERENCED_PARAMETER(pBase);
#endif
Process = PsGetCurrentProcess();
ValidateProcessSessionId(Process);
pw32p = PsGetProcessWin32Process(Process);
if (pw32p == NULL ||
(((PPROCESSINFO)pw32p)->pClientBase == NULL)) {
dwCommitOffset = (ULONG)((PBYTE)*ppCommit - (PBYTE)gpvSharedBase);
Status = CommitReadOnlyMemory(
ghSectionShared, pCommitSize, dwCommitOffset, &dCommit);
if (NT_SUCCESS(Status)) {
*ppCommit = (PBYTE) *ppCommit + dCommit;
}
} else {
/*
* Commit the memory
*/
ulClientDelta = (ULONG_PTR)((PBYTE)gpvSharedBase - (PBYTE)(PpiCurrent()->pClientBase));
pUserBase = (PVOID)((PBYTE)*ppCommit - ulClientDelta);
Status = ZwAllocateVirtualMemory(
NtCurrentProcess(),
&pUserBase,
0,
pCommitSize,
MEM_COMMIT,
PAGE_EXECUTE_READ);
if (NT_SUCCESS(Status)) {
*ppCommit = (PVOID)((PBYTE)pUserBase + ulClientDelta);
}
}
return Status;
}
PWIN32HEAP UserCreateHeap(
HANDLE hSection,
ULONG ulViewOffset,
PVOID pvBaseAddress,
DWORD dwSize,
PRTL_HEAP_COMMIT_ROUTINE pfnCommit)
{
PVOID pUserBase;
SIZE_T ulViewSize;
LARGE_INTEGER liOffset;
PEPROCESS Process = PsGetCurrentProcess();
RTL_HEAP_PARAMETERS HeapParams;
NTSTATUS Status;
ULONG HeapFlags;
ULONG CommitSize;
#if defined(_WIN64)
CommitSize = 8192;
#else
CommitSize = 4096;
#endif
/*
* Map the section into the current process and commit the
* first page of the section.
*/
ulViewSize = 0;
liOffset.LowPart = ulViewOffset;
liOffset.HighPart = 0;
pUserBase = NULL;
Status = MmMapViewOfSection(
hSection,
Process,
&pUserBase,
0,
CommitSize,
&liOffset,
&ulViewSize,
ViewUnmap,
SEC_NO_CHANGE,
PAGE_EXECUTE_READ);
if (!NT_SUCCESS(Status))
return NULL;
MmUnmapViewOfSection(Process, pUserBase);
/*
* We now have a committed page to create the heap in.
*/
RtlZeroMemory(&HeapParams, sizeof(HeapParams));
HeapParams.Length = sizeof(HeapParams);
HeapParams.InitialCommit = CommitSize;
HeapParams.InitialReserve = dwSize;
HeapParams.CommitRoutine = pfnCommit;
UserAssert(HeapParams.InitialCommit < dwSize);
HeapFlags = HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY;
#if DBG
HeapFlags |= HEAP_TAIL_CHECKING_ENABLED;
#endif // DBG
return Win32HeapCreate("UH_HEAD",
"UH_TAIL",
HeapFlags,
pvBaseAddress,
dwSize,
CommitSize,
NULL,
&HeapParams);
}