|
|
//+-------------------------------------------------------------------------
//
// 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; }
|