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.
1159 lines
33 KiB
1159 lines
33 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1993.
|
|
//
|
|
// File: scmif.cxx
|
|
//
|
|
// Contents: Entry points for scm interface.
|
|
//
|
|
// Functions: StartObjectService
|
|
// SvcActivateObject
|
|
// SvcCreateActivateObject
|
|
// ObjectServerStarted
|
|
// StopServer
|
|
//
|
|
// History: 01-May-93 Ricksa Created
|
|
// 31-Dec-93 ErikGav Chicago port
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "act.hxx"
|
|
|
|
extern void UpdateCOMPlusEnabled();
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: Dummy1
|
|
//
|
|
// Synopsis: Needed for IDL hack. Never called.
|
|
//
|
|
// Arguments: [hRpc] - RPC handle
|
|
// [orpcthis] - ORPC handle
|
|
// [localthis] - ORPC call data
|
|
// [orpcthat] - ORPC reply data
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// History: 14 Apr 95 AlexMit Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
extern "C" HRESULT DummyQueryInterfaceIOSCM(
|
|
handle_t hRpc,
|
|
ORPCTHIS *orpcthis,
|
|
LOCALTHIS *localthis,
|
|
ORPCTHAT *orpcthat,
|
|
DWORD dummy )
|
|
{
|
|
CairoleDebugOut((DEB_ERROR, "SCM Dummy function should never be called!\n" ));
|
|
orpcthat->flags = 0;
|
|
orpcthat->extensions = NULL;
|
|
return E_FAIL;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: Dummy2
|
|
//
|
|
// Synopsis: Needed for IDL hack. Never called.
|
|
//
|
|
// Arguments: [hRpc] - RPC handle
|
|
// [orpcthis] - ORPC handle
|
|
// [localthis] - ORPC call data
|
|
// [orpcthat] - ORPC reply data
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// History: 14 Apr 95 AlexMit Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
extern "C" HRESULT DummyAddRefIOSCM(
|
|
handle_t hRpc,
|
|
ORPCTHIS *orpcthis,
|
|
LOCALTHIS *localthis,
|
|
ORPCTHAT *orpcthat,
|
|
DWORD dummy )
|
|
{
|
|
CairoleDebugOut((DEB_ERROR, "SCM Dummy function should never be called!\n" ));
|
|
orpcthat->flags = 0;
|
|
orpcthat->extensions = NULL;
|
|
return E_FAIL;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: Dummy3
|
|
//
|
|
// Synopsis: Needed for IDL hack. Never called.
|
|
//
|
|
// Arguments: [hRpc] - RPC handle
|
|
// [orpcthis] - ORPC handle
|
|
// [localthis] - ORPC call data
|
|
// [orpcthat] - ORPC reply data
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// History: 14 Apr 95 AlexMit Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
extern "C" HRESULT DummyReleaseIOSCM(
|
|
handle_t hRpc,
|
|
ORPCTHIS *orpcthis,
|
|
LOCALTHIS *localthis,
|
|
ORPCTHAT *orpcthat,
|
|
DWORD dummy )
|
|
{
|
|
CairoleDebugOut((DEB_ERROR, "SCM Dummy function should never be called!\n" ));
|
|
orpcthat->flags = 0;
|
|
orpcthat->extensions = NULL;
|
|
return E_FAIL;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: ServerRegisterClsid
|
|
//
|
|
// Synopsis: Notifies SCM that server is started for a class
|
|
//
|
|
// Arguments: [hRpc] - RPC handle
|
|
// [phProcess] - context handle
|
|
// [lpDeskTop] - caller's desktop
|
|
// [pregin] - array of registration entries
|
|
// [ppregout] - array of registration cookies to return
|
|
// [rpcstat] - status code
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// History: 01-May-93 Ricksa Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
extern "C" HRESULT ServerRegisterClsid(
|
|
handle_t hRpc,
|
|
PHPROCESS phProcess,
|
|
RegInput *pregin,
|
|
RegOutput **ppregout,
|
|
error_status_t *prpcstat)
|
|
{
|
|
RegOutput* pregout;
|
|
CServerTableEntry* pClassTableEntry;
|
|
CClsidData* pClsidData = NULL;
|
|
DWORD Size, Entries, i;
|
|
UCHAR ServerState;
|
|
LONG Status;
|
|
HRESULT hr = S_OK;
|
|
CNamedObject** pRegisterEvents = NULL;
|
|
|
|
// Parameter validation
|
|
if (!prpcstat || !pregin || !ppregout)
|
|
return E_INVALIDARG;
|
|
|
|
*prpcstat = 0;
|
|
*ppregout = NULL;
|
|
|
|
CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
|
|
if (!pProcess)
|
|
return E_ACCESSDENIED;
|
|
|
|
// Allocate an array of handles to hold the register events.
|
|
pRegisterEvents = (CNamedObject**)alloca(sizeof(CNamedObject*) * pregin->dwSize);
|
|
memset(pRegisterEvents, 0, sizeof(CNamedObject*) * pregin->dwSize);
|
|
|
|
Size = sizeof(RegOutput) + (pregin->dwSize - 1) * sizeof(DWORD);
|
|
*ppregout = (RegOutput *) PrivMemAlloc(Size);
|
|
if (!(*ppregout))
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
pregout = *ppregout;
|
|
memset( pregout, 0, Size );
|
|
pregout->dwSize = pregin->dwSize;
|
|
|
|
Entries = pregin->dwSize;
|
|
|
|
//
|
|
// First loop, we add all of the registrations.
|
|
//
|
|
for ( i = 0; i < Entries; i++ )
|
|
{
|
|
pClsidData = 0;
|
|
|
|
// This path taken by non-COM+ servers, ergo
|
|
// no IComClassinfo
|
|
(void) LookupClsidData(
|
|
pregin->rginent[i].clsid,
|
|
NULL,
|
|
pProcess->GetToken(),
|
|
LOAD_APPID,
|
|
&pClsidData );
|
|
|
|
//
|
|
// Check that the caller is allowed to register this CLSID.
|
|
//
|
|
if ( pClsidData && ! pClsidData->CertifyServer( pProcess ) )
|
|
{
|
|
delete pClsidData;
|
|
hr = CO_E_WRONG_SERVER_IDENTITY;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get the register event for this clsid, to be signalled later on
|
|
// in the second loop below. If we couldn't find a pClsidData for
|
|
// this clsid, that's fine it just means it was a registration for
|
|
// an unknown clsid (which is legal).
|
|
//
|
|
if (pClsidData)
|
|
{
|
|
pRegisterEvents[i] = pClsidData->ServerRegisterEvent();
|
|
if (!pRegisterEvents[i])
|
|
{
|
|
delete pClsidData;
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ServerState = SERVERSTATE_SUSPENDED;
|
|
|
|
// Note: REGCLS_SINGLEUSE is *not* a bitflag, it's zero!
|
|
// Therefore, it is incompatible with all other flags
|
|
if ( pregin->rginent[i].dwFlags == REGCLS_SINGLEUSE )
|
|
ServerState |= SERVERSTATE_SINGLEUSE;
|
|
|
|
if ( pregin->rginent[i].dwFlags & REGCLS_SURROGATE )
|
|
ServerState |= SERVERSTATE_SURROGATE;
|
|
|
|
pClassTableEntry = gpClassTable->GetOrCreate( pregin->rginent[i].clsid );
|
|
|
|
if ( ! pClassTableEntry )
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
if ( pClassTableEntry )
|
|
{
|
|
hr = pClassTableEntry->RegisterServer(
|
|
pProcess,
|
|
pregin->rginent[i].ipid,
|
|
pClsidData,
|
|
NULL,
|
|
ServerState,
|
|
&pregout->RegKeys[i] );
|
|
|
|
pClassTableEntry->Release();
|
|
}
|
|
|
|
if ( pClsidData )
|
|
{
|
|
delete pClsidData;
|
|
pClsidData = NULL;
|
|
}
|
|
|
|
if ( hr != S_OK )
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If we encountered any errors then we remove any entries which were
|
|
// successfully added.
|
|
//
|
|
// On success, we now signal all of the class table events.
|
|
//
|
|
// This loop restarts itself in removal mode if it encounters an errors
|
|
// while trying to signal the register events.
|
|
//
|
|
for ( i = 0; i < Entries; i++ )
|
|
{
|
|
pClassTableEntry = gpClassTable->Lookup( pregin->rginent[i].clsid );
|
|
|
|
if ( S_OK == hr )
|
|
{
|
|
ASSERT( pClassTableEntry );
|
|
|
|
pClassTableEntry->UnsuspendServer( pregout->RegKeys[i] );
|
|
|
|
//
|
|
// Signal to waiting client (if any) that this clsid is registered
|
|
//
|
|
if (pRegisterEvents[i])
|
|
{
|
|
SetEvent(pRegisterEvents[i]->Handle());
|
|
pRegisterEvents[i]->Release();
|
|
pRegisterEvents[i] = NULL;
|
|
}
|
|
}
|
|
|
|
if ( (hr != S_OK) && pregout->RegKeys[i] )
|
|
{
|
|
if ( pClassTableEntry )
|
|
pClassTableEntry->RevokeServer( pProcess, pregout->RegKeys[i] );
|
|
}
|
|
|
|
if ( pClassTableEntry )
|
|
pClassTableEntry->Release();
|
|
}
|
|
|
|
if ( hr != S_OK )
|
|
memset( pregout->RegKeys, 0, pregout->dwSize * sizeof(DWORD) );
|
|
|
|
//
|
|
// Release all of the registration event handles
|
|
//
|
|
for (i = 0; i < Entries; i++)
|
|
{
|
|
if (pRegisterEvents[i])
|
|
{
|
|
pRegisterEvents[i]->Release();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: ServerRevokeClsid
|
|
//
|
|
// Synopsis: Get notification that class server is stopping
|
|
//
|
|
// Arguments: [hRpc] - RPC handle
|
|
// [prevcls] - list of classes/registrations to stop
|
|
//
|
|
// History: 01-May-93 Ricksa Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
extern "C" void ServerRevokeClsid(
|
|
handle_t hRpc,
|
|
PHPROCESS phProcess,
|
|
RevokeClasses *prevcls,
|
|
error_status_t *prpcstat)
|
|
{
|
|
CServerTableEntry* pClassTableEntry;
|
|
RevokeEntry* prevent;
|
|
DWORD Entries;
|
|
|
|
// Parameter validation
|
|
if (!prpcstat || !prevcls)
|
|
return; // E_INVALIDARG
|
|
|
|
*prpcstat = 0;
|
|
|
|
CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
|
|
if (!pProcess)
|
|
return; // E_ACCESSDENIED
|
|
|
|
Entries = prevcls->dwSize;
|
|
prevent = prevcls->revent;
|
|
|
|
for ( ; Entries--; prevent++ )
|
|
{
|
|
pClassTableEntry = gpClassTable->Lookup( prevent->clsid );
|
|
if ( pClassTableEntry )
|
|
{
|
|
pClassTableEntry->RevokeServer( pProcess, prevent->dwReg );
|
|
pClassTableEntry->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
void GetThreadID(
|
|
handle_t hRpc,
|
|
PHPROCESS phProcess,
|
|
DWORD * pThreadID,
|
|
error_status_t *prpcstat)
|
|
{
|
|
if (!CheckLocalSecurity(hRpc, phProcess))
|
|
RpcRaiseException(ERROR_ACCESS_DENIED);
|
|
|
|
// Parameter validation
|
|
if (!pThreadID || !prpcstat)
|
|
return;
|
|
|
|
*prpcstat = 0;
|
|
*pThreadID = InterlockedExchangeAdd((long *)&gNextThreadID,1);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: UpdateActivationSettings
|
|
//
|
|
// Synopsis: Re-read default activation settings.
|
|
//
|
|
// Arguments: [hRpc] - RPC handle
|
|
// [prpcstat] - communication status
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
extern void ComputeSecurity();
|
|
|
|
extern "C" void UpdateActivationSettings(
|
|
handle_t hRpc,
|
|
PHPROCESS phProcess,
|
|
error_status_t *prpcstat)
|
|
{
|
|
if (!CheckLocalSecurity(hRpc, phProcess))
|
|
RpcRaiseException(ERROR_ACCESS_DENIED);
|
|
|
|
// Parameter validation
|
|
if (!prpcstat)
|
|
return;
|
|
|
|
*prpcstat = 0;
|
|
|
|
ReadRemoteActivationKeys();
|
|
ComputeSecurity();
|
|
UpdateCOMPlusEnabled();
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: VerifyCallerIsAdministrator
|
|
//
|
|
// Synopsis: Verifies that the specified user is an administrator
|
|
//
|
|
// Returns: S_OK -- success, *pbAdmin is valid
|
|
// other -- error occurred
|
|
//
|
|
// Arguments: [pToken] - token of the user
|
|
// [pbAdmin] - out param denoting admin status
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
HRESULT VerifyCallerIsAdministrator(CToken* pToken, BOOL* pbAdmin)
|
|
{
|
|
BOOL fSuccess;
|
|
PSID psidAdmin;
|
|
SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
|
|
|
|
// Allocate sid for Administrators
|
|
fSuccess = AllocateAndInitializeSid(&SystemSidAuthority, 2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0, 0, 0, 0, 0, 0, &psidAdmin);
|
|
if (!fSuccess)
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
// Check that caller is an admin
|
|
fSuccess = CheckTokenMembership(pToken->GetToken(), psidAdmin, pbAdmin);
|
|
|
|
FreeSid(psidAdmin);
|
|
|
|
if (!fSuccess)
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: EnableDisableDynamicIPTracking
|
|
//
|
|
// Synopsis: Writes a "Y" or "N" to the HKLM\Software\MS\Ole\
|
|
// EnableSystemDynamicIPTracking string value, and sets the
|
|
// global variable gbDynamicIPChangesEnabled accordingly.
|
|
//
|
|
// Arguments: [hRpc] - RPC handle
|
|
// [phProcess] - context handle
|
|
// [fEnable] - whether to enable or disable
|
|
// [prpcstat] - communication status
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
extern "C"
|
|
HRESULT EnableDisableDynamicIPTracking(
|
|
handle_t hRpc,
|
|
PHPROCESS phProcess,
|
|
BOOL fEnable,
|
|
error_status_t* prpcstat)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bAdmin;
|
|
ORSTATUS status;
|
|
|
|
// Parameter validation
|
|
if (!prpcstat)
|
|
return E_INVALIDARG;
|
|
|
|
*prpcstat = 0; // we got here so we are OK
|
|
|
|
CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
|
|
if (!pProcess)
|
|
return E_ACCESSDENIED;
|
|
|
|
// Get token for the caller
|
|
CToken* pToken;
|
|
status = LookupOrCreateTokenForRPCClient(hRpc, FALSE, &pToken, NULL);
|
|
if (status != ERROR_SUCCESS)
|
|
return E_ACCESSDENIED;
|
|
|
|
hr = VerifyCallerIsAdministrator(pToken, &bAdmin);
|
|
pToken->Release();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
if (!bAdmin)
|
|
return E_ACCESSDENIED;
|
|
|
|
SCMVDATEHEAP();
|
|
|
|
hr = gAddrExclusionMgr.EnableDisableDynamicTracking(fEnable);
|
|
|
|
SCMVDATEHEAP();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: GetCurrentIPExclusionList
|
|
//
|
|
// Synopsis: Passes the contents of the current address exclusion list
|
|
// back to the caller
|
|
//
|
|
// Arguments: [hRpc] - RPC handle
|
|
// [phProcess] - context handle
|
|
// [pdwNumStrings] - size of the pppszStrings array
|
|
// [pppszStrings] - array of pointers to NULL-term'd strings
|
|
// [prpcstat] - communication status
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
extern "C"
|
|
HRESULT GetCurrentAddrExclusionList(
|
|
handle_t hRpc,
|
|
PHPROCESS phProcess,
|
|
DWORD* pdwNumStrings,
|
|
LPWSTR** pppszStrings,
|
|
error_status_t* prpcstat)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bAdmin;
|
|
ORSTATUS status;
|
|
|
|
// Parameter validation
|
|
if (!prpcstat || !pppszStrings || !pppszStrings)
|
|
return E_INVALIDARG;
|
|
|
|
*prpcstat = 0; // we got here so we are OK
|
|
|
|
CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
|
|
if (!pProcess)
|
|
return E_ACCESSDENIED;
|
|
|
|
// Get token for the caller
|
|
CToken* pToken;
|
|
status = LookupOrCreateTokenForRPCClient(hRpc, FALSE, &pToken, NULL);
|
|
if (status != ERROR_SUCCESS)
|
|
return E_ACCESSDENIED;
|
|
|
|
hr = VerifyCallerIsAdministrator(pToken, &bAdmin);
|
|
pToken->Release();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
if (!bAdmin)
|
|
return E_ACCESSDENIED;
|
|
|
|
SCMVDATEHEAP();
|
|
|
|
hr = gAddrExclusionMgr.GetExclusionList(
|
|
pdwNumStrings,
|
|
pppszStrings);
|
|
|
|
SCMVDATEHEAP();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SetAddrExclusionList
|
|
//
|
|
// Synopsis: Re-sets the contents of the address exclusion list, and updates
|
|
// all currently running processes with the new bindings.
|
|
//
|
|
// Arguments: [hRpc] - RPC handle
|
|
// [phProcess] - context handle
|
|
// [dwNumStrings] - size of the ppszStrings array
|
|
// [ppszStrings] - array of pointers to NULL-term'd strings
|
|
// [prpcstat] - communication status
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
extern "C"
|
|
HRESULT SetAddrExclusionList(
|
|
handle_t hRpc,
|
|
PHPROCESS phProcess,
|
|
DWORD dwNumStrings,
|
|
LPWSTR* ppszStrings,
|
|
error_status_t* prpcstat)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bAdmin;
|
|
ORSTATUS status;
|
|
|
|
// Parameter validation
|
|
if (!ppszStrings || !prpcstat)
|
|
return E_INVALIDARG;
|
|
|
|
*prpcstat = 0; // we got here so we are OK
|
|
|
|
CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
|
|
if (!pProcess)
|
|
return E_ACCESSDENIED;
|
|
|
|
// Get token for the caller
|
|
CToken* pToken;
|
|
status = LookupOrCreateTokenForRPCClient(hRpc, FALSE, &pToken, NULL);
|
|
if (status != ERROR_SUCCESS)
|
|
return E_ACCESSDENIED;
|
|
|
|
hr = VerifyCallerIsAdministrator(pToken, &bAdmin);
|
|
pToken->Release();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
if (!bAdmin)
|
|
return E_ACCESSDENIED;
|
|
|
|
SCMVDATEHEAP();
|
|
|
|
hr = gAddrExclusionMgr.SetExclusionList(
|
|
dwNumStrings,
|
|
ppszStrings);
|
|
|
|
SCMVDATEHEAP();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: FlushSCMBindings
|
|
//
|
|
// Synopsis: Remove the specified machine bindings from our remote binding
|
|
// handle cache
|
|
//
|
|
// Arguments: [hRpc] - RPC handle
|
|
// [prpcstat] - communication status
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
extern "C"
|
|
HRESULT FlushSCMBindings(
|
|
handle_t hRpc,
|
|
PHPROCESS phProcess,
|
|
WCHAR* pszMachineName,
|
|
error_status_t* prpcstat)
|
|
{
|
|
HRESULT hr;
|
|
BOOL bAdmin;
|
|
ORSTATUS status;
|
|
|
|
// Parameter validation
|
|
if (!pszMachineName || !prpcstat)
|
|
return E_INVALIDARG;
|
|
|
|
*prpcstat = 0; // we got here so we are OK
|
|
|
|
CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
|
|
if (!pProcess)
|
|
return E_ACCESSDENIED;
|
|
|
|
// Get token for the caller
|
|
CToken* pToken;
|
|
status = LookupOrCreateTokenForRPCClient(hRpc, FALSE, &pToken, NULL);
|
|
if (status != ERROR_SUCCESS)
|
|
return E_ACCESSDENIED;
|
|
|
|
hr = VerifyCallerIsAdministrator(pToken, &bAdmin);
|
|
pToken->Release();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
if (!bAdmin)
|
|
return E_ACCESSDENIED;
|
|
|
|
SCMVDATEHEAP();
|
|
|
|
hr = gpRemoteMachineList->FlushSpecificBindings(pszMachineName);
|
|
|
|
SCMVDATEHEAP();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: RetireServer
|
|
//
|
|
// Synopsis: Marks the specified server as being no longer eligible for
|
|
// component activations of any type. Currently only used
|
|
// to support COM+'s process recycling feature.
|
|
//
|
|
// Arguments: [hRpc] - RPC handle
|
|
// [pguidProcessIdentifier] - guid which identifies the server
|
|
// [prpcstat] - communication status
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
extern "C"
|
|
HRESULT RetireServer(
|
|
handle_t hRpc,
|
|
PHPROCESS phProcess,
|
|
GUID* pguidProcessIdentifier,
|
|
error_status_t* prpcstat)
|
|
{
|
|
// Parameter validation
|
|
if (!pguidProcessIdentifier || !prpcstat)
|
|
return E_INVALIDARG;
|
|
|
|
*prpcstat = 0; // we got here so we are OK
|
|
|
|
CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
|
|
if (!pProcess)
|
|
return E_ACCESSDENIED;
|
|
|
|
// Get token for the caller
|
|
CToken* pToken;
|
|
ORSTATUS status;
|
|
status = LookupOrCreateTokenForRPCClient(hRpc, FALSE, &pToken, NULL);
|
|
if (status != ERROR_SUCCESS)
|
|
return E_ACCESSDENIED;
|
|
|
|
// Make sure they're an administrator
|
|
HRESULT hr;
|
|
BOOL bAdmin;
|
|
hr = VerifyCallerIsAdministrator(pToken, &bAdmin);
|
|
pToken->Release();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
if (!bAdmin)
|
|
return E_ACCESSDENIED;
|
|
|
|
// Okay, see if we know which process they're talking about
|
|
gpProcessListLock->LockShared();
|
|
|
|
hr = E_INVALIDARG; // review for better code when we don't find the process
|
|
|
|
CBListIterator all_procs(gpProcessList);
|
|
CProcess* pprocess;
|
|
while (pprocess = (CProcess*)all_procs.Next())
|
|
{
|
|
if (*pprocess->GetGuidProcessIdentifier() == *pguidProcessIdentifier)
|
|
{
|
|
// Found it. Mark it as retired
|
|
pprocess->Retire();
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
}
|
|
|
|
gpProcessListLock->UnlockShared();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
CWIPTable gWIPTbl; // global instance of the class
|
|
CWIPTable * gpWIPTbl = &gWIPTbl;
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CopyDualStringArray
|
|
//
|
|
// Synopsis: makes a copy of the given string array
|
|
//
|
|
// History: 22-Jan-96 Rickhi Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
HRESULT CopyDualStringArray(DUALSTRINGARRAY *psa, DUALSTRINGARRAY **ppsaNew)
|
|
{
|
|
ULONG ulSize = sizeof(DUALSTRINGARRAY) + (psa->wNumEntries * sizeof(WCHAR));
|
|
|
|
*ppsaNew = (DUALSTRINGARRAY *) PrivMemAlloc(ulSize);
|
|
|
|
if (*ppsaNew == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
memcpy(*ppsaNew, psa, ulSize);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CWIPTable::AddEntry, public
|
|
//
|
|
// Synopsis: Adds a WIPEntry to the table.
|
|
//
|
|
// Arguments: [hWnd] - window handle
|
|
// [pStd] - standard marshaled interface STDOBJREF
|
|
// [pOxidInfo] - info needed to resolve the OXID
|
|
// [pdwCookie] - cookie to return (to be placed on the window)
|
|
//
|
|
// History: 22-Jan-96 Rickhi Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
HRESULT CWIPTable::AddEntry(
|
|
DWORD_PTR hWnd,
|
|
STDOBJREF *pStd,
|
|
OXID_INFO *pOxidInfo,
|
|
ULONG sessId,
|
|
void * creator,
|
|
DWORD_PTR *pdwCookie
|
|
)
|
|
{
|
|
// make a copy of the string array in the OxidInfo since MIDL will
|
|
// delete it on the way back out of the call.
|
|
|
|
DUALSTRINGARRAY *psaNew;
|
|
HRESULT hr;
|
|
|
|
if (m_fCsInitialized == FALSE)
|
|
{
|
|
ASSERT(FALSE);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
psaNew = (DUALSTRINGARRAY *) PrivMemAlloc(sizeof(DUALSTRINGARRAY) + (pOxidInfo->psa->wNumEntries * sizeof(WCHAR)));
|
|
|
|
if (psaNew == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
memcpy(psaNew, pOxidInfo->psa, sizeof(DUALSTRINGARRAY) + (pOxidInfo->psa->wNumEntries * sizeof(WCHAR)));
|
|
|
|
CLock2 lck(s_mxs);
|
|
|
|
// find a free slot in the table
|
|
DWORD_PTR dwpIndex = s_iNextFree;
|
|
|
|
if (dwpIndex == (DWORD_PTR)-1)
|
|
{
|
|
// grow the table
|
|
dwpIndex = Grow();
|
|
}
|
|
|
|
if (dwpIndex != (DWORD_PTR)-1)
|
|
{
|
|
// get the pointer to the entry,
|
|
WIPEntry *pEntry = s_pTbl + dwpIndex;
|
|
|
|
// update the next free index.
|
|
s_iNextFree = pEntry->hWnd;
|
|
|
|
// copy in the data
|
|
memcpy(&pEntry->std, pStd, sizeof(STDOBJREF));
|
|
memcpy(&pEntry->oxidInfo, pOxidInfo, sizeof(OXID_INFO));
|
|
|
|
pEntry->oxidInfo.psa = psaNew;
|
|
pEntry->hWnd = hWnd;
|
|
pEntry->dwFlags = WIPF_OCCUPIED;
|
|
pEntry->sessId = sessId;
|
|
pEntry->creator = creator;
|
|
|
|
// set the cookie to return
|
|
*pdwCookie = dwpIndex+5000;
|
|
|
|
// return success
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
// free the allocated string array
|
|
PrivMemFree(psaNew);
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CWIPTable::GetEntry, public
|
|
//
|
|
// Synopsis: Retrieves and optionally delets a WIPEntry from the table.
|
|
//
|
|
// Arguments: [hWnd] - window handle
|
|
// [dwCookie] - cookie from the window
|
|
// [pStd] - place to return STDOBJREF data
|
|
// [pOxidInfo] - place to return info needed to resolve the OXID
|
|
//
|
|
// History: 22-Jan-96 Rickhi Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
HRESULT CWIPTable::GetEntry(
|
|
DWORD_PTR hWnd,
|
|
DWORD_PTR dwCookie,
|
|
BOOL fRevoke,
|
|
ULONG sessId,
|
|
void* caller,
|
|
STDOBJREF *pStd,
|
|
OXID_INFO *pOxidInfo)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
// validate the cookie
|
|
DWORD_PTR dwpIndex = dwCookie - 5000;
|
|
if (dwpIndex >= s_cEntries)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (m_fCsInitialized == FALSE)
|
|
{
|
|
ASSERT(FALSE);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
CLock2 lck(s_mxs);
|
|
|
|
// get the pointer to the entry,
|
|
WIPEntry *pEntry = s_pTbl + dwpIndex;
|
|
|
|
// make sure the entry is occupied
|
|
if (pEntry->dwFlags & WIPF_OCCUPIED)
|
|
{
|
|
if (sessId != pEntry->sessId) // trying to access the droptarget of a different session???
|
|
return E_ACCESSDENIED;
|
|
if (fRevoke && (caller != pEntry->creator)) // trying to delete someone else's droptarget??
|
|
return E_ACCESSDENIED;
|
|
if (hWnd != pEntry->hWnd) // additional verification.. authorized clients should know what the hwnd is.
|
|
return E_ACCESSDENIED;
|
|
|
|
DUALSTRINGARRAY *psaNew;
|
|
psaNew = (DUALSTRINGARRAY *) PrivMemAlloc(sizeof(DUALSTRINGARRAY) + (pEntry->oxidInfo.psa->wNumEntries * sizeof(WCHAR)));
|
|
|
|
if (psaNew == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
memcpy(psaNew, pEntry->oxidInfo.psa, sizeof(DUALSTRINGARRAY) + (pEntry->oxidInfo.psa->wNumEntries * sizeof(WCHAR)));
|
|
|
|
// copy out the data to return
|
|
memcpy(pStd, &pEntry->std, sizeof(STDOBJREF));
|
|
memcpy(pOxidInfo, &pEntry->oxidInfo, sizeof(OXID_INFO));
|
|
pOxidInfo->psa = psaNew;
|
|
|
|
if (fRevoke)
|
|
{
|
|
// free the entry by updating the flags and the next free index
|
|
PrivMemFree(pEntry->oxidInfo.psa);
|
|
|
|
pEntry->dwFlags = WIPF_VACANT;
|
|
pEntry->hWnd = s_iNextFree;
|
|
pEntry->sessId = 0;
|
|
pEntry->creator = NULL;
|
|
s_iNextFree = dwpIndex;
|
|
}
|
|
|
|
// return success
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CWIPTable::Grow, private
|
|
//
|
|
// Synopsis: grows the WIPTable size.
|
|
//
|
|
// History: 22-Jan-96 Rickhi Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
DWORD_PTR CWIPTable::Grow()
|
|
{
|
|
// compute the size and allocate a new table
|
|
DWORD_PTR dwSize = (s_cEntries + WIPTBL_GROW_SIZE) * sizeof(WIPEntry);
|
|
WIPEntry *pNewTbl = (WIPEntry *) PrivMemAlloc((size_t)dwSize);
|
|
|
|
if (pNewTbl != NULL)
|
|
{
|
|
// copy the old table in
|
|
memcpy(pNewTbl, s_pTbl, (size_t)(s_cEntries * sizeof(WIPEntry)));
|
|
|
|
// free the old table
|
|
if (s_pTbl)
|
|
{
|
|
PrivMemFree(s_pTbl);
|
|
}
|
|
|
|
// replace the old table ptr
|
|
s_pTbl = pNewTbl;
|
|
|
|
// update the free list and mark the new entries as vacant
|
|
s_iNextFree = s_cEntries;
|
|
|
|
WIPEntry *pNext = s_pTbl + s_cEntries;
|
|
|
|
for (ULONG i=0; i< WIPTBL_GROW_SIZE; i++)
|
|
{
|
|
pNext->hWnd = ++s_cEntries;
|
|
pNext->dwFlags = WIPF_VACANT;
|
|
pNext->sessId = 0;
|
|
pNext->creator = NULL;
|
|
pNext++;
|
|
}
|
|
|
|
(pNext-1)->hWnd = (DWORD_PTR)-1; // last entry has END_OF_LIST marker
|
|
}
|
|
|
|
return s_iNextFree;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CWIPTable::RunDown, public
|
|
//
|
|
// Synopsis: Deletes all WIPEntry from the table that were created by creator.
|
|
//
|
|
// Arguments: [creator] - this is the CProcess object of the process being rundown
|
|
//
|
|
// History: 27-Mar-02 Hanyr Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void CWIPTable::RunDown(
|
|
void* creator)
|
|
{
|
|
if (m_fCsInitialized == FALSE)
|
|
{
|
|
ASSERT(FALSE);
|
|
return;
|
|
}
|
|
|
|
CLock2 lck(s_mxs);
|
|
|
|
// get the pointer to the entry,
|
|
WIPEntry *pEntry = s_pTbl;
|
|
|
|
for (ULONG i=0; i< s_cEntries; i++)
|
|
{
|
|
if ((pEntry->dwFlags == WIPF_OCCUPIED) && (pEntry->creator == creator)) // a match
|
|
{
|
|
PrivMemFree(pEntry->oxidInfo.psa);
|
|
pEntry->dwFlags = WIPF_VACANT;
|
|
pEntry->hWnd = s_iNextFree;
|
|
pEntry->sessId = 0;
|
|
pEntry->creator = NULL;
|
|
s_iNextFree = i;
|
|
}
|
|
pEntry++;
|
|
}
|
|
}
|
|
|
|
void DragDropRunDown(void *creator)
|
|
{
|
|
gpWIPTbl->RunDown(creator);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: RegisterWindowPropInterface
|
|
//
|
|
// Synopsis: Associate a window property with a (standard) marshaled
|
|
// interface.
|
|
//
|
|
// Arguments: [hRpc] - RPC handle
|
|
// [hWnd] - window handle
|
|
// [pStd] - standard marshaled interface STDOBJREF
|
|
// [pOxidInfo] - info needed to resolve the OXID
|
|
// [pdwCookie] - cookie to return (to be placed on the window)
|
|
// [prpcstat] - communication status
|
|
//
|
|
// History: 22-Jan-96 Rickhi Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
extern "C" HRESULT RegisterWindowPropInterface(
|
|
handle_t hRpc,
|
|
PHPROCESS phProcess,
|
|
DWORD_PTR hWnd,
|
|
STDOBJREF *pStd,
|
|
OXID_INFO *pOxidInfo,
|
|
DWORD_PTR *pdwCookie,
|
|
error_status_t *prpcstat)
|
|
{
|
|
// Parameter validation
|
|
if (!pStd || !pOxidInfo || !pOxidInfo->psa || !pdwCookie || !prpcstat)
|
|
return E_INVALIDARG;
|
|
|
|
*prpcstat = 0; // we got here so we are OK
|
|
|
|
CProcess *pProcess = CheckLocalSecurity(hRpc, phProcess);
|
|
if (!pProcess)
|
|
return E_ACCESSDENIED;
|
|
|
|
ULONG sessId = pProcess->GetToken()->GetSessionId();
|
|
|
|
CairoleDebugOut((DEB_SCM,
|
|
"_IN RegisterWindowPropInterface hWnd:%x pStd:%x pOxidInfo:%x\n",
|
|
hWnd, pStd, pOxidInfo));
|
|
|
|
VDATEHEAP();
|
|
|
|
HRESULT hr = gpWIPTbl->AddEntry(hWnd, pStd, pOxidInfo, sessId, pProcess, pdwCookie);
|
|
if (SUCCEEDED(hr))
|
|
pProcess->IncDropTargets();
|
|
|
|
CairoleDebugOut((DEB_SCM, "_OUT RegisterWindowPropInterface dwCookie:%x\n",
|
|
*pdwCookie));
|
|
VDATEHEAP();
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: GetWindowPropInterface
|
|
//
|
|
// Synopsis: Get the marshaled interface associated with a window property.
|
|
//
|
|
// Arguments: [hRpc] - RPC handle
|
|
// [hWnd] - window handle
|
|
// [dwCookie] - cookie from the window
|
|
// [fRevoke] - whether to revoke entry or not
|
|
// [pStd] - standard marshaled interface STDOBJREF to return
|
|
// [pOxidInfo] - info needed to resolve the OXID
|
|
// [prpcstat] - communication status
|
|
//
|
|
// History: 22-Jan-96 Rickhi Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
extern "C" HRESULT GetWindowPropInterface(
|
|
handle_t hRpc,
|
|
PHPROCESS phProcess,
|
|
DWORD_PTR hWnd,
|
|
DWORD_PTR dwCookie,
|
|
BOOL fRevoke,
|
|
STDOBJREF *pStd,
|
|
OXID_INFO *pOxidInfo,
|
|
error_status_t *prpcstat)
|
|
{
|
|
// Parameter validation
|
|
if (!pStd || !pOxidInfo || !prpcstat)
|
|
return E_INVALIDARG;
|
|
|
|
*prpcstat = 0;
|
|
|
|
CProcess *pProcess = CheckLocalSecurity(hRpc, phProcess);
|
|
if (!pProcess)
|
|
return E_ACCESSDENIED;
|
|
|
|
ULONG sessId = pProcess->GetToken()->GetSessionId();
|
|
|
|
CairoleDebugOut((DEB_SCM,
|
|
"_IN GetWindowPropInterface hWnd:%x dwCookie:%x fRevoke:%x\n",
|
|
hWnd, dwCookie, fRevoke));
|
|
|
|
VDATEHEAP();
|
|
|
|
HRESULT hr = gpWIPTbl->GetEntry(hWnd, dwCookie, fRevoke, sessId, pProcess, pStd, pOxidInfo);
|
|
if (fRevoke && SUCCEEDED(hr))
|
|
pProcess->DecDropTargets();
|
|
|
|
CairoleDebugOut((DEB_SCM,
|
|
"_OUT GetWindowPropInterface pStd:%x pOxidInfo:%x\n", pStd, pOxidInfo));
|
|
VDATEHEAP();
|
|
return hr;
|
|
}
|