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