windows-nt/Source/XPSP1/NT/admin/wmi/wbem/adapters/oledb/iscopedoperation.cpp
2020-09-26 16:20:57 +08:00

738 lines
21 KiB
C++

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