//+------------------------------------------------------------------------- // // 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" //+------------------------------------------------------------------------- // // 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 *rpcstat) { CProcess * pProcess; RegOutput * pregout; CServerTableEntry * pClassTableEntry; CClsidData * pClsidData = NULL; DWORD Size, Entries, i; UCHAR ServerState; LONG Status; HRESULT hr; HANDLE* phRegisterEvents = NULL; CheckLocalCall( hRpc ); // Parameter validation if (!pregin || !ppregout || !rpcstat) return E_INVALIDARG; *rpcstat = 0; *ppregout = 0; pProcess = ReferenceProcess( phProcess, TRUE ); if ( ! pProcess ) return E_ACCESSDENIED; // Allocate an array of handles to hold the register events. phRegisterEvents = (HANDLE*)alloca(sizeof(HANDLE) * pregin->dwSize); memset(phRegisterEvents, 0, sizeof(HANDLE) * pregin->dwSize); Size = sizeof(RegOutput) + (pregin->dwSize - 1) * sizeof(DWORD); *ppregout = (RegOutput *) PrivMemAlloc(Size); if ( ! *ppregout ) { ReleaseProcess( pProcess ); 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; #ifndef _CHICAGO_ // 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; } #endif // // 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) { phRegisterEvents[i] = pClsidData->ServerRegisterEvent(); if (!phRegisterEvents[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; #if 0 // #ifdef _CHICAGO_ // // On Win9x, we use a notification window to do lazy registers from a // single threaded apartment. We don't use the notification window if // this register is coming in from a resumed suspended registration. // This is when the overloaded REGCLS_SUSPENDED flag is set. // if ( ! (pregin->rginent[i].dwFlags | REGCLS_SUSPENDED) && IsSTAThread() ) ServerState |= SERVERSTATE_USENOTIFYWIN; #endif 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++ ) { HANDLE hRegisterEvent; 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 (phRegisterEvents[i]) { SetEvent(phRegisterEvents[i]); CloseHandle(phRegisterEvents[i]); phRegisterEvents[i] = 0; } } 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 (phRegisterEvents[i]) CloseHandle(phRegisterEvents[i]); } ReleaseProcess( pProcess ); return hr; } //+------------------------------------------------------------------------- // // Function: StopServer // // 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 *rpcstat) { CServerTableEntry* pClassTableEntry; RevokeEntry* prevent; DWORD Entries; CProcess* pProcess; CheckLocalCall( hRpc ); // Parameter validation if (!prevcls || !rpcstat) return; pProcess = ReferenceProcess(phProcess); if (!pProcess) return; *rpcstat = 0; 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, DWORD * pThreadID, error_status_t *prpcstat) { CheckLocalCall( hRpc ); // 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 // //-------------------------------------------------------------------------- #ifdef _CHICAGO_ extern HRESULT ReadRegistry(); #else extern void ComputeSecurity(); #endif _CHICAGO_ extern "C" void UpdateActivationSettings( handle_t hRpc, error_status_t *prpcstat) { CheckLocalCall( hRpc ); // Parameter validation if (!prpcstat) return; *prpcstat = 0; ReadRemoteActivationKeys(); ComputeSecurity(); } //+------------------------------------------------------------------------- // // 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; CheckLocalCall( hRpc ); // raises exception if not // Parameter validation if (!prpcstat) return E_INVALIDARG; *prpcstat = 0; // we got here so we are OK // Make sure we know who's calling CProcess* pProcess = ReferenceProcess(phProcess); if (!pProcess) return E_ACCESSDENIED; // Get token for the caller CToken* pToken; status = LookupOrCreateToken(hRpc, TRUE, &pToken); 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; CheckLocalCall( hRpc ); // raises exception if not // Parameter validation if (!pdwNumStrings || !pppszStrings || !prpcstat) return E_INVALIDARG; *prpcstat = 0; // we got here so we are OK // Make sure we know who's calling CProcess* pProcess = ReferenceProcess(phProcess); if (!pProcess) return E_ACCESSDENIED; // Get token for the caller CToken* pToken; status = LookupOrCreateToken(hRpc, TRUE, &pToken); 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; CheckLocalCall( hRpc ); // raises exception if not // Parameter validation if (!ppszStrings || !prpcstat) return E_INVALIDARG; *prpcstat = 0; // we got here so we are OK // Make sure we know who's calling CProcess* pProcess = ReferenceProcess(phProcess); if (!pProcess) return E_ACCESSDENIED; // Get token for the caller CToken* pToken; status = LookupOrCreateToken(hRpc, TRUE, &pToken); 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; CheckLocalCall( hRpc ); // raises exception if not // Parameter validation if (!pszMachineName || !prpcstat) return E_INVALIDARG; *prpcstat = 0; // we got here so we are OK // Make sure we know who's calling CProcess* pProcess = ReferenceProcess(phProcess); if (!pProcess) return E_ACCESSDENIED; // Get token for the caller CToken* pToken; status = LookupOrCreateToken(hRpc, TRUE, &pToken); 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) { CheckLocalCall( hRpc ); // raises exception if not // Parameter validation if (!pguidProcessIdentifier || !prpcstat) return E_INVALIDARG; *prpcstat = 0; // we got here so we are OK if (!pguidProcessIdentifier) return E_INVALIDARG; // Make sure we know who's calling CProcess* pProcess = ReferenceProcess(phProcess); if (!pProcess) return E_ACCESSDENIED; // Get token for the caller CToken* pToken; ORSTATUS status; status = LookupOrCreateToken(hRpc, TRUE, &pToken); 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, 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))); #if 0 // #ifdef _CHICAGO_ CLockSmMutex lck(gWIPmxs); #else CLock2 lck(s_mxs); #endif // 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; // 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, 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; } #if 0 // #ifdef _CHICAGO_ CLockSmMutex lck(gWIPmxs); #else CLock2 lck(s_mxs); #endif // get the pointer to the entry, WIPEntry *pEntry = s_pTbl + dwpIndex; // make sure the entry is occupied if (pEntry->dwFlags & WIPF_OCCUPIED) { 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; 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++; } (pNext-1)->hWnd = (DWORD_PTR)-1; // last entry has END_OF_LIST marker } return s_iNextFree; } //+------------------------------------------------------------------------- // // 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, DWORD_PTR hWnd, STDOBJREF *pStd, OXID_INFO *pOxidInfo, DWORD_PTR *pdwCookie, error_status_t *prpcstat) { CheckLocalCall( hRpc ); // Parameter validation if (!pStd || !pOxidInfo || !pOxidInfo->psa || !pdwCookie || !prpcstat) return E_INVALIDARG; *prpcstat = 0; CairoleDebugOut((DEB_SCM, "_IN RegisterWindowPropInterface hWnd:%x pStd:%x pOxidInfo:%x\n", hWnd, pStd, pOxidInfo)); VDATEHEAP(); HRESULT hr = gpWIPTbl->AddEntry(hWnd, pStd, pOxidInfo, pdwCookie); 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, DWORD_PTR hWnd, DWORD_PTR dwCookie, BOOL fRevoke, STDOBJREF *pStd, OXID_INFO *pOxidInfo, error_status_t *prpcstat) { CheckLocalCall( hRpc ); // Parameter validation if (!pStd || !pOxidInfo || !prpcstat) return E_INVALIDARG; *prpcstat = 0; CairoleDebugOut((DEB_SCM, "_IN GetWindowPropInterface hWnd:%x dwCookie:%x fRevoke:%x\n", hWnd, dwCookie, fRevoke)); VDATEHEAP(); HRESULT hr = gpWIPTbl->GetEntry(hWnd, dwCookie, fRevoke, pStd, pOxidInfo); CairoleDebugOut((DEB_SCM, "_OUT GetWindowPropInterface pStd:%x pOxidInfo:%x\n", pStd, pOxidInfo)); VDATEHEAP(); return hr; }