1928 lines
70 KiB
C++
1928 lines
70 KiB
C++
//-- == 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; i<dwNumSearchPrefs; i++) {
|
|
|
|
switch(pSearchPrefInfo[i].vValue.dwType) {
|
|
|
|
case ADSTYPE_BOOLEAN:
|
|
case ADSTYPE_INTEGER:
|
|
// do nothing
|
|
break;
|
|
|
|
case ADSTYPE_PROV_SPECIFIC:
|
|
|
|
if (pSearchPrefInfo[i].dwSearchPref == ADS_SEARCHPREF_SORT_ON) {
|
|
//
|
|
// delete the strings allocated for each of the attributes
|
|
// to be sorted
|
|
|
|
nSortKeys = pSearchPrefInfo[i].vValue.ProviderSpecific.dwLength / sizeof(ADS_SORTKEY);
|
|
pSortKey = (PADS_SORTKEY) pSearchPrefInfo[i].vValue.ProviderSpecific.lpValue;
|
|
|
|
for (DWORD j=0; pSortKey && j<nSortKeys; j++) {
|
|
FreeADsStr(pSortKey[j].pszAttrType);
|
|
}
|
|
|
|
if (pSortKey) {
|
|
FreeADsMem(pSortKey);
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
RRETURN (S_OK);
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CUtilProp::LoadDBPROPINFO
|
|
//
|
|
// Synopsis: Helper for GetPropertyInfo. Loads field of DBPROPINFO
|
|
// structure.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: TRUE : Method succeeded
|
|
// FALSE : Method failed (couldn't allocate memory)
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 08-28-96 ShankSh Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CUtilProp::LoadDBPROPINFO (
|
|
PROPSTRUCT* pPropStruct,
|
|
ULONG cProperties,
|
|
DBPROPINFO* pPropInfo
|
|
)
|
|
{
|
|
ULONG cCount;
|
|
PROPSTRUCT* pProp=NULL;
|
|
|
|
// asserts
|
|
ADsAssert( pPropInfo );
|
|
if( cProperties ) {
|
|
ADsAssert( pPropStruct );
|
|
}
|
|
|
|
//
|
|
// init the variant
|
|
//
|
|
VariantInit( &pPropInfo->vValues );
|
|
|
|
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);
|
|
|
|
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 &&
|
|
(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<cPropertySets; ul++)
|
|
{
|
|
if( rgPropertySets[ul].cPropertyIDs && !(rgPropertySets[ul].rgPropertyIDs) )
|
|
RRETURN ( E_INVALIDARG );
|
|
|
|
// Check for propper formation of DBPROPSET_PROPERTIESINERROR
|
|
if( ((dwBitMask & PROPSET_DSO) || (dwBitMask & PROPSET_COMMAND)) &&
|
|
(rgPropertySets[ul].guidPropertySet == DBPROPSET_PROPERTIESINERROR) )
|
|
{
|
|
if( (cPropertySets > 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; ul<cPropertyIDSets; ul++)
|
|
{
|
|
if( rgPropertyIDSets[ul].cPropertyIDs &&
|
|
!rgPropertyIDSets[ul].rgPropertyIDs )
|
|
RRETURN( E_INVALIDARG );
|
|
|
|
// Add 1 for the Provider Specific Rowset Properties
|
|
if( (rgPropertyIDSets[ul].guidPropertySet == DBPROPSET_DBINITALL) ||
|
|
(fDSOInitialized &&
|
|
rgPropertyIDSets[ul].guidPropertySet == DBPROPSET_ROWSETALL) )
|
|
cNewPropIDSets++;
|
|
|
|
//
|
|
// Special Guids for Property Sets can not be mixed with ordinary
|
|
// Property Set Guids. Either one or the other, not both
|
|
//
|
|
if (IsSpecialGuid(rgPropertyIDSets[ul].guidPropertySet))
|
|
fIsSpecialGUID = TRUE;
|
|
else
|
|
fIsNotSpecialGUID = TRUE;
|
|
|
|
if( fIsSpecialGUID && fIsNotSpecialGUID )
|
|
RRETURN( E_INVALIDARG );
|
|
}
|
|
|
|
// save the count of PropertyIDSets
|
|
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 )
|
|
{
|
|
if( fDSOInitialized )
|
|
cNewPropIDSets = NUMBER_OF_SUPPORTED_PROPERTY_SETS;
|
|
else
|
|
// we have 2 property sets in the DBINIT property group
|
|
cNewPropIDSets = 2;
|
|
}
|
|
|
|
// use task memory allocater to alloc a DBPROPINFOSET struct
|
|
pPropInfoSet = (DBPROPINFOSET*) _pIMalloc->Alloc(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; i<cNewPropIDSets; i++)
|
|
_pIMalloc->Free(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; i<cNewPropIDSets; i++)
|
|
_pIMalloc->Free(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<cPropertySets; ul++)
|
|
{
|
|
if( rgPropertySets[ul].cProperties &&
|
|
!(rgPropertySets[ul].rgProperties) )
|
|
RRETURN ( E_INVALIDARG );
|
|
}
|
|
|
|
for (cCount=0; cCount < cPropertySets; cCount++) {
|
|
// Not legal to Set INIT or DATASOURCE properties after Initializing
|
|
if( (dwBitMask & PROPSET_INIT) &&
|
|
(rgPropertySets[cCount].guidPropertySet == DBPROPSET_DBINIT) ) {
|
|
//
|
|
// Wrong time to set these Properties
|
|
//
|
|
for (k=0; k < rgPropertySets[cCount].cProperties; k++) {
|
|
rgPropertySets[cCount].rgProperties[k].dwStatus = DBPROPSTATUS_NOTSETTABLE;
|
|
fWarning = TRUE;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
// Trying to set the wrong Property Set
|
|
if( ((dwBitMask & PROPSET_DSO) && !(dwBitMask & PROPSET_INIT) &&
|
|
(rgPropertySets[cCount].guidPropertySet != DBPROPSET_DBINIT &&
|
|
rgPropertySets[cCount].guidPropertySet != DBPROPSET_ADSIBIND)) ||
|
|
((dwBitMask & PROPSET_DSO) && (dwBitMask & PROPSET_INIT) &&
|
|
rgPropertySets[cCount].guidPropertySet != DBPROPSET_DATASOURCEINFO) ||
|
|
((dwBitMask & PROPSET_SESSION) &&
|
|
rgPropertySets[cCount].guidPropertySet != DBPROPSET_SESSION) ||
|
|
((dwBitMask & PROPSET_COMMAND) &&
|
|
rgPropertySets[cCount].guidPropertySet != DBPROPSET_ROWSET &&
|
|
rgPropertySets[cCount].guidPropertySet != DBPROPSET_ADSISEARCH) ) {
|
|
|
|
//
|
|
// Wrong Property Set
|
|
//
|
|
for (k=0; k < rgPropertySets[cCount].cProperties; k++) {
|
|
rgPropertySets[cCount].rgProperties[k].dwStatus = DBPROPSTATUS_NOTSUPPORTED;
|
|
fWarning = TRUE;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
ULONG cPropOffset = 0;
|
|
|
|
for (j=0; j< NUMELEM(s_rgPropertySets); j++) {
|
|
if (IsEqualGUID(rgPropertySets[cCount].guidPropertySet,
|
|
*(s_rgPropertySets[j].guidPropertySet))) {
|
|
for (k=0; k < rgPropertySets[cCount].cProperties; k++) {
|
|
hr = StoreDBPROP(&(_prgProperties[cPropOffset]),
|
|
s_rgPropertySets[j].pUPropInfo,
|
|
s_rgPropertySets[j].cProperties,
|
|
&(rgPropertySets[cCount].rgProperties[k]),
|
|
j );
|
|
|
|
if( hr != S_OK )
|
|
fWarning = TRUE;
|
|
else
|
|
fNoPropertySet = FALSE;
|
|
}
|
|
break;
|
|
}
|
|
// Move to the next PropSet
|
|
cPropOffset += s_rgPropertySets[j].cProperties;
|
|
}
|
|
}
|
|
|
|
if ( fNoPropertySet && fWarning )
|
|
RRETURN ( DB_E_ERRORSOCCURRED );
|
|
else if (fWarning)
|
|
RRETURN ( DB_S_ERRORSOCCURRED );
|
|
else
|
|
RRETURN ( S_OK );
|
|
}
|
|
|
|
|
|
BOOL
|
|
CUtilProp::IsIntegratedSecurity(
|
|
void
|
|
)
|
|
{
|
|
// Check to see if SSPI is set
|
|
for (ULONG i=0; i< s_rgPropertySets[INDEX_INIT].cProperties; i++) {
|
|
if( _prgProperties[i].dwPropertyID == DBPROP_AUTH_INTEGRATED)
|
|
{
|
|
if (_prgProperties[i].pwstrVal )
|
|
return( wcscmp(_prgProperties[i].pwstrVal, L"SSPI") == 0 );
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
CUtilProp::IsADSIFlagSet()
|
|
{
|
|
ULONG PropSetOffset = 0, i;
|
|
|
|
for(i = 0; i < INDEX_ADSIBIND; i++)
|
|
PropSetOffset += s_rgPropertySets[i].cProperties;
|
|
|
|
// Check if "ADSI Flag" is set to something other than ADS_AUTH_RESERVED
|
|
for (i=0; i < s_rgPropertySets[INDEX_ADSIBIND].cProperties; i++)
|
|
if(_prgProperties[i+PropSetOffset].dwPropertyID == ADSIPROP_ADSIFLAG)
|
|
return (_prgProperties[i+PropSetOffset].longVal !=
|
|
ADS_AUTH_RESERVED);
|
|
|
|
// we should never get here
|
|
return FALSE;
|
|
}
|
|
|