/*++ Copyright (C) 1996-2001 Microsoft Corporation Module Name: Abstract: History: --*/ #include "precomp.h" #include #include #include #include #include "cimval.h" BOOL SecondsToInterval( long double ldbSeconds, LPWSTR wszText, size_t cchSize ) { int nDay, nHour, nMinute, nSecond, nMicro; nDay = int(ldbSeconds / 86400); ldbSeconds -= nDay * 86400; nHour = int(ldbSeconds / 3600); ldbSeconds -= nHour * 3600; nMinute = int(ldbSeconds / 60); ldbSeconds -= nMinute * 60; nSecond = int(ldbSeconds); ldbSeconds -= nSecond; nMicro = int(ldbSeconds * 1000000); if(FAILED(StringCchPrintfW( wszText, cchSize, L"%08.8d%02.2d%02.2d%02.2d.%06.6d:000", nDay, nHour, nMinute, nSecond, nMicro ))) return FALSE; return TRUE; } // this should be a WBEM common thing ... BOOL FileTimeToDateTime( FILETIME* pft, LPWSTR wszText, size_t cchSize ) { SYSTEMTIME st; __int64 llnss = *(__int64*)pft; if ( !FileTimeToSystemTime( pft, &st ) ) { return FALSE; } // // have to account for microseconds as well (probably a much better way // to do this.) // st.wMilliseconds = 0; FILETIME ft; if ( !SystemTimeToFileTime( &st, &ft ) ) { return FALSE; } __int64 llnss2 = *(__int64*)&ft; int nMicro = int((llnss - llnss2)/10); if (FAILED(StringCchPrintfW( wszText, cchSize, L"%04.4d%02.2d%02.2d%02.2d%02.2d%02.2d.%06.6d+000", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, nMicro ))) return FALSE; return TRUE; } BOOL SecondsToDateTime( long double ldbSeconds, LPWSTR wszText, size_t cchSize ) { FILETIME* pft; __int64 llnss = __int64(ldbSeconds * 10000000); pft = (FILETIME*)&llnss; return FileTimeToDateTime( pft, wszText, cchSize ); } BOOL IntervalToSeconds( LPCWSTR wszText, long double& rldbSeconds ) { int nDay, nHour, nMinute, nSecond, nMicro; int nRes = swscanf( wszText, L"%8d%2d%2d%2d.%6d", &nDay, &nHour, &nMinute, &nSecond, &nMicro ); if ( nRes != 5 ) { return FALSE; } rldbSeconds = nSecond + 60*nMinute + 3600*nHour + 86400*nDay; rldbSeconds += nMicro / 1000000.0; return TRUE; } BOOL DateTimeToSeconds( LPCWSTR wszText, long double& rldbSeconds ) { WORD nYear, nMonth, nDay, nHour, nMinute, nSecond, nMicro, nOffset; WCHAR wchSep; int nRes = swscanf( wszText, L"%4d%2d%2d%2d%2d%2d.%6d%c%3d", &nYear, &nMonth, &nDay, &nHour, &nMinute, &nSecond, &nMicro, &wchSep, &nOffset ); if(nRes != 9) { return FALSE; } int nSign; if( wchSep == L'+' ) { nSign = -1; } else if ( wchSep == L'-' ) { nSign = 1; } else { return FALSE; } // Convert it to SYSTEMTIME // ======================== SYSTEMTIME st; st.wYear = nYear; st.wMonth = nMonth; st.wDay = nDay; st.wHour = nHour; st.wMinute = nMinute; st.wSecond = nSecond; st.wMilliseconds = 0; // // convert SYSTEMTIME to FILETIME // FILETIME ft; if ( !SystemTimeToFileTime( &st, &ft ) ) { return FALSE; } rldbSeconds = (long double)*(__int64*)&ft; rldbSeconds += nMicro*10; rldbSeconds /= 10000000; // Now adjust for the offset // ========================= rldbSeconds += nSign * nOffset * 60; return TRUE; } BOOL DMTFToSeconds( LPCWSTR wszText, long double& rldbSeconds ) { if( wcslen(wszText) != 25 ) { return FALSE; } if ( wszText[21] != ':' ) { return DateTimeToSeconds( wszText, rldbSeconds ); } return IntervalToSeconds( wszText, rldbSeconds ); } CCimValue::CCimValue( ) : m_eType( e_Int ), m_iVal( 0 ) { } HRESULT CCimValue::GetValue( VARIANT& rvValue, ULONG lCimType ) { VariantInit( &rvValue ); WCHAR achBuff[255]; BOOL bRes; switch( lCimType ) { case CIM_SINT8: case CIM_SINT16: case CIM_SINT32: case CIM_BOOLEAN: CoerceToInt(); V_VT(&rvValue) = VT_I4; V_I4(&rvValue) = m_iVal; break; case CIM_UINT8: case CIM_UINT16: case CIM_UINT32: CoerceToUnsignedInt(); V_VT(&rvValue) = VT_I4; V_I4(&rvValue) = m_uiVal; break; case CIM_SINT64: case CIM_STRING: CoerceToLong(); _i64tow( m_lVal, achBuff, 10 ); V_VT(&rvValue) = VT_BSTR; V_BSTR(&rvValue) = SysAllocString(achBuff); break; case CIM_REAL32: CoerceToFloat(); V_VT(&rvValue) = VT_R4; V_R4(&rvValue) = m_fVal; break; case CIM_REAL64: CoerceToDouble(); V_VT(&rvValue) = VT_R8; V_R8(&rvValue) = m_dbVal; break; case CIM_UINT64: CoerceToUnsignedLong(); _ui64tow( m_ulVal, achBuff, 10 ); V_VT(&rvValue) = VT_BSTR; V_BSTR(&rvValue) = SysAllocString(achBuff); break; case CIM_INTERVAL: CoerceToLongDouble(); bRes = SecondsToInterval( m_ldbVal, achBuff, 255 ); if ( !bRes ) { return WBEM_E_TYPE_MISMATCH; } V_VT(&rvValue) = VT_BSTR; V_BSTR(&rvValue) = SysAllocString(achBuff); break; case CIM_DATETIME: CoerceToLongDouble(); bRes = SecondsToDateTime( m_ldbVal, achBuff, 255 ); if ( !bRes ) { return WBEM_E_TYPE_MISMATCH; } V_VT(&rvValue) = VT_BSTR; V_BSTR(&rvValue) = SysAllocString(achBuff); break; default: return WBEM_E_TYPE_MISMATCH; }; return WBEM_S_NO_ERROR; } HRESULT CCimValue::SetValue( VARIANT& rvValue, ULONG lCimType ) { HRESULT hr; VARIANT vValue; VariantInit( &vValue ); if ( lCimType == CIM_EMPTY ) { // // must be a numeric value. // switch( V_VT(&rvValue) ) { case VT_R4: m_eType = e_Float; m_fVal = V_R4(&rvValue); break; case VT_R8: m_eType = e_Double; m_dbVal = V_R8(&rvValue); break; case VT_BSTR: m_lVal = (__int64)_wtoi64( V_BSTR(&rvValue) ); break; default: hr = VariantChangeType( &vValue, &rvValue, 0, VT_I4 ); if ( FAILED(hr) ) return WBEM_E_TYPE_MISMATCH; m_eType = e_Int; m_iVal = V_I4(&vValue); }; return WBEM_S_NO_ERROR; } switch( lCimType ) { case CIM_SINT8: case CIM_SINT16: case CIM_SINT32: case CIM_BOOLEAN: hr = VariantChangeType( &vValue, &rvValue, 0, VT_I4 ); if ( FAILED(hr) ) return WBEM_E_TYPE_MISMATCH; m_eType = e_Int; m_iVal = V_I4(&vValue); break; case CIM_UINT8: case CIM_UINT16: case CIM_UINT32: hr = VariantChangeType( &vValue, &rvValue, 0, VT_UI4 ); if ( FAILED(hr) ) return WBEM_E_TYPE_MISMATCH; m_eType = e_UnsignedInt; m_uiVal = V_UI4(&vValue); break; case CIM_SINT64: case CIM_STRING: if ( V_VT(&rvValue) == VT_BSTR ) { m_lVal = _wtoi64( V_BSTR(&rvValue) ); } else { return WBEM_E_TYPE_MISMATCH; } m_eType = e_Long; break; case CIM_UINT64: if ( V_VT(&rvValue) == VT_BSTR ) { m_ulVal = (unsigned __int64)_wtoi64( V_BSTR(&rvValue) ); } else { return WBEM_E_TYPE_MISMATCH; } m_eType = e_UnsignedLong; break; case CIM_REAL32: hr = VariantChangeType( &vValue, &rvValue, 0, VT_R4 ); if ( FAILED(hr) ) return WBEM_E_TYPE_MISMATCH; m_eType = CCimValue::e_Float; m_fVal = V_R4(&vValue); break; case CIM_REAL64: hr = VariantChangeType( &vValue, &rvValue, 0, VT_R8 ); if ( FAILED(hr) ) return WBEM_E_TYPE_MISMATCH; m_eType = CCimValue::e_Double; m_dbVal = V_R8(&vValue); break; case CIM_DATETIME: case CIM_INTERVAL: if ( V_VT(&rvValue) == VT_BSTR ) { BOOL bRes = DMTFToSeconds( V_BSTR(&rvValue), m_ldbVal ); if ( !bRes ) { return WBEM_E_TYPE_MISMATCH; } } else { return WBEM_E_TYPE_MISMATCH; } m_eType = e_LongDouble; break; default: return WBEM_E_TYPE_MISMATCH; }; return WBEM_S_NO_ERROR; } void CCimValue::CoerceToLongDouble() { switch( m_eType ) { case e_Int: m_ldbVal = (long double)m_iVal; break; case e_UnsignedInt: m_ldbVal = (long double)m_uiVal; break; case e_Float: m_ldbVal = (long double)m_fVal; break; case e_Double: m_ldbVal = (long double)m_dbVal; break; case e_Long: m_ldbVal = (long double)m_lVal; break; case e_UnsignedLong: m_ldbVal = (long double)(__int64)m_ulVal; break; }; m_eType = e_LongDouble; } void CCimValue::CoerceToDouble() { switch( m_eType ) { case e_Int: m_dbVal = (double)m_iVal; break; case e_UnsignedInt: m_dbVal = (double)m_uiVal; break; case e_Float: m_dbVal = (double)m_fVal; break; case e_LongDouble: m_dbVal = (double)m_ldbVal; break; case e_Long: m_dbVal = (double)m_lVal; break; case e_UnsignedLong: m_dbVal = (double)(__int64)m_ulVal; break; }; m_eType = e_Double; } void CCimValue::CoerceToFloat() { switch( m_eType ) { case e_Int: m_fVal = (float)m_iVal; break; case e_UnsignedInt: m_fVal = (float)m_uiVal; break; case e_LongDouble: m_fVal = (float)m_ldbVal; break; case e_Double: m_fVal = (float)m_dbVal; break; case e_Long: m_fVal = (float)m_lVal; break; case e_UnsignedLong: m_fVal = (float)(__int64)m_ulVal; break; }; m_eType = e_Float; } void CCimValue::CoerceToUnsignedLong() { switch( m_eType ) { case e_Int: m_ulVal = (unsigned __int64)m_iVal; break; case e_UnsignedInt: m_ulVal = (unsigned __int64)m_uiVal; break; case e_Float: m_ulVal = (unsigned __int64)m_fVal; break; case e_Double: m_ulVal = (unsigned __int64)m_dbVal; break; case e_Long: m_ulVal = (unsigned __int64)m_lVal; break; case e_LongDouble: m_ulVal = (unsigned __int64)m_ldbVal; break; }; m_eType = e_UnsignedLong; } void CCimValue::CoerceToLong() { switch( m_eType ) { case e_Int: m_lVal = (__int64)m_iVal; break; case e_UnsignedInt: m_lVal = (__int64)m_uiVal; break; case e_Float: m_lVal = (__int64)m_fVal; break; case e_Double: m_lVal = (__int64)m_dbVal; break; case e_UnsignedLong: m_lVal = (__int64)m_ulVal; break; case e_LongDouble: m_lVal = (__int64)m_ldbVal; break; }; m_eType = e_Long; } void CCimValue::CoerceToUnsignedInt() { switch( m_eType ) { case e_Int: m_uiVal = (unsigned __int32)m_iVal; break; case e_Float: m_uiVal = (unsigned __int32)m_fVal; break; case e_Double: m_uiVal = (unsigned __int32)m_dbVal; break; case e_Long: m_uiVal = (unsigned __int32)m_lVal; break; case e_UnsignedLong: m_uiVal = (unsigned __int32)m_ulVal; break; case e_LongDouble: m_uiVal = (unsigned __int32)m_ldbVal; break; }; m_eType = e_UnsignedInt; } void CCimValue::CoerceToInt() { switch( m_eType ) { case e_Long: m_iVal = (__int32)m_lVal; break; case e_UnsignedInt: m_iVal = (__int32)m_uiVal; break; case e_Float: m_iVal = (__int32)m_fVal; break; case e_Double: m_iVal = (__int32)m_dbVal; break; case e_UnsignedLong: m_iVal = (__int32)m_ulVal; break; case e_LongDouble: m_iVal = (__int32)m_ldbVal; break; }; m_eType = e_Int; } void HandleConversion( CCimValue& rValA, CCimValue& rValB ) { if ( rValA.m_eType == rValB.m_eType ) { return; } if ( rValA.m_eType == CCimValue::e_LongDouble ) { rValB.CoerceToLongDouble(); return; } if ( rValB.m_eType == CCimValue::e_LongDouble ) { rValA.CoerceToLongDouble(); return; } if ( rValA.m_eType == CCimValue::e_Double ) { rValB.CoerceToDouble(); return; } if ( rValB.m_eType == CCimValue::e_Double ) { rValA.CoerceToDouble(); return; } if ( rValA.m_eType == CCimValue::e_Float ) { rValB.CoerceToFloat(); return; } if ( rValB.m_eType == CCimValue::e_Float ) { rValA.CoerceToFloat(); return; } if ( rValA.m_eType == CCimValue::e_UnsignedLong ) { rValB.CoerceToUnsignedLong(); return; } if ( rValB.m_eType == CCimValue::e_UnsignedLong ) { rValA.CoerceToUnsignedLong(); return; } if ( rValA.m_eType == CCimValue::e_Long && rValB.m_eType == CCimValue::e_UnsignedInt || rValB.m_eType == CCimValue::e_Long && rValA.m_eType == CCimValue::e_UnsignedInt ) { rValA.CoerceToUnsignedLong(); rValB.CoerceToUnsignedLong(); return; } if ( rValA.m_eType == CCimValue::e_Long ) { rValB.CoerceToLong(); return; } if ( rValB.m_eType == CCimValue::e_Long ) { rValA.CoerceToLong(); return; } if ( rValA.m_eType == CCimValue::e_UnsignedInt ) { rValB.CoerceToUnsignedInt(); return; } if ( rValB.m_eType == CCimValue::e_UnsignedInt ) { rValA.CoerceToUnsignedInt(); return; } // this means both must be e_Int, but our check in the beginning // should have handled this... assert( 0 ); } CCimValue operator+ ( CCimValue ValA, CCimValue ValB ) { HandleConversion( ValA, ValB ); assert( ValA.m_eType == ValB.m_eType ); switch( ValA.m_eType ) { case CCimValue::e_Int: ValA.m_iVal += ValB.m_iVal; break; case CCimValue::e_UnsignedInt: ValA.m_uiVal += ValB.m_uiVal; break; case CCimValue::e_Float: ValA.m_fVal += ValB.m_fVal; break; case CCimValue::e_Double: ValA.m_dbVal += ValB.m_dbVal; break; case CCimValue::e_LongDouble: ValA.m_ldbVal += ValB.m_ldbVal; break; case CCimValue::e_Long: ValA.m_lVal += ValB.m_lVal; break; case CCimValue::e_UnsignedLong: ValA.m_ulVal += ValB.m_ulVal; break; default: assert(0); }; return ValA; } CCimValue operator- ( CCimValue ValA, CCimValue ValB ) { HandleConversion( ValA, ValB ); assert( ValA.m_eType == ValB.m_eType ); switch( ValA.m_eType ) { case CCimValue::e_Int: ValA.m_iVal -= ValB.m_iVal; break; case CCimValue::e_UnsignedInt: ValA.m_uiVal -= ValB.m_uiVal; break; case CCimValue::e_Float: ValA.m_fVal -= ValB.m_fVal; break; case CCimValue::e_Double: ValA.m_dbVal -= ValB.m_dbVal; break; case CCimValue::e_Long: ValA.m_lVal -= ValB.m_lVal; break; case CCimValue::e_UnsignedLong: ValA.m_ulVal -= ValB.m_ulVal; break; case CCimValue::e_LongDouble: ValA.m_ldbVal -= ValB.m_ldbVal; break; default: assert(0); }; return ValA; } CCimValue operator* ( CCimValue ValA, CCimValue ValB ) { HandleConversion( ValA, ValB ); assert( ValA.m_eType == ValB.m_eType ); switch( ValA.m_eType ) { case CCimValue::e_Int: ValA.m_iVal *= ValB.m_iVal; break; case CCimValue::e_UnsignedInt: ValA.m_uiVal *= ValB.m_uiVal; break; case CCimValue::e_Float: ValA.m_fVal *= ValB.m_fVal; break; case CCimValue::e_Double: ValA.m_dbVal *= ValB.m_dbVal; break; case CCimValue::e_Long: ValA.m_lVal *= ValB.m_lVal; break; case CCimValue::e_UnsignedLong: ValA.m_ulVal *= ValB.m_ulVal; break; case CCimValue::e_LongDouble: ValA.m_ldbVal *= ValB.m_ldbVal; break; default: assert(0); }; return ValA; } CCimValue operator/ ( CCimValue ValA, CCimValue ValB ) { HandleConversion( ValA, ValB ); assert( ValA.m_eType == ValB.m_eType ); // // will raise a structured exception if div by 0. // caller is expected to handle this.. // switch( ValA.m_eType ) { case CCimValue::e_Int: if ( ValB.m_iVal == 0 ) throw CX_DivideByZeroException(); ValA.m_iVal /= ValB.m_iVal; break; case CCimValue::e_UnsignedInt: if ( ValB.m_uiVal == 0 ) throw CX_DivideByZeroException(); ValA.m_uiVal /= ValB.m_uiVal; break; case CCimValue::e_Float: if ( ValB.m_fVal == 0 ) throw CX_DivideByZeroException(); ValA.m_fVal /= ValB.m_fVal; break; case CCimValue::e_Double: if ( ValB.m_dbVal == 0 ) throw CX_DivideByZeroException(); ValA.m_dbVal /= ValB.m_dbVal; break; case CCimValue::e_Long: if ( ValB.m_lVal == 0 ) throw CX_DivideByZeroException(); ValA.m_lVal /= ValB.m_lVal; break; case CCimValue::e_UnsignedLong: if ( ValB.m_ulVal == 0 ) throw CX_DivideByZeroException(); ValA.m_ulVal /= ValB.m_ulVal; break; case CCimValue::e_LongDouble: if ( ValB.m_ldbVal == 0 ) throw CX_DivideByZeroException(); ValA.m_ldbVal /= ValB.m_ldbVal; break; default: assert(0); }; return ValA; } CCimValue operator% ( CCimValue ValA, CCimValue ValB ) { HandleConversion( ValA, ValB ); assert( ValA.m_eType == ValB.m_eType ); // // will raise a structured exception if div by 0. // caller is expected to handle this.. // switch( ValA.m_eType ) { case CCimValue::e_Int: if ( ValB.m_iVal == 0 ) throw CX_DivideByZeroException(); ValA.m_iVal %= ValB.m_iVal; break; case CCimValue::e_UnsignedInt: if ( ValB.m_uiVal == 0 ) throw CX_DivideByZeroException(); ValA.m_uiVal %= ValB.m_uiVal; break; case CCimValue::e_Float: case CCimValue::e_Double: case CCimValue::e_LongDouble: throw CX_InvalidFloatingPointOperationException(); case CCimValue::e_Long: if ( ValB.m_lVal == 0 ) throw CX_DivideByZeroException(); ValA.m_lVal %= ValB.m_lVal; break; case CCimValue::e_UnsignedLong: if ( ValB.m_ulVal == 0 ) throw CX_DivideByZeroException(); ValA.m_ulVal %= ValB.m_ulVal; break; default: assert(0); }; return ValA; }