//+------------------------------------------------------------------------- // // 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 #pragma hdrstop #include #include "rawdscm.h" #include "scm.hxx" #include "port.hxx" #include "cls.hxx" #include #include "dbgprt.hxx" #include "rotif.hxx" #include "clckpath.hxx" #include #include "or.hxx" #ifndef _CHICAGO_ #include extern CScmShrdTbl *g_pScmShrdTbl; #endif //+------------------------------------------------------------------------- // // 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, WCHAR * pwszWinstaDesktop, RegInput *pregin, RegOutput **ppregout, error_status_t *rpcstat) { CheckLocalCall( hRpc ); *rpcstat = 0; HRESULT hr = S_OK; #if DBG == 1 CairoleDebugOut((DEB_SCM, "_IN ObjectServerStarted\n")); #if defined(_NT1X_) && !defined(_CHICAGO_) CairoleDebugOut((DEB_SCM, "_IN Desk Top: %s\n", pwszWinstaDesktop)); #endif // _NT1X_ && !_CHICAGO_ DbgPrintRegIn("_IN Classes To Register", pregin); #endif // DBG == 1 VDATEHEAP(); // Initialize the output structure. int cOutBytes = sizeof(RegOutput) + (pregin->dwSize - 1) * sizeof(RegOutputEnt); RegOutput *pregout = (RegOutput *) PrivMemAlloc(cOutBytes); *ppregout = pregout; if (pregout == NULL) return E_OUTOFMEMORY; memset(pregout, 0, cOutBytes); pregout->dwSize = pregin->dwSize; hr = GetClassCache().SetEndPoints( #ifndef _CHICAGO_ phProcess, ((CProcess *)phProcess)->GetToken()->GetSid(), pwszWinstaDesktop, #else NULL, #endif pregin, pregout ); VDATEHEAP(); #if DBG == 1 CairoleDebugOut((DEB_SCM, "OUT ObjectServerStarted\n")); CairoleDebugOut((DEB_SCM, "OUT Hresult : %lx\n", hr)); if (SUCCEEDED(hr)) { DbgPrintRegOut("OUT Register Information", ppregout); } #endif // DBG == 1 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) { #if DBG == 1 CairoleDebugOut((DEB_SCM, "_IN StopServer\n")); DbgPrintRevokeClasses("_IN RevokeClasses:", prevcls); #endif // DBG == 1 CheckLocalCall( hRpc ); VDATEHEAP(); *rpcstat = 0; DWORD cLoops = prevcls->dwSize; RevokeEntry *prevent = prevcls->revent; for (DWORD i = 0; i < cLoops; i++, prevent++) { GetClassCache().StopServer(prevent->clsid, IFSECURITY( ((CProcess *)phProcess)->GetToken()->GetSid() ) prevent->dwReg); ((CProcess *)phProcess)->RemoveClassReg( prevent->clsid, prevent->dwReg ); } VDATEHEAP(); CairoleDebugOut((DEB_SCM, "OUT StopServer\n")); } void GetThreadID( handle_t hRpc, DWORD * pThreadID, error_status_t *prpcstat) { CheckLocalCall( hRpc ); *prpcstat = 0; *pThreadID = InterlockedExchangeAdd((long *)&gNextThreadID,1); } #ifndef _CHICAGO_ //+------------------------------------------------------------------------- // // Function: UpdateShrdTbls // // Synopsis: Update the shared memory tables. // // Arguments: [hRpc] - RPC handle // [prpcstat] - communication status // // History: 11-Jul-94 Rickhi Created // //-------------------------------------------------------------------------- extern "C" HRESULT UpdateShrdTbls( handle_t hRpc, error_status_t *prpcstat) { CheckLocalCall( hRpc ); *prpcstat = 0; CairoleDebugOut((DEB_SCM, "_IN UpdateShrdTbls\n")); VDATEHEAP(); // we dont take the lock because the caller is holding it for us. g_pScmShrdTbl->UpdateWithLock(); VDATEHEAP(); CairoleDebugOut((DEB_SCM, "OUT UpdateShrdTbls\n")); return S_OK; } //+------------------------------------------------------------------------- // // 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, error_status_t *prpcstat) { CheckLocalCall( hRpc ); *prpcstat = 0; gpClassCache->ReadRemoteActivationKeys(); ComputeSecurity(); } #endif // !_CHICAGO_ #ifdef _CHICAGO_ //+------------------------------------------------------------------------- // // Function: StartObjectService // // Synopsis: Get a class object for a client // // Arguments: [hRpc] - RPC handle // [orpcthis] - ORPC handle // [localthis] - ORPC call data // [orpcthat] - ORPC reply data // [rclsid] - class id for reequest // [dwCtrl] - type of server required // [ppIFDClassObj] - where to return the serialized class object // [ppwszDllToLoad] - where to return DLL path // // Returns: HRESULT // // History: 01-May-93 Ricksa Created // //-------------------------------------------------------------------------- extern "C" HRESULT StartObjectService( handle_t hRpc, ORPCTHIS *orpcthis, LOCALTHIS *localthis, ORPCTHAT *orpcthat, WCHAR *lpDesktop, const GUID *guidCLSID, DWORD dwCtrl, WCHAR *pwszServer, InterfaceData **ppIFDClassObj, DWORD *pdwDllType, WCHAR **ppwszDllToLoad ) { REFCLSID rclsid = *guidCLSID; #if DBG ==1 CairoleDebugOut((DEB_SCM, "_IN StartObjectServer\n")); CairoleDebugOut((DEB_SCM, "_IN Desk Top: %s\n", lpDesktop)); DbgPrintGuid("_IN ThreadId: ", &orpcthis->cid); DbgPrintGuid("_IN CLSID: ", guidCLSID); CairoleDebugOut((DEB_SCM, "_IN Context: %lX\n", dwCtrl)); CairoleDebugOut((DEB_SCM, "_IN DLL Type: %lX\n", *pdwDllType)); #endif // DBG == 1 orpcthat->flags = 0; orpcthat->extensions = NULL; VDATEHEAP(); CBaseData bd( GETCLASSOBJECT, lpDesktop, &orpcthis->cid, rclsid, dwCtrl, pdwDllType, ppwszDllToLoad, ppIFDClassObj, NULL, FALSE, NULL, NULL, NULL, NULL,FALSE); HRESULT hr = GetClassCache().ProcessScmMessage(&bd, NULL); VDATEHEAP(); #if DBG == 1 CairoleDebugOut((DEB_SCM, "OUT StartObjectServer\n")); CairoleDebugOut((DEB_SCM, "OUT Hresult : %lx\n", hr)); if (SUCCEEDED(hr)) { if (*ppIFDClassObj) { DbgPrintIFD("OUT Class Obj:", *ppIFDClassObj); } if (*ppwszDllToLoad) { CairoleDebugOut((DEB_SCM, "OUT DLL Type: %lX\n", *pdwDllType)); CairoleDebugOut((DEB_SCM, "OUT DLL: %ws\n", *ppwszDllToLoad)); } } #endif // DBG == 1 return hr; } //+------------------------------------------------------------------------- // // Function: SvcActivateObject // // Synopsis: Instantiate an object with interface // // Arguments: [hRpc] - RPC handle // [orpcthis] - ORPC handle // [localthis] - ORPC call data // [orpcthat] - ORPC reply data // [rclsid] - class id for object // [dwOptions] - type of server needed // [grfMode] - how to open file if specified // [pwszPath] - path to object // [pIFDstg] - marshaled storage // [pwszDllPath] - path to DLL // // Returns: HRESULT // // History: 01-May-93 Ricksa Created // 18-Aug-94 AlexT Add caller, callee thread id // //-------------------------------------------------------------------------- // BUGBUG [mikese] The pwszServerAddress parameter is redundant, and should // be removed from the IDL // BUGBUG: hash value is an obsolete field as well. extern "C" HRESULT SvcActivateObject( handle_t hRpc, ORPCTHIS *orpcthis, LOCALTHIS *localthis, ORPCTHAT *orpcthat, WCHAR *lpDesktop, WCHAR *pwszProtseq, const GUID *pclsid, DWORD dwOptions, DWORD grfMode, DWORD dwHash, WCHAR *pwszPath, InterfaceData *pIFDstg, InterfaceData **ppIFDunk, DWORD *pdwDllType, WCHAR **ppwszDllPath, WCHAR *pwszServerAddress ) { #if DBG ==1 CairoleDebugOut((DEB_SCM, "_IN SvcActivateObject\n")); CairoleDebugOut((DEB_SCM, "_IN Desk Top: %s\n", lpDesktop)); CairoleDebugOut((DEB_SCM, "_IN Protocol Seq: %ws\n", (pwszProtseq == NULL) ? L"None" : pwszProtseq)); DbgPrintGuid("_IN ThreadId: ", &orpcthis->cid); DbgPrintGuid("_IN CLSID: ", pclsid); CairoleDebugOut((DEB_SCM, "_IN Context: %lX\n", dwOptions)); CairoleDebugOut((DEB_SCM, "_IN Mode: %lX\n", grfMode)); CairoleDebugOut((DEB_SCM, "_IN Path: %ws\n", (pwszPath == NULL) ? L"None" : pwszPath)); CairoleDebugOut((DEB_SCM, "_IN Stg: %lX\n", pIFDstg)); CairoleDebugOut((DEB_SCM, "_IN DLL Type: %lX\n", *pdwDllType)); #endif // DBG == 1 orpcthat->flags = 0; orpcthat->extensions = NULL; VDATEHEAP(); HRESULT hr = S_OK; InterfaceData *pifdFromROT = NULL; BEGIN_BLOCK // Lock the path so that only one path may be bound at a time CLockPath lckpath(pwszPath, hr); if (FAILED(hr)) { // Couldn't lock the path -- memory problem maybe. Anyway, we // can't go anywhere from here. CairoleDebugOut((DEB_ERROR, "SvcActivateObject Lock of Path Failed %lx\n", hr)); EXIT_BLOCK; } // If there is a path Look for path in the Directory ROT if (pwszPath != NULL) { // Remember that pdwDllType is overloaded here. We use it to // indicate that we got an object from the ROT. We need to do // this because there is no guarantee that the ROT entry will // not be bad by the time we get back to the caller and therefore, // the caller will want to retry in this case. if (GetObjectFromRot(pwszPath, &pifdFromROT) == S_OK) { // Is this a local operatoin? if (pwszProtseq == NULL) { // Return the marshaled interface from the ROT to the // caller. *ppIFDunk = pifdFromROT; // So we remember not to clean up the buffer pifdFromROT = NULL; // Let caller know that we got this from the ROT so // if it doesn't work they should try again. *pdwDllType = GOT_FROM_ROT; // We got what we came for from the ROT so we can exit CairoleDebugOut((DEB_TRACE, "Found object in the ROT\n")); EXIT_BLOCK; } // Because a tabled marshaled interface is not enought // to get unmarshaled locally, we need to send it back // to the object server to get something we can pass back // to another machine. } } // BUGBUG - Until we can decide how to pass back the callee's thread // id, just hold it here. DWORD dwTIDCallee; IID IIDs[1]; HRESULT Results[1]; IIDs[0] = IID_IUnknown; CGetCreateData gcd(pwszProtseq, dwOptions, grfMode, pwszPath, pIFDstg, NULL, ppIFDunk, localthis->dwClientThread, &dwTIDCallee, pifdFromROT, 1, IIDs, Results); CBaseData bd(GETPERSISTENTOBJ, lpDesktop, &orpcthis->cid, *pclsid, dwOptions, pdwDllType, ppwszDllPath, ppIFDunk, NULL, FALSE, NULL, NULL, NULL, NULL,FALSE); hr = GetClassCache().ProcessScmMessage(&bd, &gcd); END_BLOCK; VDATEHEAP(); #if DBG == 1 CairoleDebugOut((DEB_SCM, "OUT SvcActivateObject\n")); CairoleDebugOut((DEB_SCM, "OUT Hresult : %lx\n", hr)); if (SUCCEEDED(hr)) { if (*ppIFDunk) { DbgPrintIFD("OUT Object:", *ppIFDunk); } if (*ppwszDllPath) { CairoleDebugOut((DEB_SCM, "OUT DLL Type: %lX\n", *pdwDllType)); CairoleDebugOut((DEB_SCM, "OUT DLL: %ws\n", *ppwszDllPath)); } } #endif // DBG == 1 if (pifdFromROT != NULL) { MIDL_user_free(pifdFromROT); } return hr; } //+------------------------------------------------------------------------- // // Function: SvcCreateActivateObject // // Synopsis: Create and activate a new object // // Arguments: [hRpc] - RPC handle // [orpcthis] - ORPC handle // [localthis] - ORPC call data // [orpcthat] - ORPC reply data // [rclsid] - class id for object to create // [dwOptions] - type of server required // [dwMode] - how to open storage // [pwszPath] - path to the storage // [pIFDstg] - marshaled storage // [pwszNewName] - new name of object // [ppIFDunk] - marshaled IUnknown to return // [ppwszDllPath] - path to DLL for handler or server // // Returns: HRESULT // // History: 01-May-93 Ricksa Created // 18-Aug-94 AlexT Add caller, callee thread id // //-------------------------------------------------------------------------- // BUGBUG [mikese] The pwszServerAddress parameter is redundant, and should // be removed from the IDL extern "C" HRESULT SvcCreateActivateObject( handle_t hRpc, ORPCTHIS *orpcthis, LOCALTHIS *localthis, ORPCTHAT *orpcthat, WCHAR * lpDesktop, WCHAR *pwszProtseq, const GUID *guidCLSID, DWORD dwOptions, DWORD dwMode, WCHAR *pwszPath, InterfaceData *pIFDstg, WCHAR *pwszNewName, InterfaceData **ppIFDunk, DWORD *pdwDllType, WCHAR **ppwszDllPath, WCHAR *pwszServerAddress ) { REFCLSID rclsid = *guidCLSID; #if DBG ==1 CairoleDebugOut((DEB_SCM, "_IN SvcCreateActivateObject\n")); CairoleDebugOut((DEB_SCM, "_IN Desk Top: %s\n", lpDesktop)); CairoleDebugOut((DEB_SCM, "_IN Protocol Seq: %ws\n", (pwszProtseq == NULL) ? L"None" : pwszProtseq)); DbgPrintGuid("_IN ThreadId: ", &orpcthis->cid); DbgPrintGuid("_IN CLSID: ", guidCLSID); CairoleDebugOut((DEB_SCM, "_IN Context: %lX\n", dwOptions)); CairoleDebugOut((DEB_SCM, "_IN Mode: %lX\n", dwMode)); CairoleDebugOut((DEB_SCM, "_IN Path: %ws\n", (pwszPath == NULL) ? L"None" : pwszPath)); CairoleDebugOut((DEB_SCM, "_IN Stg: %lX\n", pIFDstg)); CairoleDebugOut((DEB_SCM, "_IN New Path: %ws\n", (pwszNewName == NULL) ? L"None" : pwszNewName)); CairoleDebugOut((DEB_SCM, "_IN DLL Type: %lX\n", *pdwDllType)); #endif // DBG == 1 orpcthat->flags = 0; orpcthat->extensions = NULL; VDATEHEAP(); // Error return from function HRESULT hr=S_OK; // Lock the path so that only one path may be bound at a time. Note // that for create we don't look in the ROT since we don't want to // get an already running entry but create a new one. CLockPath lckpath(pwszPath, hr); if (FAILED(hr)) { // Couldn't lock the path -- memory problem maybe. Anyway, we // can't go anywhere from here. CairoleDebugOut((DEB_ERROR, "GetClass Failed %lx\n", hr)); return hr; } // BUGBUG - Until we can decide how to pass back the callee's thread // id, just hold it here. DWORD dwTIDCallee; IID IIDs[1]; HRESULT Results[1]; IIDs[0] = IID_IUnknown; CGetCreateData gcd(pwszProtseq, dwOptions, dwMode, pwszPath, pIFDstg, pwszNewName, ppIFDunk, localthis->dwClientThread, &dwTIDCallee, NULL, 1, IIDs, Results ); CBaseData bd(CREATEPERSISTENTOBJ, lpDesktop, &orpcthis->cid, rclsid, dwOptions, pdwDllType, ppwszDllPath, ppIFDunk, NULL, FALSE, NULL, NULL, NULL, NULL,FALSE); hr = GetClassCache().ProcessScmMessage(&bd, &gcd); CairoleDebugOut((DEB_TRACE, "Result %lx\nDll Path %ws\n", hr, *ppwszDllPath)); VDATEHEAP(); #if DBG == 1 CairoleDebugOut((DEB_SCM, "OUT SvcActivateObject\n")); CairoleDebugOut((DEB_SCM, "OUT Hresult : %lx\n", hr)); if (SUCCEEDED(hr)) { if (*ppIFDunk) { DbgPrintIFD("OUT Object:", *ppIFDunk); } if (*ppwszDllPath) { CairoleDebugOut((DEB_SCM, "OUT DLL Type: %lX\n", *pdwDllType)); CairoleDebugOut((DEB_SCM, "OUT DLL: %ws\n", *ppwszDllPath)); } } #endif // DBG == 1 return hr; } #endif // _CHICAGO_ #ifdef DCOM //+------------------------------------------------------------------------- // // Structure: WIPEntry (Window Interface Property) // // Synopsis: Stores marshaled interface info associated with a given window. // It is an entry in the CWIPTable (see below). // // History: 22-Jan-96 Rickhi Created // //-------------------------------------------------------------------------- typedef struct tagWIPEntry { DWORD hWnd; // window the interface property is stored in DWORD dwFlags; // flags (see WIPFLAGS) STDOBJREF std; // marshaled interface data OXID_INFO oxidInfo; // data needed to resolve the OXID } WIPEntry; typedef enum tagWIPFLAGS { WIPF_VACANT = 0x1, // slot is vacant WIPF_OCCUPIED = 0x2 // slot is occupied } WIPFLAGS; #define WIPTBL_GROW_SIZE 10 // grow table by 10 entries at a time //+------------------------------------------------------------------------- // // Class: CWIPTable (Window Interface Property Table) // // Synopsis: Stores marshaled interface info associated with a given window. // This is used for registering drag/drop interfaces. // // History: 22-Jan-96 Rickhi Created // //-------------------------------------------------------------------------- class CWIPTable { public: HRESULT AddEntry(DWORD hWnd, STDOBJREF *pStd, OXID_INFO *pOxidInfo, DWORD *pdwCookie); HRESULT GetEntry(DWORD hWnd, DWORD dwCookie, BOOL fRevoke, STDOBJREF *pStd, OXID_INFO *pOxidInfo); private: DWORD Grow(); static DWORD s_cEntries; // count of entries in the table static DWORD s_iNextFree; // index to first free entry in table static WIPEntry *s_pTbl; // ptr to the first entry in table static CMutexSem s_mxs; // critical section to protect data }; // static data for the table (avoids running a ctor for the class) DWORD CWIPTable::s_cEntries = 0; DWORD CWIPTable::s_iNextFree = 0xffffffff; WIPEntry *CWIPTable::s_pTbl = NULL; CMutexSem CWIPTable::s_mxs; CWIPTable gWIPTbl; // global instance of the class //+------------------------------------------------------------------------- // // 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 hWnd, STDOBJREF *pStd, OXID_INFO *pOxidInfo, DWORD *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 = CopyDualStringArray(pOxidInfo->psa, &psaNew); if (FAILED(hr)) { return hr; } CLock lck(s_mxs); // find a free slot in the table DWORD dwIndex = s_iNextFree; if (dwIndex == 0xffffffff) { // grow the table dwIndex = Grow(); } if (dwIndex != 0xffffffff) { // get the pointer to the entry, WIPEntry *pEntry = s_pTbl + dwIndex; // 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; // return success hr = S_OK; } else { // free the allocated string array PrivMemFree(psaNew); } // set the cookie to return *pdwCookie = dwIndex+5000; 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 hWnd, DWORD dwCookie, BOOL fRevoke, STDOBJREF *pStd, OXID_INFO *pOxidInfo) { HRESULT hr = E_INVALIDARG; // validate the cookie DWORD dwIndex = dwCookie - 5000; if (dwIndex < 0 || dwIndex >= s_cEntries) { return hr; } CLock lck(s_mxs); // get the pointer to the entry, WIPEntry *pEntry = s_pTbl + dwIndex; // make sure the entry is occupied if (pEntry->dwFlags & WIPF_OCCUPIED) { DUALSTRINGARRAY *psaNew; hr = CopyDualStringArray(pEntry->oxidInfo.psa, &psaNew); if (SUCCEEDED(hr)) { // 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 = dwIndex; } } } return hr; } //+------------------------------------------------------------------------- // // Member: CWIPTable::Grow, private // // Synopsis: grows the WIPTable size. // // History: 22-Jan-96 Rickhi Created // //-------------------------------------------------------------------------- DWORD CWIPTable::Grow() { // compute the size and allocate a new table DWORD dwSize = (s_cEntries + WIPTBL_GROW_SIZE) * sizeof(WIPEntry); WIPEntry *pNewTbl = (WIPEntry *) PrivMemAlloc(dwSize); if (pNewTbl != NULL) { // copy the old table in memcpy(pNewTbl, s_pTbl, (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 = 0xffffffff; // 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 hWnd, STDOBJREF *pStd, OXID_INFO *pOxidInfo, DWORD *pdwCookie, error_status_t *prpcstat) { CheckLocalCall( hRpc ); *prpcstat = 0; CairoleDebugOut((DEB_SCM, "_IN RegisterWindowPropInterface hWnd:%x pStd:%x pOxidInfo:%x\n", hWnd, pStd, pOxidInfo)); VDATEHEAP(); HRESULT hr = gWIPTbl.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 hWnd, DWORD dwCookie, BOOL fRevoke, STDOBJREF *pStd, OXID_INFO *pOxidInfo, error_status_t *prpcstat) { CheckLocalCall( hRpc ); *prpcstat = 0; CairoleDebugOut((DEB_SCM, "_IN GetWindowPropInterface hWnd:%x dwCookie:%x fRevoke:%x\n", hWnd, dwCookie, fRevoke)); VDATEHEAP(); HRESULT hr = gWIPTbl.GetEntry(hWnd, dwCookie, fRevoke, pStd, pOxidInfo); CairoleDebugOut((DEB_SCM, "_OUT GetWindowPropInterface pStd:%x pOxidInfo:%x\n", pStd, pOxidInfo)); VDATEHEAP(); return hr; } #endif // DCOM