Skip to content

Commit

Permalink
Fix ConversationIndex parsing (#813)
Browse files Browse the repository at this point in the history
* shot circuit more loops

* simplify and correct guid parsing in ci

* improve conversationindex parsing

* tighten and remove intermediate variables

* Simplify reporttag

* update mapistub

* fix formatting
  • Loading branch information
stephenegriffin authored Jan 21, 2025
1 parent 37a5584 commit c2fd771
Show file tree
Hide file tree
Showing 16 changed files with 184 additions and 127 deletions.
6 changes: 5 additions & 1 deletion UnitTest/SmartViewTestData/In/CONVERSATIONINDEX-1.dat
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
01CAE55B20E5FEE284D557D84277BAB585FBD4BB2BE900006F3E90
01
CAE55B20E5
FEE284D557D84277BAB585FBD4BB2BE9
00006F3E
90
10 changes: 9 additions & 1 deletion UnitTest/SmartViewTestData/In/CONVERSATIONINDEX-4.dat
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
01CA697FF84A28B660A5B37D4058B462AF2C2CE5CCA680011C476000005ABB40001A3E6490000246F8A00005A625B00009B7BBF0
01
CA697FF84A
28B660A5B37D4058B462AF2C2CE5CCA6
80011C4760
00005ABB40
001A3E6490
000246F8A0
0005A625B0
0009B7BBF0
10 changes: 6 additions & 4 deletions UnitTest/SmartViewTestData/Out/CONVERSATIONINDEX-out-1.dat
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
Conversation Index
Unnamed byte = 0x01 = 1
Current FILETIME: (Low = 0x20E50000, High = 0x01CAE55B) = 04:11:29.014 PM 4/26/2010
GUID = {FEE284D5-57D8-4277-BAB5-85FBD4BB2BE9}
Current FILETIME: 04:10:33.827 PM 4/26/2010
LowDateTime = 0x20E5
HighDateTime = 0x01CAE55B
GUID = {D584E2FE-D857-7742-BAB5-85FBD4BB2BE9}
ResponseLevel[0]
DeltaCode = 0
TimeDelta = 0x00006F3E = 28478
Time = 04:23:00.361 PM 4/26/2010
TimeDelta = 0x00006F3E = 28478
Random = 0x09 = 9
ResponseLevel = 0x00 = 0
28 changes: 18 additions & 10 deletions UnitTest/SmartViewTestData/Out/CONVERSATIONINDEX-out-2.dat
Original file line number Diff line number Diff line change
@@ -1,39 +1,47 @@
Conversation Index
Unnamed byte = 0x01 = 1
Current FILETIME: (Low = 0x06360000, High = 0x01CB8689) = 06:55:38.303 PM 11/17/2010
GUID = {77A2CE55-DFB0-4D19-9A5F-3C0723B540DB}
Current FILETIME: 06:55:27.883 PM 11/17/2010
LowDateTime = 0x0636
HighDateTime = 0x01CB8689
GUID = {55CEA277-B0DF-194D-9A5F-3C0723B540DB}
ResponseLevel[0]
DeltaCode = 0
TimeDelta = 0x00005D40 = 23872
Time = 07:05:53.673 PM 11/17/2010
TimeDelta = 0x00005D40 = 23872
Random = 0x07 = 7
ResponseLevel = 0x00 = 0
ResponseLevel[1]
DeltaCode = 0
TimeDelta = 0x00664616 = 6702614
Time = 07:43:52.887 PM 11/19/2010
TimeDelta = 0x00664616 = 6702614
Random = 0x0D = 13
ResponseLevel = 0x00 = 0
ResponseLevel[2]
DeltaCode = 0
TimeDelta = 0x00000D12 = 3346
Time = 06:56:55.596 PM 11/17/2010
TimeDelta = 0x00000D12 = 3346
Random = 0x03 = 3
ResponseLevel = 0x00 = 0
ResponseLevel[3]
DeltaCode = 0
TimeDelta = 0x0000C7FE = 51198
Time = 07:17:50.008 PM 11/17/2010
TimeDelta = 0x0000C7FE = 51198
Random = 0x0D = 13
ResponseLevel = 0x00 = 0
ResponseLevel[4]
DeltaCode = 0
TimeDelta = 0x00001445 = 5189
Time = 06:57:43.909 PM 11/17/2010
TimeDelta = 0x00001445 = 5189
Random = 0x03 = 3
ResponseLevel = 0x00 = 0
ResponseLevel[5]
DeltaCode = 0
TimeDelta = 0x0236274C = 37103436
Time = 01:06:12.196 AM 11/29/2010
TimeDelta = 0x0236274C = 37103436
Random = 0x0B = 11
ResponseLevel = 0x00 = 0
ResponseLevel[6]
DeltaCode = 0
TimeDelta = 0x00001865 = 6245
Time = 06:58:11.592 PM 11/17/2010
TimeDelta = 0x00001865 = 6245
Random = 0x05 = 5
ResponseLevel = 0x00 = 0
25 changes: 16 additions & 9 deletions UnitTest/SmartViewTestData/Out/CONVERSATIONINDEX-out-3.dat
Original file line number Diff line number Diff line change
@@ -1,34 +1,41 @@
Conversation Index
Unnamed byte = 0x01 = 1
Current FILETIME: (Low = 0xF84A0000, High = 0x01CA697F) = 01:22:48.084 AM 11/20/2009
GUID = {28B660A5-B37D-4058-B462-AF2C2CE5CCA6}
Current FILETIME: 01:15:51.530 AM 11/20/2009
LowDateTime = 0xF84A
HighDateTime = 0x01CA697F
GUID = {A560B628-7DB3-5840-B462-AF2C2CE5CCA6}
ResponseLevel[0]
DeltaCode = 0
TimeDelta = 0x00011C47 = 72775
Time = 01:47:39.283 AM 11/20/2009
TimeDelta = 0x00011C47 = 72775
Random = 0x06 = 6
ResponseLevel = 0x00 = 0
ResponseLevel[1]
DeltaCode = 0
TimeDelta = 0x00005ABB = 23227
Time = 01:26:00.412 AM 11/20/2009
TimeDelta = 0x00005ABB = 23227
Random = 0x04 = 4
ResponseLevel = 0x00 = 0
ResponseLevel[2]
DeltaCode = 0
TimeDelta = 0x001A3E64 = 1719908
Time = 01:47:17.886 PM 11/20/2009
TimeDelta = 0x001A3E64 = 1719908
Random = 0x09 = 9
ResponseLevel = 0x00 = 0
ResponseLevel[3]
DeltaCode = 0
TimeDelta = 0x000246F8 = 149240
Time = 02:21:03.767 AM 11/20/2009
TimeDelta = 0x000246F8 = 149240
Random = 0x0A = 10
ResponseLevel = 0x00 = 0
ResponseLevel[4]
DeltaCode = 0
TimeDelta = 0x0005A625 = 370213
Time = 03:57:36.442 AM 11/20/2009
TimeDelta = 0x0005A625 = 370213
Random = 0x0B = 11
ResponseLevel = 0x00 = 0
ResponseLevel[5]
DeltaCode = 0
TimeDelta = 0x0009B7BB = 636859
Time = 05:54:06.407 AM 11/20/2009
TimeDelta = 0x0009B7BB = 636859
Random = 0x0F = 15
ResponseLevel = 0x00 = 0
25 changes: 16 additions & 9 deletions UnitTest/SmartViewTestData/Out/CONVERSATIONINDEX-out-4.dat
Original file line number Diff line number Diff line change
@@ -1,34 +1,41 @@
Conversation Index
Unnamed byte = 0x01 = 1
Current FILETIME: (Low = 0xF84A0000, High = 0x01CA697F) = 01:22:48.084 AM 11/20/2009
GUID = {28B660A5-B37D-4058-B462-AF2C2CE5CCA6}
Current FILETIME: 01:15:51.530 AM 11/20/2009
LowDateTime = 0xF84A
HighDateTime = 0x01CA697F
GUID = {A560B628-7DB3-5840-B462-AF2C2CE5CCA6}
ResponseLevel[0]
DeltaCode = 1
TimeDelta = 0x00011C47 = 72775
Time = 06:13:19.625 PM 11/20/2009
TimeDelta = 0x00011C47 = 72775
Random = 0x06 = 6
ResponseLevel = 0x00 = 0
ResponseLevel[1]
DeltaCode = 0
TimeDelta = 0x00005ABB = 23227
Time = 01:26:00.412 AM 11/20/2009
TimeDelta = 0x00005ABB = 23227
Random = 0x04 = 4
ResponseLevel = 0x00 = 0
ResponseLevel[2]
DeltaCode = 0
TimeDelta = 0x001A3E64 = 1719908
Time = 01:47:17.886 PM 11/20/2009
TimeDelta = 0x001A3E64 = 1719908
Random = 0x09 = 9
ResponseLevel = 0x00 = 0
ResponseLevel[3]
DeltaCode = 0
TimeDelta = 0x000246F8 = 149240
Time = 02:21:03.767 AM 11/20/2009
TimeDelta = 0x000246F8 = 149240
Random = 0x0A = 10
ResponseLevel = 0x00 = 0
ResponseLevel[4]
DeltaCode = 0
TimeDelta = 0x0005A625 = 370213
Time = 03:57:36.442 AM 11/20/2009
TimeDelta = 0x0005A625 = 370213
Random = 0x0B = 11
ResponseLevel = 0x00 = 0
ResponseLevel[5]
DeltaCode = 0
TimeDelta = 0x0009B7BB = 636859
Time = 05:54:06.407 AM 11/20/2009
TimeDelta = 0x0009B7BB = 636859
Random = 0x0F = 15
ResponseLevel = 0x00 = 0
2 changes: 1 addition & 1 deletion UnitTest/SmartViewTestData/Out/REPORTTAG-out-1.dat
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Report Tag
Cookie
cb: 9 lpb: 504344464542303900
Version = 0x00010002 = CurrentVersion
Version = 0x00020001 = CurrentVersion
SearchFolderEntryID
cb: 46 lpb: 0000000096614EC66601D211A3B10008C728E7F1010085FA5C86FCE6D111A3A60008C728E7F1000000019EC00000
MessageSearchKey
Expand Down
2 changes: 1 addition & 1 deletion core/interpret/flagArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -1182,7 +1182,7 @@ FLAG_ARRAY_ENTRY g_FlagArray[] = {
NON_PROP_FLAG_ENTRY(flagOverrideFlags, ARO_APPTCOLOR, flagFLAG)
NON_PROP_FLAG_ENTRY(flagOverrideFlags, ARO_EXCEPTIONAL_BODY, flagFLAG)

NON_PROP_FLAG_ENTRY_NAMED(flagReportTagVersion, 0x00010002, L"CurrentVersion", flagVALUE) // STRING_OK
NON_PROP_FLAG_ENTRY_NAMED(flagReportTagVersion, 0x00020001, L"CurrentVersion", flagVALUE) // STRING_OK
NON_PROP_FLAG_ENTRY_NAMED(flagReportTagVersion, 0x00010001, L"NoSearchFolderVersion", flagVALUE) // STRING_OK

NON_PROP_FLAG_ENTRY_NAMED(flagGlobalObjectIdMonth, 0x01, L"January", flagVALUE) // STRING_OK
Expand Down
130 changes: 63 additions & 67 deletions core/smartview/ConversationIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,10 @@ namespace smartview
{
void ResponseLevel::parse()
{
const auto r1 = blockT<BYTE>::parse(parser);
const auto r2 = blockT<BYTE>::parse(parser);
const auto r3 = blockT<BYTE>::parse(parser);
const auto r4 = blockT<BYTE>::parse(parser);
TimeDelta = blockT<DWORD>::parse(parser);
TimeDelta->setData(std::byteswap(TimeDelta->getData()));

TimeDelta = blockT<DWORD>::create(
static_cast<DWORD>(*r1 << 24 | *r2 << 16 | *r3 << 8 | *r4),
r1->getSize() + r2->getSize() + r3->getSize() + r4->getSize(),
r1->getOffset());

DeltaCode = blockT<bool>::create(false, TimeDelta->getSize(), TimeDelta->getOffset());
DeltaCode = blockT<bool>::create(false, 1, TimeDelta->getOffset());
if (*TimeDelta & 0x80000000)
{
TimeDelta->setData(*TimeDelta & ~0x80000000);
Expand All @@ -29,58 +22,62 @@ namespace smartview
Level = blockT<BYTE>::create(static_cast<BYTE>(*r5 & 0xf), r5->getSize(), r5->getOffset());
}

void ResponseLevel::parseBlocks()
_Check_return_ FILETIME AddFileTime(const FILETIME& ft, const FILETIME& dwDelta)
{
addChild(DeltaCode, L"DeltaCode = %1!d!", DeltaCode->getData());
addChild(TimeDelta, L"TimeDelta = 0x%1!08X! = %1!d!", TimeDelta->getData());
addChild(Random, L"Random = 0x%1!02X! = %1!d!", Random->getData());
addChild(Level, L"ResponseLevel = 0x%1!02X! = %1!d!", Level->getData());
auto ftResult = FILETIME{};
auto li = LARGE_INTEGER{};
li.LowPart = ft.dwLowDateTime;
li.HighPart = ft.dwHighDateTime;
auto liDelta = LARGE_INTEGER{};
liDelta.LowPart = dwDelta.dwLowDateTime;
liDelta.HighPart = dwDelta.dwHighDateTime;
li.QuadPart += liDelta.QuadPart;
ftResult.dwLowDateTime = li.LowPart;
ftResult.dwHighDateTime = li.HighPart;
return ftResult;
}

void ConversationIndex::parse()
void ResponseLevel::parseBlocks()
{
m_UnnamedByte = blockT<BYTE>::parse(parser);
const auto h1 = blockT<BYTE>::parse(parser);
const auto h2 = blockT<BYTE>::parse(parser);
const auto h3 = blockT<BYTE>::parse(parser);

// Encoding of the file time drops the high byte, which is always 1
// So we add it back to get a time which makes more sense
addChild(DeltaCode, L"DeltaCode = %1!d!", DeltaCode->getData());
auto ft = FILETIME{};
ft.dwHighDateTime = 1 << 24 | *h1 << 16 | *h2 << 8 | *h3;

const auto l1 = blockT<BYTE>::parse(parser);
const auto l2 = blockT<BYTE>::parse(parser);
ft.dwLowDateTime = *l1 << 24 | *l2 << 16;

m_ftCurrent = blockT<FILETIME>::create(
ft, h1->getSize() + h2->getSize() + h3->getSize() + l1->getSize() + l2->getSize(), h1->getOffset());

auto guid = GUID{};
const auto g1 = blockT<BYTE>::parse(parser);
const auto g2 = blockT<BYTE>::parse(parser);
const auto g3 = blockT<BYTE>::parse(parser);
const auto g4 = blockT<BYTE>::parse(parser);
guid.Data1 = *g1 << 24 | *g2 << 16 | *g3 << 8 | *g4;
unsigned int td = *TimeDelta;
if (*DeltaCode)
{
ft.dwHighDateTime |= ((td >> 24) & 0x7F) << 15 | ((td >> 16) & 0xFF) << 7 | ((td >> 8) & 0xFF) >> 1;
ft.dwLowDateTime = (static_cast<DWORD>((td >> 8) & 0xFF) << 31) | (static_cast<DWORD>(td & 0xFF) << 23);
}
else
{
ft.dwHighDateTime |= ((td >> 24) & 0x7F) << 10 | ((td >> 16) & 0xFF) << 2 | ((td >> 8) & 0xFF) >> 6;
ft.dwLowDateTime = (static_cast<DWORD>((td >> 8) & 0xFF) << 26) | (static_cast<DWORD>(td & 0xFF) << 18);
}

const auto g5 = blockT<BYTE>::parse(parser);
const auto g6 = blockT<BYTE>::parse(parser);
guid.Data2 = static_cast<unsigned short>(*g5 << 8 | *g6);
ft = AddFileTime(currentFileTime, ft);

const auto g7 = blockT<BYTE>::parse(parser);
const auto g8 = blockT<BYTE>::parse(parser);
guid.Data3 = static_cast<unsigned short>(*g7 << 8 | *g8);
std::wstring PropString;
std::wstring AltPropString;
strings::FileTimeToString(ft, PropString, AltPropString);
const auto ftBlock = blockT<FILETIME>::create(ft, TimeDelta->getSize(), TimeDelta->getOffset());
addChild(ftBlock, L"Time = %1!ws!", PropString.c_str());

auto size = g1->getSize() + g2->getSize() + g3->getSize() + g4->getSize() + g5->getSize() + g6->getSize() +
g7->getSize() + g8->getSize();
for (auto& i : guid.Data4)
{
const auto d = blockT<BYTE>::parse(parser);
i = *d;
size += d->getSize();
}
ftBlock->addChild(TimeDelta, L"TimeDelta = 0x%1!08X! = %1!d!", TimeDelta->getData());
addChild(Random, L"Random = 0x%1!02X! = %1!d!", Random->getData());
addChild(Level, L"ResponseLevel = 0x%1!02X! = %1!d!", Level->getData());
}

m_guid = blockT<GUID>::create(guid, size, g1->getOffset());
void ConversationIndex::parse()
{
dwHighDateTime = blockT<DWORD>::parse(parser);
dwHighDateTime->setData(std::byteswap(dwHighDateTime->getData()));
dwLowDateTime = blockT<WORD>::parse(parser);
dwLowDateTime->setData(std::byteswap(dwLowDateTime->getData()));
currentFileTime = blockT<FILETIME>::create(
FILETIME{*dwLowDateTime, *dwHighDateTime},
dwHighDateTime->getSize() + dwLowDateTime->getSize(),
dwHighDateTime->getOffset());

threadGuid = blockT<GUID>::parse(parser);
auto ulResponseLevels = ULONG{};
if (parser->getSize() > 0)
{
Expand All @@ -89,10 +86,13 @@ namespace smartview

if (ulResponseLevels && ulResponseLevels < _MaxEntriesSmall)
{
m_lpResponseLevels.reserve(ulResponseLevels);
responseLevels.reserve(ulResponseLevels);
for (ULONG i = 0; i < ulResponseLevels; i++)
{
m_lpResponseLevels.emplace_back(block::parse<ResponseLevel>(parser, false));
auto responseLevel = std::make_shared<smartview::ResponseLevel>(currentFileTime->getData());
responseLevel->block::parse(parser, false);
if (!responseLevel->isSet()) break;
responseLevels.emplace_back(responseLevel);
}
}
}
Expand All @@ -103,23 +103,19 @@ namespace smartview

std::wstring PropString;
std::wstring AltPropString;
strings::FileTimeToString(*m_ftCurrent, PropString, AltPropString);
addChild(m_UnnamedByte, L"Unnamed byte = 0x%1!02X! = %1!d!", m_UnnamedByte->getData());
addChild(
m_ftCurrent,
L"Current FILETIME: (Low = 0x%1!08X!, High = 0x%2!08X!) = %3!ws!",
m_ftCurrent->getData().dwLowDateTime,
m_ftCurrent->getData().dwHighDateTime,
PropString.c_str());
addChild(m_guid, L"GUID = %1!ws!", guid::GUIDToString(*m_guid).c_str());
strings::FileTimeToString(*currentFileTime, PropString, AltPropString);

addChild(currentFileTime, L"Current FILETIME: %1!ws!", PropString.c_str());
currentFileTime->addChild(dwLowDateTime, L"LowDateTime = 0x%1!04X!", dwLowDateTime->getData());
currentFileTime->addChild(dwHighDateTime, L"HighDateTime = 0x%1!08X!", dwHighDateTime->getData());
addChild(threadGuid, L"GUID = %1!ws!", guid::GUIDToString(*threadGuid).c_str());

if (!m_lpResponseLevels.empty())
if (!responseLevels.empty())
{
auto i = 0;
for (const auto& responseLevel : m_lpResponseLevels)
for (const auto& responseLevel : responseLevels)
{
addChild(responseLevel, L"ResponseLevel[%1!d!]", i);

i++;
}
}
Expand Down
Loading

0 comments on commit c2fd771

Please sign in to comment.