How to Decode the CIM_DATETIME Format Employed in WMI Queries Using C++






4.78/5 (5 votes)
A robust approach to decoding CIM_DATETIME for C++ programmers
Introduction
This will show how a C++ programmer may convert a time value returned from a WMI query into a format she/he will be more familiar with.
Background
WMI queries use a date and time format called CIM_DATETIME (Common Information Model). In the MSDN example Getting WMI Data from the local computer, the WIN32_OperatingSystem class contains this property:
datetime LastBootUpTime;
This is a CIM_DATETIME
format string. It is also known as DMTF (Distributed Management Task Force) datetime format. Date and time are encoded as a string
containing UTC time with an appended offset in minutes for the current locale. This is the offset of local time from UTC time. Encoded time values have a one microsecond resolution.
Scripting services are provided with SWbemDateTime() to parse this format. C# programmers may employ ManagementDateTimeConverter.ToDateTime
:
// Convert DMTF datetime to System.DateTime
string dmtfDate = "20140408141835.999999+480";
DateTime dt = ManagementDateTimeConverter.ToDateTime(dmtfDate);
For C++ programmers in an unmanaged environment, they can if they wish parse the string
directly. This is a perfectly acceptable approach. If in the future the encoded format is altered, then dependent code would be affected. Fortunately, SWbemDateTime()
also exposes a COM interface which can be instantiated in this way:
ISWbemDateTime *pSWbemDateTime = NULL;
HRESULT hr = CoCreateInstance(CLSID_SWbemDateTime, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pSWbemDateTime));
Using the Code
SWbemDateTime()
can convert CIM_DATETIME
values to and from FILETIME
and VT_DATE
values. VT_DATE
is a lower precision format (500 millisecond) so this tip will concentrate on the FILETIME
format which is probably of more interest to C++ programmers. The function CIMDateTimetoFiletime()
below may be used to convert a CIM_DATETIME
to a FILETIME
in either local time or UTC time.
// Convert CIM_DATETIME to FILETIME either as UTC or local time.
// Input: CIM_DATETIME as LPCWSTR
// Input: bool blocaltime: true compute local time else compute UTC time
// Output: FILETIME pointer
// Return: true for success
bool CIMDateTimetoFiletime(__in LPCWSTR cimdatetime, __out LPFILETIME filetime,
__in const bool blocaltime = true)
{
bool bSuccess = false;
// Get a SWbemDateTime object.
ISWbemDateTime *pSWbemDateTime = NULL;
HRESULT hr = CoCreateInstance(CLSID_SWbemDateTime, NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pSWbemDateTime));
if (SUCCEEDED(hr))
{
BSTR timebstr = SysAllocString(cimdatetime);
if (timebstr)
{
// Set time value.
hr = pSWbemDateTime->put_Value(timebstr);
if (SUCCEEDED(hr))
{
BSTR bstrFileTime;
// Get a FILETIME.
hr = pSWbemDateTime->GetFileTime(blocaltime?VARIANT_TRUE:VARIANT_FALSE,
&bstrFileTime);
if (SUCCEEDED(hr))
{
ULARGE_INTEGER tempFT;
// 64-bit value representing the number of 100-nanosecond intervals
// since January 1, 1601 (UTC).
tempFT.QuadPart = _wtoi64(bstrFileTime);
// FILETIME is a structure of two 32-bit integers.
filetime->dwLowDateTime = tempFT.LowPart;
filetime->dwHighDateTime = tempFT.HighPart;
bSuccess = true;
SysFreeString(bstrFileTime);
}
}
SysFreeString(timebstr);
}
pSWbemDateTime->Release();
}
return bSuccess;
}
The project supplied uses the example from MSDN to extract the LastBootTime
and convert to FILETIME
as both UTC and local times.
History
- v1.00 07-04-2014