378 lines
8.6 KiB
C++
378 lines
8.6 KiB
C++
/*++
|
||
|
||
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();
|
||
}
|