522 lines
14 KiB
C++
522 lines
14 KiB
C++
|
|
/*
|
||
|
|
** CPQDIF_COMSupport class. Implements support member functions so that
|
||
|
|
** make dealing with COM/OLE/ActiveX much easier.
|
||
|
|
** --------------------------------------------------------------------------
|
||
|
|
** This class is a Singleton class; this means that only one instance of it
|
||
|
|
** should ever be created. This instance is made global, and is one of the
|
||
|
|
** only global objects in the entire system.
|
||
|
|
** --------------------------------------------------------------------------
|
||
|
|
**
|
||
|
|
** File name: $Workfile: pqdsupport.cpp $
|
||
|
|
** Last modified: $Modtime: 4/15/02 3:19p $
|
||
|
|
** Last modified by: $Author: Wadef $
|
||
|
|
**
|
||
|
|
** VCS archive path: $Archive: /PQDIF/PQDcom/PQDcom4/pqdiflib/pqdsupport.cpp $
|
||
|
|
** VCS revision: $Revision: 5 $
|
||
|
|
*/
|
||
|
|
|
||
|
|
#ifdef PQDIF_USE_COM
|
||
|
|
|
||
|
|
#include "PQDIF_classes.h"
|
||
|
|
#include "pqdsupport.h"
|
||
|
|
|
||
|
|
const GUID ID_NULL = { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
|
||
|
|
|
||
|
|
// The one and only support object (Singleton)
|
||
|
|
CPQDIF_COMSupport theSupport;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
// Construction
|
||
|
|
// ============
|
||
|
|
|
||
|
|
CPQDIF_COMSupport::CPQDIF_COMSupport()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
CPQDIF_COMSupport::~CPQDIF_COMSupport()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
bool CPQDIF_COMSupport::NewVariantArrayFromGUID
|
||
|
|
(
|
||
|
|
VARIANT& var,
|
||
|
|
const GUID& guid
|
||
|
|
)
|
||
|
|
{
|
||
|
|
bool status = false;
|
||
|
|
const int countLongs = 4;
|
||
|
|
BYTE * pbData;
|
||
|
|
|
||
|
|
// Set the variant to a 1-byte array
|
||
|
|
VariantInit( &var );
|
||
|
|
var.vt = VT_ARRAY + VT_I4;
|
||
|
|
var.parray = SafeArrayCreateVector( VT_I4, 0, countLongs );
|
||
|
|
|
||
|
|
// If a safe array of doubles was passed then ...
|
||
|
|
if( var.parray != NULL)
|
||
|
|
{
|
||
|
|
if( !FAILED( SafeArrayAccessData( var.parray, (void **) &pbData ) ) )
|
||
|
|
{
|
||
|
|
// Copy the contents of the GUID
|
||
|
|
memcpy( pbData, &guid, countLongs * sizeof( long ) );
|
||
|
|
SafeArrayUnaccessData( var.parray );
|
||
|
|
status = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
bool CPQDIF_COMSupport::SetGUIDFromVariantArray
|
||
|
|
(
|
||
|
|
GUID& guid,
|
||
|
|
const VARIANT& var
|
||
|
|
) const
|
||
|
|
{
|
||
|
|
bool status = false;
|
||
|
|
long lLower;
|
||
|
|
long lUpper;
|
||
|
|
long countItems;
|
||
|
|
BYTE * pbData;
|
||
|
|
|
||
|
|
guid = ID_NULL;
|
||
|
|
|
||
|
|
// Valid array of long [ 4 ]?
|
||
|
|
if( ( var.vt & VT_ARRAY ) /* && ( var.vt & VT_I4 )*/ && var.parray )
|
||
|
|
{
|
||
|
|
// Validate the size of the array
|
||
|
|
SafeArrayGetUBound( var.parray, 1, &lUpper );
|
||
|
|
SafeArrayGetLBound( var.parray, 1, &lLower );
|
||
|
|
countItems = (lUpper - lLower + 1);
|
||
|
|
|
||
|
|
if( countItems == 4 )
|
||
|
|
{
|
||
|
|
VARIANT HUGEP *pvLongs;
|
||
|
|
|
||
|
|
if (!FAILED(SafeArrayAccessData(var.parray, reinterpret_cast<void HUGEP**>(&pvLongs))))
|
||
|
|
{
|
||
|
|
if (var.vt & VT_VARIANT)
|
||
|
|
{
|
||
|
|
INT4 * pInt = (INT4 *)&guid;
|
||
|
|
|
||
|
|
for (int count = 0; count < 4; count++, pInt++)
|
||
|
|
*pInt = pvLongs[count].lVal;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
pbData = (BYTE *)pvLongs;
|
||
|
|
// Copy the GUID
|
||
|
|
memcpy( &guid, pbData, sizeof( guid ) );
|
||
|
|
status = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
SafeArrayUnaccessData( var.parray );
|
||
|
|
}
|
||
|
|
} // Got safe array data
|
||
|
|
} // Valid safe array
|
||
|
|
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
bool CPQDIF_COMSupport::NewVariantArrayFromVector
|
||
|
|
(
|
||
|
|
VARIANT& var,
|
||
|
|
CPQDIF_E_Vector& vect
|
||
|
|
)
|
||
|
|
{
|
||
|
|
bool status = false;
|
||
|
|
VARTYPE vtSingle;
|
||
|
|
long typePhysical;
|
||
|
|
long sizePhysical;
|
||
|
|
long countItems;
|
||
|
|
BYTE * pbData;
|
||
|
|
INT1 * pdataSource;
|
||
|
|
|
||
|
|
// Check the physical type for the size we need...
|
||
|
|
// (and how many items are in the array)
|
||
|
|
typePhysical = vect.GetPhysicalType();
|
||
|
|
sizePhysical = theInfo.GetNumBytesOfType( typePhysical );
|
||
|
|
vect.GetCount( countItems );
|
||
|
|
|
||
|
|
_variant_t varV;
|
||
|
|
// Grab the first item to see what variant type the array should be...
|
||
|
|
status = vect.GetValue( 0, varV );
|
||
|
|
if( status )
|
||
|
|
{
|
||
|
|
// Got the variant type
|
||
|
|
vtSingle = varV.vt;
|
||
|
|
status = false;
|
||
|
|
|
||
|
|
// Set the variant to an array of this type
|
||
|
|
VariantInit( &var );
|
||
|
|
|
||
|
|
var.vt = VT_ARRAY | vtSingle;
|
||
|
|
var.parray = SafeArrayCreateVector( vtSingle, 0, countItems );
|
||
|
|
|
||
|
|
// If a safe array of doubles was passed then ...
|
||
|
|
if( var.parray != NULL)
|
||
|
|
{
|
||
|
|
if( !FAILED( SafeArrayAccessData( var.parray, (void **) &pbData ) ) )
|
||
|
|
{
|
||
|
|
pdataSource = reinterpret_cast<INT1 *>(vect.GetRawData());
|
||
|
|
if( pdataSource )
|
||
|
|
{
|
||
|
|
// Copy the entire block of data across by physical item size
|
||
|
|
memcpy( pbData, pdataSource, countItems * sizePhysical );
|
||
|
|
status = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
SafeArrayUnaccessData( var.parray );
|
||
|
|
} // Got safe array data
|
||
|
|
} // Valid safe array
|
||
|
|
} // Valid data type
|
||
|
|
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
bool CPQDIF_COMSupport::NewVariantArrayFromDouble
|
||
|
|
(
|
||
|
|
VARIANT& var,
|
||
|
|
double * arValues,
|
||
|
|
long countItems
|
||
|
|
)
|
||
|
|
{
|
||
|
|
bool status = false;
|
||
|
|
VARTYPE vtSingle;
|
||
|
|
long sizePhysical;
|
||
|
|
BYTE * pbData;
|
||
|
|
|
||
|
|
// Set the variant to an array of this type
|
||
|
|
sizePhysical = sizeof( double );
|
||
|
|
vtSingle = VT_R8;
|
||
|
|
VariantInit( &var );
|
||
|
|
var.vt = VT_ARRAY | vtSingle;
|
||
|
|
var.parray = SafeArrayCreateVector( vtSingle, 0, countItems );
|
||
|
|
|
||
|
|
// If a safe array of doubles was passed then ...
|
||
|
|
if( var.parray != NULL)
|
||
|
|
{
|
||
|
|
if( !FAILED( SafeArrayAccessData( var.parray, (void **) &pbData ) ) )
|
||
|
|
{
|
||
|
|
if( arValues )
|
||
|
|
{
|
||
|
|
// Copy the entire block across
|
||
|
|
memcpy( pbData, (BYTE *) arValues, sizePhysical * countItems );
|
||
|
|
status = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
SafeArrayUnaccessData( var.parray );
|
||
|
|
} // Got safe array data
|
||
|
|
} // Valid safe array
|
||
|
|
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
long GetPhysicalTypeFromVariant( const VARIANT& var, long typeElement )
|
||
|
|
{
|
||
|
|
long typePhysical = 0;
|
||
|
|
BOOL isArray = FALSE;
|
||
|
|
int countDims = 0;
|
||
|
|
long lUpper;
|
||
|
|
long lLower;
|
||
|
|
long countItemsLastDim = 0;
|
||
|
|
|
||
|
|
SAFEARRAY * psa = NULL;
|
||
|
|
|
||
|
|
// Is this an array?
|
||
|
|
if( var.vt & VT_ARRAY )
|
||
|
|
{
|
||
|
|
// Which safearray?
|
||
|
|
if( var.vt & VT_BYREF )
|
||
|
|
{
|
||
|
|
if( var.pparray )
|
||
|
|
psa = *var.pparray;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
psa = var.parray;
|
||
|
|
}
|
||
|
|
|
||
|
|
if( psa )
|
||
|
|
{
|
||
|
|
isArray = TRUE;
|
||
|
|
countDims = SafeArrayGetDim( psa );
|
||
|
|
|
||
|
|
// Count the number of items in the last dimension...
|
||
|
|
SafeArrayGetUBound( var.parray, countDims, &lUpper );
|
||
|
|
SafeArrayGetLBound( var.parray, countDims, &lLower );
|
||
|
|
countItemsLastDim = (lUpper - lLower + 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Is this a vector? If so, we only consider it an "array" if there
|
||
|
|
// are two dimensions.
|
||
|
|
if( typeElement == ID_ELEMENT_TYPE_VECTOR && isArray )
|
||
|
|
{
|
||
|
|
if( countDims < 2 )
|
||
|
|
{
|
||
|
|
isArray = FALSE;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
switch( var.vt & VT_TYPEMASK )
|
||
|
|
{
|
||
|
|
case VT_BOOL:
|
||
|
|
typePhysical = ID_PHYS_TYPE_BOOLEAN2 ;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case VT_I1:
|
||
|
|
typePhysical = ID_PHYS_TYPE_INTEGER1 ;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case VT_I2:
|
||
|
|
typePhysical = ID_PHYS_TYPE_INTEGER2 ;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case VT_I4:
|
||
|
|
typePhysical = ID_PHYS_TYPE_INTEGER4 ;
|
||
|
|
if( isArray && countItemsLastDim == 4 )
|
||
|
|
{
|
||
|
|
typePhysical = ID_PHYS_TYPE_GUID;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
// Real/complex
|
||
|
|
case VT_R4:
|
||
|
|
typePhysical = ID_PHYS_TYPE_REAL4 ;
|
||
|
|
if( isArray && countItemsLastDim == 2 )
|
||
|
|
{
|
||
|
|
typePhysical = ID_PHYS_TYPE_COMPLEX8;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case VT_R8:
|
||
|
|
typePhysical = ID_PHYS_TYPE_REAL8;
|
||
|
|
if( isArray && countItemsLastDim == 2 )
|
||
|
|
{
|
||
|
|
typePhysical = ID_PHYS_TYPE_COMPLEX16;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
// Date/time
|
||
|
|
case VT_DATE:
|
||
|
|
typePhysical = ID_PHYS_TYPE_TIMESTAMPPQDIF ;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return typePhysical;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
bool CPQDIF_COMSupport::SetVectorArrayFromVariant( CPQDIF_E_Vector& vect, VARIANT& values )
|
||
|
|
{
|
||
|
|
bool status = false;
|
||
|
|
long typePhysical;
|
||
|
|
unsigned int sizeSingle;
|
||
|
|
long sizeType;
|
||
|
|
BYTE * pbData;
|
||
|
|
INT1 * pdataTarget;
|
||
|
|
|
||
|
|
SAFEARRAY * psa = NULL;
|
||
|
|
|
||
|
|
long lLower;
|
||
|
|
long lUpper;
|
||
|
|
long countItems;
|
||
|
|
long countDimensions;
|
||
|
|
long countItemsDim2 = 0;
|
||
|
|
|
||
|
|
// Make sure it is an array
|
||
|
|
if( values.vt & VT_ARRAY )
|
||
|
|
{
|
||
|
|
// Is valid physical type set?
|
||
|
|
//typePhysical = vect.GetPhysicalType();
|
||
|
|
typePhysical = 0;
|
||
|
|
if( typePhysical == 0 )
|
||
|
|
{
|
||
|
|
typePhysical = GetPhysicalTypeFromVariant(
|
||
|
|
values, vect.GetElementType() );
|
||
|
|
|
||
|
|
vect.SetPhysicalType( typePhysical );
|
||
|
|
sizeType = theInfo.GetNumBytesOfType( typePhysical );
|
||
|
|
}
|
||
|
|
|
||
|
|
// Which safearray?
|
||
|
|
if( values.vt & VT_BYREF )
|
||
|
|
{
|
||
|
|
if( values.pparray )
|
||
|
|
psa = *values.pparray;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
psa = values.parray;
|
||
|
|
}
|
||
|
|
|
||
|
|
if( !FAILED( SafeArrayAccessData( psa, (void **)&pbData ) ) )
|
||
|
|
{
|
||
|
|
// Get the physical size of each element
|
||
|
|
sizeSingle = SafeArrayGetElemsize( values.parray );
|
||
|
|
|
||
|
|
// Get the size of the new array.
|
||
|
|
SafeArrayGetUBound( values.parray, 1, &lUpper );
|
||
|
|
SafeArrayGetLBound( values.parray, 1, &lLower );
|
||
|
|
countItems = (lUpper - lLower + 1);
|
||
|
|
|
||
|
|
// Is there a second dimension?
|
||
|
|
countDimensions = SafeArrayGetDim( values.parray );
|
||
|
|
if( countDimensions > 1 )
|
||
|
|
{
|
||
|
|
SafeArrayGetUBound( values.parray, 2, &lUpper );
|
||
|
|
SafeArrayGetLBound( values.parray, 2, &lLower );
|
||
|
|
countItemsDim2 = (lUpper - lLower + 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Configure vector
|
||
|
|
vect.SetCount( countItems );
|
||
|
|
|
||
|
|
pdataTarget = reinterpret_cast<INT1 *>(vect.GetRawData());
|
||
|
|
|
||
|
|
if( pdataTarget && (int) sizeType == (int) sizeSingle )
|
||
|
|
{
|
||
|
|
// Copy the caller's data into the array.
|
||
|
|
memcpy( pdataTarget, pbData, countItems * sizeSingle );
|
||
|
|
status = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
SafeArrayUnaccessData( psa );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
bool CPQDIF_COMSupport::NewArrayUINT4FromVariant
|
||
|
|
(
|
||
|
|
UINT4 ** aidxChannelTriggerLocal,
|
||
|
|
long& countItems,
|
||
|
|
VARIANT& var
|
||
|
|
)
|
||
|
|
{
|
||
|
|
bool status = false;
|
||
|
|
long lLower;
|
||
|
|
long lUpper;
|
||
|
|
BYTE * pbData;
|
||
|
|
long * pSource;
|
||
|
|
UINT4 * pTarget;
|
||
|
|
|
||
|
|
// Init
|
||
|
|
*aidxChannelTriggerLocal = NULL;
|
||
|
|
countItems = 0;
|
||
|
|
|
||
|
|
// Valid array of long?
|
||
|
|
if( ( var.vt & VT_ARRAY ) && ( var.vt & VT_I4 ) && var.parray )
|
||
|
|
{
|
||
|
|
// Validate the size of the array
|
||
|
|
SafeArrayGetUBound( var.parray, 1, &lUpper );
|
||
|
|
SafeArrayGetLBound( var.parray, 1, &lLower );
|
||
|
|
countItems = (lUpper - lLower + 1);
|
||
|
|
|
||
|
|
if( countItems > 0 )
|
||
|
|
{
|
||
|
|
if( !FAILED( SafeArrayAccessData( var.parray, (void **) &pbData ) ) )
|
||
|
|
{
|
||
|
|
// Allocate space
|
||
|
|
*aidxChannelTriggerLocal = new UINT4[ countItems ];
|
||
|
|
|
||
|
|
// Create temp pointers (to be incremented) and copy
|
||
|
|
pSource = (long *) pbData;
|
||
|
|
pTarget = *aidxChannelTriggerLocal;
|
||
|
|
for( long idx = 0; idx < countItems; idx++, pSource++, pTarget++ )
|
||
|
|
{
|
||
|
|
*pTarget = (UINT4) *pSource;
|
||
|
|
}
|
||
|
|
|
||
|
|
status = true;
|
||
|
|
SafeArrayUnaccessData( var.parray );
|
||
|
|
}
|
||
|
|
} // Got safe array data
|
||
|
|
} // Valid safe array
|
||
|
|
|
||
|
|
return status;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
bool CPQDIF_COMSupport::NewComStringFromVector( CPQDIF_E_Vector& vect, BSTR * str )
|
||
|
|
{
|
||
|
|
bool status = false;
|
||
|
|
long countItems;
|
||
|
|
string strOutput;
|
||
|
|
INT1 * pdataSource;
|
||
|
|
|
||
|
|
// Init
|
||
|
|
strOutput = "";
|
||
|
|
vect.GetCount( countItems );
|
||
|
|
|
||
|
|
switch( vect.GetPhysicalType() )
|
||
|
|
{
|
||
|
|
case ID_PHYS_TYPE_CHAR1:
|
||
|
|
pdataSource = reinterpret_cast<INT1 *>(vect.GetRawData());
|
||
|
|
if( pdataSource )
|
||
|
|
{
|
||
|
|
// Convert it to a string
|
||
|
|
USES_CONVERSION;
|
||
|
|
strOutput = (const char *) pdataSource;
|
||
|
|
*str = SysAllocString(_bstr_t(strOutput.c_str()));
|
||
|
|
status = true;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case ID_PHYS_TYPE_CHAR2:
|
||
|
|
// NOT SUPPORTED
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
status = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
bool CPQDIF_COMSupport::SetVectorArrayFromString( CPQDIF_E_Vector& vect, BSTR * str )
|
||
|
|
{
|
||
|
|
bool status = false;
|
||
|
|
|
||
|
|
USES_CONVERSION;
|
||
|
|
|
||
|
|
// Init
|
||
|
|
vect.SetValues( W2A(*str) );
|
||
|
|
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
bool CPQDIF_COMSupport::SetDateFromTimeStamp( DATE& date, const TIMESTAMPPQDIF& ts )
|
||
|
|
{
|
||
|
|
date = (double) ts.day
|
||
|
|
+ ( (double) ts.sec / (double) SECONDS_PER_DAY );
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
bool CPQDIF_COMSupport::SetTimeStampFromDate( TIMESTAMPPQDIF& ts, const DATE& date )
|
||
|
|
{
|
||
|
|
// Take integral portion for the day
|
||
|
|
ts.day = (UINT4) date;
|
||
|
|
|
||
|
|
// Take the fractional portion for the seconds
|
||
|
|
ts.sec = ( (REAL8) SECONDS_PER_DAY ) * ( (REAL8) date - (REAL8) ts.day );
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif // PQDIF_USE_COM
|