//-- == 0------------------------------------------------------------------------- // // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1995 // // File: utilprop.cxx // // Contents: // // // History: 08-28-96 shanksh Created. // //---------------------------------------------------------------------------- // Notes - there are two main methods in this module: // - CUtilProps::GetPropertyInfo, a helper function for // GetProperty method on Data Source // - CUtilProps::GetProperties, a helper function for // GetProperties method on Data Source, Session and Command objects // - CUtilProps::SetProperties, a helper function for // SetProperties method on Data Source, Session and Command objects // // // The implementation is very simple - we keep a global table of the // properties we support in s_rgprop. We search this table sequentially. // #include "oleds.hxx" #pragma hdrstop PROPSTRUCT s_rgDBInitProp[] = { {DBPROP_AUTH_PASSWORD, F_DBINITRW, VT_BSTR, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Password"}, {DBPROP_AUTH_USERID, F_DBINITRW, VT_BSTR, VARIANT_FALSE, 0, OPT_REQ, NULL, L"User ID"}, {DBPROP_AUTH_ENCRYPT_PASSWORD, F_DBINITRW, VT_BOOL, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Encrypt Password"}, {DBPROP_AUTH_INTEGRATED, F_DBINITRW, VT_BSTR, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Integrated Security"}, {DBPROP_INIT_DATASOURCE, F_DBINITRW, VT_BSTR, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Data Source"}, {DBPROP_INIT_LOCATION, F_DBINITRW, VT_BSTR, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Location"}, {DBPROP_INIT_PROVIDERSTRING, F_DBINITRW, VT_BSTR, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Extended Properties"}, {DBPROP_INIT_TIMEOUT, F_DBINITRW, VT_I4, VARIANT_FALSE, 90, OPT_REQ, NULL, L"Connect Timeout"}, {DBPROP_INIT_PROMPT, F_DBINITRW, VT_I2, VARIANT_FALSE, DBPROMPT_NOPROMPT, OPT_REQ, NULL, L"Prompt"}, {DBPROP_INIT_HWND, F_DBINITRW, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Window Handle"}, {DBPROP_INIT_MODE, F_DBINITRW, VT_I4, VARIANT_FALSE, DB_MODE_READ, OPT_REQ, NULL, L"Mode"} #if (!defined(BUILD_FOR_NT40)) , {DBPROP_INIT_BINDFLAGS, F_DBINITRW, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Bind Flags"} #endif }; PROPSTRUCT s_rgADSIBindProp[] = { // initialize this property to a reserved value. The client is not supposed // to set this property to the reserved value. This reserved value prevents // ADSIFLAG from overriding ENCRYPT_PASSWORD when VB initializes this // property to its default value. See IsValidValue(). {ADSIPROP_ADSIFLAG, F_DBINITRW, VT_I4, VARIANT_FALSE, ADS_AUTH_RESERVED, OPT_REQ, NULL, L"ADSI Flag"} }; PROPSTRUCT s_rgDSInfoProp[] = { {DBPROP_ACTIVESESSIONS, F_DSRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Active Sessions"}, {DBPROP_BYREFACCESSORS, F_DSRO, VT_BOOL, VARIANT_FALSE, 1, OPT_REQ, NULL, L"Pass By Ref Accessors"}, {DBPROP_CATALOGLOCATION, F_DSRO, VT_I4, VARIANT_FALSE, DBPROPVAL_CL_START, OPT_REQ, NULL, L"Catalog Location"}, {DBPROP_CATALOGTERM, F_DSRO, VT_BSTR, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Catalog Term"}, {DBPROP_CATALOGUSAGE, F_DSRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Catalog Usage"}, {DBPROP_DATASOURCENAME, F_DSRO, VT_BSTR, VARIANT_FALSE, 0, OPT_REQ, L"Active Directory Service Interfaces", L"Data Source Name"}, {DBPROP_DATASOURCEREADONLY, F_DSRO, VT_BOOL, VARIANT_TRUE, 0, OPT_REQ, NULL, L"Read-Only Data Source"}, // {DBPROP_DBMSNAME, F_DSRO, VT_BSTR, VARIANT_FALSE, 0, OPT_REQ, NULL, L"DBMS Name"}, // {DBPROP_DBMSVER, F_DSRO, VT_BSTR, VARIANT_FALSE, 0, OPT_REQ, NULL, L"DBMS Version"}, {DBPROP_DSOTHREADMODEL, F_DSRO, VT_I4, VARIANT_FALSE, DBPROPVAL_RT_FREETHREAD, OPT_REQ, NULL, L"Data Source Object Threading Model"}, {DBPROP_MAXROWSIZE, F_DSRO, VT_I4, VARIANT_FALSE, 0, OPT_SIC, NULL, L"Maximum Row Size"}, #if (!defined(BUILD_FOR_NT40)) {DBPROP_OLEOBJECTS, F_DSRO, VT_I4, VARIANT_FALSE, DBPROPVAL_OO_ROWOBJECT | DBPROPVAL_OO_DIRECTBIND | DBPROPVAL_OO_SINGLETON, OPT_REQ, NULL, L"OLE Object Support"}, #endif {DBPROP_PERSISTENTIDTYPE, F_DSRO, VT_I4, VARIANT_FALSE, DBPROPVAL_PT_NAME, OPT_SIC, NULL, L"Persistent ID Type"}, {DBPROP_PROVIDERFRIENDLYNAME, F_DSRO, VT_BSTR, VARIANT_FALSE, 0, OPT_REQ, L"Microsoft OLE DB Provider for ADSI", L"Provider Friendly Name"}, {DBPROP_PROVIDERNAME, F_DSRO, VT_BSTR, VARIANT_FALSE, 0, OPT_REQ, L"ACTIVEDS.DLL", L"Provider Name"}, {DBPROP_PROVIDEROLEDBVER, F_DSRO, VT_BSTR, VARIANT_FALSE, 0, OPT_REQ, L"02.50", L"OLE DB Version"}, {DBPROP_PROVIDERVER, F_DSRO, VT_BSTR, VARIANT_FALSE, 0, OPT_REQ, L"02.50.0000", L"Provider Version"}, {DBPROP_SQLSUPPORT, F_DSRO, VT_I4, VARIANT_FALSE, DBPROPVAL_SQL_ODBC_MINIMUM, OPT_REQ, NULL, L"SQL Support"}, {DBPROP_ROWSETCONVERSIONSONCOMMAND, F_DSRO, VT_BOOL, VARIANT_TRUE, 0, OPT_REQ, NULL, L"Rowset Conversions on Command"}, {DBPROP_USERNAME, F_DSRO, VT_BSTR, VARIANT_FALSE, 0, OPT_REQ, NULL, L"User Name"} }; PROPSTRUCT s_rgRowsetProp[] = { {DBPROP_IAccessor, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_REQ, NULL, L"IAccessor"}, {DBPROP_IColumnsInfo, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_REQ, NULL, L"IColumnsInfo"}, #if (!defined(BUILD_FOR_NT40)) {DBPROP_IColumnsInfo2, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_REQ, NULL, L"IColumnsInfo2"}, #endif {DBPROP_IConvertType, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_REQ, NULL, L"IConvertType"}, #if (!defined(BUILD_FOR_NT40)) {DBPROP_IGetSession, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_REQ, NULL, L"IGetSession"}, {DBPROP_IRow, F_ROWSETRW, VT_BOOL, VARIANT_FALSE, 0, OPT_REQ, NULL, L"IRow"}, {DBPROP_IGetRow, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_REQ, NULL, L"IGetRow"}, #endif {DBPROP_IRowset, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_REQ, NULL, L"IRowset"}, {DBPROP_IRowsetIdentity, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_SIC, NULL, L"IRowsetIdentity"}, {DBPROP_IRowsetInfo, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_REQ, NULL, L"IRowsetInfo"}, {DBPROP_IRowsetLocate, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_REQ, NULL, L"IRowsetLocate"}, {DBPROP_IRowsetScroll, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_REQ, NULL, L"IRowsetScroll"}, {DBPROP_ABORTPRESERVE, F_ROWSETRO, VT_BOOL, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Preserve on Abort"}, {DBPROP_BLOCKINGSTORAGEOBJECTS, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_REQ, NULL, L"Blocking Storage Objects"}, {DBPROP_BOOKMARKS, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_REQ, NULL, L"Use Bookmarks"}, {DBPROP_BOOKMARKSKIPPED, F_ROWSETRO, VT_BOOL, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Skip Deleted Bookmarks"}, {DBPROP_BOOKMARKTYPE, F_ROWSETRO, VT_I4, VARIANT_FALSE, DBPROPVAL_BMK_NUMERIC, OPT_REQ, NULL, L"Bookmark Type"}, {DBPROP_CANFETCHBACKWARDS, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_SIC, NULL, L"Fetch Backwards"}, {DBPROP_CANHOLDROWS, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_SIC, NULL, L"Hold Rows"}, {DBPROP_CANSCROLLBACKWARDS, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_SIC, NULL, L"Scroll Backwards"}, {DBPROP_COLUMNRESTRICT, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_SIC, NULL, L"Column Privileges"}, {DBPROP_COMMITPRESERVE, F_ROWSETRO, VT_BOOL, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Preserve on Commit"}, {DBPROP_IMMOBILEROWS, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_SIC, NULL, L"Immobile Rows"}, {DBPROP_LITERALBOOKMARKS, F_ROWSETRO, VT_BOOL, VARIANT_FALSE, 0, OPT_SIC, NULL, L"Literal Bookmarks"}, {DBPROP_LITERALIDENTITY, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_REQ, NULL, L"Literal Row Identity"}, {DBPROP_MAXOPENROWS, F_ROWSETRW, VT_I4, VARIANT_FALSE, 0, OPT_SIC, NULL, L"Maximum Open Rows"}, {DBPROP_MAXPENDINGROWS, F_ROWSETRO, VT_I4, VARIANT_FALSE, 0, OPT_SIC, NULL, L"Maximum Pending Rows"}, {DBPROP_MAXROWS, F_ROWSETRO, VT_I4, VARIANT_FALSE, 0, OPT_SIC, NULL, L"Maximum Rows"}, {DBPROP_NOTIFICATIONPHASES, F_ROWSETRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Notification Phases"}, // {DBPROP_NOTIFYCOLUMNRECALCULATED, F_ROWSETRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"NotifyColumnRecalculated"}, {DBPROP_NOTIFYCOLUMNSET, F_ROWSETRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Column Set Notification"}, // {DBPROP_NOTIFYROWACTIVATE, F_ROWSETRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"NotifyRowActivate"}, {DBPROP_NOTIFYROWDELETE, F_ROWSETRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Row Delete Notification"}, {DBPROP_NOTIFYROWFIRSTCHANGE, F_ROWSETRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Row First Change Notification"}, {DBPROP_NOTIFYROWINSERT, F_ROWSETRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Row Insert Notification"}, // {DBPROP_NOTIFYROWRELEASE, F_ROWSETRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"NotifyRowRelease"}, {DBPROP_NOTIFYROWRESYNCH, F_ROWSETRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Row Resynchronization Notification"}, {DBPROP_NOTIFYROWSETRELEASE, F_ROWSETRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Rowset Release Notification"}, {DBPROP_NOTIFYROWSETFETCHPOSITIONCHANGE, F_ROWSETRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Rowset Fetch Position Change Notification"}, {DBPROP_NOTIFYROWUNDOCHANGE, F_ROWSETRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Row Undo Change Notification"}, {DBPROP_NOTIFYROWUNDODELETE, F_ROWSETRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Row Undo Delete Notification"}, {DBPROP_NOTIFYROWUNDOINSERT, F_ROWSETRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Row Undo Insert Notification"}, {DBPROP_NOTIFYROWUPDATE, F_ROWSETRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Row Update Notification"}, {DBPROP_ORDEREDBOOKMARKS, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_SIC, NULL, L"Bookmarks Ordered"}, {DBPROP_OWNINSERT, F_ROWSETRO, VT_BOOL, VARIANT_FALSE, 0, OPT_SIC, NULL, L"Own Inserts Visible"}, {DBPROP_OWNUPDATEDELETE, F_ROWSETRO, VT_BOOL, VARIANT_FALSE, 0, OPT_SIC, NULL, L"Own Changes Visible"}, {DBPROP_QUICKRESTART, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_SIC, NULL, L"Quick Restart"}, {DBPROP_REENTRANTEVENTS, F_ROWSETRO, VT_BOOL, VARIANT_TRUE, 0, OPT_REQ, NULL, L"Reentrant Events"}, {DBPROP_REMOVEDELETED, F_ROWSETRO, VT_BOOL, VARIANT_FALSE, 0, OPT_SIC, NULL, L"Remove Deleted Rows"}, {DBPROP_REPORTMULTIPLECHANGES, F_ROWSETRO, VT_BOOL, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Report Multiple Changes"}, {DBPROP_ROWRESTRICT, F_ROWSETRO, VT_BOOL, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Row Privileges"}, {DBPROP_ROWTHREADMODEL, F_ROWSETRO, VT_I4, VARIANT_FALSE, DBPROPVAL_RT_FREETHREAD, OPT_REQ, NULL, L"Row Threading Model"}, {DBPROP_STRONGIDENTITY, F_ROWSETRO, VT_BOOL, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Strong Row Identity"}, }; PROPSTRUCT s_rgDBSessProp[] = { {DBPROP_SESS_AUTOCOMMITISOLEVELS, F_SESSRO, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Autocommit Isolation Levels"}, }; PROPSTRUCT s_rgADSISearchProp[12] = { {ADSIPROP_ASYNCHRONOUS, F_ADSIRW, VT_BOOL, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Asynchronous"}, {ADSIPROP_DEREF_ALIASES, F_ADSIRW, VT_I4, VARIANT_FALSE, ADS_DEREF_NEVER, OPT_REQ, NULL, L"Deref Aliases"}, {ADSIPROP_SIZE_LIMIT, F_ADSIRW, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Size Limit"}, {ADSIPROP_TIME_LIMIT, F_ADSIRW, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Server Time Limit"}, {ADSIPROP_ATTRIBTYPES_ONLY, F_ADSIRW, VT_BOOL, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Column Names only"}, {ADSIPROP_SEARCH_SCOPE, F_ADSIRW, VT_I4, VARIANT_FALSE, ADS_SCOPE_SUBTREE, OPT_REQ, NULL, L"SearchScope"}, {ADSIPROP_TIMEOUT, F_ADSIRW, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Timeout"}, {ADSIPROP_PAGESIZE, F_ADSIRW, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Page size"}, {ADSIPROP_PAGED_TIME_LIMIT, F_ADSIRW, VT_I4, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Time limit"}, {ADSIPROP_CHASE_REFERRALS, F_ADSIRW, VT_I4, VARIANT_FALSE, ADS_CHASE_REFERRALS_NEVER, OPT_REQ, NULL, L"Chase referrals"}, {ADSIPROP_SORT_ON, F_ADSIRW, VT_BSTR, VARIANT_FALSE, 0, OPT_REQ, NULL, L"Sort On"}, {ADSIPROP_CACHE_RESULTS, F_ADSIRW, VT_BOOL, VARIANT_TRUE, 0, OPT_REQ, NULL, L"Cache Results"} }; // Number of supported properties per property set #define NUMBER_OF_SUPPORTED_PROPERTY_SETS 6 static PROPSET s_rgPropertySets[NUMBER_OF_SUPPORTED_PROPERTY_SETS] = { {&DBPROPSET_DBINIT, NUMELEM(s_rgDBInitProp), s_rgDBInitProp}, {&DBPROPSET_ADSIBIND, NUMELEM(s_rgADSIBindProp), s_rgADSIBindProp}, {&DBPROPSET_DATASOURCEINFO, NUMELEM(s_rgDSInfoProp), s_rgDSInfoProp}, {&DBPROPSET_SESSION, NUMELEM(s_rgDBSessProp), s_rgDBSessProp}, {&DBPROPSET_ROWSET, NUMELEM(s_rgRowsetProp), s_rgRowsetProp}, {&DBPROPSET_ADSISEARCH, NUMELEM(s_rgADSISearchProp),s_rgADSISearchProp} }; // // WARNING: Don't change the order. Add new property sets at the end // // Update: New property sets should not always be added at the end. // Property sets which have properties in the Initialization property group // have to be added before DATASOURCEINFO and prop. sets with properties // in the data source information property groups have to be added // before INDEX_SESSION and so on. This is for GetProperties to work correctly. // #define INDEX_INIT 0 #define INDEX_ADSIBIND 1 #define INDEX_DATASOURCEINFO 2 #define INDEX_SESSION 3 #define INDEX_ROWSET 4 #define INDEX_ADSISEARCH 5 //+--------------------------------------------------------------------------- // // Function: CUtilProp::CUtilProp // // Synopsis: Constructor for this class // // Arguments: // // Returns: // // Modifies: // // History: 08-28-96 ShankSh Created. // //---------------------------------------------------------------------------- CUtilProp::CUtilProp( void ) { _pIMalloc = NULL; _pCredentials = NULL; _prgProperties = NULL; _dwDescBufferLen = 0; } //+--------------------------------------------------------------------------- // // Function: CUtilProp::FInit // // Synopsis: // // Arguments: // // Returns: // // Modifies: // // History: 09-20-96 ShankSh Created. // // Update: pCredentials may be NULL if called from CRowset. // //---------------------------------------------------------------------------- STDMETHODIMP CUtilProp::FInit( CCredentials *pCredentials ) { HRESULT hr=S_OK; ULONG i, j; ULONG c = 0; // // Get the IMalloc interface pointer // hr = CoGetMalloc(MEMCTX_TASK, &_pIMalloc); BAIL_ON_FAILURE( hr ); _pCredentials = pCredentials; _prgProperties = (PROPSTRUCT*) AllocADsMem(sizeof(PROPSTRUCT) * (NUMELEM(s_rgDBInitProp) + NUMELEM(s_rgADSIBindProp) + NUMELEM(s_rgDSInfoProp) + NUMELEM(s_rgDBSessProp) + NUMELEM(s_rgRowsetProp) + NUMELEM(s_rgADSISearchProp)) ); if( !_prgProperties ) BAIL_ON_FAILURE ( hr=E_OUTOFMEMORY ); for (i=c=0; i< NUMBER_OF_SUPPORTED_PROPERTY_SETS; i++) { for (j=0; j < s_rgPropertySets[i].cProperties; j++) { // Copy static structure memcpy( &_prgProperties[c], &s_rgPropertySets[i].pUPropInfo[j], sizeof(PROPSTRUCT) ); // Allocate new BSTR value _prgProperties[c].pwstrVal = AllocADsStr(s_rgPropertySets[i].pUPropInfo[j].pwstrVal); // Add description length if( s_rgPropertySets[i].pUPropInfo[j].pwszDescription ) { _dwDescBufferLen += wcslen(s_rgPropertySets[i].pUPropInfo[j].pwszDescription) + 1; } c++; } } _dwDescBufferLen *= sizeof(WCHAR); ADsAssert( c == NUMELEM(s_rgDBInitProp) + NUMELEM(s_rgADSIBindProp) + NUMELEM(s_rgDSInfoProp) + NUMELEM(s_rgDBSessProp) + NUMELEM(s_rgRowsetProp) + NUMELEM(s_rgADSISearchProp) ); error: RRETURN( hr ); } //+--------------------------------------------------------------------------- // // Function: CUtilProp::~CUtilProp // // Synopsis: Destructor for this class // // Arguments: // // Returns: // // Modifies: // // History: 08-28-96 ShankSh Created. // //---------------------------------------------------------------------------- CUtilProp:: ~CUtilProp ( void ) { ULONG c = 0; if( _prgProperties ) { // Clear all of the String values for (ULONG i=c=0; i< NUMBER_OF_SUPPORTED_PROPERTY_SETS; i++) { for (ULONG j=0; j < s_rgPropertySets[i].cProperties; j++) { if( _prgProperties[c].pwstrVal ) FreeADsStr(_prgProperties[c].pwstrVal); c++; } } FreeADsMem(_prgProperties); } if( _pIMalloc ) _pIMalloc->Release(); return; } PROPSET * CUtilProp::GetPropSetFromGuid ( GUID guidPropSet ) { for (int j=0; j< NUMELEM(s_rgPropertySets); j++) { if (IsEqualGUID(guidPropSet, *(s_rgPropertySets[j].guidPropertySet))) return &(s_rgPropertySets[j]); } return NULL; } HRESULT CUtilProp::GetSearchPrefInfo( DBPROPID dwPropId, PADS_SEARCHPREF_INFO pSearchPrefInfo ) { PADS_SORTKEY pSortKey = NULL; LPWSTR pszAttrs = NULL; LPWSTR pszFirstAttr = NULL; LPWSTR pszCurrentAttr = NULL, pszNextAttr = NULL, pszOrder = NULL; DWORD cAttrs = 0; HRESULT hr = S_OK; DWORD index; if (!pSearchPrefInfo) { RRETURN (E_INVALIDARG); } if (dwPropId >= g_cMapDBPropToSearchPref) RRETURN(E_FAIL); pSearchPrefInfo->dwSearchPref = g_MapDBPropIdToSearchPref[dwPropId]; // // Get index of where ADSI search properties begin // index = NUMELEM(s_rgDBInitProp) + NUMELEM(s_rgADSIBindProp) + NUMELEM(s_rgDSInfoProp) + NUMELEM(s_rgDBSessProp) + NUMELEM(s_rgRowsetProp); switch (_prgProperties[index + dwPropId].vtType) { case VT_BOOL: pSearchPrefInfo->vValue.dwType = ADSTYPE_BOOLEAN; pSearchPrefInfo->vValue.Boolean = _prgProperties[index + dwPropId].boolVal == VARIANT_TRUE ? TRUE : FALSE; break; case VT_I4: case VT_I2: pSearchPrefInfo->vValue.dwType = ADSTYPE_INTEGER; pSearchPrefInfo->vValue.Integer = _prgProperties[index + dwPropId].longVal; break; case VT_BSTR: { if (pSearchPrefInfo->dwSearchPref != ADS_SEARCHPREF_SORT_ON) { // // right now, this is the only string preference supported // RRETURN (E_FAIL); } // // The preference is a list of atributes to be sorted on (in that order // and an optional indication of whether it has to be sorted ascending // or not. // eg., "name ASC, usnchanged DESC, cn" // pSearchPrefInfo->vValue.dwType = ADSTYPE_PROV_SPECIFIC; if (!_prgProperties[index + dwPropId].pwstrVal || !_wcsicmp(_prgProperties[index + dwPropId].pwstrVal, L"")) { pSearchPrefInfo->vValue.ProviderSpecific.dwLength = 0; pSearchPrefInfo->vValue.ProviderSpecific.lpValue = NULL; break; } // make a copy pszAttrs = AllocADsStr(_prgProperties[index + dwPropId].pwstrVal); pszCurrentAttr = pszFirstAttr = wcstok(pszAttrs, L","); for(cAttrs=0; pszCurrentAttr != NULL; cAttrs++ ) { pszCurrentAttr = wcstok(NULL, L","); } if(cAttrs == 0) { BAIL_ON_FAILURE ( hr = E_ADS_BAD_PARAMETER ); } pSortKey = (PADS_SORTKEY) AllocADsMem(sizeof(ADS_SORTKEY) * cAttrs); if (!pSortKey) { BAIL_ON_FAILURE ( E_OUTOFMEMORY ); } pszCurrentAttr = pszFirstAttr; for (DWORD i=0 ; i < cAttrs; i++) { pszNextAttr = pszCurrentAttr + wcslen(pszCurrentAttr) + 1; pszCurrentAttr = RemoveWhiteSpaces(pszCurrentAttr); pszOrder = wcstok(pszCurrentAttr, L" "); pszOrder = pszOrder ? wcstok(NULL, L" ") : NULL; if (pszOrder && !_wcsicmp(pszOrder, L"DESC")) pSortKey[i].fReverseorder = 1; else pSortKey[i].fReverseorder = 0; // This is the default pSortKey[i].pszAttrType = AllocADsStr(pszCurrentAttr); pSortKey[i].pszReserved = NULL; pszCurrentAttr = pszNextAttr; } pSearchPrefInfo->vValue.ProviderSpecific.dwLength = sizeof(ADS_SORTKEY) * cAttrs; pSearchPrefInfo->vValue.ProviderSpecific.lpValue = (LPBYTE) pSortKey; break; } default: RRETURN (E_FAIL); } error: if (pszAttrs) { FreeADsStr(pszAttrs); } RRETURN(hr); } HRESULT CUtilProp::FreeSearchPrefInfo( PADS_SEARCHPREF_INFO pSearchPrefInfo, DWORD dwNumSearchPrefs ) { PADS_SORTKEY pSortKey = NULL; DWORD nSortKeys = 0; if (!pSearchPrefInfo || !dwNumSearchPrefs) { RRETURN (S_OK); } for (DWORD i=0; ivValues ); for (cCount=0; cCount < cProperties; cCount++) { if(pPropInfo->dwPropertyID == pPropStruct[cCount].dwPropertyID) break; } if(cCount == cProperties) { pPropInfo->dwFlags = DBPROPFLAGS_NOTSUPPORTED; pPropInfo->pwszDescription = NULL; RRETURN (DB_S_ERRORSOCCURRED); } pProp = &(pPropStruct[cCount]); // // set the easy fields.. // pPropInfo->dwPropertyID = pProp->dwPropertyID; pPropInfo->dwFlags = pProp->dwFlags; pPropInfo->vtType = pProp->vtType; // fill in the description if (pPropInfo->pwszDescription) wcscpy(pPropInfo->pwszDescription, pProp->pwszDescription); RRETURN(S_OK); } //+--------------------------------------------------------------------------- // // Function: CUtilProp::LoadDBPROP // // Synopsis: Helper for GetProperties. Loads field of DBPROP structure. // // Arguments: // // Returns: TRUE : Method succeeded // FALSE : Method failed (couldn't allocate memory) // // Modifies: // // History: 08-28-96 ShankSh Created. // //---------------------------------------------------------------------------- STDMETHODIMP CUtilProp::LoadDBPROP ( PROPSTRUCT* pPropStruct, ULONG cProperties, DBPROP* pPropSupport, BOOL IsDBInitPropSet ) { ULONG cCount; PROPSTRUCT* pProp=NULL; LPWSTR szUserName=NULL, szPassword=NULL; BOOL fAuthFlags=0; // asserts ADsAssert( pPropSupport ); if( cProperties ) { ADsAssert( pPropStruct ); } // // init the variant // VariantInit( &pPropSupport->vValue ); for (cCount=0; cCount < cProperties; cCount++) { if( pPropSupport->dwPropertyID == pPropStruct[cCount].dwPropertyID ) break; } if( cCount == cProperties ) { pPropSupport->dwStatus = DBPROPSTATUS_NOTSUPPORTED; RRETURN ( DB_S_ERRORSOCCURRED ); } pProp = &(pPropStruct[cCount]); pPropSupport->colid = DB_NULLID; pPropSupport->dwOptions = pProp->dwOptions; // // set pPropSupport->vValue based on Variant type // switch (pProp->vtType) { case VT_BOOL: V_VT( &pPropSupport->vValue ) = VT_BOOL; V_BOOL( &pPropSupport->vValue ) = (SHORT)pProp->boolVal; break; case VT_I4: V_VT( &pPropSupport->vValue ) = VT_I4; V_I4( &pPropSupport->vValue ) = pProp->longVal; break; case VT_I2: V_VT( &pPropSupport->vValue ) = VT_I2; V_I2( &pPropSupport->vValue ) = (short)pProp->longVal; break; case VT_BSTR: // // If requesting password, get it from the credentials structure // as it is not stored anywhere else // if (IsDBInitPropSet && pPropSupport->dwPropertyID == DBPROP_AUTH_PASSWORD) { PWSTR pszPassword = NULL; if (FAILED(_pCredentials->GetPassword(&pszPassword))) { VariantClear( &pPropSupport->vValue ); return DB_S_ERRORSOCCURRED; } if (pszPassword) { V_VT(&pPropSupport->vValue) = VT_BSTR; V_BSTR(&pPropSupport->vValue)= SysAllocString(pszPassword); // // Zero out the password before freeing it // SecureZeroMemory(pszPassword, wcslen(pszPassword) * sizeof(WCHAR)); FreeADsMem(pszPassword); if( V_BSTR(&pPropSupport->vValue) == NULL ) { VariantClear( &pPropSupport->vValue ); return DB_S_ERRORSOCCURRED; } } } else if( pProp->pwstrVal ) { V_VT(&pPropSupport->vValue) = VT_BSTR; V_BSTR(&pPropSupport->vValue)= SysAllocString(pProp->pwstrVal); if( V_BSTR(&pPropSupport->vValue) == NULL ) { VariantClear( &pPropSupport->vValue ); return DB_S_ERRORSOCCURRED; } } break; default: ADsAssert( !"LoadDBPROP unknown variant type!\n\r" ); pPropSupport->dwStatus = DBPROPSTATUS_BADVALUE; RRETURN (DB_S_ERRORSOCCURRED); break; } // // all went well // pPropSupport->dwStatus = DBPROPSTATUS_OK; RRETURN(S_OK); } //+--------------------------------------------------------------------------- // // Function: CUtilProp::StoreDBProp // // Synopsis: Helper for SetProperties. Loads field of DBPROP structure. // // Arguments: // // Returns: // // // Modifies: // // History: 09-28-96 ShankSh Created. // //---------------------------------------------------------------------------- STDMETHODIMP CUtilProp::StoreDBPROP ( PROPSTRUCT* pPropStruct, PROPSTRUCT* pStaticPropStruct, ULONG cProperties, DBPROP* pPropSupport, DWORD dwPropIndex ) { // asserts ADsAssert( pPropStruct ); ADsAssert( pPropSupport ); ULONG i; HRESULT hr=S_OK; // Initialize the status to DBPROPSTATUS_OK pPropSupport->dwStatus = DBPROPSTATUS_OK; for (i=0; i < cProperties; i++) { if(pPropStruct[i].dwPropertyID == pPropSupport->dwPropertyID) { // arg checking for the prop if( pPropSupport->dwOptions != DBPROPOPTIONS_OPTIONAL && pPropSupport->dwOptions != DBPROPOPTIONS_REQUIRED ) { pPropSupport->dwStatus = DBPROPSTATUS_BADOPTION; hr = DB_S_ERRORSOCCURRED; goto error; } if( (pPropStruct[i].vtType != V_VT(&pPropSupport->vValue) && V_VT(&pPropSupport->vValue) != VT_EMPTY) || (IsValidValue(pPropSupport, dwPropIndex) == S_FALSE) ) { pPropSupport->dwStatus = DBPROPSTATUS_BADVALUE; hr = DB_S_ERRORSOCCURRED; goto error; } // // If property being set is password, we get out here. // Reason is we have already stored it in the Credentials structure // in encrypted form in the function IsVaidValue above. // We should not store it in plain text in pPropStruct[i]. // if (dwPropIndex == INDEX_INIT && pPropSupport->dwPropertyID == DBPROP_AUTH_PASSWORD) { pPropSupport->dwStatus = DBPROPSTATUS_OK; pPropStruct[i].dwOptions = pPropSupport->dwOptions; goto error; } if( !(pPropStruct[i].dwFlags & DBPROPFLAGS_WRITE) ) { // Check the value - if they are the same, do nothing if ( (V_VT(&pPropSupport->vValue) == VT_EMPTY) || ((V_VT(&pPropSupport->vValue) == VT_BOOL) && (pPropStruct[i].boolVal == V_BOOL(&pPropSupport->vValue))) || ((V_VT(&pPropSupport->vValue) == VT_I4) && (pPropStruct[i].longVal == V_I4(&pPropSupport->vValue))) || ((V_VT(&pPropSupport->vValue) == VT_I2) && ((short)pPropStruct[i].longVal == V_I2(&pPropSupport->vValue))) || ((V_VT(&pPropSupport->vValue) == VT_BSTR) && pPropStruct[i].pwstrVal && (NULL != V_BSTR(&pPropSupport->vValue)) && (wcscmp(pPropStruct[i].pwstrVal,V_BSTR(&pPropSupport->vValue)) == 0)) ) goto error; if( pPropSupport->dwOptions != DBPROPOPTIONS_OPTIONAL ) pPropSupport->dwStatus = DBPROPSTATUS_NOTSETTABLE; else pPropSupport->dwStatus = DBPROPSTATUS_NOTSET; hr = DB_S_ERRORSOCCURRED; goto error; } switch (pPropStruct[i].vtType) { case VT_BOOL: if( V_VT(&pPropSupport->vValue) != VT_EMPTY ) pPropStruct[i].boolVal = V_BOOL( &pPropSupport->vValue ); else pPropStruct[i].boolVal = pStaticPropStruct[i].boolVal; break; case VT_I4: if( V_VT(&pPropSupport->vValue) != VT_EMPTY ) pPropStruct[i].longVal = V_I4( &pPropSupport->vValue ); else pPropStruct[i].longVal = pStaticPropStruct[i].longVal; break; case VT_I2: if( V_VT(&pPropSupport->vValue) != VT_EMPTY ) pPropStruct[i].longVal = V_I2( &pPropSupport->vValue ); else pPropStruct[i].longVal = pStaticPropStruct[i].longVal; break; case VT_BSTR: if(pPropStruct[i].pwstrVal) { FreeADsStr(pPropStruct[i].pwstrVal); pPropStruct[i].pwstrVal = NULL; } if( V_VT(&pPropSupport->vValue) == VT_EMPTY ) pPropStruct[i].pwstrVal = AllocADsStr(( pStaticPropStruct[i].pwstrVal )); else { if (V_BSTR( &pPropSupport->vValue) == NULL && pPropSupport->dwPropertyID == DBPROP_AUTH_INTEGRATED) { // // For integrated security, NULL bstrVal implies 'use default // provider', which is "SSPI" for us. The reason we don't set // the defult value to SSPI in the static structure is // because this property is special. Unless set, it should // not be used. // pPropStruct[i].pwstrVal = AllocADsStr(L"SSPI"); } else pPropStruct[i].pwstrVal = AllocADsStr(V_BSTR( &pPropSupport->vValue )); } if( !pPropStruct[i].pwstrVal && V_VT(&pPropSupport->vValue) == VT_BSTR ) { hr = E_FAIL; goto error; } break; default: pPropSupport->dwStatus = DBPROPSTATUS_BADVALUE; hr = DB_S_ERRORSOCCURRED; goto error; } pPropSupport->dwStatus = DBPROPSTATUS_OK; pPropStruct[i].dwOptions = pPropSupport->dwOptions; break; } } if (i == cProperties) { pPropSupport->dwStatus = DBPROPSTATUS_NOTSUPPORTED; hr = DB_E_ERRORSOCCURRED; goto error; } error: RRETURN(hr); } //+--------------------------------------------------------------------------- // // Function: CUtilProp::IsValidValue // // Synopsis: Helper for SetProperties. Check the valid values for the Property. // // Arguments: // // Returns: // // // Modifies: // // History: 09-28-96 ShankSh Created. // //---------------------------------------------------------------------------- HRESULT CUtilProp::IsValidValue ( DBPROP* pDBProp, DWORD dwPropIndex ) { // Check BOOLEAN values if( (pDBProp->vValue.vt == VT_BOOL) && !((V_BOOL(&(pDBProp->vValue)) == VARIANT_TRUE) || (V_BOOL(&(pDBProp->vValue)) == VARIANT_FALSE)) ) return S_FALSE; if( pDBProp->vValue.vt != VT_EMPTY && dwPropIndex == INDEX_INIT ) { switch( pDBProp->dwPropertyID ) { case DBPROP_INIT_PROMPT: // These are the only values we support (from spec). if (!(V_I2(&pDBProp->vValue) == DBPROMPT_PROMPT || V_I2(&pDBProp->vValue) == DBPROMPT_COMPLETE || V_I2(&pDBProp->vValue) == DBPROMPT_COMPLETEREQUIRED || V_I2(&pDBProp->vValue) == DBPROMPT_NOPROMPT)) return S_FALSE; break; case DBPROP_INIT_TIMEOUT: if( (pDBProp->vValue.vt != VT_I4) || (V_I4(&pDBProp->vValue) < 0) ) return S_FALSE; break; case DBPROP_AUTH_USERID: if( (!_pCredentials) || (S_OK != _pCredentials->SetUserName(V_BSTR(&pDBProp->vValue))) ) return S_FALSE; break; case DBPROP_AUTH_PASSWORD: if( (!_pCredentials) || (S_OK != _pCredentials->SetPassword(V_BSTR(&pDBProp->vValue))) ) return S_FALSE; break; case DBPROP_AUTH_INTEGRATED: // // For integrated security, NULL bstrVal implies 'use default // provider', which is "SSPI" for us. // if( ((pDBProp->vValue.vt != VT_BSTR) && (pDBProp->vValue.vt != VT_NULL)) || ((V_BSTR(&pDBProp->vValue) != NULL) && (wcscmp(V_BSTR(&pDBProp->vValue), L"SSPI") != 0))) return S_FALSE; break; case DBPROP_INIT_MODE: if( (pDBProp->vValue.vt != VT_I4) || (S_FALSE == IsValidInitMode(V_I4(&pDBProp->vValue))) ) return S_FALSE; break; #if (!defined(BUILD_FOR_NT40)) case DBPROP_INIT_BINDFLAGS: if( (pDBProp->vValue.vt != VT_I4) || (S_FALSE == IsValidBindFlag(V_I4(&pDBProp->vValue))) ) return S_FALSE; break; #endif case DBPROP_AUTH_ENCRYPT_PASSWORD: if( !_pCredentials ) return S_FALSE; if( IsADSIFlagSet() ) // override this property if the user set the authentication break; BOOL fAuthFlags = _pCredentials->GetAuthFlags(); if( V_BOOL(&pDBProp->vValue) ) _pCredentials->SetAuthFlags(fAuthFlags | ADS_SECURE_AUTHENTICATION); else _pCredentials->SetAuthFlags(fAuthFlags & ~ADS_SECURE_AUTHENTICATION); break; } } else if( pDBProp->vValue.vt != VT_EMPTY && dwPropIndex == INDEX_ADSIBIND ) { switch( pDBProp->dwPropertyID ) { case ADSIPROP_ADSIFLAG: if( !_pCredentials ) // don't think this will ever happen return S_FALSE; // prevent default initialization by VB from setting the // AUTH flags. The client should not specify ADS_AUTH_RESERVED // for this property (this might happen if the client behaves // like VB i.e, does GetProperties and then SetProperties // without ORing in any flags. In this case, ENCRYPT_PASSWORD // will not be overwritten by this property due to this check). if( ADS_AUTH_RESERVED == (V_I4(&pDBProp->vValue)) ) break; // the following call might overwrite ENCRYPT_PASSWORD _pCredentials->SetAuthFlags((V_I4(&pDBProp->vValue)) & (~ADS_AUTH_RESERVED) ); break; } } else if( pDBProp->vValue.vt != VT_EMPTY && dwPropIndex == INDEX_SESSION ) { switch( pDBProp->dwPropertyID ) { case DBPROP_SESS_AUTOCOMMITISOLEVELS: // These are the only values we support (from spec). if( (pDBProp->vValue.vt != VT_I4) || (V_I4(&pDBProp->vValue) != 0 && V_I4(&pDBProp->vValue) != DBPROPVAL_TI_CHAOS && V_I4(&pDBProp->vValue) != DBPROPVAL_TI_READUNCOMMITTED && V_I4(&pDBProp->vValue) != DBPROPVAL_TI_READCOMMITTED && V_I4(&pDBProp->vValue) != DBPROPVAL_TI_REPEATABLEREAD && V_I4(&pDBProp->vValue) != DBPROPVAL_TI_SERIALIZABLE) ) return S_FALSE; break; } } else if( pDBProp->vValue.vt != VT_EMPTY && dwPropIndex == INDEX_ROWSET ) { switch( pDBProp->dwPropertyID ) { case DBPROP_MAXOPENROWS: if( (pDBProp->vValue.vt != VT_I4) || (V_I4(&pDBProp->vValue) < 0) ) return S_FALSE; break; } } return S_OK; // Is valid } //---------------------------------------------------------------------------- // IsValidInitMode // // Checks if a given value is a valid value for DBPROP_INIT_MODE // //---------------------------------------------------------------------------- HRESULT CUtilProp::IsValidInitMode( long lVal ) { // check if any bit that shouldn't be set is actually set if( lVal & (~(DB_MODE_READWRITE | DB_MODE_SHARE_EXCLUSIVE | DB_MODE_SHARE_DENY_NONE)) ) return S_FALSE; return S_OK; } //--------------------------------------------------------------------------- // IsValidInitBindFlag // // Checks if a given value is a valid value for DBPROP_INIT_BINDFLAGS // //--------------------------------------------------------------------------- HRESULT CUtilProp::IsValidBindFlag( long lVal ) { #if (!defined(BUILD_FOR_NT40)) // check if any bit that shouldn't be set is actually set if( lVal & (~(DB_BINDFLAGS_DELAYFETCHCOLUMNS | DB_BINDFLAGS_DELAYFETCHSTREAM | DB_BINDFLAGS_RECURSIVE | DB_BINDFLAGS_OUTPUT | DB_BINDFLAGS_COLLECTION | DB_BINDFLAGS_OPENIFEXISTS | DB_BINDFLAGS_OVERWRITE | DB_BINDFLAGS_ISSTRUCTUREDDOCUMENT)) ) return S_FALSE; // check for mutually exclusive flags if( (lVal & DB_BINDFLAGS_OPENIFEXISTS) && (lVal & DB_BINDFLAGS_OVERWRITE) ) return S_FALSE; return S_OK; #else return E_FAIL; #endif } //+--------------------------------------------------------------------------- // // Function: CUtilProp::GetPropertiesArgChk // // Synopsis: Initialize the buffers and check for E_INVALIDARG // // Arguments: // cPropertyIDSets # of restiction property IDs // rgPropertyIDSets[] restriction guids // pcPropertySets count of properties returned // prgPropertySets property information returned // dwBitMask which property group // // Returns: // S_OK | The method succeeded // E_INVALIDARG | pcPropertyIDSets or prgPropertyInfo was NULL // // Modifies: // // History: 08-28-96 ShankSh Created. // //---------------------------------------------------------------------------- HRESULT CUtilProp::GetPropertiesArgChk( ULONG cPropertySets, const DBPROPIDSET rgPropertySets[], ULONG* pcProperties, DBPROPSET** prgProperties, DWORD dwBitMask ) { // Initialize values if( pcProperties ) *pcProperties = 0; if( prgProperties ) *prgProperties = NULL; // Check Arguments if( ((cPropertySets > 0) && !rgPropertySets) || !pcProperties || !prgProperties ) RRETURN ( E_INVALIDARG ); // New argument check for > 1 cPropertyIDs and NULL pointer for // array of property ids. for(ULONG ul=0; ul 1) || (rgPropertySets[ul].cPropertyIDs != 0) || (rgPropertySets[ul].rgPropertyIDs != NULL) ) RRETURN ( E_INVALIDARG ); } } RRETURN ( S_OK ); } //+--------------------------------------------------------------------------- // // Function: CUtilProp::GetPropertyInfo // // Synopsis: Returns information about rowset and data source properties // supported by the provider // // Arguments: // cPropertyIDSets # properties // rgPropertyIDSets[] Array of property sets // pcPropertyInfoSets # DBPROPSET structures // prgPropertyInfoSets DBPROPSET structures property // information returned // ppDescBuffer Property descriptions // // Returns: // S_OK | The method succeeded // E_INVALIDARG | pcPropertyIDSets or prgPropertyInfo was NULL // E_OUTOFMEMORY | Out of memory // // Modifies: // // History: 08-28-96 ShankSh Created. // //---------------------------------------------------------------------------- STDMETHODIMP CUtilProp::GetPropertyInfo ( ULONG cPropertyIDSets, const DBPROPIDSET rgPropertyIDSets[], ULONG* pcPropertyInfoSets, DBPROPINFOSET** pprgPropertyInfoSets, WCHAR** ppDescBuffer, BOOL fDSOInitialized ) { DBPROPINFO* pPropInfo = NULL; DBPROPINFOSET* pPropInfoSet = NULL; BOOL fNoPropInfoGot = TRUE; BOOL fWarning=FALSE; HRESULT hr; LPWSTR pwszDescBuffer=NULL; ULONG cPropertySets=0, cProperties=0; ULONG cCount, j, i; ULONG cNewPropIDSets = 0; BOOL fIsSpecialGUID = FALSE; BOOL fIsNotSpecialGUID = FALSE; ULONG ul; BOOL fNewDescription = TRUE; // asserts ADsAssert( _pIMalloc ); // init out params if( pcPropertyInfoSets ) *pcPropertyInfoSets = 0; if( pprgPropertyInfoSets ) *pprgPropertyInfoSets = NULL; if( ppDescBuffer ) *ppDescBuffer = NULL; // Check Arguments, on failure post HRESULT to error queue if( (cPropertyIDSets > 0 && !rgPropertyIDSets) || !pcPropertyInfoSets || !pprgPropertyInfoSets ) RRETURN( E_INVALIDARG ); // New argument check for > 1 cPropertyIDs and NULL pointer for // array of property ids. for(ul=0; ulAlloc(cNewPropIDSets * sizeof( DBPROPINFOSET )); if( !pPropInfoSet ) BAIL_ON_FAILURE ( hr=E_OUTOFMEMORY ); memset( pPropInfoSet, 0, (cNewPropIDSets * sizeof( DBPROPINFOSET ))); if( ppDescBuffer ) { // Allocating more memory than actually required, since // _dwDescBufferLen is th etotal for all property sets together, not // just for one property set pwszDescBuffer = (LPWSTR) _pIMalloc->Alloc(_dwDescBufferLen * cNewPropIDSets); if( !pwszDescBuffer ) BAIL_ON_FAILURE ( hr=E_OUTOFMEMORY ); memset( pwszDescBuffer, 0, _dwDescBufferLen * cNewPropIDSets); *ppDescBuffer = pwszDescBuffer; } // If no restrictions return all properties from the three supported property sets if( cPropertyIDSets == 0 ) { // Fill in all of the Providers Properties for (j=0; j< cNewPropIDSets; j++) pPropInfoSet[j].guidPropertySet = *s_rgPropertySets[j].guidPropertySet; } else { cCount = 0; // // Deal with the Special GUID's // for (j=0; j< cPropertyIDSets; j++) { if( rgPropertyIDSets[j].guidPropertySet == DBPROPSET_DBINITALL ) { pPropInfoSet[cCount].guidPropertySet = DBPROPSET_DBINIT; // Adjust for ADSI_BIND (provider specific) property set cCount++; pPropInfoSet[cCount].guidPropertySet = DBPROPSET_ADSIBIND; } else if( fDSOInitialized && rgPropertyIDSets[j].guidPropertySet == DBPROPSET_DATASOURCEINFOALL ) pPropInfoSet[cCount].guidPropertySet = DBPROPSET_DATASOURCEINFO; else if( fDSOInitialized && rgPropertyIDSets[j].guidPropertySet == DBPROPSET_SESSIONALL ) pPropInfoSet[cCount].guidPropertySet = DBPROPSET_SESSION; else if( fDSOInitialized && rgPropertyIDSets[j].guidPropertySet == DBPROPSET_ROWSETALL ) { pPropInfoSet[cCount].guidPropertySet = DBPROPSET_ROWSET; // Adjust for the Provider Specific cCount++; pPropInfoSet[cCount].guidPropertySet = DBPROPSET_ADSISEARCH; } else { pPropInfoSet[cCount].guidPropertySet = rgPropertyIDSets[j].guidPropertySet; pPropInfoSet[cCount].cPropertyInfos = rgPropertyIDSets[j].cPropertyIDs; } cCount++; } } // // For each supported Property Set // for (cPropertySets=0; cPropertySets < cNewPropIDSets; cPropertySets++) { // Set cProperties to the numerber passed in cProperties = pPropInfoSet[cPropertySets].cPropertyInfos; pPropInfo = NULL; // Get the correct Static data. We have 2 property sets in the // INIT property group. Note that we assume that both these property // sets occur successively in s_rgPropertySets. for (j=0; j< (fDSOInitialized ? NUMELEM(s_rgPropertySets) : 2); j++) { if( IsEqualGUID(pPropInfoSet[cPropertySets].guidPropertySet, *(s_rgPropertySets[j].guidPropertySet)) ) { if( pPropInfoSet[cPropertySets].cPropertyInfos == 0 ) cProperties = s_rgPropertySets[j].cProperties; break; } } if( cProperties ) { // // use task memory allocater to alloc array of DBPROPINFO structs // pPropInfo = (DBPROPINFO*) _pIMalloc->Alloc(cProperties * sizeof( DBPROPINFO )); if( !pPropInfo ) { for (i=0; iFree(pPropInfoSet[i].rgPropertyInfos); BAIL_ON_FAILURE ( hr=E_OUTOFMEMORY ); } memset(pPropInfo, 0, cProperties * sizeof(DBPROPINFO)); for (cCount=0; cCount < cProperties; cCount++) { if( pPropInfoSet[cPropertySets].cPropertyInfos == 0 ) pPropInfo[cCount].dwPropertyID = s_rgPropertySets[j].pUPropInfo[cCount].dwPropertyID; else pPropInfo[cCount].dwPropertyID = rgPropertyIDSets[cPropertySets].rgPropertyIDs[cCount]; // set the description pointer. If this property was already // requested in this call, then we reuse the same description // pointer. DWORD dwTmp; for(dwTmp = 0; dwTmp < cCount; dwTmp++) if(pPropInfo[dwTmp].dwPropertyID == pPropInfo[cCount].dwPropertyID) // same property requested more than once break; if(dwTmp == cCount) { fNewDescription = TRUE; pPropInfo[cCount].pwszDescription = pwszDescBuffer; } else { fNewDescription = FALSE; pPropInfo[cCount].pwszDescription = pPropInfo[dwTmp].pwszDescription; } hr = LoadDBPROPINFO( ((j < (fDSOInitialized ? NUMELEM(s_rgPropertySets) : 2)) ? s_rgPropertySets[j].pUPropInfo : NULL), ((j < (fDSOInitialized ? NUMELEM(s_rgPropertySets) : 2)) ? s_rgPropertySets[j].cProperties : 0), &pPropInfo[cCount] ); if( FAILED(hr) ) { ULONG ulFor; // // something went wrong // clear all variants used so far.. // for (ulFor = 0; ulFor < cCount; ulFor++) VariantClear( &pPropInfo[ulFor].vValues ); // // .. delete the pPropInfo array, return failure // for (i=0; iFree(pPropInfoSet[i].rgPropertyInfos); _pIMalloc->Free(pPropInfo); BAIL_ON_FAILURE ( hr=E_OUTOFMEMORY ); } if( hr != S_OK ) fWarning = TRUE; else fNoPropInfoGot = FALSE; // move the description pointer to the next, if required if( pPropInfo[cCount].pwszDescription && fNewDescription) pwszDescBuffer += (wcslen(pPropInfo[cCount].pwszDescription) + 1); } } else fWarning = TRUE; pPropInfoSet[cPropertySets].rgPropertyInfos = pPropInfo; pPropInfoSet[cPropertySets].cPropertyInfos = cProperties; } // for each property set // // set count of properties and property information // *pcPropertyInfoSets= cNewPropIDSets; *pprgPropertyInfoSets = pPropInfoSet; if( fNoPropInfoGot ) { if( ppDescBuffer ) *ppDescBuffer = NULL; if( pwszDescBuffer ) _pIMalloc->Free(pwszDescBuffer); RRETURN ( DB_E_ERRORSOCCURRED ); } else if( fWarning ) RRETURN ( DB_S_ERRORSOCCURRED ); else RRETURN ( S_OK ); error: if( pPropInfoSet ) _pIMalloc->Free(pPropInfoSet); if( pwszDescBuffer ) _pIMalloc->Free(pwszDescBuffer); RRETURN ( hr ); } //---------------------------------------------------------------------------- // IsSpecialGuid // // Check if the the property set GUID is one of the special GUIDs // //---------------------------------------------------------------------------- BOOL CUtilProp::IsSpecialGuid( GUID guidPropSet ) { if( (DBPROPSET_ROWSETALL == guidPropSet) || (DBPROPSET_DATASOURCEALL == guidPropSet) || (DBPROPSET_DATASOURCEINFOALL == guidPropSet) || (DBPROPSET_SESSIONALL == guidPropSet) || (DBPROPSET_DBINITALL == guidPropSet) #if (!defined(BUILD_FOR_NT40)) || (DBPROPSET_COLUMNALL == guidPropSet) || (DBPROPSET_CONSTRAINTALL == guidPropSet) || (DBPROPSET_INDEXALL == guidPropSet) || (DBPROPSET_TABLEALL == guidPropSet) || (DBPROPSET_TRUSTEEALL == guidPropSet) || (DBPROPSET_VIEWALL == guidPropSet) #endif ) return TRUE; else return FALSE; } //+--------------------------------------------------------------------------- // // Function: CUtilProp::GetProperties // // Synopsis: Returns current settings of all properties supported // by the DSO/rowset // // Arguments: // // cPropertyIDSets # of restiction property IDs // rgPropertyIDSets[] restriction guids // pcPropertySets count of properties returned // prgPropertySets property information returned // // // Returns: // S_OK | The method succeeded // E_INVALIDARG | pcPropertyIDSets or prgPropertyInfo was NULL // E_OUTOFMEMORY | Out of memory // // Modifies: // // History: 08-28-96 ShankSh Created. // //---------------------------------------------------------------------------- STDMETHODIMP CUtilProp::GetProperties ( ULONG cPropertyIDSets, const DBPROPIDSET rgPropertyIDSets[], ULONG* pcPropertySets, DBPROPSET** pprgPropertySets, DWORD dwBitMask ) { ULONG cPropertySets, cProperties; ULONG cNewPropIDSets = 0; ULONG cCount, j, i; DBPROP* pProp = NULL; DBPROPSET* pPropSet = NULL; HRESULT hr = E_FAIL; BOOL fNoPropertyGot = TRUE; BOOL fWarning = FALSE; BOOL fFound = FALSE; ULONG cOffset = 0; // asserts ADsAssert(_pIMalloc); // Assign in the count cNewPropIDSets = cPropertyIDSets; // If the consumer does not restrict the property sets // by specify an array of property sets and a cPropertySets // greater than 0, then we need to make sure we // have some to return if( cPropertyIDSets == 0 ) { // Set the count of properties cNewPropIDSets = 1; if(dwBitMask & PROPSET_DSO) { if(dwBitMask & PROPSET_INIT) // if the data src object has been initialized, return // properties in the DBInit, DSInfo and ADSIBind property sets. cNewPropIDSets = 3; else // Return DBInit and ADSIBind property sets only. Note that we // are counting on ADSIBind being the second property set in // s_rgPropertySets, since we are leaving cOffset as 0 cNewPropIDSets = 2; } if(dwBitMask & PROPSET_COMMAND) cNewPropIDSets = 2; } // Figure out the Offset if( dwBitMask & PROPSET_SESSION ) cOffset = INDEX_SESSION; else if( dwBitMask & PROPSET_COMMAND ) cOffset = INDEX_ROWSET; // // use task memory allocater to alloc a DBPROPSET struct // pPropSet = (DBPROPSET*) _pIMalloc->Alloc(cNewPropIDSets * sizeof( DBPROPSET )); if( !pPropSet ) BAIL_ON_FAILURE ( hr=E_OUTOFMEMORY ); memset( pPropSet, 0, (cNewPropIDSets * sizeof( DBPROPSET ))); // // For each supported Property Set // for (cPropertySets=0; cPropertySets < cNewPropIDSets; cPropertySets++) { // Initialize variable ULONG cPropOffset = 0; int cNumDSOProps = 0; cProperties = 0; pProp = NULL; fFound = FALSE; // Setup the PropSet GUID if( cPropertyIDSets == 0 ) { pPropSet[cPropertySets].guidPropertySet = *s_rgPropertySets[cPropertySets+cOffset].guidPropertySet; } else { cProperties = rgPropertyIDSets[cPropertySets].cPropertyIDs; pPropSet[cPropertySets].guidPropertySet = rgPropertyIDSets[cPropertySets].guidPropertySet; } if(dwBitMask & PROPSET_DSO) // we have 2 property sets whose properties can be set before // initialization and one whose properties can be set only after // init. Set the count of properties accordingly. cNumDSOProps = 1 + !!(dwBitMask & PROPSET_INIT); // Setup the count of Properties for that PropSet for (j=0; j <= cOffset+ cNumDSOProps + !!(dwBitMask & PROPSET_COMMAND); j++) { if( j >= cOffset && IsEqualGUID(pPropSet[cPropertySets].guidPropertySet, *(s_rgPropertySets[j].guidPropertySet)) ) { if (rgPropertyIDSets == NULL || rgPropertyIDSets[cPropertySets].cPropertyIDs == 0) cProperties = s_rgPropertySets[j].cProperties; fFound = TRUE; break; } // Move to the next PropSet cPropOffset += s_rgPropertySets[j].cProperties; } if( cProperties != 0 ) { // use task memory allocator to alloc array of DBPROP struct pProp = (DBPROP*) _pIMalloc->Alloc(cProperties * sizeof( DBPROP )); if( pProp == NULL ) { for (i=0; i < cPropertySets; i++) _pIMalloc->Free(pPropSet[i].rgProperties); BAIL_ON_FAILURE ( hr=E_OUTOFMEMORY ); } memset( pProp, 0, (cProperties * sizeof( DBPROP ))); if( rgPropertyIDSets == NULL || rgPropertyIDSets[cPropertySets].cPropertyIDs == 0 ) { for (cCount=0; cCount < cProperties; cCount++) pProp[cCount].dwPropertyID = s_rgPropertySets[j-!fFound].pUPropInfo[cCount].dwPropertyID; } else { for (cCount=0; cCount < cProperties; cCount++) pProp[cCount].dwPropertyID = rgPropertyIDSets[cPropertySets].rgPropertyIDs[cCount]; } } else fWarning = TRUE; // // for each prop in our table.. // for (cCount = 0; cCount < cProperties; cCount++) { hr = LoadDBPROP((fFound ? &(_prgProperties[cPropOffset]) : NULL), (fFound ? s_rgPropertySets[j-!fFound].cProperties : 0), &pProp[cCount], pPropSet[cPropertySets].guidPropertySet == DBPROPSET_DBINIT ); if( FAILED(hr) ) { // something went wrong // clear all variants used so far.. for (i=0; i < cCount; i++) VariantClear( &pProp[i].vValue ); for (i=0; i < cPropertySets; i++) _pIMalloc->Free(pPropSet[i].rgProperties); _pIMalloc->Free(pProp); BAIL_ON_FAILURE( hr ); } if( hr != S_OK ) fWarning = TRUE; else fNoPropertyGot = FALSE; } // for each property pPropSet[cPropertySets].rgProperties = pProp; pPropSet[cPropertySets].cProperties = cProperties; } // for each property set // set count of properties and property informatio *pcPropertySets = cNewPropIDSets; *pprgPropertySets = pPropSet; if( fNoPropertyGot ) RRETURN( DB_E_ERRORSOCCURRED ); else if( fWarning ) RRETURN( DB_S_ERRORSOCCURRED ); else RRETURN( S_OK ); error: if( pPropSet ) _pIMalloc->Free(pPropSet); RRETURN( hr ); } //+--------------------------------------------------------------------------- // // Function: CUtilProp::SetProperties // // Synopsis: Set current settings of properties supported by the DSO/rowset // // Arguments: // // cPropertyIDSets, # of DBPROPSET // rgPropertyIDSets[] Array of property sets // // Returns: // S_OK | The method succeeded // E_INVALIDARG | pcPropertyIDSets or prgPropertyInfo was NULL // E_OUTOFMEMORY | Out of memory // // Modifies: // // History: 08-28-96 ShankSh Created. // //---------------------------------------------------------------------------- STDMETHODIMP CUtilProp::SetProperties( ULONG cPropertySets, DBPROPSET rgPropertySets[], DWORD dwBitMask ) { ULONG cCount, j, k; HRESULT hr; BOOL fNoPropertySet = TRUE; BOOL fWarning = FALSE; // check params if( cPropertySets > 0 && !rgPropertySets ) RRETURN ( E_INVALIDARG ); // New argument check for > 1 cPropertyIDs and NULL pointer for // array of property ids. for(ULONG ul=0; ul