/////////////////////////////////////////////////////////////////////////// // // Microsoft WMIOLE DB Provider // // (C) Copyright 2000-1999 Microsoft Corporation. All Rights Reserved. // // IBindResource.CPP CImplIBindResource interface implementation // /////////////////////////////////////////////////////////////////////////// #include "headers.h" //////////////////////////////////////////////////////////////////////////////// // Method of the IBindResource which binds the requested URL // Returns one of the following values: // S_OK Bind succeeded // DB_S_ERRORSOCCURRED Bind succeeded, but some bind flags // or properties were not satisfied // DB_E_NOAGGREGATION Aggregation not supported by the // object requested // DB_E_NOTFOUND Object requested as from URL not found // DB_E_OBJECTMISMATCH The object requested and the URL passed // does not match // DB_SEC_E_PERMISSIONDENIED User does not have permission for the // object requested // E_FAIL Other error ( WMI specifice errors) // E_INVALIDARG one or more arguments are not valid // E_NOINTERFACE The interface requested is not supported // E_UNEXPECTED unexpected error // NOTE: This should be allowed for only Scopes as the path of the objects in // scope have the path of the scope in which they are and make sense only for // that. In case of objects in container, these objects can be in as many // container as it wants and its path need not be dependent on the containee //////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CImpIScopedOperations::Bind(IUnknown * pUnkOuter, LPCOLESTR pwszURL, DBBINDURLFLAG dwBindURLFlags, REFGUID rguid, REFIID riid, IAuthenticate * pAuthenticate, DBIMPLICITSESSION * pImplSession, DBBINDURLSTATUS * pdwBindStatus, IUnknown ** ppUnk) { HRESULT hr = DB_E_NOTSUPPORTED; WCHAR * pstrUrl = NULL; CSetStructuredExceptionHandler seh; // Bind is allowed only for Scopes if(!m_pObj->IsContainer()) { TRY_BLOCK; // Serialize the object CAutoBlock cab(m_pObj->GetCriticalSection()); g_pCError->ClearErrorInfo(); // If URL is NULL return Invalid Argument if(pwszURL == NULL) { hr = E_INVALIDARG; } else { try { // Allocate the string pstrUrl = new WCHAR[wcslen(pwszURL) + 1]; hr = S_OK; } catch(...) { SAFE_DELETE_PTR(pstrUrl); } wcscpy(pstrUrl,pwszURL); if(SUCCEEDED(hr = CheckIfProperURL(pstrUrl,rguid))) { if( pUnkOuter != NULL && riid != IID_IUnknown) { hr = DB_E_NOAGGREGATION; } else { //======================================================================== // Calling this to bind the URL to the appropriate object //======================================================================== hr = BindURL(pUnkOuter,pstrUrl,dwBindURLFlags,rguid,riid,pImplSession,pdwBindStatus,ppUnk); } } SAFE_DELETE_ARRAY(pstrUrl); } CATCH_BLOCK_HRESULT(hr,L"IScopedOperations::Bind"); } hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IBindResource); return hr; } //////////////////////////////////////////////////////////////////////////////// // Copy link from one container to another container // Returns one of the following values: //////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CImpIScopedOperations::Copy(DBCOUNTITEM cRows, LPCOLESTR __RPC_FAR rgpwszSourceURLs[ ], LPCOLESTR __RPC_FAR rgpwszDestURLs[ ], DWORD dwCopyFlags, IAuthenticate __RPC_FAR *pAuthenticate, DBSTATUS __RPC_FAR rgdwStatus[ ], LPOLESTR __RPC_FAR rgpwszNewURLs[ ], OLECHAR __RPC_FAR *__RPC_FAR *ppStringsBuffer) { HRESULT hr = S_OK; CSetStructuredExceptionHandler seh; TRY_BLOCK; // Seriliaze the object CAutoBlock cab(m_pObj->GetCriticalSection()); // Clear Error information g_pCError->ClearErrorInfo(); if(!m_pObj->IsContainer() && !(dwCopyFlags & DBCOPY_NON_RECURSIVE)) { hr = DB_E_NOTSUPPORTED; LogMessage("Copy of the entire sub tree is not supported for Scopes"); } else if(cRows) { //====================================================================================================== // The last parameter specifies ManipulateObjects to Copy objects from one scope/contianer to another //====================================================================================================== ManipulateObjects(cRows,rgpwszSourceURLs,rgpwszDestURLs,rgdwStatus,rgpwszNewURLs,ppStringsBuffer,FALSE); } CATCH_BLOCK_HRESULT(hr,L"IScopedOperations::Copy"); return hr; } //////////////////////////////////////////////////////////////////////////////// // Moving item from one container to another container // Returns one of the following values: //////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CImpIScopedOperations::Move(DBCOUNTITEM cRows, LPCOLESTR __RPC_FAR rgpwszSourceURLs[ ], LPCOLESTR __RPC_FAR rgpwszDestURLs[ ], DWORD dwMoveFlags, IAuthenticate __RPC_FAR *pAuthenticate, DBSTATUS __RPC_FAR rgdwStatus[ ], LPOLESTR __RPC_FAR rgpwszNewURLs[ ], OLECHAR __RPC_FAR *__RPC_FAR *ppStringsBuffer) { HRESULT hr = S_OK; CSetStructuredExceptionHandler seh; // Seriliaze the object CAutoBlock cab(m_pObj->GetCriticalSection()); // Clear Error information g_pCError->ClearErrorInfo(); ppStringsBuffer = NULL; TRY_BLOCK if(!m_pObj->IsContainer()) { hr = DB_E_NOTSUPPORTED; LogMessage("Move not supported on a scope object"); } else if(cRows) { //====================================================================================================== // The last parameter specifies ManipulateObjects to Move objects from one contianer to another //====================================================================================================== hr = ManipulateObjects(cRows,rgpwszSourceURLs,rgpwszDestURLs,rgdwStatus,rgpwszNewURLs,ppStringsBuffer,TRUE); } CATCH_BLOCK_HRESULT(hr,L"IScopedOperations::Move"); hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IBindResource); return hr; } //////////////////////////////////////////////////////////////////////////////// // Deleting objects from container. This can also be used to delete // items from scope // Returns one of the following values: //////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CImpIScopedOperations::Delete(DBCOUNTITEM cRows, LPCOLESTR __RPC_FAR rgpwszURLs[ ], DWORD dwDeleteFlags, DBSTATUS __RPC_FAR rgdwStatus[ ]) { HRESULT hr = S_OK; BOOL bContainer = FALSE; DBSTATUS dbStatus; DBCOUNTITEM cError = 0; WCHAR * pstrUrl = NULL; CSetStructuredExceptionHandler seh; // Seriliaze the object CAutoBlock cab(m_pObj->GetCriticalSection()); // Clear Error information g_pCError->ClearErrorInfo(); if(cRows > 0) { TRY_BLOCK for ( DBCOUNTITEM item = 0 ; item < cRows ; item++) { dbStatus = DBSTATUS_S_OK; try { // Allocate the string pstrUrl = new WCHAR[wcslen(rgpwszURLs[item]) + 1]; } catch(...) { SAFE_DELETE_PTR(pstrUrl); } if(pstrUrl) { memset(pstrUrl,0,(wcslen(rgpwszURLs[item]) + 1) * sizeof(WCHAR)); hr = S_OK; wcscpy(pstrUrl,rgpwszURLs[item]); } else { hr = E_OUTOFMEMORY; break; } //============================================= // check if the URL passed is valid //============================================= if(SUCCEEDED(hr = CheckIfProperURL(pstrUrl,DBGUID_ROW))) { //====================================================== // call this function to delete the object passed // refered in the URL //====================================================== if(FAILED(m_pObj->Delete(pstrUrl,dwDeleteFlags,dbStatus))) { cError++; } if(rgdwStatus) { rgdwStatus[item] = dbStatus; } } else { if(rgdwStatus) { rgdwStatus[item] = DBSTATUS_E_INVALIDURL; } cError++; hr = S_OK; } SAFE_DELETE_PTR(pstrUrl); } // for loop if(SUCCEEDED(hr)) { hr = cError > 0 ? DB_S_ERRORSOCCURRED: S_OK; } hr = cError >= cRows ? DB_E_ERRORSOCCURRED: hr; hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IBindResource); CATCH_BLOCK_HRESULT(hr,L"IScopedOperations::Delete"); } return hr; } //////////////////////////////////////////////////////////////////////////////// // Opening a rowset contiang objects in scope/container // Returns one of the following values: //////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CImpIScopedOperations::OpenRowset(IUnknown __RPC_FAR *pUnkOuter, DBID __RPC_FAR *pTableID, DBID __RPC_FAR *pIndexID, REFIID riid, ULONG cPropertySets, DBPROPSET __RPC_FAR rgPropertySets[ ], IUnknown __RPC_FAR *__RPC_FAR *ppRowset) { HRESULT hr = S_OK; WCHAR * pTempStr = NULL; WCHAR * pStrURL = NULL; CSetStructuredExceptionHandler seh; if( ppRowset ) { *ppRowset = NULL; } TRY_BLOCK; // Seriliaze the object CAutoBlock cab(m_pObj->GetCriticalSection()); // Clear Error information g_pCError->ClearErrorInfo(); //===================================================================== // Check Arguments //===================================================================== if ( riid == IID_NULL) { hr = E_NOINTERFACE; // return g_pCError->PostHResult(E_NOINTERFACE,&IID_IOpenRowset) ; } else //========================================================== // We only accept NULL for pIndexID at this present time //========================================================== if( pIndexID ) { hr = DB_E_NOINDEX; // return g_pCError->PostHResult(DB_E_NOINDEX,&IID_IOpenRowset) ; } else //=================================================================================== // We do not allow the riid to be anything other than IID_IUnknown for aggregation //=================================================================================== if ( (pUnkOuter) && (riid != IID_IUnknown) ) { hr = DB_E_NOAGGREGATION; // return g_pCError->PostHResult(DB_E_NOAGGREGATION,&IID_IOpenRowset) ; } if (pTableID == NULL || (pTableID != NULL && pTableID->eKind == DBKIND_NAME && pTableID->uName.pwszName == NULL) || (pTableID != NULL && pTableID->eKind == DBKIND_NAME && !wcscmp(pTableID->uName.pwszName,L"") )) { pTempStr = NULL; } else { pTempStr = pTableID->uName.pwszName; } if(SUCCEEDED(hr)) { if(pTempStr) { pStrURL = new WCHAR [ wcslen(pTempStr) + 1]; if(pStrURL) { wcscpy(pStrURL,pTempStr); } else { hr = E_OUTOFMEMORY; } } //==================================================== // Check if the URL passed is in the require format //==================================================== if(SUCCEEDED(hr) && SUCCEEDED(hr =CheckIfProperURL(pStrURL,DBGUID_ROWSET))) { //============================== // Open the rowset //============================== hr = m_pObj->OpenRowset(pStrURL,pUnkOuter,riid,TRUE,ppRowset,cPropertySets,rgPropertySets); } SAFE_DELETE_ARRAY(pStrURL); } hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IScopedOperations); CATCH_BLOCK_HRESULT(hr,L"IScopedOperations::OpenRowset"); return hr; } //////////////////////////////////////////////////////////////////////////////////////////// // Function which checks if the URL flags matches the requested object // This is as per the OLEDB specs /////////////////////////////////////////////////////////////////////////////////////////// BOOL CImpIScopedOperations::CheckBindURLFlags(DBBINDURLFLAG dwBindURLFlags , REFGUID rguid) { BOOL bFlag = FALSE; if( DBGUID_ROW == rguid) { bFlag = TRUE; } if( DBGUID_ROWSET == rguid) { if(!((dwBindURLFlags & DBBINDURLFLAG_DELAYFETCHCOLUMNS) || // Flags cannot have any of these two values (dwBindURLFlags & DBBINDURLFLAG_DELAYFETCHSTREAM))) bFlag = TRUE; } return bFlag; } //////////////////////////////////////////////////////////////////////////////////////////// // Function which checks if the URL is valid for the requested object /////////////////////////////////////////////////////////////////////////////////////////// HRESULT CImpIScopedOperations::CheckIfProperURL(LPOLESTR & lpszURL,REFGUID rguid) { HRESULT hr = S_OK; LONG lUrlType = -1; CURLParser urlParser; BOOL bEmptyURL = FALSE; // IScopedOperations::Bind supports binding of only // to rowset and row objects if(!(rguid == DBGUID_ROW || rguid == DBGUID_ROWSET)) { hr = DB_E_NOTSUPPORTED; } else // Empty URL can be passed only for OpenRowset call if(!lpszURL && rguid != DBGUID_ROWSET) { hr = E_INVALIDARG; } else if(urlParser.IsValidURL(lpszURL) != RELATIVEURL) { bEmptyURL = (lpszURL == NULL || (lpszURL != NULL && wcslen(lpszURL) == 0)); // if URL is null or empty string then the requested object has to be rowset or // if URL of the current row object and the object requested is same and if the row object is // requested then there is no meaning as the current row is reffering to the object if( (bEmptyURL && rguid != DBGUID_ROWSET) ||( wbem_wcsicmp(lpszURL,m_pObj->m_strURL) == 0 && rguid == DBGUID_ROW)) { hr = E_INVALIDARG; } else { // If URL is passed then the URL should be in the scope of the current object // otherwise there error should be returned if(!bEmptyURL && SUCCEEDED(hr = urlParser.SetURL(lpszURL))) { if(wbem_wcsincmp(m_pObj->m_strURL,lpszURL,wcslen(m_pObj->m_strURL))) { hr = DB_E_RESOURCEOUTOFSCOPE; } } } } return hr; } /////////////////////////////////////////////////////////////////////////// // Function to bind the requested URL /////////////////////////////////////////////////////////////////////////// HRESULT CImpIScopedOperations::BindURL(IUnknown * pUnkOuter, LPCOLESTR pwszURL, DBBINDURLFLAG dwBindURLFlags, REFGUID rguid, REFIID riid, DBIMPLICITSESSION * pImplSession, DBBINDURLSTATUS * pdwBindStatus, IUnknown ** ppUnk) { HRESULT hr = E_FAIL; IUnknown *pTempUnk = NULL; LONG lInitFlags = 0; LONG lBindFlags = 0; REFGUID guidTemp = GUID_NULL; IUnknown* pReqestedPtr = NULL; WCHAR * pStrTemp = NULL; GetInitAndBindFlagsFromBindFlags(dwBindURLFlags,lInitFlags,lBindFlags); //========================================================================================= // If requested object is row then call function to // to create a row //========================================================================================= if( rguid == DBGUID_ROW) { pReqestedPtr = NULL; hr = m_pObj->OpenRow(pwszURL,pUnkOuter,riid,&pReqestedPtr); } //========================================================================================= // If requested object is rowset then call function to // to create a rowset //========================================================================================= if( rguid == DBGUID_ROWSET) { pReqestedPtr = NULL; // This has to be changed to path . URL should not be sent // if DBBINDURLFLAG_COLLECTION flag of bindflags is set then , it means that the rowset is to // be opened as container hr = m_pObj->OpenRowset(pStrTemp,pUnkOuter,riid,(dwBindURLFlags & DBBINDURLFLAG_COLLECTION),&pReqestedPtr); } if( SUCCEEDED(hr)) { *ppUnk = pReqestedPtr; } return hr ; } ////////////////////////////////////////////////////////////////////////////////////////////// // Function to Move/Copy objects from one container to another ////////////////////////////////////////////////////////////////////////////////////////////// HRESULT CImpIScopedOperations::ManipulateObjects(DBCOUNTITEM cRows, LPCOLESTR __RPC_FAR rgpwszSourceURLs[ ], LPCOLESTR __RPC_FAR rgpwszDestURLs[ ], DBSTATUS __RPC_FAR rgdwStatus[ ], LPOLESTR __RPC_FAR rgpwszNewURLs[ ], OLECHAR __RPC_FAR *__RPC_FAR *ppStringsBuffer, BOOL bMoveObjects) { HRESULT hr = S_OK; WCHAR * pstrSrcURL = NULL; WCHAR * pStrDstURL = NULL; WCHAR * pstrNewURL = NULL; DBCOUNTITEM item = 0; DBCOUNTITEM cError = 0; DBSTATUS dbStatus = DBSTATUS_S_OK; // NTRaid:111804 // 06/07/00 WCHAR ** prgURL = NULL; if(cRows) { prgURL = new WCHAR*[cRows]; // NTRaid:111803 // 06/07/00 if(prgURL) { for(item = 0 ; item < cRows ; item++) { prgURL[item] = NULL; } try { for ( item = 0 ; item < cRows ; item++) { dbStatus = DBSTATUS_S_OK; // Allocate the string pstrSrcURL = new WCHAR[wcslen(rgpwszSourceURLs[item]) + 1]; pStrDstURL = new WCHAR[wcslen(rgpwszDestURLs[item]) + 1]; // NTRaid:111805 & 111806 // 06/07/00 if(!pstrSrcURL || !pStrDstURL) { SAFE_DELETE_ARRAY(pstrSrcURL); SAFE_DELETE_ARRAY(pStrDstURL); SAFE_DELETE_ARRAY(prgURL); hr = E_OUTOFMEMORY; break; } else { memset(pstrSrcURL,0,(wcslen(rgpwszSourceURLs[item]) + 1) * sizeof(WCHAR)); memset(pStrDstURL,0,(wcslen(rgpwszDestURLs[item]) + 1) * sizeof(WCHAR)); hr = S_OK; wcscpy(pstrSrcURL,rgpwszSourceURLs[item]); wcscpy(pStrDstURL,rgpwszDestURLs[item]); if((SUCCEEDED(hr = CheckIfProperURL(pstrSrcURL,DBGUID_ROW))) && (SUCCEEDED(hr = CheckIfProperURL(pStrDstURL,DBGUID_ROW)))) { if(bMoveObjects) { hr = m_pObj->MoveObjects(pStrDstURL,pstrSrcURL,prgURL[item],dbStatus); } else { hr = m_pObj->CopyObjects(pStrDstURL,pstrSrcURL,prgURL[item],dbStatus); } if(FAILED(hr)) { hr = S_OK; cError++; } else if(rgdwStatus) { rgdwStatus[item] = dbStatus; } } else { if(rgdwStatus) { rgdwStatus[item] = DBSTATUS_E_INVALIDURL; } cError++; hr = S_OK; } } SAFE_DELETE_ARRAY(pstrSrcURL); SAFE_DELETE_ARRAY(pStrDstURL); SAFE_DELETE_ARRAY(prgURL); } // for loop if(SUCCEEDED(hr)) { DBCOUNTITEM lNumberOfCharacters; for(item = 0 ; item < cRows ; item++) { if(rgpwszNewURLs) { rgpwszNewURLs[item] = prgURL[item]; } lNumberOfCharacters += wcslen(prgURL[item]); lNumberOfCharacters++; } //================================================================== // if the pointer is not NULL then allocate buffer for the // URL strings and fill the data //================================================================== if(ppStringsBuffer) { WCHAR *pTemp; *ppStringsBuffer = (OLECHAR *)g_pIMalloc->Alloc(lNumberOfCharacters * sizeof(WCHAR)); pTemp = *ppStringsBuffer; DBLENGTH lBytesToCopy = 0; for(item = 0 ; item < cRows ; item++) { lBytesToCopy = (wcslen(prgURL[item]) + 1) * sizeof(WCHAR); memcpy(pTemp,prgURL[item],lBytesToCopy); pTemp = (WCHAR *)(((BYTE *)pTemp) + lBytesToCopy); } } //================================================================== // if the output parameter is NULL then delete all the memory // allocated //================================================================== if(!rgpwszNewURLs) { for(item = 0 ; item < cRows ; item++) { SAFE_DELETE_ARRAY(prgURL[item]); } } } } catch(...) { //===================================== // Release the memory allocated //===================================== for(item = 0 ; item < cRows ; item++) { SAFE_DELETE_ARRAY(prgURL[item]); } SAFE_DELETE_ARRAY(pstrSrcURL); SAFE_DELETE_ARRAY(pStrDstURL); SAFE_DELETE_ARRAY(prgURL); if(*ppStringsBuffer) { g_pIMalloc->Free(*ppStringsBuffer); } throw; } if(SUCCEEDED(hr)) { hr = cError > 0 ? DB_S_ERRORSOCCURRED: S_OK; hr = (cError >= cRows) ? DB_E_ERRORSOCCURRED: hr; } else { if(ppStringsBuffer) { *ppStringsBuffer = NULL; } for(item = 0 ; item < cRows ; item++) { SAFE_DELETE_ARRAY(prgURL[item]); } SAFE_DELETE_ARRAY(pstrSrcURL); SAFE_DELETE_ARRAY(pStrDstURL); } SAFE_DELETE_ARRAY(prgURL); } else { hr = E_OUTOFMEMORY; } } return hr; }