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.
 
 
 
 
 
 

879 lines
30 KiB

/*++
Copyright (C) Microsoft Corporation, 1991 - 1999
Module Name:
initnt.cxx
Abstract:
This module contains the code used to initialize the RPC runtime. One
routine gets called when a process attaches to the dll. Another routine
gets called the first time an RPC API is called.
Author:
Michael Montague (mikemon) 03-May-1991
Revision History:
Kamen Moutafov (KamenM) Dec 99 - Feb 2000 - Support for cell debugging stuff
--*/
#include <precomp.hxx>
#include <hndlsvr.hxx>
#include <thrdctx.hxx>
#include <rpccfg.h>
#include <rc4.h>
#include <randlib.h>
#include <epmap.h>
#include <CellHeap.hxx>
#include <lpcpack.hxx>
#include <dispatch.h>
#include <avrf.h>
int RpcHasBeenInitialized = 0;
RTL_CRITICAL_SECTION GlobalMutex;
RPC_SERVER * GlobalRpcServer = NULL;
BOOL g_fClientSideDebugInfoEnabled = FALSE;
BOOL g_fServerSideDebugInfoEnabled = FALSE;
BOOL g_fSendEEInfo = FALSE;
BOOL g_fIgnoreDelegationFailure = FALSE;
LRPC_SERVER *GlobalLrpcServer = NULL;
HINSTANCE hInstanceDLL ;
EXTERN_C HINSTANCE g_hRpcrt4;
DWORD gPageSize;
DWORD gThreadTimeout;
UINT gNumberOfProcessors;
DWORD gAllocationGranularity;
BOOL gfServerPlatform;
ULONGLONG gPhysicalMemorySize; // in megabytes
DWORD gProcessStartTime;
// The local machine's name.
RPC_CHAR *gLocalComputerName;
// The length of the name in TCHAR's including the terminating NULL.
DWORD gLocalComputerNameLength;
UNICODE_STRING *pBaseNameUnicodeString;
//
// RPC Verifier settings
//
BOOL gfAppVerifierEnabled = false;
BOOL gfPagedHeapEnabled = false;
BOOL gfRPCVerifierEnabled = false;
BOOL gfRpcVerifierCorruptionExpected = false;
// The basic rules for the RPC verifier settings are as follows:
//
// - If the app verifier is enabled RPC will do some basic checks.
// gfAppVerifierEnabled == true
// gfRPCVerifierEnabled == false
//
// - If the /rpc switch is enabled for the app verifier the RPC verifier
// will do extensive checks and will query for corruption injection settings.
// gfAppVerifierEnabled == true
// gfRPCVerifierEnabled == true
//
// - If paged heap is enabled the RPC verifier will be enabled and will do
// extensive checks silently. No breaks will occur, by default. We will also
// query for the corruption injection settings.
// gfPagedHeapEnabled == true;
// gfRPCVerifierEnabled == true;
// gfAppVerifierEnabled == false;
//
// In the other cases the RPC verifier code is inactive.
// The contents of the RpcVerifierFlags key of the image file options.
DWORD RpcVerifierFlags = 0x00000000;
// RPC verifier flag constants.
//
// These are written to RpcVerifierFlags key in the image file execution options
// in the registry. We query the flags on RPC initialization and set the global
// variables accordingly.
#define FLAG_FAULT_INJECT_IMPERSONATE_CLIENT 0x00000001
#define FLAG_CORRUPTION_INJECT_SERVER_RECEIVES 0x00000010
#define FLAG_CORRUPTION_INJECT_CLIENT_RECEIVES 0x00000020
#define FLAG_FAULT_INJECT_TRANSPORTS 0x00000100
#define FLAG_PAUSE_INJECT_EXTERNAL_APIS 0x00001000
#define FLAG_SUPRESS_APP_VERIFIER_BREAKS 0x00010000
#define FLAG_BCACHE_MODE_DIRECT 0x00020000
// The structure will be allocated and initialised with the RPC
// verifier settings whenever the RPC verifier is enabled.
tRpcVerifierSettings *pRpcVerifierSettings = NULL;
//
// By default the non pipe arguments cannot be more than 4 Megs
//
DWORD gMaxRpcSize = 0x400000;
DWORD gProrateStart = 0;
DWORD gProrateMax = 0;
DWORD gProrateFactor = 0;
void *g_rc4SafeCtx = 0;
BOOL gfRpcDisableVerifyOrUnsealAssert = FALSE;
extern "C" {
BOOLEAN
InitializeDLL (
IN HINSTANCE DllHandle,
IN ULONG Reason,
IN PCONTEXT Context OPTIONAL
)
/*++
Routine Description:
This routine will get called: when a process attaches to this dll, and
when a process detaches from this dll.
Return Value:
TRUE - Initialization successfully occurred.
FALSE - Insufficient memory is available for the process to attach to
this dll.
--*/
{
NTSTATUS NtStatus;
UNUSED(Context);
switch (Reason)
{
case DLL_PROCESS_ATTACH:
hInstanceDLL = DllHandle ;
g_hRpcrt4 = DllHandle;
GlobalMutex.DebugInfo = NULL;
NtStatus = RtlInitializeCriticalSectionAndSpinCount(&GlobalMutex, PREALLOCATE_EVENT_MASK);
if (NT_SUCCESS(NtStatus) == 0)
{
return(FALSE);
}
// initialize safe rc4 operations.
if(!rc4_safe_startup( &g_rc4SafeCtx ))
{
(void) RtlDeleteCriticalSection(&GlobalMutex);
return FALSE;
}
break;
case DLL_PROCESS_DETACH:
//
// If shutting down because of a FreeLibrary call, cleanup
//
if (Context == NULL)
{
ShutdownLrpcClient();
}
if (GlobalMutex.DebugInfo != NULL)
{
NtStatus = RtlDeleteCriticalSection(&GlobalMutex);
ASSERT(NT_SUCCESS(NtStatus));
}
if (g_rc4SafeCtx)
rc4_safe_shutdown( g_rc4SafeCtx ); // free safe rc4 resources.
break;
case DLL_THREAD_DETACH:
THREAD * Thread = RpcpGetThreadPointer();
#ifdef RPC_OLD_IO_PROTECTION
if (Thread)
{
Thread->UnprotectThread();
}
#else
delete Thread;
#endif
break;
}
return(TRUE);
}
} //extern "C" end
#ifdef NO_RECURSIVE_MUTEXES
unsigned int RecursionCount = 0;
#endif // NO_RECURSIVE_MUTEXES
extern int InitializeRpcAllocator(void);
extern RPC_STATUS ReadPolicySettings(void);
const ULONG MEGABYTE = 0x100000;
typedef struct tagBasicSystemInfo
{
DWORD m_dwPageSize;
ULONGLONG m_dwPhysicalMemorySize;
DWORD m_dwNumberOfProcessors;
ULONG AllocationGranularity;
BOOL m_fServerPlatform;
} BasicSystemInfo;
BOOL
GetBasicSystemInfo (
IN OUT BasicSystemInfo *basicSystemInfo
)
/*++
Routine Description:
Gets basic system information. We don't use the Win32 GetSystemInfo, because
under NT it accesses the image header, which may not be available if the image
was loaded from the network, and the network failed. Therefore, we need a function
that accesses just what we need, and nothing else.
Arguments:
The basic system info structure.
Return Value:
0 - failure
non-0 - success.
--*/
{
//
// Query system info (for # of processors) and product type
//
SYSTEM_BASIC_INFORMATION BasicInfo;
NTSTATUS Status;
BOOL b;
Status = NtQuerySystemInformation(
SystemBasicInformation,
&BasicInfo,
sizeof(BasicInfo),
NULL
);
if ( !NT_SUCCESS(Status) )
{
DbgPrintEx(DPFLTR_RPCPROXY_ID,
DPFLTR_ERROR_LEVEL,
"RPCTRANS: NtQuerySystemInformation failed: %x\n",
Status);
return 0;
}
basicSystemInfo->m_dwPageSize = BasicInfo.PageSize;
basicSystemInfo->m_dwNumberOfProcessors = BasicInfo.NumberOfProcessors;
basicSystemInfo->m_dwPhysicalMemorySize = ((BasicInfo.NumberOfPhysicalPages * (ULONGLONG) basicSystemInfo->m_dwPageSize) / MEGABYTE);
basicSystemInfo->AllocationGranularity = BasicInfo.AllocationGranularity;
NT_PRODUCT_TYPE type;
b = RtlGetNtProductType(&type);
if (b)
{
basicSystemInfo->m_fServerPlatform = (type != NtProductWinNt);
return 1;
}
else
{
DbgPrintEx(DPFLTR_RPCPROXY_ID,
DPFLTR_ERROR_LEVEL,
"RpcGetNtProductType failed, usign default\n");
return 0;
}
}
// Used in InitializeRpcVerifier
// The macro requires pBaseNameUnicodeString to be declared in order to function.
#define READ_DWORD_FROM_EXECUTION_OPTIONS(Key, Variable) \
{ \
LdrQueryImageFileExecutionOptions (pBaseNameUnicodeString, \
Key, \
REG_DWORD, \
&Variable, \
sizeof(Variable), \
NULL); \
}
// This is the global RPC heap where all allocations go to.
// If we are running with read-only RPC page heap then this
// will be a special heap created for us by Avrf rather then
// the process heap.
extern HANDLE hRpcHeap;
void
InitializeRpcVerifier (
void
)
/*++
Routine Description:
Performs initialization of the RPC verifier. Sets everything necessary for the basic
checks and extensive checks. Queries the image file options for custom
checks and enbales the selected ones
Arguments:
None
Return Value:
None - The only failure paths are registry IOs. We will just skip some checks on failures.
--*/
{
HMODULE hDll;
VERIFIER_QUERY_RUNTIME_FLAGS_FUNCTION VerifierQueryRuntimeFlags;
VERIFIER_CREATE_RPC_PAGE_HEAP_FUNCTION VerifierCreateRpcPageHeap;
DWORD dwTmp;
// Allocate the RPC verifier settings.
pRpcVerifierSettings = new tRpcVerifierSettings;
// If we could not allocate them, ignore the failure and return.
// We chose not to run with the RPC verifier rather then prevent the process
// from initializing.
if (pRpcVerifierSettings == NULL)
{
return;
}
//
// Set the RPC verifier settings to defaults.
//
// Fault injecting ImpersonateClient calls
pRpcVerifierSettings->fFaultInjectImpersonateClient = false;
pRpcVerifierSettings->ProbFaultInjectImpersonateClient = 100; // Default is 0.01
pRpcVerifierSettings->DelayFaultInjectImpersonateClient = 0; // Delay before fault injection starts is 0 sec.
// Corruption injecting the received data
pRpcVerifierSettings->fCorruptionInjectServerReceives = false;
pRpcVerifierSettings->fCorruptionInjectClientReceives = false;
pRpcVerifierSettings->ProbRpcHeaderCorruption = 100; // Default is 0.01
pRpcVerifierSettings->ProbDataCorruption = 100; // Default is 0.01
pRpcVerifierSettings->ProbSecureDataCorruption = 10; // Default is 0.001
pRpcVerifierSettings->CorruptionPattern = Randomize;
pRpcVerifierSettings->CorruptionSizeType = RandomSize;
pRpcVerifierSettings->CorruptionSize = 2;
pRpcVerifierSettings->CorruptionDistributionType = LocalizedDistribution;
pRpcVerifierSettings->ProbBufferTruncation = 0;
pRpcVerifierSettings->MaxBufferTruncationSize = 0x10;
// Fault injecting calls to transport routines
pRpcVerifierSettings->fFaultInjectTransports = false;
pRpcVerifierSettings->ProbFaultInjectTransports = 10; // Default is 0.001
// Inserting pauses after calls to external APIs
pRpcVerifierSettings->fPauseInjectExternalAPIs = false;
pRpcVerifierSettings->ProbPauseInjectExternalAPIs = 100; // Default is 0.01
pRpcVerifierSettings->PauseInjectExternalAPIsMaxWait = 10; // Default average delay is 10 milliseconds.
// By default all verifier breaks are active.
pRpcVerifierSettings->fSupressAppVerifierBreaks = false;
pRpcVerifierSettings->fReadonlyPagedHeap = false;
//
// Enable the basic checks.
//
// Catch orphaned critical sections on return from the server managed routines.
DispatchToStubInC = DispatchToStubInCAvrf;
//
// Check if the RPC verifier is enabled.
//
// When running under the app verifier we query it
// to see whether the RPC verifier is enabled.
if (gfAppVerifierEnabled)
{
// Try to load the app verifier dll.
hDll = LoadLibrary(RPC_CONST_SSTRING("verifier.dll"));
if (hDll != NULL)
{
// Try to import the function to query the app verifier flags.
VerifierQueryRuntimeFlags = (VERIFIER_QUERY_RUNTIME_FLAGS_FUNCTION)GetProcAddress(hDll, "VerifierQueryRuntimeFlags");
if (VerifierQueryRuntimeFlags != NULL)
{
LOGICAL fEnabled = FALSE;
ULONG Flags = 0;
// Query the app veirfier flags and see if the rpc switch is set.
NTSTATUS Status = VerifierQueryRuntimeFlags(&fEnabled, &Flags);
if ((Status == STATUS_SUCCESS) &&
(fEnabled) &&
(Flags & RTL_VRF_FLG_RPC_CHECKS))
{
gfRPCVerifierEnabled = true;
}
}
// Try to import the function to create a read-only paged heap.
VerifierCreateRpcPageHeap = (VERIFIER_CREATE_RPC_PAGE_HEAP_FUNCTION)GetProcAddress(hDll, "VerifierCreateRpcPageHeap");
FreeLibrary(hDll);
}
}
// If app verifier is not enabled we must be initializing because of paged heap.
else
{
ASSERT(gfPagedHeapEnabled);
gfRPCVerifierEnabled = true;
// When initializing under paged heap - disable verifier breaks.
pRpcVerifierSettings->fSupressAppVerifierBreaks = true;
}
//
// If the RPC Verifier is enabled load the settings from the image file options.
//
if (gfRPCVerifierEnabled)
{
DWORD PageHeapFaultProbability = 0;
//
// Enable the extensive checks.
//
// Use read-only paged heap if the app verifier and the RPC verifier are enabled.
// The trigger to use the read-only "RPC" paged heap is a reg key or
// the use of process-wide paged heap.
if (gfAppVerifierEnabled &&
gfPagedHeapEnabled)
{
// Try to create the read-only RPC heap.
if (VerifierCreateRpcPageHeap != NULL)
{
VERIFIER_DBG_PRINT_0("Creating RPC pahe heap with VerifierCreateRpcPageHeap\n");
PVOID pRpcPageHeap = VerifierCreateRpcPageHeap (
HEAP_GROWABLE
| HEAP_TAIL_CHECKING_ENABLED
| HEAP_FREE_CHECKING_ENABLED, // Flags
NULL, // HeapBase
16 * 1024 - 512, // ReserveSize
NULL, // CommitSize
NULL, // Lock
NULL); // PRTL_HEAP_PARAMETERS Parameters
VERIFIER_DBG_PRINT_1("VerifierCreateRpcPageHeap returned 0x%x\n", pRpcPageHeap);
if (pRpcPageHeap != NULL)
{
hRpcHeap = pRpcPageHeap;
pRpcVerifierSettings->fReadonlyPagedHeap = true;
// Set BCache to direct mode. Allocations will be done on the heap
// and will skip caching.
gBCacheMode = BCacheModeDirect;
}
}
}
// Extend the RPC log size.
// At this point the RPC allocator has been initialized and this resulted in the creation
// of the event log and the addition of some events. We will just re-allocate for simplicity.
// There are no threads in the RPC runtime and we are holding the global lock, so there
// are no races.
struct RPC_EVENT * TmpRpcEvents;
TmpRpcEvents = (struct RPC_EVENT *) HeapReAlloc(GetProcessHeap(),
0,
RpcEvents,
2*EventArrayLength*sizeof(RPC_EVENT));
// If reallocation has failed we will just keep the old log.
if (TmpRpcEvents != NULL)
{
RpcEvents = TmpRpcEvents;
EventArrayLength *= 2;
}
//
// Query and enable the custom checks.
//
// Query the image file execution options for the custom checks and their options.
READ_DWORD_FROM_EXECUTION_OPTIONS (L"RpcVerifierFlags",
RpcVerifierFlags);
// Set the global flags in accordance with the enabled checks.
if (RpcVerifierFlags & FLAG_FAULT_INJECT_IMPERSONATE_CLIENT)
pRpcVerifierSettings->fFaultInjectImpersonateClient = true;
if (RpcVerifierFlags & FLAG_CORRUPTION_INJECT_SERVER_RECEIVES)
{
pRpcVerifierSettings->fCorruptionInjectServerReceives = true;
// if we are corrupting receives, then corruption asserts
// are expected
gfRpcVerifierCorruptionExpected = true;
}
if (RpcVerifierFlags & FLAG_CORRUPTION_INJECT_CLIENT_RECEIVES)
{
pRpcVerifierSettings->fCorruptionInjectClientReceives = true;
// if we are corrupting receives, then corruption asserts
// are expected
gfRpcVerifierCorruptionExpected = true;
}
if (RpcVerifierFlags & FLAG_FAULT_INJECT_TRANSPORTS)
pRpcVerifierSettings->fFaultInjectTransports = true;
if (RpcVerifierFlags & FLAG_PAUSE_INJECT_EXTERNAL_APIS)
pRpcVerifierSettings->fPauseInjectExternalAPIs = true;
if (RpcVerifierFlags & FLAG_SUPRESS_APP_VERIFIER_BREAKS)
pRpcVerifierSettings->fSupressAppVerifierBreaks = true;
if (RpcVerifierFlags & FLAG_BCACHE_MODE_DIRECT)
gBCacheMode = BCacheModeDirect;
// Check if we should fault-inject ImpersonateClient calls.
// If paged heap is enabled with fault injection
// we should set ImpersonateClient to fail and use the paged heap settings
READ_DWORD_FROM_EXECUTION_OPTIONS (L"PageHeapFaultProbability",
PageHeapFaultProbability);
if (PageHeapFaultProbability)
{
pRpcVerifierSettings->fFaultInjectImpersonateClient = true;
pRpcVerifierSettings->ProbFaultInjectImpersonateClient = PageHeapFaultProbability;
READ_DWORD_FROM_EXECUTION_OPTIONS (L"PageHeapFaultTimeOut",
pRpcVerifierSettings->DelayFaultInjectImpersonateClient);
}
// Check to see if explicit setting are given in the registry.
// We will overwrite the paged heap settings with the explicit ones.
if (pRpcVerifierSettings->fFaultInjectImpersonateClient)
{
READ_DWORD_FROM_EXECUTION_OPTIONS (L"RpcVerifierProbFaultInjectImpersonateClient",
pRpcVerifierSettings->ProbFaultInjectImpersonateClient);
READ_DWORD_FROM_EXECUTION_OPTIONS (L"RpcVerifierDelayFaultInjectImpersonateClient",
pRpcVerifierSettings->DelayFaultInjectImpersonateClient);
}
// Check if we should corruption-inject server receives.
if (pRpcVerifierSettings->fCorruptionInjectServerReceives)
{
// If yes, then whack the server receive IOEventDispatchTable entries to point to
// Avrf routines for the server receives.
IOEventDispatchTable[ConnectionServerReceive] = ProcessConnectionServerReceivedEventAvrf;
IOEventDispatchTable[DatagramServerReceive] = ProcessDatagramServerReceiveEventAvrf;
IOEventDispatchTable[COMPLEX_T | CONNECTION | RECEIVE | SERVER] = ProcessComplexTReceiveAvrf;
}
// Check if we should corruption-inject client receives.
if (pRpcVerifierSettings->fCorruptionInjectClientReceives)
{
// If yes, then whack the client receive IOEventDispatchTable entries to point to
// Avrf routines for the client receives.
IOEventDispatchTable[ConnectionClientReceive] = ProcessConnectionClientReceiveEventAvrf;
IOEventDispatchTable[DatagramClientReceive] = ProcessDatagramClientReceiveEventAvrf;
IOEventDispatchTable[COMPLEX_T | CONNECTION | RECEIVE | CLIENT] = ProcessComplexTReceiveAvrf;
// The SyncSendRecv and SyncRecv members of the transport interfaces will
// be overwritten on transport load:
//
// TCP_TransportInterface: WS_SyncRecv->WS_SyncRecv_Avrf
// NMP_TransportInterface: NMP_SyncSendRecv->NMP_SyncSendRecv_Avrf, CO_SyncRecv->CO_SyncRecv_Avrf
// UDP_TransportInterface: DG_ReceivePacket->DG_ReceivePacket_Avrf;
// CDP_TransportInterface: DG_ReceivePacket->DG_ReceivePacket_Avrf;
//
// This will allow the corruption of sync client receives.
}
// If we are corruption-injecting, read the corruption settings from the registry.
if (pRpcVerifierSettings->fCorruptionInjectServerReceives ||
pRpcVerifierSettings->fCorruptionInjectClientReceives)
{
READ_DWORD_FROM_EXECUTION_OPTIONS (L"RpcVerifierProbRpcHeaderCorruption",
pRpcVerifierSettings->ProbRpcHeaderCorruption);
READ_DWORD_FROM_EXECUTION_OPTIONS (L"RpcVerifierProbDataCorruption",
pRpcVerifierSettings->ProbDataCorruption);
READ_DWORD_FROM_EXECUTION_OPTIONS (L"RpcVerifierProbSecureDataCorruption",
pRpcVerifierSettings->ProbSecureDataCorruption);
READ_DWORD_FROM_EXECUTION_OPTIONS (L"RpcVerifierCorruptionPattern",
pRpcVerifierSettings->CorruptionPattern);
ASSERT(pRpcVerifierSettings->CorruptionPattern == ZeroOut ||
pRpcVerifierSettings->CorruptionPattern == Negate ||
pRpcVerifierSettings->CorruptionPattern == BitFlip ||
pRpcVerifierSettings->CorruptionPattern == IncDec ||
pRpcVerifierSettings->CorruptionPattern == Randomize ||
pRpcVerifierSettings->CorruptionPattern == AllPatterns);
READ_DWORD_FROM_EXECUTION_OPTIONS (L"RpcVerifierCorruptionSizeType",
pRpcVerifierSettings->CorruptionSizeType);
ASSERT (pRpcVerifierSettings->CorruptionDistributionType == FixedSize ||
pRpcVerifierSettings->CorruptionDistributionType == RandomSize);
READ_DWORD_FROM_EXECUTION_OPTIONS (L"RpcVerifierCorruptionSize",
pRpcVerifierSettings->CorruptionSize);
READ_DWORD_FROM_EXECUTION_OPTIONS (L"RpcVerifierCorruptionDistributionType",
pRpcVerifierSettings->CorruptionDistributionType);
ASSERT(pRpcVerifierSettings->CorruptionDistributionType == LocalizedDistribution ||
pRpcVerifierSettings->CorruptionDistributionType == RandomizedDistribution);
READ_DWORD_FROM_EXECUTION_OPTIONS (L"RpcVerifierProbBufferTruncation",
pRpcVerifierSettings->ProbBufferTruncation);
READ_DWORD_FROM_EXECUTION_OPTIONS (L"RpcVerifierMaxBufferTruncationSize",
pRpcVerifierSettings->MaxBufferTruncationSize);
}
}
}
RPC_STATUS
PerformRpcInitialization (
void
)
/*++
Routine Description:
This routine will get called the first time that an RPC runtime API is
called. There is actually a race condition, which we prevent by grabbing
a mutex and then performing the initialization. We only want to
initialize once.
Return Value:
RPC_S_OK - This status code indicates that the runtime has been correctly
initialized and is ready to go.
RPC_S_OUT_OF_MEMORY - If initialization failed, it is most likely due to
insufficient memory being available.
--*/
{
RPC_STATUS Status = RPC_S_OK;
#if DBG
// Catch cases when this function is called recursively.
// This can lead to stack overflow in low-memory conditions.
static BOOL fInPerformRpcInitialization; // Initialized to FALSE.
#endif
if ( RpcHasBeenInitialized == 0 )
{
RequestGlobalMutex();
#if DBG
ASSERT(fInPerformRpcInitialization == FALSE);
fInPerformRpcInitialization = TRUE;
#endif
if ( RpcHasBeenInitialized == 0 )
{
BasicSystemInfo SystemInfo;
BOOL b;
// We need to make sure that from this point on RPC will not be
// unloaded. This requires a load library call to "lock" rpcrt4.dll in
// memory. If the dll is not locked then it may be unloaded as a dependency with
// active critical sections, etc.
if (LoadLibrary(RPC_CONST_SSTRING("rpcrt4.dll")) == 0)
{
Status = RPC_S_OUT_OF_MEMORY;
goto Cleanup;
}
b = GetBasicSystemInfo(&SystemInfo);
if (!b)
{
Status = RPC_S_OUT_OF_MEMORY;
goto Cleanup;
}
gNumberOfProcessors = SystemInfo.m_dwNumberOfProcessors;
gPageSize = SystemInfo.m_dwPageSize;
gAllocationGranularity = SystemInfo.AllocationGranularity;
gfServerPlatform = SystemInfo.m_fServerPlatform;
gPhysicalMemorySize = SystemInfo.m_dwPhysicalMemorySize;
gProcessStartTime = GetTickCount();
//
// We need to init the RPC allocator before doing any memory allocations.
//
// Should be something like 64kb / 4kb.
ASSERT(gAllocationGranularity % gPageSize == 0);
if (( InitializeRpcAllocator() != 0)
|| ( InitializeServerDLL() != 0 ))
{
Status = RPC_S_OUT_OF_MEMORY;
goto Cleanup;
}
// Allocate space for the computer name.
gLocalComputerName = new RPC_CHAR[MAX_COMPUTERNAME_LENGTH+1];
if (gLocalComputerName == NULL)
{
Status = RPC_S_OUT_OF_MEMORY;
goto Cleanup;
}
gLocalComputerNameLength = MAX_COMPUTERNAME_LENGTH+1;
b = GetComputerNameW(gLocalComputerName,
&gLocalComputerNameLength);
if (b != TRUE)
{
DWORD LastError = GetLastError();
if (LastError == ERROR_NOT_ENOUGH_MEMORY)
{
Status = RPC_S_OUT_OF_MEMORY;
}
else if ((LastError == ERROR_NOT_ENOUGH_QUOTA)
|| (LastError == ERROR_NO_SYSTEM_RESOURCES))
{
Status = RPC_S_OUT_OF_RESOURCES;
}
else if (LastError == ERROR_WRITE_PROTECT)
{
Status = RPC_S_ACCESS_DENIED;
}
else
{
ASSERT(0);
Status = RPC_S_OUT_OF_MEMORY;
}
goto Cleanup;
}
// GetComputerNameW returns in gLocalComputerNameLength the size of
// the computer name in TCHARs NOT including the terminating NULL.
// We define this length to include the NULL and need to increment it.
gLocalComputerNameLength++;
//
// Check for the app verifier settings.
//
gfAppVerifierEnabled = (NtCurrentPeb()->NtGlobalFlag & FLG_APPLICATION_VERIFIER) != 0;
gfPagedHeapEnabled = (NtCurrentPeb()->NtGlobalFlag & FLG_HEAP_PAGE_ALLOCS) != 0;
// Initialize the image base name to be used when querying the execution options.
pBaseNameUnicodeString = FastGetImageBaseNameUnicodeString();
// Initialize the RPC verifier if app verifier is enabled or paged heap is enabled.
if (gfAppVerifierEnabled
|| gfPagedHeapEnabled)
{
// The function does not fail.
// The worst thing that happens is we don't get some checks.
InitializeRpcVerifier();
}
Status = InitializeEPMapperClient();
if (Status != RPC_S_OK)
{
goto Cleanup;
}
Status = ReadPolicySettings();
if (Status != RPC_S_OK)
{
goto Cleanup;
}
if (gfServerPlatform)
{
gThreadTimeout = 90*1000;
}
else
{
gThreadTimeout = 30*1000;
}
Status = InitializeCellHeap();
if (Status != RPC_S_OK)
{
goto Cleanup;
}
RpcHasBeenInitialized = 1;
goto Cleanup;
}
else
{
goto Cleanup;
}
}
return(RPC_S_OK);
Cleanup:
#if DBG
ASSERT(fInPerformRpcInitialization == TRUE);
fInPerformRpcInitialization = FALSE;
#endif
GlobalMutexVerifyOwned();
ClearGlobalMutex();
return Status;
}
#ifdef DBG
long lGlobalMutexCount = 0;
#endif
void
GlobalMutexRequestExternal (
void
)
/*++
Routine Description:
Request the global mutex.
--*/
{
GlobalMutexRequest();
}
void
GlobalMutexClearExternal (
void
)
/*++
Routine Description:
Clear the global mutex.
--*/
{
GlobalMutexClear();
}