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.
 
 
 
 
 
 

369 lines
8.7 KiB

/*++
Copyright (c) 1985 - 1999, Microsoft Corporation
Module Name:
w32init.c
Abstract:
This is the Win32 subsystem driver initializatiion module
Author:
Mark Lucovsky (markl) 31-Oct-1994
Revision History:
--*/
#include "ntosp.h"
#define DO_INLINE
#include "w32p.h"
#include "windef.h"
#include "wingdi.h"
#include "winerror.h"
#include "winddi.h"
#include "usergdi.h"
#include "w32err.h"
/*
* Globals declared and initialized in ntuser\kernel\init.c
*/
extern CONST ULONG W32ProcessSize;
extern CONST ULONG W32ProcessTag;
extern CONST ULONG W32ThreadSize;
extern CONST ULONG W32ThreadTag;
extern PFAST_MUTEX gpW32FastMutex;
__inline VOID
ReferenceW32Process(
IN PW32PROCESS pW32Process)
{
PEPROCESS pEProcess = pW32Process->Process;
UserAssert(pEProcess != NULL);
ObReferenceObject(pEProcess);
UserAssert(pW32Process->RefCount < MAXULONG);
InterlockedIncrement(&pW32Process->RefCount);
}
VOID
DereferenceW32Process(
IN PW32PROCESS pW32Process)
{
PEPROCESS pEProcess = pW32Process->Process;
/*
* Dereference the object. It'll get freed when ref count goes to zero.
*/
UserAssert(pW32Process->RefCount > 0);
if (InterlockedDecrement(&pW32Process->RefCount) == 0) {
UserDeleteW32Process(pW32Process);
}
/*
* Dereference the kernel object.
*/
UserAssert(pEProcess != NULL);
ObDereferenceObject(pEProcess);
}
VOID
LockW32Process(
IN PW32PROCESS pW32Process,
IN OUT PTL ptl)
{
PushW32ThreadLock(pW32Process, ptl, DereferenceW32Process);
if (pW32Process != NULL) {
ReferenceW32Process(pW32Process);
}
}
NTSTATUS
AllocateW32Process(
IN OUT PEPROCESS pEProcess)
{
NTSTATUS Status = STATUS_SUCCESS;
PW32PROCESS pW32Process;
KeEnterCriticalRegion();
ExAcquireFastMutexUnsafe(gpW32FastMutex);
/*
* Allocate the process object if we haven't already done so.
*/
if ((pW32Process = PsGetProcessWin32Process(pEProcess)) == NULL) {
pW32Process = Win32AllocPoolWithQuota(W32ProcessSize, W32ProcessTag);
if (pW32Process) {
RtlZeroMemory(pW32Process, W32ProcessSize);
pW32Process->Process = pEProcess;
Status = PsSetProcessWin32Process(pEProcess, pW32Process, NULL);
if (NT_SUCCESS(Status)) {
ReferenceW32Process(pW32Process);
} else {
NtCurrentTeb()->LastErrorValue = ERROR_ACCESS_DENIED;
Win32FreePool(pW32Process);
}
} else {
NtCurrentTeb()->LastErrorValue = ERROR_NOT_ENOUGH_MEMORY;
Status = STATUS_NO_MEMORY;
}
}
ExReleaseFastMutexUnsafe(gpW32FastMutex);
KeLeaveCriticalRegion();
return Status;
}
extern PEPROCESS gpepCSRSS;
__inline VOID
FreeW32Process(
IN OUT PW32PROCESS pW32Process)
{
ASSERT(pW32Process == W32GetCurrentProcess());
ASSERT(pW32Process != NULL);
/*
* Dereference the object. It'll get freed when ref count goes to zero.
*/
DereferenceW32Process(pW32Process);
}
NTSTATUS
W32pProcessCallout(
IN PEPROCESS Process,
IN BOOLEAN Initialize)
/*++
Routine Description:
This function is called whenever a Win32 process is created or deleted.
Creattion occurs when the calling process calls NtConvertToGuiThread.
Deletion occurs during PspExitthread processing for the last thread in
a process.
Arguments:
Process - Supplies the address of the W32PROCESS to initialize.
Initialize - Supplies a boolean value that is true if the process
is being created.
Return Value:
TBD
--*/
{
NTSTATUS Status;
PW32PROCESS pW32Process;
if (Initialize) {
Status = AllocateW32Process(Process);
if (!NT_SUCCESS(Status)) {
return Status;
}
pW32Process = (PW32PROCESS)PsGetProcessWin32Process(Process);
pW32Process->W32Pid = W32GetCurrentPID();
} else {
pW32Process = (PW32PROCESS)PsGetProcessWin32Process(Process);
}
TAGMSG3(DBGTAG_Callout,
"W32: Process Callout for W32P %#p EP %#p called for %s",
pW32Process,
Process,
Initialize ? "Creation" : "Deletion");
Status = xxxUserProcessCallout(pW32Process, Initialize);
if (Status == STATUS_ALREADY_WIN32) {
return Status;
}
/*
* Always call GDI at cleanup time. If GDI initialiatzion fails,
* call USER for cleanup.
*/
if (NT_SUCCESS(Status) || !Initialize) {
Status = GdiProcessCallout(pW32Process, Initialize);
if (!NT_SUCCESS(Status) && Initialize) {
xxxUserProcessCallout(pW32Process, FALSE);
}
}
/*
* If this is not an initialization or initialization failed, free the
* W32 process structure.
*/
if (!Initialize || !NT_SUCCESS(Status)) {
FreeW32Process(pW32Process);
}
return Status;
}
__inline VOID
ReferenceW32Thread(
IN PW32THREAD pW32Thread)
{
PETHREAD pEThread = pW32Thread->pEThread;
UserAssert(pEThread != NULL);
ObReferenceObject(pEThread);
UserAssert(pW32Thread->RefCount < MAXULONG);
InterlockedIncrement(&pW32Thread->RefCount);
}
VOID
DereferenceW32Thread(
IN PW32THREAD pW32Thread)
{
PETHREAD pEThread = pW32Thread->pEThread;
/*
* Dereference the object. It'll get freed when ref count goes to zero.
*/
UserAssert(pW32Thread->RefCount > 0);
if (InterlockedDecrement(&pW32Thread->RefCount) == 0) {
UserDeleteW32Thread(pW32Thread);
}
/*
* Dereference the kernel object.
*/
UserAssert(pEThread != NULL);
ObDereferenceObject(pEThread);
}
VOID
LockW32Thread(
IN PW32THREAD pW32Thread,
IN OUT PTL ptl)
{
PushW32ThreadLock(pW32Thread, ptl, DereferenceW32Thread);
if (pW32Thread != NULL) {
ReferenceW32Thread(pW32Thread);
}
}
VOID
LockExchangeW32Thread(
IN PW32THREAD pW32Thread,
IN OUT PTL ptl)
{
if (pW32Thread != NULL) {
ReferenceW32Thread(pW32Thread);
}
ExchangeW32ThreadLock(pW32Thread, ptl);
}
NTSTATUS
AllocateW32Thread(
IN OUT PETHREAD pEThread)
{
PW32THREAD pW32Thread;
UserAssert(pEThread == PsGetCurrentThread());
pW32Thread = Win32AllocPoolWithQuota(W32ThreadSize, W32ThreadTag);
if (pW32Thread) {
RtlZeroMemory(pW32Thread, W32ThreadSize);
pW32Thread->pEThread = pEThread;
PsSetThreadWin32Thread(pEThread, pW32Thread, NULL);
ReferenceW32Thread(pW32Thread);
return STATUS_SUCCESS;
}
return STATUS_NO_MEMORY;
}
VOID
CleanupW32ThreadLocks(
IN PW32THREAD pW32Thread)
{
PTL ptl;
while (ptl = pW32Thread->ptlW32) {
PopAndFreeW32ThreadLock(ptl);
}
}
NTSTATUS
W32pThreadCallout(
IN PETHREAD pEThread,
IN PSW32THREADCALLOUTTYPE CalloutType)
/*++
Routine Description:
This function is called whenever a Win32 Thread is initialized,
exited or deleted.
Initialization occurs when the calling thread calls NtConvertToGuiThread.
Exit occurs during PspExitthread processing and deletion during
PspThreadDelete processing.
Arguments:
Thread - Supplies the address of the ETHREAD object
CalloutType - Supplies the callout type
Return Value:
TBD
--*/
{
NTSTATUS Status;
TAGMSG2(DBGTAG_Callout,
"W32: Thread Callout for ETHREAD %x called for %s\n",
pEThread,
CalloutType == PsW32ThreadCalloutInitialize ? "Initialization" :
CalloutType == PsW32ThreadCalloutExit ? "Exit" : "Deletion");
TAGMSG2(DBGTAG_Callout,
" PID = %x TID = %x\n",
PsGetThreadProcessId(pEThread),
PsGetThreadId(pEThread));
if (CalloutType == PsW32ThreadCalloutInitialize) {
Status = AllocateW32Thread(pEThread);
if (!NT_SUCCESS(Status)) {
NtCurrentTeb()->LastErrorValue = ERROR_NOT_ENOUGH_MEMORY;
return Status;
}
}
/*
* If CalloutType == PsW32ThreadCalloutInitialize, assuming that:
* - GdiThreadCallout never fails.
* - If UserThreadCallout fails, there is no need to call
* GdiThreadCallout for clean up.
*/
GdiThreadCallout(pEThread, CalloutType);
Status = UserThreadCallout(pEThread, CalloutType);
if (CalloutType == PsW32ThreadCalloutExit || !NT_SUCCESS(Status)) {
FreeW32Thread(pEThread);
}
return Status;
}