Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

746 lines
27 KiB

//-----------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: oledbutl.cpp
//
// Contents:
//
//
// History: 07/10/96 RenatoB Created, lifted from EricJ code
//
//-----------------------------------------------------------------------------
// Includes
#include "oleds.hxx"
// All the '256's below should be 4 (the length of a pointer to a string). Because
// of a bug in the TempTable, this has been temporarily done.
//
// Note: Provider-specific types are returned as octet strings
//
MAPTYPE_STRUCT g_MapADsTypeToDBType[] = {
{DBTYPE_NULL, 0}, /* ADSTYPE_INVALID = 0, */
{DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_DN_STRING, */
{DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_CASE_EXACT_STRING, */
{DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_CASE_IGNORE_STRING, */
{DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_PRINTABLE_STRING, */
{DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_NUMERIC_STRING, */
{DBTYPE_BOOL, 2}, /* ADSTYPE_BOOLEAN, */
{DBTYPE_I4, 4}, /* ADSTYPE_INTEGER, */
{DBTYPE_BYTES | DBTYPE_BYREF, 256}, /* ADSTYPE_OCTET_STRING, */
{DBTYPE_DATE, 8}, /* ADSTYPE_UTC_TIME, */
{DBTYPE_VARIANT |DBTYPE_BYREF,16}, /* ADSTYPE_LARGE_INTEGER, */
{DBTYPE_BYTES | DBTYPE_BYREF, 256}, /* ADSTYPE_PROV_SPECIFIC */
{DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_OBJECT_CLASS, */
{DBTYPE_NULL, 0}, /* ADSTYPE_CASEIGNORE_LIST */
{DBTYPE_NULL, 0}, /* ADSTYPE_OCTET_LIST */
{DBTYPE_NULL, 0}, /* ADSTYPE_PATH */
{DBTYPE_NULL, 0}, /* ADSTYPE_POSTALADDRESS */
{DBTYPE_NULL, 0}, /* ADSTYPE_TIMESTAMP */
{DBTYPE_NULL, 0}, /* ADSTYPE_BACKLINK */
{DBTYPE_NULL, 0}, /* ADSTYPE_TYPEDNAME */
{DBTYPE_NULL, 0}, /* ADSTYPE_HOLD */
{DBTYPE_NULL, 0}, /* ADSTYPE_NETADDRESS */
{DBTYPE_NULL, 0}, /* ADSTYPE_REPLICAPOINTER */
{DBTYPE_NULL, 0}, /* ADSTYPE_FAXNUMBER */
{DBTYPE_NULL, 0}, /* ADSTYPE_EMAIL */
{DBTYPE_BYTES | DBTYPE_BYREF, 256}, /* ADSTYPE_NT_SECURITY_DESC */
{DBTYPE_NULL, 0}, /* ADSTYPE_UNKNOWN */
{DBTYPE_VARIANT |DBTYPE_BYREF,16}, /* ADSTYPE_DN_WITH_BINARY */
{DBTYPE_VARIANT |DBTYPE_BYREF,16} /* ADSTYPE_DN_WITH_STRING */
};
DWORD g_cMapADsTypeToDBType = (sizeof(g_MapADsTypeToDBType) /
sizeof(g_MapADsTypeToDBType[0]));
// The row object does not use IDirectorySearch when a direct bind or SELECT
// * happens. In this case, it uses IADs::Get. It is possible that a variant
// with VT_DISPATCH may be returned in this case - for ADSTYPE_NT_SECURITY_DESC
// DNWithBin or DNWithStr. In this case, they cannot be converted to any other
// DBTYPE. So, they will be returned as DBTYPE_VARIANT.
MAPTYPE_STRUCT g_MapADsTypeToDBType2[] = {
{DBTYPE_NULL, 0}, /* ADSTYPE_INVALID = 0, */
{DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_DN_STRING, */
{DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_CASE_EXACT_STRING, */
{DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_CASE_IGNORE_STRING, */
{DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_PRINTABLE_STRING, */
{DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_NUMERIC_STRING, */
{DBTYPE_BOOL, 2}, /* ADSTYPE_BOOLEAN, */
{DBTYPE_I4, 4}, /* ADSTYPE_INTEGER, */
{DBTYPE_BYTES | DBTYPE_BYREF, 256}, /* ADSTYPE_OCTET_STRING, */
{DBTYPE_DATE, 8}, /* ADSTYPE_UTC_TIME, */
{DBTYPE_VARIANT, 16}, /* ADSTYPE_LARGE_INTEGER, */
{DBTYPE_BYTES | DBTYPE_BYREF, 256}, /* ADSTYPE_PROV_SPECIFIC */
{DBTYPE_WSTR | DBTYPE_BYREF, 256}, /* ADSTYPE_OBJECT_CLASS, */
{DBTYPE_NULL, 0}, /* ADSTYPE_CASEIGNORE_LIST */
{DBTYPE_NULL, 0}, /* ADSTYPE_OCTET_LIST */
{DBTYPE_NULL, 0}, /* ADSTYPE_PATH */
{DBTYPE_NULL, 0}, /* ADSTYPE_POSTALADDRESS */
{DBTYPE_NULL, 0}, /* ADSTYPE_TIMESTAMP */
{DBTYPE_NULL, 0}, /* ADSTYPE_BACKLINK */
{DBTYPE_NULL, 0}, /* ADSTYPE_TYPEDNAME */
{DBTYPE_NULL, 0}, /* ADSTYPE_HOLD */
{DBTYPE_NULL, 0}, /* ADSTYPE_NETADDRESS */
{DBTYPE_NULL, 0}, /* ADSTYPE_REPLICAPOINTER */
{DBTYPE_NULL, 0}, /* ADSTYPE_FAXNUMBER */
{DBTYPE_NULL, 0}, /* ADSTYPE_EMAIL */
{DBTYPE_BYTES | DBTYPE_BYREF, 256}, /* ADSTYPE_NT_SECURITY_DESC */
{DBTYPE_NULL, 0}, /* ADSTYPE_UNKNOWN */
{DBTYPE_VARIANT, 16}, /* ADSTYPE_DN_WITH_BINARY */
{DBTYPE_VARIANT, 16} /* ADSTYPE_DN_WITH_STRING */
};
DWORD g_cMapADsTypeToDBType2 = (sizeof(g_MapADsTypeToDBType2) /
sizeof(g_MapADsTypeToDBType2[0]));
VARTYPE g_MapADsTypeToVarType[] = {
VT_NULL, /* ADSTYPE_INVALID = 0, */
VT_BSTR, /* ADSTYPE_DN_STRING, */
VT_BSTR, /* ADSTYPE_CASE_EXACT_STRING, */
VT_BSTR, /* ADSTYPE_CASE_IGNORE_STRING, */
VT_BSTR, /* ADSTYPE_PRINTABLE_STRING, */
VT_BSTR, /* ADSTYPE_NUMERIC_STRING, */
VT_BOOL, /* ADSTYPE_BOOLEAN, */
VT_I4, /* ADSTYPE_INTEGER, */
VT_UI1 | VT_ARRAY, /* ADSTYPE_OCTET_STRING, */
VT_DATE, /* ADSTYPE_UTC_TIME, */
VT_DISPATCH, /* ADSTYPE_LARGE_INTEGER, */
VT_UI1 | VT_ARRAY, /* ADSTYPE_PROV_SPECIFIC */
VT_BSTR, /* ADSTYPE_OBJECT_CLASS */
VT_NULL, /* ADSTYPE_CASEIGNORE_LIST */
VT_NULL, /* ADSTYPE_OCTET_LIST */
VT_NULL, /* ADSTYPE_PATH */
VT_NULL, /* ADSTYPE_POSTALADDRESS */
VT_NULL, /* ADSTYPE_TIMESTAMP */
VT_NULL, /* ADSTYPE_BACKLINK */
VT_NULL, /* ADSTYPE_TYPEDNAME */
VT_NULL, /* ADSTYPE_HOLD */
VT_NULL, /* ADSTYPE_NETADDRESS */
VT_NULL, /* ADSTYPE_REPLICAPOINTER */
VT_NULL, /* ADSTYPE_FAXNUMBER */
VT_NULL, /* ADSTYPE_EMAIL */
VT_UI1 | VT_ARRAY, /* ADSTYPE_NT_SECURITY_DESC */
VT_NULL, /* ADSTYPE_UNKNOWN */
VT_DISPATCH, /* ADSTYPE_DN_WITH_BINARY */
VT_DISPATCH /* ADSTYPE_DN_WITH_STRING */
};
DWORD g_cMapADsTypeToVarType = (sizeof(g_MapADsTypeToVarType) /
sizeof(g_MapADsTypeToVarType[0]));
ADS_SEARCHPREF g_MapDBPropIdToSearchPref[] = {
ADS_SEARCHPREF_ASYNCHRONOUS,
ADS_SEARCHPREF_DEREF_ALIASES,
ADS_SEARCHPREF_SIZE_LIMIT,
ADS_SEARCHPREF_TIME_LIMIT,
ADS_SEARCHPREF_ATTRIBTYPES_ONLY,
ADS_SEARCHPREF_SEARCH_SCOPE,
ADS_SEARCHPREF_TIMEOUT,
ADS_SEARCHPREF_PAGESIZE,
ADS_SEARCHPREF_PAGED_TIME_LIMIT,
ADS_SEARCHPREF_CHASE_REFERRALS,
ADS_SEARCHPREF_SORT_ON,
ADS_SEARCHPREF_CACHE_RESULTS
};
DWORD g_cMapDBPropToSearchPref = (sizeof(g_MapDBPropIdToSearchPref) /
sizeof(g_MapDBPropIdToSearchPref[0]));
//+---------------------------------------------------------------------------
//
// Function: CpAccessors2Rowset
//
// Synopsis: @ffunc Implements inheritance of Accessors. Copies to
// a Rowset the accessors existing on the command
//
// Called by: CRowset::Finit
// Called when: At runtime.
// Overridden: No. (Private)
// Arguments:
//
//
// Returns: @rdesc HRESULT
// @flag S_OK | OK
// @flag E_OUTOFMEMORY |could not get IMalloc
// @flag E_FAIL| An accessor could not be created
//
//----------------------------------------------------------------------------
HRESULT
CpAccessors2Rowset(
IAccessor *pAccessorCommand, //@parm IN |Command's IAccessor
IAccessor *pAccessorRowset, //@parm IN |Rowset's IAccessor
ULONG cAccessors, //@parm IN |Count,Commnands accessors
HACCESSOR rgAccessors[], //@parm IN |Array,Command's accessors
CImpIAccessor *pCAccessor //accessor object of rowset
)
{
HRESULT hr;
IMalloc * pMalloc = NULL;
DBCOUNTITEM cBindings;
DBBINDING * pBindings = NULL;
DBBINDSTATUS * prgBindStatus = NULL;
ULONG i,j;
DBACCESSORFLAGS AccessorFlags;
HACCESSOR hAccessor;
hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
BAIL_ON_FAILURE(hr);
//for each of the command's accessors,
// we create a Rowset accessor.
// if anyone fails, return E_FAIL
for (i=0; i<cAccessors; i++) {
AccessorFlags = 0;
hr=pAccessorCommand->GetBindings(
rgAccessors[i],
&AccessorFlags,
&cBindings,
&pBindings
);
// Not a valid accessor handle
if (hr == DB_E_BADACCESSORHANDLE) {
// Rowset will also inherit the bad accessor
hr = pCAccessor->CreateBadAccessor();
BAIL_ON_FAILURE( hr );
continue;
}
BAIL_ON_FAILURE( hr );
// Allocate memory for the Status values
prgBindStatus = (DBBINDSTATUS*) pMalloc->Alloc((ULONG)(cBindings *
sizeof(DBBINDSTATUS)));
if (NULL == prgBindStatus)
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
hr=pAccessorRowset->CreateAccessor(
AccessorFlags,
cBindings,
pBindings,
0,
&hAccessor,
prgBindStatus
);
//
// If CreateAccessor fails fixup DB_E_ERRORSOCCURRED
//
if (hr == DB_E_ERRORSOCCURRED) {
// Fixup the HResult
for(j=0; j < cBindings; j++) {
switch (prgBindStatus[j])
{
case DBBINDSTATUS_NOINTERFACE:
BAIL_ON_FAILURE( hr=E_NOINTERFACE );
case DBBINDSTATUS_BADBINDINFO:
BAIL_ON_FAILURE( hr=DB_E_BADBINDINFO );
case DBBINDSTATUS_BADORDINAL:
BAIL_ON_FAILURE( hr=DB_E_BADORDINAL );
case DBBINDSTATUS_BADSTORAGEFLAGS:
BAIL_ON_FAILURE( hr=DB_E_BADSTORAGEFLAGS );
case DBBINDSTATUS_UNSUPPORTEDCONVERSION:
BAIL_ON_FAILURE( hr=DB_E_UNSUPPORTEDCONVERSION );
case DBBINDSTATUS_MULTIPLESTORAGE:
BAIL_ON_FAILURE( hr=DB_E_MULTIPLESTORAGE );
case DBBINDSTATUS_OK:
default:
hr=E_FAIL;
break;
}
}
// Should never be E_FAIL
ADsAssert(hr != E_FAIL);
}
BAIL_ON_FAILURE( hr );
if( pBindings )
pMalloc->Free(pBindings);
pBindings = NULL;
if( prgBindStatus )
pMalloc->Free(prgBindStatus);
prgBindStatus = NULL;
};
error:
if (pMalloc)
{
if( pBindings )
pMalloc->Free(pBindings);
if( prgBindStatus )
pMalloc->Free(prgBindStatus);
pMalloc->Release();
}
RRETURN( hr );
}
HRESULT
GetDSInterface(
LPWSTR lpszPath,
CCredentials& Credentials,
REFIID iid,
void FAR * FAR * ppObject
)
{
HRESULT hr = E_FAIL;
LPWSTR lpszUserName=NULL, lpszPassword=NULL;
DWORD dwAuthFlags = 0;
hr = Credentials.GetUserName(&lpszUserName);
BAIL_ON_FAILURE( hr );
hr = Credentials.GetPassword(&lpszPassword);
BAIL_ON_FAILURE( hr );
dwAuthFlags = Credentials.GetAuthFlags();
hr = ADsOpenObject(
lpszPath,
lpszUserName,
lpszPassword,
dwAuthFlags,
iid,
ppObject
);
if( INVALID_CREDENTIALS_ERROR(hr) )
BAIL_ON_FAILURE( hr=DB_SEC_E_PERMISSIONDENIED );
if( FAILED(hr) )
BAIL_ON_FAILURE( hr=DB_E_NOTABLE );
error:
if( lpszUserName )
FreeADsMem(lpszUserName);
if( lpszPassword )
{
SecureZeroMemory(lpszPassword, wcslen(lpszPassword) * sizeof(WCHAR));
FreeADsMem(lpszPassword);
}
RRETURN( hr );
}
//+---------------------------------------------------------------------------
//
// Function: GetCredentialsFromIAuthenticate
//
// Synopsis: Gets credentials (user name, password) from IAuthenticate
// interface pointer.
//
// Returns: HRESULT
//----------------------------------------------------------------------------
HRESULT GetCredentialsFromIAuthenticate(
IAuthenticate *pAuthenticate,
CCredentials& refCredentials
)
{
Assert(pAuthenticate);
HRESULT hr = S_OK;
HWND hwnd;
PWSTR pszUsername = NULL;
PWSTR pszPassword = NULL;
if (pAuthenticate->Authenticate(&hwnd, &pszUsername, &pszPassword) != S_OK)
RRETURN(E_INVALIDARG);
if ((hwnd != INVALID_HANDLE_VALUE) &&
(hwnd != 0))
{
//don't know if and how to handle this case
RRETURN(S_OK);
}
else
{
hr = refCredentials.SetUserName(pszUsername);
if (SUCCEEDED(hr))
{
hr = refCredentials.SetPassword(pszPassword);
}
if (pszPassword)
{
SecureZeroMemory(pszPassword, wcslen(pszPassword) * sizeof(WCHAR));
CoTaskMemFree(pszPassword);
}
if (pszUsername)
{
CoTaskMemFree(pszUsername);
}
}
RRETURN(hr);
}
//+---------------------------------------------------------------------------
//
// Function: RemoveWhiteSpaces
//
// Synopsis: Removes the leading and trailing white spaces
//
// Arguments: pszText Text strings from which the leading
// and trailing white spaces are to be
// removed
//
// Returns: LPWSTR Pointer to the modified string
//
// Modifies:
//
// History: 08-15-96 ShankSh Created.
//
//----------------------------------------------------------------------------
LPWSTR
RemoveWhiteSpaces(LPWSTR pszText)
{
LPWSTR pChar;
if( !pszText )
return( pszText );
while(*pszText && iswspace(*pszText))
pszText++;
for(pChar = pszText + wcslen(pszText) - 1; pChar >= pszText; pChar--) {
if( !iswspace(*pChar) )
break;
else
*pChar = L'\0';
}
return pszText;
}
//+---------------------------------------------------------------------------
//
// Function: CanConvertHelper
//
// Synopsis: Helper that tells the consumer if the conversion is supported.
//
// Arguments: DBTYPE wSrcType
// DBTYPE wDstType
//
// Returns: HRESULT
//
// Modifies:
//
// History: 08-15-96 ShankSh Created.
//
//----------------------------------------------------------------------------
//
// Bitmask of supported conversions --
// - src type is index into array,
// - dst type is bit in that ULONG
//
static ULONG s_rgConvertBitmap[] =
{
// 3 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0.
// 0 8 6 4 2 0 8 6 4 2 0 8 6 4 2 0.
// 3 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0.
// 1 9 7 5 3 1 9 7 5 3 1 9 7 5 3 1.
// DBTYPE_EMPTY
0xe3bfd9ff, // 11100011101111111101100111111111
// DBTYPE_NULL
0x60001002, // 01100000000000000001000000000010
// DBTYPE_I2
0xdf9fd9ff, // 11011111100111111101100111111111
// DBTYPE_I4
0xdfdfd9ff, // 11011111110111111101100111111111
// DBTYPE_R4
0xdf9fd9ff, // 11011111100111111101100111111111
// DBTYPE_R8
0xdf9fd9ff, // 11011111100111111101100111111111
// DBTYPE_CY
0xc39fd97f, // 11000011100111111101100101111111
// DBTYPE_DATE
0x7d9f99bf, // 01111101100111111001100110111111
// DBTYPE_BSTR
0xffffd9ff, // 11111111111111111101100111111111
// DBTYPE_IDISPATCH
0x4087fbff, // 01000000100001111111101111111111
// DBTYPE_ERROR
0x01001500, // 00000001000000000001010100000000
// DBTYPE_BOOL
0xc39fd9ff, // 11000011100111111101100111111111
// DBTYPE_VARIANT
0xffffffff, // 11111111111111111111111111111111
// DBTYPE_IUNKNOWN
0x00003203, // 00000000000000000011001000000011
// DBTYPE_DECIMAL
0x9f9fd97f, // 10011111100111111101100101111111
// DBTYPE_I1
0x9f9fd9ff, // 10011111100111111101100111111111
// DBTYPE_UI1
0xdf9fd9ff, // 11011111100111111101100111111111
// DBTYPE_UI2
0xdf9fd9ff, // 11011111100111111101100111111111
// DBTYPE_UI4
0xdfdfd9ff, // 11011111110111111101100111111111
// DBTYPE_I8
0x619fd13f, // 01100001100111111101000100111111
// DBTYPE_UI8
0x619fd13f, // 01100001100111111101000100111111
// DBTYPE_GUID
0x41a01103, // 01000001101000000001000100000011
// DBTYPE_BYTES
0x41c4110b, // 01000001110001000001000100001011
// DBTYPE_STR
0xffffd9ff, // 11111111111111111101100111111111
// DBTYPE_WSTR
0xffffd9ff, // 11111111111111111101100111111111
// DBTYPE_NUMERIC
0xc39fd97f, // 11000011100111111101100101111111
// DBTYPE_DBDATE
0x3d801183, // 00111101100000000001000110000011
// DBTYPE_DBTIME
0x3d801183, // 00111101100000000001000110000011
// DBTYPE_DBTIMESTAMP
0x3d801183, // 00111101100000000001000110000011
// DBTYPE_FILETIME
0x7d981183, // 01111101100110000001000110000011
// DBTYPE_PROPVARIANT
0xffffffff, // 11111111111111111111111111111111
// DBTYPE_VARNUMERIC
0x839fd97f, // 10000011100111111101100101111111
};
static HRESULT IsLegalDBtype(DBTYPE);
static LONG IndexDBTYPE(DBTYPE wType);
STDMETHODIMP
CanConvertHelper(
DBTYPE wSrcType,
DBTYPE wDstType,
DBCONVERTFLAGS dwConvertFlags
)
{
//
// Check in-params and NULL out-params in case of error
//
if( (dwConvertFlags &
~(DBCONVERTFLAGS_ISLONG |
DBCONVERTFLAGS_ISFIXEDLENGTH |
DBCONVERTFLAGS_FROMVARIANT)) != DBCONVERTFLAGS_COLUMN )
RRETURN( DB_E_BADCONVERTFLAG );
//
// Make sure that we check that the type is a variant if they say so
//
if( dwConvertFlags & DBCONVERTFLAGS_FROMVARIANT ) {
DBTYPE wVtType = wSrcType & VT_TYPEMASK;
// Take out all of the Valid VT_TYPES (36 is VT_RECORD in VC 6)
if( (wVtType > VT_DECIMAL && wVtType < VT_I1) ||
((wVtType > VT_LPWSTR && wVtType < VT_FILETIME) && wVtType !=36) ||
(wVtType > VT_CLSID) )
RRETURN( DB_E_BADTYPE );
}
//
// Don't allow _ISLONG on fixed-length types
//
if( dwConvertFlags & DBCONVERTFLAGS_ISLONG ) {
switch ( wSrcType & ~(DBTYPE_RESERVED|DBTYPE_VECTOR|DBTYPE_ARRAY|DBTYPE_BYREF) )
{
case DBTYPE_BYTES:
case DBTYPE_STR:
case DBTYPE_WSTR:
case DBTYPE_VARNUMERIC:
break;
default:
RRETURN( DB_E_BADCONVERTFLAG );
}
}
// Check for valid types
if( wSrcType > DBTYPE_DECIMAL )
{
if( FAILED(IsLegalDBtype(wSrcType)) )
RRETURN( S_FALSE );
}
if( wDstType > DBTYPE_DECIMAL )
{
if( FAILED(IsLegalDBtype(wDstType)) )
RRETURN( S_FALSE );
}
// Check for unsupported type modifiers
if( (wSrcType & (DBTYPE_VECTOR|DBTYPE_ARRAY|DBTYPE_RESERVED)) ||
(wDstType & (DBTYPE_VECTOR|DBTYPE_ARRAY|DBTYPE_RESERVED)) )
RRETURN( S_FALSE );
// Handle BYREF destination separately
if( wDstType & DBTYPE_BYREF ) {
// Turn off BYREF bit
wDstType &= ~DBTYPE_BYREF;
// We only allow BYREF destination for variable length types
switch ( wDstType ) {
case DBTYPE_BYTES:
case DBTYPE_STR:
case DBTYPE_WSTR:
case DBTYPE_VARNUMERIC:
break;
default:
// Fixed-length BYREFs are not supported
RRETURN( S_FALSE );
}
}
// Turn off BYREF bit
wSrcType &= ~DBTYPE_BYREF;
// Get the indices for the src and dst types
LONG iSrc = IndexDBTYPE(wSrcType);
ADsAssert(iSrc < NUMELEM(s_rgConvertBitmap)); // better not be larger than our array
LONG iDst = IndexDBTYPE(wDstType);
ADsAssert(iDst < (sizeof(ULONG) * 8) ); // or the number of bits in a ULONG
// Make sure we have two supported types -- we don't support UDT
if( iSrc < 0 || iDst < 0 )
RRETURN( S_FALSE );
// And do the lookup -- bit will be set if conversion supported
if( s_rgConvertBitmap[iSrc] & (1 << iDst) )
RRETURN( S_OK );
// No bit, no support
RRETURN( S_FALSE );
}
HRESULT IsLegalDBtype(DBTYPE dbtype)
{
// NOTE: optimized for speed, rather than for maintainablity
if( dbtype & (DBTYPE_VECTOR|DBTYPE_BYREF|DBTYPE_ARRAY|DBTYPE_RESERVED) )
dbtype &= ~(DBTYPE_VECTOR|DBTYPE_BYREF|DBTYPE_ARRAY|DBTYPE_RESERVED);
if( (dbtype >= DBTYPE_EMPTY && dbtype <= DBTYPE_DECIMAL) ||
(dbtype >= DBTYPE_I1 && dbtype <= DBTYPE_UI8) ||
dbtype == DBTYPE_GUID ||
(dbtype >= DBTYPE_BYTES && dbtype <= DBTYPE_DBTIMESTAMP) ||
(dbtype >= DBTYPE_FILETIME && dbtype <= DBTYPE_VARNUMERIC) )
RRETURN( S_OK );
RRETURN( DB_E_BADBINDINFO );
}
LONG IndexDBTYPE(DBTYPE wType)
{
switch ( wType ) {
case DBTYPE_EMPTY: // 0
case DBTYPE_NULL: // 1
case DBTYPE_I2: // 2
case DBTYPE_I4: // 3
case DBTYPE_R4: // 4
case DBTYPE_R8: // 5
case DBTYPE_CY: // 6
case DBTYPE_DATE: // 7
case DBTYPE_BSTR: // 8
case DBTYPE_IDISPATCH: // 9
case DBTYPE_ERROR: // 10
case DBTYPE_BOOL: // 11
case DBTYPE_VARIANT: // 12
case DBTYPE_IUNKNOWN: // 13
case DBTYPE_DECIMAL: // 14
// 0 - 14
return (ULONG)wType;
case DBTYPE_I1: // 16
case DBTYPE_UI1: // 17
case DBTYPE_UI2: // 18
case DBTYPE_UI4: // 19
case DBTYPE_I8: // 20
case DBTYPE_UI8: // 21
// 15 - 20
return (ULONG)(wType - 1);
case DBTYPE_GUID: // 72
// 21
return 21;
case DBTYPE_BYTES: // 128
case DBTYPE_STR: // 129
case DBTYPE_WSTR: // 130
case DBTYPE_NUMERIC: // 131
// 22 - 25
return (ULONG)(wType - 106);
case DBTYPE_DBDATE: // 133
case DBTYPE_DBTIME: // 134
case DBTYPE_DBTIMESTAMP:// 135
// 26 - 28
return (ULONG)(wType - 107);
case DBTYPE_FILETIME: // 64
// 29
return wType - 35;
case DBTYPE_PROPVARIANT:// 138
case DBTYPE_VARNUMERIC: // 139
// 30 - 31
return (ULONG)(wType - 108);
}
// No match
return -1;
}
BYTE SetPrecision(DBTYPE dbType)
{
switch(dbType)
{
case DBTYPE_I1:
case DBTYPE_UI1:
return 3;
case DBTYPE_I2:
case DBTYPE_UI2:
return 5;
case DBTYPE_I4:
case DBTYPE_UI4:
return 10;
case DBTYPE_I8:
return 19;
case DBTYPE_UI8:
return 20;
case DBTYPE_R4:
return 7;
case DBTYPE_R8:
return 15;
case DBTYPE_CY:
return 19;
case DBTYPE_DECIMAL:
return 29;
case DBTYPE_NUMERIC:
return 39;
case DBTYPE_VARNUMERIC:
return 255;
default:
return ((BYTE) (~0));
}
}