windows-nt/Source/XPSP1/NT/ds/adsi/router/dbid.cxx
2020-09-26 16:20:57 +08:00

409 lines
9.2 KiB
C++

//------------------------------------------------------------------------------
//
// Microsoft Sidewalk
// Copyright (C) Microsoft Corporation, 1997.
//
// File: oledbhelp.cpp
//
// Contents: OLE DB helper methods
//
// Owner: BassamT
//
// History: 11/30/97 BassamT Created.
//
//------------------------------------------------------------------------------
#include "oleds.hxx"
#if (!defined(BUILD_FOR_NT40))
#define dimensionof(x) sizeof(x)/sizeof(x[0])
HRESULT IsValidDBID
//------------------------------------------------------------------------------
// checks if we have a valid DBID
(
const DBID * pdbid1
// [in] the DBID to check
)
{
Assert(pdbid1 != NULL);
if (pdbid1 &&
((pdbid1->eKind == DBKIND_GUID_NAME) ||
(pdbid1->eKind == DBKIND_GUID_PROPID) ||
(pdbid1->eKind == DBKIND_NAME) ||
(pdbid1->eKind == DBKIND_PGUID_NAME) ||
(pdbid1->eKind == DBKIND_PGUID_PROPID) ||
(pdbid1->eKind == DBKIND_PROPID) ||
(pdbid1->eKind == DBKIND_GUID)))
{
return S_OK;
}
else
{
return S_FALSE;
}
}
BOOL CompareDBIDs
//------------------------------------------------------------------------------
// Compares two DBIDs. Given two DBIDS to determine if they are the same.
// Returns TRUE if they are the same DBIDs or FALSE if different
(
const DBID * pdbid1,
// [in] pointer to DBID 1; can be badly formed eKind
const DBID * pdbid2
// [in] pointer to DBID 2; assumed valid eKind
)
{
// Array of valid eKind matches, in addition to matching exactly.
static BYTE abKind[] =
{
DBKIND_PGUID_NAME, // DBKIND_GUID_NAME
DBKIND_PGUID_PROPID, // DBKIND_GUID_PROPID
DBKIND_NAME, // DBKIND_NAME
DBKIND_GUID_NAME, // DBKIND_PGUID_NAME
DBKIND_GUID_PROPID, // DBKIND_PGUID_PROPID
DBKIND_PROPID, // DBKIND_PROPID
DBKIND_GUID // DBKIND_GUID
};
// Verify that offsets are correct (header file might change).
Assert( 0 == DBKIND_GUID_NAME &&
1 == DBKIND_GUID_PROPID &&
2 == DBKIND_NAME &&
3 == DBKIND_PGUID_NAME &&
4 == DBKIND_PGUID_PROPID &&
5 == DBKIND_PROPID &&
6 == DBKIND_GUID);
if (pdbid1 == NULL || pdbid2 == NULL)
{
return FALSE;
}
// Assume a match, and discard early if we can.
// Don't assert for 1, since might be badly-formed.
// 2 is assumed to be well-formed.
Assert(inrange(((SHORT)pdbid2->eKind), 0, dimensionof(abKind)));
if (pdbid1->eKind != pdbid2->eKind &&
pdbid1->eKind != abKind[pdbid2->eKind])
{
return FALSE;
}
if (DBID_USE_GUID_OR_PGUID(pdbid1->eKind))
{
if (!DBID_USE_GUID_OR_PGUID(pdbid2->eKind))
{
return FALSE;
}
// Compare GUIDs.
// Note that _GUID_ is equivalent to _PGUID_.
if (!IsEqualGUID(
DBID_USE_PGUID(pdbid1->eKind) ? *(pdbid1->uGuid.pguid) : pdbid1->uGuid.guid,
DBID_USE_PGUID(pdbid2->eKind) ? *(pdbid2->uGuid.pguid) : pdbid2->uGuid.guid))
{
return FALSE;
}
}
if (DBID_USE_NAME(pdbid1->eKind))
{
if (!DBID_USE_NAME(pdbid2->eKind))
{
return FALSE;
}
// Compare names.
// Need to check if 1 is null and the other is not.
if (((pdbid1->uName.pwszName == NULL) && (pdbid2->uName.pwszName != NULL)) ||
((pdbid1->uName.pwszName != NULL) && (pdbid2->uName.pwszName == NULL)))
{
return FALSE;
}
// Since the above check does not rule out both being null, which is
// a valid comparison, and wcscmp will GPF if they were, we need
// to check for valid pointers
if(pdbid1->uName.pwszName != NULL && pdbid2->uName.pwszName != NULL)
{
// Assume null-terminated.
if (_wcsicmp(pdbid1->uName.pwszName, pdbid2->uName.pwszName) != 0)
{
return FALSE;
}
}
}
if (DBID_USE_PROPID(pdbid1->eKind))
{
if (!DBID_USE_PROPID(pdbid2->eKind))
{
return FALSE;
}
// Compare PROPID.
if (pdbid1->uName.ulPropid != pdbid2->uName.ulPropid)
{
return FALSE;
}
}
// a match
return TRUE;
}
void FreeDBID
//------------------------------------------------------------------------------
// FreeDBID
// Given a DBID free an allocated buffers
(
DBID *pdbidSrc
//[in] Pointer to DBID
)
{
Assert(pdbidSrc);
switch (pdbidSrc->eKind)
{
case DBKIND_GUID_NAME:
CLIENT_FREE(pdbidSrc->uName.pwszName);
break;
case DBKIND_NAME:
CLIENT_FREE(pdbidSrc->uName.pwszName);
break;
case DBKIND_PGUID_NAME:
CLIENT_FREE(pdbidSrc->uGuid.pguid);
CLIENT_FREE(pdbidSrc->uName.pwszName);
break;
case DBKIND_PGUID_PROPID:
CLIENT_FREE(pdbidSrc->uGuid.pguid);
break;
case DBKIND_GUID_PROPID:
case DBKIND_PROPID:
case DBKIND_GUID:
break;
default:
Assert(NULL && L"Unhandled dbid1.ekind");
break;
}
}
HRESULT CopyDBIDs
//------------------------------------------------------------------------------
// Given a DBID to copy, put it in the new buffer
//
// Need to use IMalloc->Alloc and IMalloc->Free since this routine
// is used to copy the DBIDs from storage back into the memory handed to
// the consumer.
//
// HRESULT indicating the status of the copy
// S_OK = Copied
// S_FALSE = Problems copying
// E_OUTOFMEMORY = Could not allocate resources
//
(
DBID * pdbidDest,
// [in,out] Pointer to Destination DBID
const DBID *pdbidSrc
// [in] Pointer to Source DBID
)
{
Assert(pdbidDest);
Assert(pdbidSrc);
size_t cwchBuffer;
HRESULT hr;
memset(pdbidDest, 0, sizeof(*pdbidDest));
// Save eKind
pdbidDest->eKind = pdbidSrc->eKind;
switch (pdbidSrc->eKind)
{
case DBKIND_GUID_NAME:
pdbidDest->uGuid.guid = pdbidSrc->uGuid.guid;
cwchBuffer = wcslen(pdbidSrc->uName.pwszName) + 1;
if (pdbidDest->uName.pwszName = (PWSTR)CLIENT_MALLOC(cwchBuffer * sizeof(WCHAR)))
{
wcsncpy(pdbidDest->uName.pwszName, pdbidSrc->uName.pwszName, cwchBuffer);
}
else
{
hr = E_OUTOFMEMORY;
//ErrorTrace(hr);
goto Error;
}
break;
case DBKIND_GUID_PROPID:
pdbidDest->uGuid.guid = pdbidSrc->uGuid.guid;
pdbidDest->uName.ulPropid = pdbidSrc->uName.ulPropid;
break;
case DBKIND_NAME:
cwchBuffer = wcslen(pdbidSrc->uName.pwszName) + 1;
if (pdbidDest->uName.pwszName = (PWSTR)CLIENT_MALLOC(cwchBuffer * sizeof(WCHAR)))
{
wcsncpy(pdbidDest->uName.pwszName, pdbidSrc->uName.pwszName, cwchBuffer);
}
else
{
hr = E_OUTOFMEMORY;
//ErrorTrace(hr);
goto Error;
}
break;
case DBKIND_PGUID_NAME:
// convert the pguid into a guid so that we don't have to do an extra malloc
pdbidDest->eKind = DBKIND_GUID_NAME;
pdbidDest->uGuid.guid = *pdbidSrc->uGuid.pguid;
cwchBuffer = wcslen(pdbidSrc->uName.pwszName) + 1;
if (pdbidDest->uName.pwszName = (PWSTR)CLIENT_MALLOC(cwchBuffer * sizeof(WCHAR)))
{
wcsncpy(pdbidDest->uName.pwszName, pdbidSrc->uName.pwszName, cwchBuffer);
}
else
{
hr = E_OUTOFMEMORY;
//ErrorTrace(hr);
goto Error;
}
break;
case DBKIND_PGUID_PROPID:
// convert the pguid into a guid so that we don't have to do an extra malloc
pdbidDest->eKind = DBKIND_GUID_PROPID;
pdbidDest->uGuid.guid = *pdbidSrc->uGuid.pguid;
pdbidDest->uName.ulPropid = pdbidSrc->uName.ulPropid;
break;
case DBKIND_PROPID:
pdbidDest->uName.ulPropid = pdbidSrc->uName.ulPropid;
break;
case DBKIND_GUID:
pdbidDest->uGuid.guid = pdbidSrc->uGuid.guid;
break;
default:
Assert(NULL && L"Unhandled dbid ekind");
hr = E_FAIL;
//ErrorTrace(hr);
goto Error;
}
return NOERROR;
Error:
Assert(FAILED(hr));
return hr;
}
INT CompareOLEDBTypes
//------------------------------------------------------------------------------
// Compares two value of the same DBTYPE.
//
// Returns :
//
// 0 if both values are equal
// >0 if pvValue1 is greater than pvValue2
// <0 if pvValue1 is less than pvValue2
//
(
DBTYPE wType,
// [in] the OLE DB type of both values
void * pvValue1,
// [in] a pointer to Value1
void * pvValue2
// [in] a pointer to Value2
)
{
Assert (pvValue1 != NULL);
Assert (pvValue2 != NULL);
// TODO : Is this right ?
INT comp = -1;
/*
// TODO : how do we handle these ?
case DBTYPE_ARRAY:
case DBTYPE_BYREF:
case DBTYPE_VECTOR:
*/
// TODO : support the other DB_TYPES and check that all types work
// TODO : What about NULL values ?
// TODO : WE could generalize this function and let it handle values
// of different types.
switch (wType)
{
case DBTYPE_I2:
comp = (*(SHORT*)pvValue1) - (*(SHORT*)pvValue2);
break;
case DBTYPE_I4:
comp = (*(LONG*)pvValue1) - (*(LONG*)pvValue2);
break;
case DBTYPE_UI1:
comp = (*(UCHAR*)pvValue1) - (*(UCHAR*)pvValue2);
break;
case DBTYPE_I1:
comp = (*(CHAR*)pvValue1) - (*(CHAR*)pvValue2);
break;
case DBTYPE_UI2:
comp = (*(USHORT*)pvValue1) - (*(USHORT*)pvValue2);
break;
case DBTYPE_UI4:
comp = (*(ULONG*)pvValue1) - (*(ULONG*)pvValue2);
break;
case DBTYPE_STR:
comp = strcmp((CHAR*)(pvValue1), (CHAR*)pvValue2);
break;
case DBTYPE_WSTR:
comp = wcscmp((WCHAR*)(pvValue1), (WCHAR*)pvValue2);
break;
case DBTYPE_GUID:
case DBTYPE_I8:
case DBTYPE_UI8:
case DBTYPE_R4:
case DBTYPE_R8:
case DBTYPE_CY:
case DBTYPE_DATE:
case DBTYPE_BSTR:
case DBTYPE_IDISPATCH:
case DBTYPE_ERROR:
case DBTYPE_BOOL:
case DBTYPE_VARIANT:
case DBTYPE_IUNKNOWN:
case DBTYPE_DECIMAL:
case DBTYPE_RESERVED:
case DBTYPE_BYTES:
case DBTYPE_NUMERIC:
case DBTYPE_UDT:
case DBTYPE_DBDATE:
case DBTYPE_DBTIME:
case DBTYPE_DBTIMESTAMP:
default:
Assert(FALSE && "CIndex : Data type not supported");
return -1;
}
return comp;
}
#endif