windows-nt/Source/XPSP1/NT/com/rpc/runtime/mtrt/init.cxx

378 lines
8.6 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
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>
int RpcHasBeenInitialized = 0;
RTL_CRITICAL_SECTION GlobalMutex;
RPC_SERVER * GlobalRpcServer;
BOOL g_fClientSideDebugInfoEnabled = FALSE;
BOOL g_fServerSideDebugInfoEnabled = FALSE;
BOOL g_fSendEEInfo = 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
//
// 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;
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;
}
}
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.
--*/
{
if ( RpcHasBeenInitialized == 0 )
{
RequestGlobalMutex();
if ( RpcHasBeenInitialized == 0 )
{
RPC_STATUS Status;
BasicSystemInfo SystemInfo;
BOOL b;
b = GetBasicSystemInfo(&SystemInfo);
if (!b)
{
ClearGlobalMutex();
return RPC_S_OUT_OF_MEMORY;
}
gNumberOfProcessors = SystemInfo.m_dwNumberOfProcessors;
gPageSize = SystemInfo.m_dwPageSize;
gAllocationGranularity = SystemInfo.AllocationGranularity;
gfServerPlatform = SystemInfo.m_fServerPlatform;
gPhysicalMemorySize = SystemInfo.m_dwPhysicalMemorySize;
// Should be something like 64kb / 4kb.
ASSERT(gAllocationGranularity % gPageSize == 0);
if (( InitializeRpcAllocator() != 0)
|| ( InitializeServerDLL() != 0 ))
{
ClearGlobalMutex();
return(RPC_S_OUT_OF_MEMORY);
}
Status = InitializeEPMapperClient();
if (Status != RPC_S_OK)
{
ClearGlobalMutex();
return Status;
}
Status = ReadPolicySettings();
if (Status != RPC_S_OK)
{
ClearGlobalMutex();
return Status;
}
if (gfServerPlatform)
{
gThreadTimeout = 90*1000;
}
else
{
gThreadTimeout = 30*1000;
}
Status = InitializeCellHeap();
if (Status != RPC_S_OK)
{
ClearGlobalMutex();
return Status;
}
RpcHasBeenInitialized = 1;
ClearGlobalMutex();
if (LoadLibrary(RPC_CONST_SSTRING("rpcrt4.dll")) == 0)
{
return RPC_S_OUT_OF_MEMORY;
}
}
else
{
ClearGlobalMutex();
}
}
return(RPC_S_OK);
}
#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();
}