Skip to content

Commit

Permalink
Added visualizer for COleDateTime.
Browse files Browse the repository at this point in the history
Display all 3 times via the FILETIME output so they all show UTC & local times.
  • Loading branch information
David-FromVS authored and David-FromVS committed Dec 30, 2020
1 parent 7eb64b0 commit 851eac2
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 15 deletions.
19 changes: 19 additions & 0 deletions CppCustomVisualizer/TargetApp/TargetApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
#include <iostream>
#include <windows.h>
#include <propkey.h>
#include <tchar.h>
#include <ATLComTime.h>
//#include <ctime>

class MyClass
{
Expand All @@ -20,9 +23,21 @@ class MyClass
}
};

//#include <atlbase.h>
//#include <atlsecurity.h>

int wmain(int argc, WCHAR* argv[])
{
// LOGFONT lf;

COleDateTime dt{COleDateTime::GetCurrentTime()};
// Create one in summer time
COleDateTime dtSummer( dt.GetYear(), 6, 16, 1, 2, 3 );
// Another in winter time
COleDateTime dtWinter(dt.GetYear(), 12, 25, 4, 5, 6);

CString str = dt.Format();

FILETIME ft;
SYSTEMTIME st;

Expand Down Expand Up @@ -52,6 +67,10 @@ int wmain(int argc, WCHAR* argv[])

FILETIME FTZero = {};

#if 0 //Ineffective, no unique struct definition
time_t tim;
time( &tim );
#endif
__debugbreak(); // program will stop here. Evaluate 'myC', key, st, ft, lst in the debugtip, locals or watch windows.
std::cout << "Test complete\n";

Expand Down
7 changes: 6 additions & 1 deletion CppCustomVisualizer/dll/CppCustomVisualizer.vsdconfigxml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ For more information about this file, see https://github.com/Microsoft/ConcordEx
<Configuration xmlns="http://schemas.microsoft.com/vstudio/vsdconfig/2008">

<!--TODO: If you copy the sample, ensure to regenerate the GUIDs in this file. This
can be done with the 'Create GUID' tool ('Tools->Create GUID' in Visual Sudio or
can be done with the 'Create GUID' tool ('Tools->Create GUID' in Visual Studio or
guidgen.exe from the command line). -->

<NativeComponent
Expand All @@ -35,12 +35,17 @@ For more information about this file, see https://github.com/Microsoft/ConcordEx
<InterfaceGroup>
<!--NOTE: These VisualizerId(s) are also used in the .natvis file.-->
<Filter>
<!--COleDateTime-->
<VisualizerId RequiredValue="C27383FF-1889-4959-A0E4-99DB41295CB3"/>
<!--FILETIME-->
<VisualizerId RequiredValue="34A6191C-7D6D-4B36-9C3F-A4D051289DEB"/>
<!--SYSTEMTIME-->
<VisualizerId RequiredValue="1AC4A977-2954-4316-8CE6-A6251EEBA144"/>
<!--PROPERTYKEY-->
<VisualizerId RequiredValue="47D01893-3FA1-4326-9ED2-5236246CF231"/>
<!--time_t Ineffective, no unique struct definition
<VisualizerId RequiredValue="C7B69925-4654-434D-A657-631AAB40BB82"/>
-->
</Filter>
<Interface Name="IDkmCustomVisualizer"/>
</InterfaceGroup>
Expand Down
13 changes: 13 additions & 0 deletions CppCustomVisualizer/dll/DavesCustomVisualizer.natvis
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,17 @@ For information about natvis files see: https://docs.microsoft.com/en-us/visuals
<Type Name="_tagpropertykey">
<CustomVisualizer VisualizerId="47D01893-3FA1-4326-9ED2-5236246CF231"/>
</Type>
<!--
Ineffective, no unique struct definition
<Type Name="__time64_t">
<CustomVisualizer VisualizerId="C7B69925-4654-434D-A657-631AAB40BB82"/>
</Type>
-->
<Type Name="ATL::COleDateTime">
<!--<CustomVisualizer Condition="m_status == DateTimeStatus::valid" VisualizerId="C27383FF-1889-4959-A0E4-99DB41295CB3"/>-->
<CustomVisualizer VisualizerId="C27383FF-1889-4959-A0E4-99DB41295CB3"/>
<!--<DisplayString Condition="m_status != DateTimeStatus::valid">Invalid</DisplayString>-->
<!--<DisplayString Condition="m_status == DateTimeStatus::valid">{m_dt}</DisplayString>-->
</Type>

</AutoVisualizer>
91 changes: 80 additions & 11 deletions CppCustomVisualizer/dll/_EntryPoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@
#include "_EntryPoint.h"
#include "FileAndSystemTimeViz.h"
#include "PropertyKeyViz.h"
//#include <ctime>
#include <ATLComTime.h>

#define INITGUID
#include <initguid.h>

// These GUID values are referenced in the .natvis file where the're associated with the named type
// {34A6191C-7D6D-4B36-9C3F-A4D051289DEB}
DEFINE_GUID( FILETIME_VIZ_ID, 0x34a6191c, 0x7d6d, 0x4b36, 0x9c, 0x3f, 0xa4, 0xd0, 0x51, 0x28, 0x9d, 0xeb );

Expand All @@ -19,22 +23,29 @@ DEFINE_GUID( SYSTEMTIME_VIZ_ID, 0x1ac4a977, 0x2954, 0x4316, 0x8c, 0xe6, 0xa6, 0x
// {47D01893-3FA1-4326-9ED2-5236246CF231}
DEFINE_GUID( PROPKEY_VIZ_ID, 0x47d01893, 0x3fa1, 0x4326, 0x9e, 0xd2, 0x52, 0x36, 0x24, 0x6c, 0xf2, 0x31 );

// {C7B69925-4654-434D-A657-631AAB40BB82}
//DEFINE_GUID( TIME_T_VIZ_ID, 0xc7b69925, 0x4654, 0x434d, 0xa6, 0x57, 0x63, 0x1a, 0xab, 0x40, 0xbb, 0x82 );

// {C27383FF-1889-4959-A0E4-99DB41295CB3}
DEFINE_GUID( COleDateTime_VIZ_ID,
0xc27383ff, 0x1889, 0x4959, 0xa0, 0xe4, 0x99, 0xdb, 0x41, 0x29, 0x5c, 0xb3 );

HRESULT STDMETHODCALLTYPE CCppCustomVisualizerService::EvaluateVisualizedExpression(
_In_ Evaluation::DkmVisualizedExpression* pVisualizedExpression,
_Deref_out_opt_ Evaluation::DkmEvaluationResult** ppResultObject
)
{
HRESULT hr;

// This method is called to visualize a FILETIME variable. Its basic job is to create
// This method is called to visualize one of the variable types this extension handles. Its basic job is to create
// a DkmEvaluationResult object. A DkmEvaluationResult is the data that backs a row in the
// watch window -- a name, value, and type, a flag indicating if the item can be expanded, and
// lots of other additional properties.

Evaluation::DkmPointerValueHome* pPointerValueHome = Evaluation::DkmPointerValueHome::TryCast(pVisualizedExpression->ValueHome());
if (pPointerValueHome == nullptr)
{
// This sample only handles visualizing in-memory FILETIME structures
// This sample only handles visualizing in-memory structures
return E_NOTIMPL;
}

Expand All @@ -48,7 +59,7 @@ HRESULT STDMETHODCALLTYPE CCppCustomVisualizerService::EvaluateVisualizedExpress
DkmProcess* pTargetProcess = pVisualizedExpression->RuntimeInstance()->Process();
CString strValue;

auto vizId = pVisualizedExpression->VisualizerId();
const auto & vizId = pVisualizedExpression->VisualizerId();

if ( vizId == FILETIME_VIZ_ID )
{
Expand All @@ -74,8 +85,12 @@ HRESULT STDMETHODCALLTYPE CCppCustomVisualizerService::EvaluateVisualizedExpress
return E_NOTIMPL;
}

// Format as a string
strValue = FormatSystemTime( value );
// Convert to FILETIME (UTC) to pass to the string conversion that shows both UTC & local
FILETIME ft;
if ( SystemTimeToFileTime( &value, &ft ) )
{
strValue = FileTimeToText( ft, pRootVisualizedExpression->InspectionContext()->Radix() );
}

// An empty returned string indicates an invalid SYSTEMTIME
if ( strValue.IsEmpty() )
Expand All @@ -97,6 +112,58 @@ HRESULT STDMETHODCALLTYPE CCppCustomVisualizerService::EvaluateVisualizedExpress
// Format as a string
strValue = GetKeyName( value );
}
#if 0 //Ineffective, no unique struct definition
else if ( vizId == TIME_T_VIZ_ID)
{
// Read the time_t value from the target process
time_t value;
hr = pTargetProcess->ReadMemory( pPointerValueHome->Address(), DkmReadMemoryFlags::None, &value, sizeof( value ), nullptr );
if ( FAILED( hr ) )
{
// If the bytes of the value cannot be read from the target process, just fall back to the default visualization
return E_NOTIMPL;
}

// Format as a string
{
tm tmm;
gmtime_s( &tmm, &value );
char buffer[100];
asctime_s( buffer, &tmm );
strValue = buffer;
}
}
#endif
else if ( vizId == COleDateTime_VIZ_ID )
{
/*ATL::*/COleDateTime value;

hr = pTargetProcess->ReadMemory( pPointerValueHome->Address(), DkmReadMemoryFlags::None, &value, sizeof( value ), nullptr );
if ( FAILED( hr ) )
{
// If the bytes of the value cannot be read from the target process, just fall back to the default visualization
return E_NOTIMPL;
}

// Convert -> SYSTEMTIME -> FILETIME in order to use the FILETIME string output function
SYSTEMTIME st;
if ( value.GetAsSystemTime( st ) )
{
// Convert to FILETIME (UTC) to pass to the string conversion that shows both UTC & local
FILETIME ft;
if ( SystemTimeToFileTime( &st, &ft ) )
{
strValue = FileTimeToText( ft, pRootVisualizedExpression->InspectionContext()->Radix() );
}
}

// An empty returned string indicates an invalid SYSTEMTIME
if ( strValue.IsEmpty() )
{
// Note: If the COleDateTime is invalid, this returns appropriate text
strValue = value.Format();
}
}
else
{
// Don't know what it's for
Expand All @@ -105,8 +172,10 @@ HRESULT STDMETHODCALLTYPE CCppCustomVisualizerService::EvaluateVisualizedExpress

CString strEditableValue;

auto pType = pRootVisualizedExpression->Type();

// If we are formatting a pointer, we want to also show the address of the pointer
if (pRootVisualizedExpression->Type() != nullptr && wcschr(pRootVisualizedExpression->Type()->Value(), '*') != nullptr)
if ( ( pType != nullptr ) && ( wcschr( pType->Value(), '*') != nullptr ) )
{
// Make the editable value just the pointer string
UINT64 address = pPointerValueHome->Address();
Expand Down Expand Up @@ -278,11 +347,11 @@ HRESULT STDMETHODCALLTYPE CCppCustomVisualizerService::UseDefaultEvaluationBehav

CComPtr<DkmEvaluationResult> pEEEvaluationResult;
hr = pVisualizedExpression->EvaluateExpressionCallback(
pInspectionContext,
pLanguageExpression,
pVisualizedExpression->StackFrame(),
&pEEEvaluationResult
);
pInspectionContext,
pLanguageExpression,
pVisualizedExpression->StackFrame(),
&pEEEvaluationResult
);
if (FAILED(hr))
{
return hr;
Expand Down
2 changes: 1 addition & 1 deletion CppCustomVisualizer/vsix/Build-x64.targets
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ because the .vsix contains both an x86 and x64 implementation.
</PropertyGroup>

<Target Name="Build-x64" BeforeTargets="ZipItems">
<!--Unfortunately we can't use the 'MSBuild' task here but must instead spawn a new instance of msbuild. The problem is that the 'MSBuild' task will stil
<!--Unfortunately we can't use the 'MSBuild' task here but must instead spawn a new instance of msbuild. The problem is that the 'MSBuild' task will still
inherit some aspects of the current solution configuration, and when it is resolving project to project references will reference the output from the
wrong configuration-->
<Error Condition="'$(_BuildActionType)'==''" Text="'_BuildActionType' is not defined."/>
Expand Down
4 changes: 2 additions & 2 deletions CppCustomVisualizer/vsix/source.extension.vsixmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<Description xml:space="preserve">Win32 Debug Visualizers</Description>
<MoreInfo>https://github.com/Dave-Lowndes/DavesVisualStudioVisualizers/tree/master/CppCustomVisualizer</MoreInfo>
<ReleaseNotes>https://github.com/Dave-Lowndes/DavesVisualStudioVisualizers/tree/master/CppCustomVisualizer</ReleaseNotes>
<Tags>FILETIME;SYSTEMTIME;PROPERTYKEY</Tags>
<Version>1.0</Version>
<Tags>FILETIME;SYSTEMTIME;PROPERTYKEY;COleDateTime</Tags>
<Version>2.0</Version>
</Metadata>
<Installation>
<InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[14.0, 17.0)" />
Expand Down

0 comments on commit 851eac2

Please sign in to comment.