553 lines
17 KiB
C++
553 lines
17 KiB
C++
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft WMIOLE DB Provider
|
|
// (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
// IDBProperties and IDBInfo interface implementations
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#include "headers.h"
|
|
|
|
WCHAR g_szKeyWords[] = L"CLUSTERED,COMMITTED,COMPUTE,CONFIRM,CONTROLROW,DATABASE,DENY,DISK,DISTRIBUTED,DUMMY,DUMP,"
|
|
L"ERRLVL,ERROREXIT,EXIT,FILLFACTOR,FLOPPY,HOLDLOCK,IDENTITY_INSERT,IDENTITYCOL,IF,INDEX,KILL,"
|
|
L"LINENO,LOAD,LOG,NOCHECK,NONCLUSTERED,OFF,OFFSETS,ONCE,OVER,PERCENT,PERM,PERMANENT,PIPE,PLAN,"
|
|
L"PRINT,PROC,PROCESSEXIT,QUALIFIER,RECONFIGURE,REPEATABLE,REPLICATION,RETURN,ROWCOUNT,RULE,SAVE,"
|
|
L"SETUSER,SHUTDOWN,STATISTICS,TAPE,TEMP,TEXTSIZE,TOP,TRAN,TRUNCATE,TSEQUAL,UNCOMMITTED,"
|
|
L"UPDATETEXT,WHILE";
|
|
|
|
|
|
#define KEYWORD_MAXSIZE 1024
|
|
#define NUMBER_OF_SUPPORTED_LITERALS 7
|
|
|
|
DBLITERAL g_SupportedLiterals[] = { DBLITERAL_CATALOG_NAME,
|
|
DBLITERAL_CHAR_LITERAL,
|
|
DBLITERAL_COLUMN_NAME,
|
|
DBLITERAL_SCHEMA_NAME,
|
|
DBLITERAL_SCHEMA_SEPARATOR,
|
|
DBLITERAL_TABLE_NAME,
|
|
DBLITERAL_TEXT_COMMAND};
|
|
DBLITERALINFO g_SupportedInfo[] = {
|
|
{ L"",
|
|
L"!\"%&()*+-,/;:<=>?@[\\]^{|}~" ,
|
|
L"0123456789!\"%%&()*+-,/;:<=>?@[\\]^{|}~_ ",
|
|
DBLITERAL_CATALOG_NAME,
|
|
TRUE,
|
|
~0
|
|
} ,
|
|
|
|
{ L"",
|
|
L"" ,
|
|
L"",
|
|
DBLITERAL_CHAR_LITERAL,
|
|
TRUE,
|
|
0
|
|
} ,
|
|
{ L"",
|
|
L"!\"%&()*+-,/;:<=>?@[\\]^{|}~" ,
|
|
L"0123456789!\"%%&()*+-,/;:<=>?@[\\]^{|}~_ ",
|
|
DBLITERAL_COLUMN_NAME,
|
|
TRUE,
|
|
~0
|
|
} ,
|
|
{ L"",
|
|
L"!\"%&()*+-,/;:<=>?@[\\]^{|}~" ,
|
|
L"0123456789!\"%%&()*+-,/;:<=>?@[\\]^{|}~_ ",
|
|
DBLITERAL_SCHEMA_NAME,
|
|
TRUE,
|
|
~0
|
|
} ,
|
|
{ L".",
|
|
L"",
|
|
L"",
|
|
DBLITERAL_SCHEMA_SEPARATOR,
|
|
TRUE,
|
|
1
|
|
} ,
|
|
{ L"",
|
|
L"!\"%&()*+-,/;:<=>?@[\\]^{|}~" ,
|
|
L"0123456789!\"%%&()*+-,/;:<=>?@[\\]^{|}~_ ",
|
|
DBLITERAL_TABLE_NAME,
|
|
TRUE,
|
|
~0
|
|
} ,
|
|
{ L"",
|
|
L"",
|
|
L"",
|
|
DBLITERAL_TEXT_COMMAND,
|
|
TRUE,
|
|
0
|
|
}
|
|
};
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IDBInfo specific interface methods
|
|
//
|
|
// Returns information about keywords used in text commands
|
|
//
|
|
// HRESULT
|
|
// S_OK Keywords successfully returned, NULL because no keywords
|
|
// E_INVALIDARG ppwszKeywords was NULL
|
|
// E_UNEXPECTED Can not be called unless initialized
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CImpIDBInfo::GetKeywords( LPWSTR* ppwszKeywords )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CSetStructuredExceptionHandler seh;
|
|
WCHAR wcsKeyWords[KEYWORD_MAXSIZE];
|
|
wcscpy(wcsKeyWords,L"");
|
|
|
|
TRY_BLOCK;
|
|
|
|
WMIOledb_LoadStringW(IDS_DBKEYWORDS,wcsKeyWords,KEYWORD_MAXSIZE * sizeof(WCHAR));
|
|
//=========================
|
|
// Serialize the object
|
|
//=========================
|
|
CAutoBlock cab(DATASOURCE->GetCriticalSection());
|
|
g_pCError->ClearErrorInfo();
|
|
|
|
//=================================================================
|
|
// Initialize
|
|
//=================================================================
|
|
if (ppwszKeywords){
|
|
*ppwszKeywords = NULL;
|
|
}
|
|
|
|
//=================================================================
|
|
// check params
|
|
//=================================================================
|
|
if (NULL == ppwszKeywords){
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
//=================================================================
|
|
// check if we are initialized
|
|
//=================================================================
|
|
else if (!m_pObj->m_fDSOInitialized){
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
*ppwszKeywords = (LPWSTR)g_pIMalloc->Alloc((wcslen(wcsKeyWords) + 1) * sizeof(WCHAR));
|
|
}
|
|
catch(...)
|
|
{
|
|
if(*ppwszKeywords)
|
|
{
|
|
g_pIMalloc->Free(*ppwszKeywords);
|
|
}
|
|
throw;
|
|
}
|
|
|
|
if(*ppwszKeywords)
|
|
{
|
|
wcscpy(*ppwszKeywords, wcsKeyWords);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IDBInfo);
|
|
|
|
CATCH_BLOCK_HRESULT(hr,L"IDBInfo::GetKeywords");
|
|
return hr;
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Returns information about literals used in text command
|
|
//
|
|
// HRESULT
|
|
// S_OK cLiterals was 0
|
|
// E_INVALIDARG cLiterals not equal to 0 and rgLiterals was NULL or pcLiteralInfo,
|
|
// prgLiteralInfo, or ppCharBuffer was NULL
|
|
// E_UNEXPECTED Can not be called unless initialized
|
|
// DB_E_ERRORSOCCURRED None of the requested literals are supported
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CImpIDBInfo::GetLiteralInfo (
|
|
ULONG cLiterals, // IN Number of literals being asked about
|
|
const DBLITERAL rgLiterals[], // IN Array of literals about which to return information
|
|
ULONG* pcLiteralInfo, // OUT Number of literals for which info is returned
|
|
DBLITERALINFO** prgLiteralInfo, // OUT Array of info structures
|
|
WCHAR** ppCharBuffer // OUT Buffer for characters
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CSetStructuredExceptionHandler seh;
|
|
|
|
TRY_BLOCK;
|
|
|
|
//==================================================================
|
|
// Initialize
|
|
//==================================================================
|
|
if( pcLiteralInfo ){
|
|
*pcLiteralInfo = 0;
|
|
}
|
|
if( prgLiteralInfo ){
|
|
*prgLiteralInfo = NULL;
|
|
}
|
|
if( ppCharBuffer ){
|
|
*ppCharBuffer = NULL;
|
|
}
|
|
|
|
// Serialize the object
|
|
CAutoBlock cab(DATASOURCE->GetCriticalSection());
|
|
g_pCError->ClearErrorInfo();
|
|
|
|
//==================================================================
|
|
// check params
|
|
//==================================================================
|
|
if ((cLiterals != 0) && (rgLiterals == NULL))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else if (!pcLiteralInfo || !prgLiteralInfo || !ppCharBuffer)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else if (!m_pObj->m_fDSOInitialized)
|
|
{
|
|
//==============================================================
|
|
// check if we are initialized
|
|
//==============================================================
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
else
|
|
{
|
|
|
|
ULONG cLiteralsToFetch = cLiterals == 0 ? NUMBER_OF_SUPPORTED_LITERALS : cLiterals;
|
|
|
|
//==========================================================
|
|
// Allocate memory for return information
|
|
// - DBLITERALINFO array
|
|
//==========================================================
|
|
try
|
|
{
|
|
*prgLiteralInfo = (DBLITERALINFO*)g_pIMalloc->Alloc(cLiteralsToFetch * sizeof(DBLITERALINFO));
|
|
*ppCharBuffer = (WCHAR *)g_pIMalloc->Alloc(GetStringBufferSize(cLiterals,rgLiterals));
|
|
}
|
|
catch(...)
|
|
{
|
|
if(*prgLiteralInfo)
|
|
{
|
|
g_pIMalloc->Free(*prgLiteralInfo);
|
|
*prgLiteralInfo = NULL;
|
|
}
|
|
if(*ppCharBuffer)
|
|
{
|
|
g_pIMalloc->Free(*ppCharBuffer);
|
|
*ppCharBuffer = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
if (!(*prgLiteralInfo) || !(*ppCharBuffer))
|
|
{
|
|
|
|
if(*prgLiteralInfo)
|
|
{
|
|
g_pIMalloc->Free(*prgLiteralInfo);
|
|
*prgLiteralInfo = NULL;
|
|
}
|
|
if(*ppCharBuffer)
|
|
{
|
|
g_pIMalloc->Free(*ppCharBuffer);
|
|
*ppCharBuffer = NULL;
|
|
}
|
|
hr= E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
LONG lLiteralIndex = 0;
|
|
WCHAR *pTemp = *ppCharBuffer;
|
|
|
|
memset(*prgLiteralInfo , 0 , sizeof(DBLITERALINFO) * cLiteralsToFetch);
|
|
memset(*ppCharBuffer , 0 , GetStringBufferSize(cLiterals,rgLiterals));
|
|
|
|
for(ULONG lIndex = 0; lIndex < cLiteralsToFetch ; lIndex++)
|
|
{
|
|
lLiteralIndex = -1;
|
|
lLiteralIndex = cLiterals == 0 ? lIndex : GetLiteralIndex(rgLiterals[lIndex]);
|
|
|
|
if(lLiteralIndex >= 0)
|
|
{
|
|
if(g_SupportedInfo[lLiteralIndex].pwszLiteralValue != NULL)
|
|
{
|
|
// copy the litervalue
|
|
wcscpy(pTemp,g_SupportedInfo[lLiteralIndex].pwszLiteralValue);
|
|
(*prgLiteralInfo)[lIndex].pwszLiteralValue = pTemp;
|
|
(*prgLiteralInfo)[lIndex].cchMaxLen = wcslen(pTemp);
|
|
pTemp += (wcslen(pTemp) + 1);
|
|
}
|
|
else
|
|
{
|
|
(*prgLiteralInfo)[lIndex].pwszLiteralValue = NULL;
|
|
}
|
|
|
|
if(g_SupportedInfo[lLiteralIndex].pwszInvalidChars != NULL)
|
|
{
|
|
// copy the litervalue
|
|
wcscpy(pTemp,g_SupportedInfo[lLiteralIndex].pwszInvalidChars);
|
|
(*prgLiteralInfo)[lIndex].pwszInvalidChars = pTemp;
|
|
if(wcslen(pTemp) > (*prgLiteralInfo)[lIndex].cchMaxLen)
|
|
{
|
|
(*prgLiteralInfo)[lIndex].cchMaxLen = wcslen(pTemp);
|
|
}
|
|
|
|
pTemp += (wcslen(pTemp) + 1);
|
|
}
|
|
else
|
|
{
|
|
(*prgLiteralInfo)[lIndex].pwszInvalidChars = NULL;
|
|
}
|
|
|
|
if(g_SupportedInfo[lLiteralIndex].pwszInvalidStartingChars != NULL)
|
|
{
|
|
// copy the litervalue
|
|
wcscpy(pTemp,g_SupportedInfo[lLiteralIndex].pwszInvalidStartingChars);
|
|
(*prgLiteralInfo)[lIndex].pwszInvalidStartingChars = pTemp;
|
|
if(wcslen(pTemp) > (*prgLiteralInfo)[lIndex].cchMaxLen)
|
|
{
|
|
(*prgLiteralInfo)[lIndex].cchMaxLen = wcslen(pTemp);
|
|
}
|
|
pTemp += (wcslen(pTemp) + 1);
|
|
}
|
|
else
|
|
{
|
|
(*prgLiteralInfo)[lIndex].pwszInvalidStartingChars = NULL;
|
|
}
|
|
|
|
(*prgLiteralInfo)[lIndex].lt = g_SupportedInfo[lLiteralIndex].lt;
|
|
(*prgLiteralInfo)[lIndex].fSupported = TRUE;
|
|
|
|
} // if valid literal index
|
|
|
|
} // for loop
|
|
|
|
} // after succesfull memory allocation
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
*pcLiteralInfo = cLiteralsToFetch;
|
|
}
|
|
|
|
} // initial parameter checking
|
|
|
|
|
|
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IDBInfo);
|
|
|
|
CATCH_BLOCK_HRESULT(hr,L"IDBInfo::GetLiteralInfo");
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
// Get index of the given literal in the global array
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
LONG CImpIDBInfo::GetLiteralIndex(DBLITERAL rgLiterals)
|
|
{
|
|
LONG lRet = -1;
|
|
for( int i = 0 ; i < NUMBER_OF_SUPPORTED_LITERALS ; i++)
|
|
{
|
|
if(g_SupportedLiterals[i] == rgLiterals)
|
|
{
|
|
lRet = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
// Get length of buffer to be allocated for strings
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
LONG CImpIDBInfo::GetStringBufferSize(ULONG cLiterals, // IN Number of literals being asked about
|
|
const DBLITERAL rgLiterals[])
|
|
{
|
|
LONG lBuffSize = 0;
|
|
|
|
LONG lLiteralIndex = 0;
|
|
LONG cLiteralsToFetch = cLiterals == 0 ? NUMBER_OF_SUPPORTED_LITERALS : cLiterals;
|
|
|
|
for(LONG lIndex =0 ; lIndex < cLiteralsToFetch ; lIndex++)
|
|
{
|
|
lLiteralIndex = -1;
|
|
lLiteralIndex = cLiterals == 0 ? lIndex : GetLiteralIndex(rgLiterals[lIndex]);
|
|
|
|
if(lLiteralIndex >= 0)
|
|
{
|
|
lBuffSize += wcslen(g_SupportedInfo[lLiteralIndex].pwszLiteralValue) + 1;
|
|
lBuffSize += wcslen(g_SupportedInfo[lLiteralIndex].pwszInvalidChars) + 1;
|
|
lBuffSize += wcslen(g_SupportedInfo[lLiteralIndex].pwszInvalidStartingChars) + 1;
|
|
}
|
|
}
|
|
lBuffSize *= sizeof(WCHAR);
|
|
return lBuffSize;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Returns information about rowset and data source properties supported by the provider
|
|
//
|
|
// HRESULT
|
|
// S_OK The method succeeded
|
|
// E_INVALIDARG pcPropertyInfo or prgPropertyInfo was NULL
|
|
// E_OUTOFMEMORY Out of memory
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CImpIDBProperties::GetPropertyInfo (
|
|
ULONG cPropertySets, // IN Number of properties being asked about
|
|
const DBPROPIDSET rgPropertySets[], // IN Array of cPropertySets properties about which to return information
|
|
ULONG* pcPropertyInfoSets, // OUT Number of properties for which information is being returned
|
|
DBPROPINFOSET** prgPropertyInfoSets,// OUT Buffer containing default values returned
|
|
WCHAR** ppDescBuffer // OUT Buffer containing property descriptions
|
|
)
|
|
{
|
|
assert( m_pObj );
|
|
assert( m_pObj->m_pUtilProp );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
CSetStructuredExceptionHandler seh;
|
|
|
|
TRY_BLOCK;
|
|
|
|
// Serialize the object
|
|
CAutoBlock cab(DATASOURCE->GetCriticalSection());
|
|
g_pCError->ClearErrorInfo();
|
|
|
|
//=====================================================================================
|
|
// just pass this call on to the utility object that manages our properties
|
|
//=====================================================================================
|
|
hr = m_pObj->m_pUtilProp->GetPropertyInfo(
|
|
m_pObj->m_fDSOInitialized,
|
|
cPropertySets,
|
|
rgPropertySets,
|
|
pcPropertyInfoSets,
|
|
prgPropertyInfoSets,
|
|
ppDescBuffer);
|
|
|
|
|
|
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IDBProperties);
|
|
|
|
CATCH_BLOCK_HRESULT(hr,L"IDBProperties::GetPropertyInfo");
|
|
return hr;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Returns current settings of all properties in the FLAGS_DATASRCINF property group
|
|
//
|
|
// HRESULT
|
|
// S_OK The method succeeded
|
|
// E_INVALIDARG pcProperties or prgPropertyInfo was NULL
|
|
// E_OUTOFMEMORY Out of memory
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CImpIDBProperties::GetProperties (
|
|
ULONG cPropertySets, // IN count of restiction guids
|
|
const DBPROPIDSET rgPropertySets[], // IN restriction guids
|
|
ULONG* pcProperties, // OUT count of properties returned
|
|
DBPROPSET** prgProperties // OUT property information returned
|
|
)
|
|
{
|
|
DWORD dwBitMask = PROPSET_DSO;
|
|
|
|
assert( m_pObj );
|
|
assert( m_pObj->m_pUtilProp );
|
|
HRESULT hr = S_OK;
|
|
|
|
CSetStructuredExceptionHandler seh;
|
|
|
|
TRY_BLOCK;
|
|
|
|
// Serialize the object
|
|
CAutoBlock cab(DATASOURCE->GetCriticalSection());
|
|
g_pCError->ClearErrorInfo();
|
|
|
|
//=================================================================================
|
|
// set BitMask
|
|
//=================================================================================
|
|
if ( m_pObj->m_fDSOInitialized ){
|
|
dwBitMask |= PROPSET_INIT;
|
|
}
|
|
|
|
//=================================================================================
|
|
// Check Arguments
|
|
//=================================================================================
|
|
hr = m_pObj->m_pUtilProp->GetPropertiesArgChk(dwBitMask, cPropertySets, rgPropertySets, pcProperties, prgProperties,m_pObj->m_fDSOInitialized);
|
|
if ( !FAILED(hr) ){
|
|
|
|
//=============================================================================
|
|
// Just pass this call on to the utility object that manages our properties
|
|
//=============================================================================
|
|
hr = m_pObj->m_pUtilProp->GetProperties(dwBitMask,cPropertySets, rgPropertySets,pcProperties, prgProperties );
|
|
}
|
|
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IDBProperties);
|
|
|
|
CATCH_BLOCK_HRESULT(hr,L"IDBProperties::GetProperties");
|
|
return hr;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Set properties in the FLAGS_DATASRCINF property group
|
|
//
|
|
// HRESULT
|
|
// S_OK | The method succeeded
|
|
// E_INVALIDARG | cProperties was not equal to 0 and rgProperties was NULL
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CImpIDBProperties::SetProperties ( ULONG cProperties,DBPROPSET rgProperties[] )
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
DWORD dwBitMask = PROPSET_DSO;
|
|
|
|
assert( m_pObj );
|
|
assert( m_pObj->m_pUtilProp );
|
|
|
|
CSetStructuredExceptionHandler seh;
|
|
|
|
TRY_BLOCK;
|
|
|
|
// Serialize the object
|
|
CAutoBlock cab(DATASOURCE->GetCriticalSection());
|
|
g_pCError->ClearErrorInfo();
|
|
|
|
//===================================================================================
|
|
// Quick return if the Count of Properties is 0
|
|
//===================================================================================
|
|
if( cProperties == 0 ){
|
|
hr = S_OK ;
|
|
}
|
|
|
|
//===================================================================================
|
|
// Check Arguments for use by properties
|
|
//===================================================================================
|
|
hr = m_pObj->m_pUtilProp->SetPropertiesArgChk(cProperties, rgProperties,m_pObj->m_fDSOInitialized);
|
|
if( !FAILED(hr) ){
|
|
|
|
//===================================================================================
|
|
// set BitMask
|
|
//===================================================================================
|
|
if ( m_pObj->m_fDSOInitialized )
|
|
dwBitMask |= PROPSET_INIT;
|
|
|
|
//===================================================================================
|
|
// just pass this call on to the utility object that manages our properties
|
|
//===================================================================================
|
|
hr = m_pObj->m_pUtilProp->SetProperties(dwBitMask,cProperties, rgProperties);
|
|
}
|
|
|
|
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IDBProperties);
|
|
|
|
CATCH_BLOCK_HRESULT(hr,L"IDBProperties::SetProperties");
|
|
return hr;
|
|
}
|
|
|
|
|