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.
 
 
 
 
 
 

1078 lines
33 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
ObjEx.cxx
Abstract:
Main entry point for the object exporter service.
Author:
Mario Goertzel [MarioGo]
Revision History:
MarioGo 02-28-95 Bits 'n pieces
ronans 04-14-97 HTTP support
--*/
#include <or.hxx>
#include <mach.hxx>
#include <misc.hxx>
#include <ntlsa.h>
extern "C"
{
#define SECURITY_WIN32 // Used by sspi.h
#include <sspi.h> // EnumerateSecurityPackages
}
//
// Process globals - read-only except during init.
//
// MID of the string bindings for this machine.
MID gLocalMid = 0;
// Contains the buffer of protseq's to listen on from the registry
PWSTR gpwstrProtseqs = 0;
// Number of remote protseqs used by this process.
USHORT cMyProtseqs = 0;
// ProtseqIds of the remote protseqs used by this process.
USHORT *aMyProtseqs = 0;
BOOL g_fClientHttp = FALSE;
//
// Process globals - read-write
//
CSharedLock *gpServerLock = 0;
CSharedLock *gpClientLock = 0;
CSharedLock *gpProcessListLock = 0;
CSharedLock *gpIPCheckLock = 0;
CHashTable *gpServerOxidTable = 0;
CHashTable *gpClientOxidTable = 0;
CPList *gpClientOxidPList = 0;
CHashTable *gpServerOidTable = 0;
CServerOidPList *gpServerOidPList = 0;
CList *gpServerPinnedOidList = 0;
CHashTable *gpClientOidTable = 0;
CServerSetTable *gpServerSetTable = 0;
CHashTable *gpClientSetTable = 0;
CPList *gpClientSetPList = 0;
CHashTable *gpMidTable = 0;
CList *gpTokenList = 0;
DWORD gNextThreadID = 1;
HANDLE gLSAHandle;
PSID gSidService;
WCHAR *gpwszDefaultDomainName;
//+-------------------------------------------------------------------------
//
// Function: ComputeSecurity
//
// Synopsis: Looks up some registry keys and enumerates the security
// packages on this machine.
//
//--------------------------------------------------------------------------
// These variables hold values read out of the registry and cached.
// s_fEnableDCOM is false if DCOM is disabled. The others contain
// authentication information for legacy applications.
BOOL s_fCatchServerExceptions;
BOOL s_fBreakOnSilencedServerExceptions;
BOOL s_fEnableDCOM;
DWORD s_lAuthnLevel;
DWORD s_lImpLevel;
BOOL s_fMutualAuth;
BOOL s_fSecureRefs;
WCHAR *s_pLegacySecurity;
DWORD s_dwLegacySecurityLen; // cached length of s_pLegacySecurity
// ronans - s_fEnableDCOMHTTP is false if DCOMHTTP is disabled.
BOOL s_fEnableDCOMHTTP;
// s_sServerSvc is a list of security providers that OLE servers can use.
// s_aClientSvc is a list of security providers that OLE clients can use.
// The difference is that Chicago only supports the client side of some
// security providers and OLE servers must know how to determine the
// principal name for the provider. Clients get the principal name from
// the server.
DWORD s_cServerSvc = 0;
USHORT *s_aServerSvc = NULL;
DWORD s_cClientSvc = 0;
SECPKG *s_aClientSvc = NULL;
// The registry key for OLE's registry data.
HKEY s_hOle = NULL;
//+-------------------------------------------------------------------------
//
// Function: FindSvc
//
// Synopsis: Returns index of the specified authentication service or -1.
//
//--------------------------------------------------------------------------
DWORD FindSvc( USHORT AuthnSvc, USHORT *aAuthnSvc, DWORD cAuthnSvc )
{
DWORD i;
// Look for the id in the array.
for (i = 0; i < cAuthnSvc; i++)
if (aAuthnSvc[i] == AuthnSvc)
return i;
return -1;
}
//+-------------------------------------------------------------------------
//
// Function: FindSvc
//
// Synopsis: Returns index of the specified authentication service or -1.
//
//--------------------------------------------------------------------------
DWORD FindSvc( USHORT AuthnSvc, SECPKG *aAuthnSvc, DWORD cAuthnSvc )
{
DWORD i;
// Look for the id in the array.
for (i = 0; i < cAuthnSvc; i++)
if (aAuthnSvc[i].wId == AuthnSvc)
return i;
return -1;
}
//+-------------------------------------------------------------------------
//
// Function: ComputeSecurity
//
// Synopsis: Looks up some registry keys and enumerates the security
// packages on this machine.
//
//--------------------------------------------------------------------------
void ComputeSecurity()
{
SecPkgInfo *pAllPkg;
SecPkgInfo *pNext;
HRESULT hr;
DWORD i;
DWORD j;
DWORD lMaxLen;
HKEY hKey;
DWORD lType;
DWORD lData;
DWORD lDataSize;
WCHAR cBuffer[80];
WCHAR *pSecProt = cBuffer;
DWORD cServerSvc;
USHORT *aServerSvc = NULL;
DWORD cClientSvc;
SECPKG *aClientSvc = NULL;
BOOL fFiltered = FALSE;
// Get the list of security packages.
cClientSvc = 0;
cServerSvc = 0;
hr = EnumerateSecurityPackages( &lMaxLen, &pAllPkg );
if (hr == SEC_E_OK)
{
// Allocate memory for both service lists.
aServerSvc = (USHORT*)MIDL_user_allocate(sizeof(USHORT) * lMaxLen);
aClientSvc = (SECPKG*)MIDL_user_allocate(sizeof(SECPKG) * lMaxLen);
if (aServerSvc == NULL || aClientSvc == NULL)
{
hr = E_OUTOFMEMORY;
MIDL_user_free(aServerSvc);
MIDL_user_free(aClientSvc);
aServerSvc = NULL;
aClientSvc = NULL;
// if out-of-mem, don't keep going.
FreeContextBuffer(pAllPkg);
return;
}
else
{
ZeroMemory(aServerSvc, sizeof(USHORT) * lMaxLen);
ZeroMemory(aClientSvc, sizeof(SECPKG) * lMaxLen);
// Check all packages.
pNext = pAllPkg;
for (i = 0; i < lMaxLen; i++)
{
// Authentication services with RPC id SECPKG_ID_NONE (0xffff)
// won't work with RPC.
if (pNext->wRPCID != SECPKG_ID_NONE)
{
// Determine if clients can use the package but don't
// save duplicates.
if ((pNext->fCapabilities & SECPKG_FLAG_CONNECTION) &&
FindSvc(pNext->wRPCID, aClientSvc, cClientSvc) == -1)
{
// Copy rpcid
aClientSvc[cClientSvc].wId = pNext->wRPCID;
// Copy secpkg name if there is one
if (pNext->Name)
{
DWORD dwBufSize = (lstrlen(pNext->Name) + 1) * sizeof(WCHAR);
aClientSvc[cClientSvc].pName = (WCHAR*)MIDL_user_allocate(dwBufSize);
if (!aClientSvc[cClientSvc].pName)
{
// No mem. Clean up what we have, and return
FreeContextBuffer(pAllPkg);
CleanupClientServerSvcs(cClientSvc,
aClientSvc,
cServerSvc,
aServerSvc);
return;
}
lstrcpy(aClientSvc[cClientSvc].pName, pNext->Name);
}
cClientSvc++;
}
// Determine if servers can use the package but don't save dups.
if ( (pNext->fCapabilities & SECPKG_FLAG_CONNECTION) &&
~(pNext->fCapabilities & (SECPKG_FLAG_CLIENT_ONLY)) &&
FindSvc(pNext->wRPCID, aServerSvc, cServerSvc) == -1)
{
aServerSvc[cServerSvc++] = pNext->wRPCID;
}
}
pNext++;
}
}
FreeContextBuffer(pAllPkg);
pAllPkg = NULL;
}
// Sort and filter the security provider list by the security protocol value.
hr = RegOpenKeyEx( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\RPC",
NULL, KEY_QUERY_VALUE, &hKey );
if (hr == ERROR_SUCCESS)
{
// Query the value for DCOM Security
// Note: this key is undocumented and is meant only for use by the test team.
lDataSize = sizeof(cBuffer);
hr = RegQueryValueEx( hKey, L"DCOM Security", NULL, &lType,
(unsigned char *) pSecProt, &lDataSize );
// Retry with more space if necessary
if (hr == ERROR_MORE_DATA)
{
pSecProt = (WCHAR *) _alloca(lDataSize);
hr = RegQueryValueEx( hKey, L"DCOM Security", NULL, &lType,
(unsigned char *) pSecProt, &lDataSize );
}
if (hr == ERROR_SUCCESS && lType == REG_MULTI_SZ && lDataSize > 3)
{
fFiltered = TRUE;
// Save original list
DWORD cServerSvcPreFilter = cServerSvc;
USHORT *aServerSvcPreFilter = aServerSvc;
cServerSvc = 0;
aServerSvc = NULL;
// Allocate memory for server service list.
aServerSvc = (USHORT*)MIDL_user_allocate(sizeof(USHORT) * cServerSvcPreFilter);
if (!aServerSvc)
{
// No mem, cleanup and return
CleanupClientServerSvcs(cClientSvc,
aClientSvc,
cServerSvcPreFilter,
aServerSvcPreFilter);
return;
}
ZeroMemory(aServerSvc, sizeof(USHORT) * cServerSvcPreFilter);
// Fill in filtered list
while (*pSecProt != 0 && (cServerSvc < cServerSvcPreFilter))
{
i = _wtoi( pSecProt );
ASSERT(i <= USHRT_MAX); // this would be a test bug
if (FindSvc( (USHORT)i, aServerSvcPreFilter, (USHORT)cServerSvcPreFilter ) != -1)
aServerSvc[cServerSvc++] = (USHORT)i;
pSecProt += wcslen(pSecProt)+1;
}
// Cleanup old server svc list. Will save filtered list below on normal path
MIDL_user_free(aServerSvcPreFilter);
aServerSvcPreFilter = NULL;
cServerSvcPreFilter = 0;
}
// Close the key.
RegCloseKey( hKey );
}
// Find snego in the client list.
for (i = 0; i < cClientSvc; i++)
if (aClientSvc[i].wId == RPC_C_AUTHN_GSS_NEGOTIATE)
break;
// If snego exists and is not first, move it first.
if (i < cClientSvc && i != 0)
{
SECPKG sSwap = s_aClientSvc[i];
memmove( &aClientSvc[1], &aClientSvc[0], sizeof(SECPKG)*i );
aClientSvc[0] = sSwap;
}
// If there is no DCOM security value, move snego first in the server list.
if (!fFiltered)
{
// Find snego in the server list.
for (i = 0; i < cServerSvc; i++)
if (aServerSvc[i] == RPC_C_AUTHN_GSS_NEGOTIATE)
break;
// If snego exists and is not first, move it first.
if (i < cServerSvc && i != 0)
{
USHORT usSwap = aServerSvc[i];
memmove( &aServerSvc[1], &aServerSvc[0], sizeof(USHORT)*i );
aServerSvc[0] = usSwap;
}
}
// Save new client\server svc lists.
SetClientServerSvcs(cClientSvc, aClientSvc, cServerSvc, aServerSvc);
// Set all the security flags to their default values.
s_fEnableDCOM = FALSE;
s_fEnableDCOMHTTP = FALSE;
s_fCatchServerExceptions = TRUE;
s_fBreakOnSilencedServerExceptions = FALSE;
s_lAuthnLevel = RPC_C_AUTHN_LEVEL_CONNECT;
s_lImpLevel = RPC_C_IMP_LEVEL_IDENTIFY;
s_fMutualAuth = FALSE;
s_fSecureRefs = FALSE;
// Open the security key. s_hOle will only be non-NULL on the first pass
// thru this code, after that we keep it open forever.
if (s_hOle == NULL)
{
HKEY hOle = NULL;
hr = RegOpenKeyEx( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\OLE",
NULL, KEY_READ, &hOle );
if (hr != ERROR_SUCCESS)
return;
LPVOID pv = InterlockedCompareExchangePointer ( (void **) &s_hOle, (void *) hOle, NULL);
if ( pv != NULL )
{
RegCloseKey(hOle);
}
}
ASSERT(s_hOle);
// Query the value for EnableDCOM.
lDataSize = sizeof(lData );
hr = RegQueryValueEx( s_hOle, L"EnableDCOM", NULL, &lType,
(unsigned char *) &lData, &lDataSize );
if (hr == ERROR_SUCCESS && lType == REG_SZ && lDataSize != 0)
{
if (*((WCHAR *) &lData) == L'y' ||
*((WCHAR *) &lData) == L'Y')
s_fEnableDCOM = TRUE;
}
// ronans - Query the value for EnableDCOMHTTP.
lDataSize = sizeof(lData );
hr = RegQueryValueEx( s_hOle, L"EnableDCOMHTTP", NULL, &lType,
(unsigned char *) &lData, &lDataSize );
if (hr == ERROR_SUCCESS && lType == REG_SZ && lDataSize != 0)
{
if (*((WCHAR *) &lData) == L'y' ||
*((WCHAR *) &lData) == L'Y')
{
s_fEnableDCOMHTTP = TRUE;
KdPrintEx((DPFLTR_DCOMSS_ID,
DPFLTR_WARNING_LEVEL,
"OR: EnableDCOMHTTP set to TRUE\n"));
}
}
if (!s_fEnableDCOMHTTP)
{
KdPrintEx((DPFLTR_DCOMSS_ID,
DPFLTR_WARNING_LEVEL,
"OR: EnableDCOMHTTP set to FALSE\n"));
}
// Query the value for IgnoreServerExceptions. This value is just
// to let some ISVs debug their servers a little easier. In normal
// operation these exceptions should be caught.
lDataSize = sizeof(lData );
hr = RegQueryValueEx( s_hOle, L"IgnoreServerExceptions", NULL, &lType,
(unsigned char *) &lData, &lDataSize );
if (hr == ERROR_SUCCESS && lType == REG_SZ && lDataSize != 0)
{
if (*((WCHAR *) &lData) == L'y' ||
*((WCHAR *) &lData) == L'Y')
s_fCatchServerExceptions = FALSE;
}
// Allow ISVs to enable debugbreaks on all silenced exceptions if there's a debugger present
lDataSize = sizeof(lData );
hr = RegQueryValueEx( s_hOle, L"BreakOnSilencedServerExceptions", NULL, &lType,
(unsigned char *) &lData, &lDataSize );
if (hr == ERROR_SUCCESS && lType == REG_SZ && lDataSize != 0)
{
if (*((WCHAR *) &lData) == L'y' ||
*((WCHAR *) &lData) == L'Y')
s_fBreakOnSilencedServerExceptions = TRUE;
}
// Query the value for the legacy services. Note: this key is undocumented
// and is meant only for use by the test team.
lDataSize = 0;
hr = RegQueryValueEx( s_hOle, L"LegacyAuthenticationService", NULL,
&lType, NULL, &lDataSize );
if (hr == ERROR_SUCCESS && lType == REG_BINARY &&
lDataSize >= sizeof(SECURITYBINDING))
{
WCHAR* pNewLegacySecurity = (WCHAR*)MIDL_user_allocate(sizeof(BYTE) * lDataSize);
if (pNewLegacySecurity != NULL)
{
hr = RegQueryValueEx( s_hOle, L"LegacyAuthenticationService", NULL,
&lType, (unsigned char *) pNewLegacySecurity,
&lDataSize );
// Verify that the data is a security binding.
if (hr != ERROR_SUCCESS ||
lType != REG_BINARY ||
lDataSize < sizeof(SECURITYBINDING) ||
pNewLegacySecurity[1] != 0 ||
pNewLegacySecurity[(lDataSize >> 1) - 1] != 0)
{
MIDL_user_free(pNewLegacySecurity);
pNewLegacySecurity = NULL;
lDataSize = 0;
}
// Set it whether success or not. A misconfigured registry will cause
// us to set it back to NULL.
SetLegacySecurity(pNewLegacySecurity, lDataSize);
}
}
// Query the value for the authentication level.
lDataSize = sizeof(lData);
hr = RegQueryValueEx( s_hOle, L"LegacyAuthenticationLevel", NULL,
&lType, (unsigned char *) &lData, &lDataSize );
if (hr == ERROR_SUCCESS && lType == REG_DWORD)
{
s_lAuthnLevel = lData;
}
// Query the value for the impersonation level.
lDataSize = sizeof(lData);
hr = RegQueryValueEx( s_hOle, L"LegacyImpersonationLevel", NULL,
&lType, (unsigned char *) &lData, &lDataSize );
if (hr == ERROR_SUCCESS && lType == REG_DWORD)
{
s_lImpLevel = lData;
}
// Query the value for mutual authentication.
lDataSize = sizeof(lData);
hr = RegQueryValueEx( s_hOle, L"LegacyMutualAuthentication", NULL,
&lType, (unsigned char *) &lData, &lDataSize );
if (hr == ERROR_SUCCESS && lType == REG_SZ && lDataSize != 0)
{
if (*((WCHAR *) &lData) == L'y' ||
*((WCHAR *) &lData) == L'Y')
s_fMutualAuth = TRUE;
}
// Query the value for secure interface references.
lDataSize = sizeof(lData);
hr = RegQueryValueEx( s_hOle, L"LegacySecureReferences", NULL,
&lType, (unsigned char *) &lData, &lDataSize );
if (hr == ERROR_SUCCESS && lType == REG_SZ && lDataSize != 0)
{
if (*((WCHAR *) &lData) == L'y' ||
*((WCHAR *) &lData) == L'Y')
s_fSecureRefs = TRUE;
}
ASSERT(gpPingSetQuotaManager);
// Query the value for per-user pingset quota.
lDataSize = sizeof(lData);
hr = RegQueryValueEx( s_hOle, L"UserPingSetQuota", NULL,
&lType, (unsigned char *) &lData, &lDataSize );
if (hr == ERROR_SUCCESS && lType == REG_DWORD && lDataSize != 0)
{
gpPingSetQuotaManager->SetPerUserPingSetQuota(lData);
}
}
void
CleanupClientServerSvcs(
DWORD cClientSvcs,
SECPKG* aClientSvcs,
DWORD cServerSvcs, // unused
USHORT* aServerSvcs
)
{
DWORD i;
for (i = 0; i < cClientSvcs; i++)
{
if (aClientSvcs[i].pName)
{
MIDL_user_free(aClientSvcs[i].pName);
}
}
MIDL_user_free(aClientSvcs);
MIDL_user_free(aServerSvcs);
return;
}
void
SetClientServerSvcs(
DWORD cClientSvcs,
SECPKG* aClientSvcs,
DWORD cServerSvcs,
USHORT* aServerSvcs
)
/*++
Routine Description:
Saves the supplied client\server security svcs.
Return Value:
None
--*/
{
gpClientLock->LockExclusive();
// Cleanup the old ones
CleanupClientServerSvcs(s_cClientSvc, s_aClientSvc, s_cServerSvc, s_aServerSvc);
// Save the new ones
s_cClientSvc = cClientSvcs;
s_aClientSvc = aClientSvcs;
s_cServerSvc = cServerSvcs;
s_aServerSvc = aServerSvcs;
gpClientLock->UnlockExclusive();
return;
}
BOOL
GetClientServerSvcs(
DWORD* pcClientSvcs,
SECPKG** paClientSvcs,
DWORD* pcServerSvcs,
USHORT** paServerSvcs
)
/*++
Routine Description:
Saves the supplied client\server security svcs.
Return Value:
TRUE -- success
FALSE -- no mem
--*/
{
BOOL fReturn = FALSE;
SECPKG* aClientSvcs = NULL;
USHORT* aServerSvcs = NULL;
gpClientLock->LockShared();
*pcClientSvcs = 0;
*paClientSvcs = NULL;
*pcServerSvcs = 0;
*paServerSvcs = NULL;
aServerSvcs = (USHORT*)MIDL_user_allocate(sizeof(USHORT) * s_cServerSvc);
if (aServerSvcs)
{
// Copy server svcs
CopyMemory(aServerSvcs, s_aServerSvc, sizeof(USHORT) * s_cServerSvc);
aClientSvcs = (SECPKG*)MIDL_user_allocate(sizeof(SECPKG) * s_cClientSvc);
if (aClientSvcs)
{
DWORD i;
ZeroMemory(aClientSvcs, sizeof(SECPKG) * s_cClientSvc);
// Copy client svcs
for (i = 0; i < s_cClientSvc; i++)
{
// Copy the id
aClientSvcs[i].wId = s_aClientSvc[i].wId;
// Copy the name if it has one
if (s_aClientSvc[i].pName)
{
DWORD dwLen = lstrlen(s_aClientSvc[i].pName) + 1;
aClientSvcs[i].pName = (WCHAR*)MIDL_user_allocate(sizeof(WCHAR) * dwLen);
if (!aClientSvcs[i].pName)
{
// Cleanup what we have, then return
CleanupClientServerSvcs(s_cClientSvc,
aClientSvcs,
s_cServerSvc,
aServerSvcs);
break;
}
lstrcpy(aClientSvcs[i].pName, s_aClientSvc[i].pName);
}
}
if (i == s_cClientSvc)
{
// Success - caller will now own the memory
*pcClientSvcs = s_cClientSvc;
*paClientSvcs = aClientSvcs;
*pcServerSvcs = s_cServerSvc;
*paServerSvcs = aServerSvcs;
fReturn = TRUE;
}
}
else
{
MIDL_user_free(aServerSvcs);
}
}
gpClientLock->UnlockShared();
return fReturn;
}
BOOL
GetLegacySecurity(
WCHAR** ppszLegacySecurity
)
{
BOOL fRet = TRUE;
DWORD dwLen;
*ppszLegacySecurity = NULL;
gpClientLock->LockShared();
if (s_dwLegacySecurityLen)
{
*ppszLegacySecurity = (WCHAR*)MIDL_user_allocate(sizeof(BYTE) * s_dwLegacySecurityLen);
if (*ppszLegacySecurity)
{
CopyMemory(*ppszLegacySecurity, s_pLegacySecurity, sizeof(BYTE) * s_dwLegacySecurityLen);
fRet = TRUE;
}
else
fRet = FALSE;
}
gpClientLock->UnlockShared();
return fRet;
};
void
SetLegacySecurity(
WCHAR* pszLegacySecurity,
DWORD dwDataSize
)
{
gpClientLock->LockExclusive();
// Free the old one, save the new one
MIDL_user_free(s_pLegacySecurity);
s_pLegacySecurity = pszLegacySecurity;
// Cache the size of the new data
s_dwLegacySecurityLen = dwDataSize;
gpClientLock->UnlockExclusive();
return;
}
//
// Startup
//
static CONST PWSTR gpwstrProtocolsPath = L"Software\\Microsoft\\Rpc";
static CONST PWSTR gpwstrProtocolsValue = L"DCOM Protocols";
DWORD StartObjectExporter(
void
)
/*++
Routine Description:
Starts the object resolver service.
Arguments:
None
Return Value:
None
Notes: This function is a bit weak on cleanup code in case of errors. This
is because if this function fails for any reason, RPCSS will not
start. Usually this function will never fail since 1) we always
start at machine boot, when lots of memory is available; and 2) we
don't support stopping or restarting of RPCSS.
--*/
{
ORSTATUS status;
int i;
DWORD tid;
HANDLE hThread;
RPC_BINDING_VECTOR *pbv;
DWORD SidSize;
status = RtlInitializeCriticalSection(&gcsFastProcessLock);
if (!NT_SUCCESS(status))
return status;
status = RtlInitializeCriticalSection(&gcsTokenLock);
if (!NT_SUCCESS(status))
return status;
status = OR_OK;
// Allocate PingSet quota manager
gpPingSetQuotaManager = new CPingSetQuotaManager(status);
if ((status != OR_OK) || !gpPingSetQuotaManager)
{
delete gpPingSetQuotaManager;
gpPingSetQuotaManager = NULL;
return OR_NOMEM;
}
// Lookup security data.
ComputeSecurity();
UpdateState(SERVICE_START_PENDING);
// Allocate tables
// Assume 16 exporting processes/threads.
gpServerOxidTable = new CHashTable(status, DEBUG_MIN(16,4));
if (status != OR_OK)
{
delete gpServerOxidTable;
gpServerOxidTable = 0;
}
// Assume 11 exported OIDs per process/thread.
gpServerOidTable = new CHashTable(status, 11*(DEBUG_MIN(16,4)));
if (status != OR_OK)
{
delete gpServerOidTable;
gpServerOidTable = 0;
}
gpServerSetTable = new CServerSetTable(status);
if (status != OR_OK)
{
delete gpServerSetTable;
gpServerSetTable = 0;
}
// Assume < 16 imported OXIDs
gpClientOxidTable = new CHashTable(status, DEBUG_MIN(16,4));
if (status != OR_OK)
{
delete gpClientOxidTable;
gpClientOxidTable = 0;
}
// Assume an average of 4 imported object ids per imported oxid
gpClientOidTable = new CHashTable(status, 4*DEBUG_MIN(16,4));
if (status != OR_OK)
{
delete gpClientOidTable;
gpClientOidTable = 0;
}
// Assume <16 servers (remote machines) in use per client.
gpClientSetTable = new CHashTable(status, DEBUG_MIN(16,4));
if (status != OR_OK)
{
delete gpClientSetTable;
gpClientSetTable = 0;
}
gpMidTable = new CHashTable(status, DEBUG_MIN(16,2));
if (status != OR_OK)
{
delete gpMidTable;
gpMidTable = 0;
}
// Allocate lists
gpClientOxidPList = new CPList(status, BasePingInterval);
if (status != OR_OK)
{
delete gpClientOxidPList;
gpClientOxidPList = 0;
}
gpServerOidPList = new CServerOidPList(status);
if (status != OR_OK)
{
delete gpServerOidPList;
gpServerOidPList = 0;
}
gpClientSetPList = new CPList(status, BasePingInterval);
if (status != OR_OK)
{
delete gpClientSetPList;
gpClientSetPList = 0;
}
gpTokenList = new CList();
gpProcessList = new CBList(DEBUG_MIN(128,4));
gpServerPinnedOidList = new CList();
// Allocate RPC security callback manager
gpCRpcSecurityCallbackMgr = new CRpcSecurityCallbackManager(status);
if (status != OR_OK)
{
delete gpCRpcSecurityCallbackMgr;
gpCRpcSecurityCallbackMgr = NULL;
}
SidSize = SECURITY_MAX_SID_SIZE;
gSidService = LocalAlloc(LMEM_ZEROINIT, SidSize);
gpwszDefaultDomainName = (WCHAR*)LocalAlloc(LMEM_ZEROINIT, (DNLEN+1)*sizeof(WCHAR));
if ( status != OR_OK
|| !gpServerLock
|| !gpClientLock
|| !gpServerOxidTable
|| !gpClientOxidTable
|| !gpClientOxidPList
|| !gpServerOidTable
|| !gpServerOidPList
|| !gpClientOidTable
|| !gpMidTable
|| !gpServerSetTable
|| !gpClientSetTable
|| !gpClientSetPList
|| !gpTokenList
|| !gpProcessList
|| !gpServerPinnedOidList
|| !gSidService
|| !gpwszDefaultDomainName
|| !gpCRpcSecurityCallbackMgr
)
{
return(OR_NOMEM);
}
// Read protseqs from the registry
DWORD dwType;
DWORD dwLenBuffer = 118;
HKEY hKey;
status =
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
gpwstrProtocolsPath,
0,
KEY_READ,
&hKey);
ASSERT(gpwstrProtseqs == 0);
if (status == ERROR_SUCCESS)
{
do
{
delete gpwstrProtseqs;
gpwstrProtseqs = new WCHAR[(dwLenBuffer + 1 )/2];
if (gpwstrProtseqs)
{
status = RegQueryValueEx(hKey,
gpwstrProtocolsValue,
0,
&dwType,
(PBYTE)gpwstrProtseqs,
&dwLenBuffer
);
}
else
{
return(OR_NOMEM);
}
}
while (status == ERROR_MORE_DATA);
RegCloseKey(hKey);
}
if ( status != ERROR_SUCCESS
|| dwType != REG_MULTI_SZ )
{
KdPrintEx((DPFLTR_DCOMSS_ID,
DPFLTR_WARNING_LEVEL,
"OR: No protseqs configured\n"));
delete gpwstrProtseqs;
gpwstrProtseqs = 0;
}
// Always listen to local protocols
// If this fails, the service should fail.
status = UseProtseqIfNecessary(ID_LPC);
if (status != RPC_S_OK)
{
return(status);
}
UpdateState(SERVICE_START_PENDING);
// set g_fClientHttp to false initially
g_fClientHttp = FALSE;
// This fails during setup. If it fails, only remote secure activations
// will be affected so it is safe to ignore.
RegisterAuthInfoIfNecessary();
// Construct remote protseq id and compressed binding arrays.
status = StartListeningIfNecessary();
if (status != OR_OK)
{
return(status);
}
UpdateState(SERVICE_START_PENDING);
// Register OR server interfaces.
status = RpcServerRegisterIfEx(_ILocalObjectExporter_ServerIfHandle,
NULL,
NULL,
0,
RPC_C_LISTEN_MAX_CALLS_DEFAULT,
LocalInterfaceOnlySecCallback);
ASSERT(status == RPC_S_OK);
// IObjectExporter must be able to receive unauthenticated calls, hence
// we do not specify a security callback function.
status =
RpcServerRegisterIfEx(_IObjectExporter_ServerIfHandle,
NULL,
NULL,
0,
RPC_C_LISTEN_MAX_CALLS_DEFAULT,
NULL);
ASSERT(status == RPC_S_OK);
if (!CreateWellKnownSid(WinServiceSid, NULL, gSidService, &SidSize))
{
status = GetLastError();
}
return(status);
}
NTSTATUS ConnectToLsa()
{
NTSTATUS Status ;
STRING LogonProcess ;
ULONG Mode ;
RtlInitString( &LogonProcess, "DCOMSCM");
ASSERT(!gLSAHandle);
Status = LsaRegisterLogonProcess( &LogonProcess,
&gLSAHandle,
&Mode );
ASSERT(NT_SUCCESS(Status));
ASSERT(gLSAHandle);
return Status;
}
BOOL GetDefaultDomainName()
{
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS NtStatus;
INT Result;
DWORD err = 0;
LSA_HANDLE LsaPolicyHandle = NULL;
PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo = NULL;
PUNICODE_STRING pDomain;
ASSERT(gpwszDefaultDomainName);
InitializeObjectAttributes( &ObjectAttributes, // object attributes
NULL, // name
0L, // attributes
NULL, // root directory
NULL ); // security descriptor
NtStatus = LsaOpenPolicy( NULL, // system name
&ObjectAttributes, // object attributes
POLICY_EXECUTE, // access mask
&LsaPolicyHandle ); // policy handle
if( !NT_SUCCESS( NtStatus ) )
{
return(FALSE);
}
NtStatus = LsaQueryInformationPolicy( LsaPolicyHandle,
PolicyAccountDomainInformation,
(PVOID *) &DomainInfo );
LsaClose(LsaPolicyHandle);
if (!NT_SUCCESS(NtStatus))
{
return(FALSE);
}
CopyMemory( gpwszDefaultDomainName,
DomainInfo->DomainName.Buffer,
DomainInfo->DomainName.Length );
gpwszDefaultDomainName[DomainInfo->DomainName.Length / sizeof(WCHAR)] = L'\0';
LsaFreeMemory( (PVOID)DomainInfo );
return TRUE;
}