Remove ATL dependencies (#676) (#719)

* Remove CComBSTR dependency.
* Replace CStructureArray with std::vector.
* Remove CComPtr dependency.
* Add try blocks.
* Remove CString dependency.
* Add comments for string helper functions.
* Remove CComAllocator dependency.

Fixes #676.
This commit is contained in:
Richard Yu 2019-05-22 01:32:43 +08:00 committed by Dustin L. Howett (MSFT)
parent 68d0c23246
commit fd2fb07bcf
25 changed files with 487 additions and 711 deletions

View file

@ -49,6 +49,7 @@
#include <wil/Result.h>
#include <wil/resource.h>
#include <wil/wistd_memory.h>
#include <wil/com.h>
// GSL
// Block GSL Multi Span include because it both has C++17 deprecated iterators

View file

@ -6,6 +6,7 @@
#define __GENERATE_DIRECTED_FUZZING
#include "fuzzing_logic.h"
#include "fuzzing_directed.h"
#include "string_helper.h"
using namespace fuzz;
@ -21,22 +22,22 @@ const CHAR C1CSI[2] { static_cast<CHAR>(static_cast<unsigned char>(0x9b)), 0x0 }
// VT100 spec defines the OSC sequence as ESC followed by ]
const CHAR OSC[3] { 0x1b, 0x5d, 0x0 };
static CStringA GenerateSGRToken();
static CStringA GenerateCUXToken();
static CStringA GenerateCUXToken2();
static CStringA GenerateCUXToken3();
static CStringA GeneratePrivateModeParamToken();
static CStringA GenerateDeviceAttributesToken();
static CStringA GenerateDeviceStatusReportToken();
static CStringA GenerateEraseToken();
static CStringA GenerateScrollToken();
static CStringA GenerateWhiteSpaceToken();
static CStringA GenerateInvalidToken();
static CStringA GenerateTextToken();
static CStringA GenerateOscTitleToken();
static CStringA GenerateHardResetToken();
static CStringA GenerateSoftResetToken();
static CStringA GenerateOscColorTableToken();
static std::string GenerateSGRToken();
static std::string GenerateCUXToken();
static std::string GenerateCUXToken2();
static std::string GenerateCUXToken3();
static std::string GeneratePrivateModeParamToken();
static std::string GenerateDeviceAttributesToken();
static std::string GenerateDeviceStatusReportToken();
static std::string GenerateEraseToken();
static std::string GenerateScrollToken();
static std::string GenerateWhiteSpaceToken();
static std::string GenerateInvalidToken();
static std::string GenerateTextToken();
static std::string GenerateOscTitleToken();
static std::string GenerateHardResetToken();
static std::string GenerateSoftResetToken();
static std::string GenerateOscColorTableToken();
const fuzz::_fuzz_type_entry<BYTE> g_repeatMap[] =
{
@ -45,7 +46,7 @@ const fuzz::_fuzz_type_entry<BYTE> g_repeatMap[] =
{ 20, [](BYTE) { return (BYTE)0; } }
};
const std::function<CStringA()> g_tokenGenerators[] =
const std::function<std::string()> g_tokenGenerators[] =
{
GenerateSGRToken,
GenerateCUXToken,
@ -62,35 +63,35 @@ const std::function<CStringA()> g_tokenGenerators[] =
GenerateOscColorTableToken
};
CStringA GenerateTokenLowProbability()
std::string GenerateTokenLowProbability()
{
const _fuzz_type_entry<CStringA> tokenGeneratorMap[] =
const _fuzz_type_entry<std::string> tokenGeneratorMap[] =
{
{ 3, [&](CStringA) { return CFuzzChance::SelectOne(g_tokenGenerators, ARRAYSIZE(g_tokenGenerators))(); } },
{ 1, [](CStringA) { return GenerateInvalidToken(); } },
{ 1, [](CStringA) { return GenerateTextToken(); } },
{ 5, [](CStringA) { return GenerateWhiteSpaceToken(); } }
{ 3, [&](std::string) { return CFuzzChance::SelectOne(g_tokenGenerators, ARRAYSIZE(g_tokenGenerators))(); } },
{ 1, [](std::string) { return GenerateInvalidToken(); } },
{ 1, [](std::string) { return GenerateTextToken(); } },
{ 5, [](std::string) { return GenerateWhiteSpaceToken(); } }
};
CFuzzType<CStringA> ft(FUZZ_MAP(tokenGeneratorMap), CStringA(""));
CFuzzType<std::string> ft(FUZZ_MAP(tokenGeneratorMap), std::string(""));
return (CStringA)ft;
return (std::string)ft;
}
CStringA GenerateToken()
std::string GenerateToken()
{
const _fuzz_type_entry<CStringA> tokenGeneratorMap[] =
const _fuzz_type_entry<std::string> tokenGeneratorMap[] =
{
{ 50, [](CStringA) { return GenerateTextToken(); } },
{ 40, [&](CStringA) { return CFuzzChance::SelectOne(g_tokenGenerators, ARRAYSIZE(g_tokenGenerators))(); } },
{ 1, [](CStringA) { return GenerateInvalidToken(); } },
{ 3, [](CStringA) { return GenerateWhiteSpaceToken(); } }
{ 50, [](std::string) { return GenerateTextToken(); } },
{ 40, [&](std::string) { return CFuzzChance::SelectOne(g_tokenGenerators, ARRAYSIZE(g_tokenGenerators))(); } },
{ 1, [](std::string) { return GenerateInvalidToken(); } },
{ 3, [](std::string) { return GenerateWhiteSpaceToken(); } }
};
CFuzzType<CStringA> ft(FUZZ_MAP(tokenGeneratorMap), CStringA(""));
CFuzzType<std::string> ft(FUZZ_MAP(tokenGeneratorMap), std::string(""));
return (CStringA)ft;
return (std::string)ft;
}
CStringA GenerateWhiteSpaceToken()
std::string GenerateWhiteSpaceToken()
{
const _fuzz_type_entry<DWORD> ftMap[] =
{
@ -99,16 +100,16 @@ CStringA GenerateWhiteSpaceToken()
};
CFuzzType<DWORD> ft(FUZZ_MAP(ftMap), 0);
CStringA s;
std::string s;
for (DWORD i = 0; i < (DWORD)ft; i++)
{
s.Append(" ");
s.append(" ");
}
return s;
}
CStringA GenerateTextToken()
std::string GenerateTextToken()
{
const LPSTR tokens[] =
{
@ -128,66 +129,64 @@ CStringA GenerateTextToken()
"0xFF"
};
return CStringA(CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens)));
return std::string(CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens)));
}
CStringA GenerateInvalidToken()
std::string GenerateInvalidToken()
{
const LPSTR tokens[] { ":", "'", "\"", "\\" };
return CStringA(CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens)));
return std::string(CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens)));
}
CStringA GenerateFuzzedToken(
__in_ecount(cmap) const _fuzz_type_entry<CStringA> *map,
std::string GenerateFuzzedToken(
__in_ecount(cmap) const _fuzz_type_entry<std::string> *map,
__in DWORD cmap,
__in_ecount(ctokens) const LPSTR *tokens,
__in DWORD ctokens)
{
CStringA csis[] = { CSI, C1CSI };
CStringA s = CFuzzChance::SelectOne(csis);
std::string csis[] = { CSI, C1CSI };
std::string s = CFuzzChance::SelectOne(csis);
BYTE manipulations = (BYTE)CFuzzType<BYTE>(FUZZ_MAP(g_repeatMap), 1);
for (BYTE i = 0; i < manipulations; i++)
{
CFuzzType<CStringA> ft(map, cmap, CStringA(""));
s.AppendFormat("%s%s%s%s%s",
GenerateTokenLowProbability().GetString(),
((CStringA)ft).GetBuffer(),
GenerateTokenLowProbability().GetString(),
(i + 1 == manipulations) ? "" : ";",
GenerateTokenLowProbability().GetString());
CFuzzType<std::string> ft(map, cmap, std::string(""));
s += GenerateTokenLowProbability();
s += (std::string)ft;
s += GenerateTokenLowProbability();
s += (i + 1 == manipulations) ? "" : ";";
s += GenerateTokenLowProbability();
}
s.Append(CFuzzChance::SelectOne(tokens, ctokens));
s.append(CFuzzChance::SelectOne(tokens, ctokens));
return s;
}
CStringA GenerateFuzzedOscToken(
__in_ecount(cmap) const _fuzz_type_entry<CStringA> *map,
std::string GenerateFuzzedOscToken(
__in_ecount(cmap) const _fuzz_type_entry<std::string> *map,
__in DWORD cmap,
__in_ecount(ctokens) const LPSTR *tokens,
__in DWORD ctokens)
{
CStringA s(OSC);
std::string s(OSC);
BYTE manipulations = (BYTE)CFuzzType<BYTE>(FUZZ_MAP(g_repeatMap), 1);
for (BYTE i = 0; i < manipulations; i++)
{
CFuzzType<CStringA> ft(map, cmap, CStringA(""));
s.AppendFormat("%s%s%s%s%s",
GenerateTokenLowProbability().GetString(),
((CStringA)ft).GetBuffer(),
GenerateTokenLowProbability().GetString(),
(i + 1 == manipulations) ? "" : ";",
GenerateTokenLowProbability().GetString());
CFuzzType<std::string> ft(map, cmap, std::string(""));
s += GenerateTokenLowProbability();
s += (std::string)ft;
s += GenerateTokenLowProbability();
s += (i + 1 == manipulations) ? "" : ";";
s += GenerateTokenLowProbability();
}
s.Append(CFuzzChance::SelectOne(tokens, ctokens));
s.append(CFuzzChance::SelectOne(tokens, ctokens));
return s;
}
// For SGR attributes, multiple can be specified in a row separated by ; and processed accordingly.
// For instance, 37;1;44m will do foreground white (low intensity, so effectively a gray) then set high intensity blue background.
CStringA GenerateSGRToken()
std::string GenerateSGRToken()
{
const BYTE psValid[] =
{
@ -198,12 +197,12 @@ CStringA GenerateSGRToken()
};
const LPSTR tokens[] = { "m" };
const _fuzz_type_entry<CStringA> map[] =
const _fuzz_type_entry<std::string> map[] =
{
{ 40, [&](CStringA) { CStringA s; s.AppendFormat("%02d", CFuzzChance::SelectOne(psValid, ARRAYSIZE(psValid))); return s; } },
{ 10, [](CStringA) { CStringA s; s.AppendFormat("%d", CFuzzChance::GetRandom<BYTE>()); return s; } },
{ 25, [](CStringA) { return CStringA("35;5"); } },
{ 25, [](CStringA) { return CStringA("48;5"); } },
{ 40, [&](std::string) { std::string s; AppendFormat(s, "%02d", CFuzzChance::SelectOne(psValid, ARRAYSIZE(psValid))); return s; } },
{ 10, [](std::string) { std::string s; AppendFormat(s, "%d", CFuzzChance::GetRandom<BYTE>()); return s; } },
{ 25, [](std::string) { return std::string("35;5"); } },
{ 25, [](std::string) { return std::string("48;5"); } },
};
return GenerateFuzzedToken(FUZZ_MAP(map), tokens, ARRAYSIZE(tokens));
@ -211,13 +210,13 @@ CStringA GenerateSGRToken()
// Cursor positioning, this function handles moving the cursor relative to the current location
// For example, moving the cursor to the next line, previous line, up, down, etc.
CStringA GenerateCUXToken()
std::string GenerateCUXToken()
{
const LPSTR tokens[] = { "A", "B", "C", "D", "E", "F", "G" };
const _fuzz_type_entry<CStringA> map[] =
const _fuzz_type_entry<std::string> map[] =
{
{ 25, [](CStringA) { CStringA s; s.AppendFormat("%d", CFuzzChance::GetRandom<USHORT>()); return s; } },
{ 25, [](CStringA) { CStringA s; s.AppendFormat("%d", CFuzzChance::GetRandom<BYTE>()); return s; } }
{ 25, [](std::string) { std::string s; AppendFormat(s, "%d", CFuzzChance::GetRandom<USHORT>()); return s; } },
{ 25, [](std::string) { std::string s; AppendFormat(s, "%d", CFuzzChance::GetRandom<BYTE>()); return s; } }
};
return GenerateFuzzedToken(FUZZ_MAP(map), tokens, ARRAYSIZE(tokens));
@ -225,27 +224,26 @@ CStringA GenerateCUXToken()
// Cursor positioning, this function handles saving and restoring the cursor position.
// Differs from other cursor functions since these are ESC sequences and not CSI sequences.
CStringA GenerateCUXToken2()
std::string GenerateCUXToken2()
{
const LPSTR tokens[] = { "7", "8" };
CStringA cux(ESC);
cux.AppendFormat("%s%s%s",
GenerateTokenLowProbability().GetString(),
CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens)),
GenerateTokenLowProbability().GetString());
std::string cux(ESC);
cux += GenerateTokenLowProbability();
cux += CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens));
cux += GenerateTokenLowProbability();
return cux;
}
// Cursor positioning with two arguments
CStringA GenerateCUXToken3()
std::string GenerateCUXToken3()
{
const LPSTR tokens[]{ "H" };
const _fuzz_type_entry<CStringA> map[] =
const _fuzz_type_entry<std::string> map[] =
{
{60, [](CStringA) { CStringA s; s.AppendFormat("%d;%d", CFuzzChance::GetRandom<BYTE>(), CFuzzChance::GetRandom<BYTE>()); return s; } }, // 60% give us two numbers in the valid range
{10, [](CStringA) { return CStringA(";"); } }, // 10% give us just a ;
{10, [](CStringA) { CStringA s; s.AppendFormat("%d;", CFuzzChance::GetRandom<BYTE>()); return s; } }, // 10% give us a column and no line
{10, [](CStringA) { CStringA s; s.AppendFormat(";%d", CFuzzChance::GetRandom<BYTE>()); return s; } }, // 10% give us a line and no column
{60, [](std::string) { std::string s; AppendFormat(s, "%d;%d", CFuzzChance::GetRandom<BYTE>(), CFuzzChance::GetRandom<BYTE>()); return s; } }, // 60% give us two numbers in the valid range
{10, [](std::string) { return std::string(";"); } }, // 10% give us just a ;
{10, [](std::string) { std::string s; AppendFormat(s, "%d;", CFuzzChance::GetRandom<BYTE>()); return s; } }, // 10% give us a column and no line
{10, [](std::string) { std::string s; AppendFormat(s, ";%d", CFuzzChance::GetRandom<BYTE>()); return s; } }, // 10% give us a line and no column
// 10% give us nothing
};
@ -253,94 +251,90 @@ CStringA GenerateCUXToken3()
}
// Hard Reset (has no args)
CStringA GenerateHardResetToken()
std::string GenerateHardResetToken()
{
const LPSTR tokens[] = { "c" };
CStringA cux(ESC);
cux.AppendFormat("%s%s%s",
GenerateTokenLowProbability().GetString(),
CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens)),
GenerateTokenLowProbability().GetString());
std::string cux(ESC);
cux += GenerateTokenLowProbability();
cux += CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens));
cux += GenerateTokenLowProbability();
return cux;
}
// Soft Reset (has no args)
CStringA GenerateSoftResetToken()
std::string GenerateSoftResetToken()
{
const LPSTR tokens[] = { "p" };
CStringA cux(CSI);
cux.AppendFormat("%s%s%s",
GenerateTokenLowProbability().GetString(),
CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens)),
GenerateTokenLowProbability().GetString());
std::string cux(CSI);
cux += GenerateTokenLowProbability();
cux += CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens));
cux += GenerateTokenLowProbability();
return cux;
}
// Private Mode parameters. These cover a wide range of behaviors - hiding the cursor,
// enabling mouse mode, changing to the alt buffer, blinking the cursor, etc.
CStringA GeneratePrivateModeParamToken()
std::string GeneratePrivateModeParamToken()
{
const LPSTR tokens[] = { "h", "l" };
const _fuzz_type_entry<CStringA> map[] =
const _fuzz_type_entry<std::string> map[] =
{
{ 12, [](CStringA) { CStringA s; s.AppendFormat("?%02d", CFuzzChance::GetRandom<BYTE>()); return s; } },
{ 8, [](CStringA) { return CStringA("?1"); } },
{ 8, [](CStringA) { return CStringA("?3"); } },
{ 8, [](CStringA) { return CStringA("?12"); } },
{ 8, [](CStringA) { return CStringA("?25"); } },
{ 8, [](CStringA) { return CStringA("?1000"); } },
{ 8, [](CStringA) { return CStringA("?1002"); } },
{ 8, [](CStringA) { return CStringA("?1003"); } },
{ 8, [](CStringA) { return CStringA("?1005"); } },
{ 8, [](CStringA) { return CStringA("?1006"); } },
{ 8, [](CStringA) { return CStringA("?1007"); } },
{ 8, [](CStringA) { return CStringA("?1049"); } }
{ 12, [](std::string) { std::string s; AppendFormat(s, "?%02d", CFuzzChance::GetRandom<BYTE>()); return s; } },
{ 8, [](std::string) { return std::string("?1"); } },
{ 8, [](std::string) { return std::string("?3"); } },
{ 8, [](std::string) { return std::string("?12"); } },
{ 8, [](std::string) { return std::string("?25"); } },
{ 8, [](std::string) { return std::string("?1000"); } },
{ 8, [](std::string) { return std::string("?1002"); } },
{ 8, [](std::string) { return std::string("?1003"); } },
{ 8, [](std::string) { return std::string("?1005"); } },
{ 8, [](std::string) { return std::string("?1006"); } },
{ 8, [](std::string) { return std::string("?1007"); } },
{ 8, [](std::string) { return std::string("?1049"); } }
};
return GenerateFuzzedToken(FUZZ_MAP(map), tokens, ARRAYSIZE(tokens));
}
// Erase sequences, valid numerical values are 0-2. If no numeric value is specified, 0 is assumed.
CStringA GenerateEraseToken()
std::string GenerateEraseToken()
{
const LPSTR tokens[] = { "J", "K" };
const _fuzz_type_entry<CStringA> map[] =
const _fuzz_type_entry<std::string> map[] =
{
{ 9, [](CStringA) { return CStringA(""); } },
{ 25, [](CStringA) { return CStringA("0"); } },
{ 25, [](CStringA) { return CStringA("1"); } },
{ 25, [](CStringA) { return CStringA("2"); } },
{ 25, [](CStringA) { return CStringA("3"); } },
{ 1, [](CStringA) { CStringA s; s.AppendFormat("%02d", CFuzzChance::GetRandom<BYTE>()); return s; } }
{ 9, [](std::string) { return std::string(""); } },
{ 25, [](std::string) { return std::string("0"); } },
{ 25, [](std::string) { return std::string("1"); } },
{ 25, [](std::string) { return std::string("2"); } },
{ 25, [](std::string) { return std::string("3"); } },
{ 1, [](std::string) { std::string s; AppendFormat(s, "%02d", CFuzzChance::GetRandom<BYTE>()); return s; } }
};
return GenerateFuzzedToken(FUZZ_MAP(map), tokens, ARRAYSIZE(tokens));
}
// Device Attributes
CStringA GenerateDeviceAttributesToken()
std::string GenerateDeviceAttributesToken()
{
const LPSTR tokens[] = { "c" };
const _fuzz_type_entry<CStringA> map[] =
const _fuzz_type_entry<std::string> map[] =
{
{ 70, [](CStringA) { return CStringA(""); } }, // 70% leave it blank (valid)
{ 29, [](CStringA) { return CStringA("0"); } }, // 29% put in a 0 (valid)
{ 1, [](CStringA) { CStringA s; s.AppendFormat("%02d", CFuzzChance::GetRandom<BYTE>()); return s; } } // 1% make a mess (anything else)
{ 70, [](std::string) { return std::string(""); } }, // 70% leave it blank (valid)
{ 29, [](std::string) { return std::string("0"); } }, // 29% put in a 0 (valid)
{ 1, [](std::string) { std::string s; AppendFormat(s, "%02d", CFuzzChance::GetRandom<BYTE>()); return s; } } // 1% make a mess (anything else)
};
return GenerateFuzzedToken(FUZZ_MAP(map), tokens, ARRAYSIZE(tokens));
}
// Device Attributes
CStringA GenerateDeviceStatusReportToken()
std::string GenerateDeviceStatusReportToken()
{
const LPSTR tokens[] = { "n" };
const _fuzz_type_entry<CStringA> map[] =
const _fuzz_type_entry<std::string> map[] =
{
{ 50, [](CStringA) { return CStringA("6"); } }, // 50% of the time, give us the one we were looking for (6, cursor report)
{ 49, [](CStringA) { CStringA s; s.AppendFormat("%02d", CFuzzChance::GetRandom<BYTE>()); return s; } } // 49% of the time, put in a random value
{ 50, [](std::string) { return std::string("6"); } }, // 50% of the time, give us the one we were looking for (6, cursor report)
{ 49, [](std::string) { std::string s; AppendFormat(s, "%02d", CFuzzChance::GetRandom<BYTE>()); return s; } } // 49% of the time, put in a random value
// 1% leave it blank
};
@ -348,22 +342,22 @@ CStringA GenerateDeviceStatusReportToken()
}
// Scroll sequences, valid numeric values include 0-16384.
CStringA GenerateScrollToken()
std::string GenerateScrollToken()
{
const LPSTR tokens[] = { "S", "T" };
const _fuzz_type_entry<CStringA> map[] =
const _fuzz_type_entry<std::string> map[] =
{
{ 5, [](CStringA) { CStringA s; s.AppendFormat("%08d", CFuzzChance::GetRandom<ULONG>()); return s; } },
{ 5, [](CStringA) { CStringA s; s.AppendFormat("%08d", CFuzzChance::GetRandom<USHORT>()); return s; } },
{ 50, [](CStringA) { CStringA s; s.AppendFormat("%d", CFuzzChance::GetRandom<USHORT>(0, 0x4000)); return s; } },
{ 20, [](CStringA) { CStringA s; s.AppendFormat("%02d", CFuzzChance::GetRandom<BYTE>()); return s; } }
{ 5, [](std::string) { std::string s; AppendFormat(s, "%08d", CFuzzChance::GetRandom<ULONG>()); return s; } },
{ 5, [](std::string) { std::string s; AppendFormat(s, "%08d", CFuzzChance::GetRandom<USHORT>()); return s; } },
{ 50, [](std::string) { std::string s; AppendFormat(s, "%d", CFuzzChance::GetRandom<USHORT>(0, 0x4000)); return s; } },
{ 20, [](std::string) { std::string s; AppendFormat(s, "%02d", CFuzzChance::GetRandom<BYTE>()); return s; } }
};
return GenerateFuzzedToken(FUZZ_MAP(map), tokens, ARRAYSIZE(tokens));
}
// Resize sequences, valid numeric values include 0-16384.
CStringA GenerateResizeToken()
std::string GenerateResizeToken()
{
const LPSTR tokens[] = { "t" };
// 5% - generate a random window manipulation with 1 params
@ -372,14 +366,14 @@ CStringA GenerateResizeToken()
// 45% - generate a resize with two params
// 10% - generate a resize with only the first param
// 10% - generate a resize with only the second param
const _fuzz_type_entry<CStringA> map[] =
const _fuzz_type_entry<std::string> map[] =
{
{ 5, [](CStringA) { CStringA s; s.AppendFormat("%d;%d;%d", CFuzzChance::GetRandom<USHORT>(0, 0x4000), CFuzzChance::GetRandom<USHORT>(0, 0x4000), CFuzzChance::GetRandom<USHORT>(0, 0x4000)); return s; } },
{ 5, [](CStringA) { CStringA s; s.AppendFormat("%d;%d", CFuzzChance::GetRandom<USHORT>(0, 0x4000), CFuzzChance::GetRandom<USHORT>(0, 0x4000)); return s; } },
{ 5, [](CStringA) { CStringA s; s.AppendFormat("%d", CFuzzChance::GetRandom<USHORT>(0, 0x4000)); return s; } },
{ 45, [](CStringA) { CStringA s; s.AppendFormat("8;%d;%d", CFuzzChance::GetRandom<USHORT>(0, 0x4000), CFuzzChance::GetRandom<USHORT>(0, 0x4000)); return s; } },
{ 10, [](CStringA) { CStringA s; s.AppendFormat("8;%d;", CFuzzChance::GetRandom<USHORT>(0, 0x4000)); return s; } },
{ 10, [](CStringA) { CStringA s; s.AppendFormat("8;;%d", CFuzzChance::GetRandom<USHORT>(0, 0x4000)); return s; } },
{ 5, [](std::string) { std::string s; AppendFormat(s, "%d;%d;%d", CFuzzChance::GetRandom<USHORT>(0, 0x4000), CFuzzChance::GetRandom<USHORT>(0, 0x4000), CFuzzChance::GetRandom<USHORT>(0, 0x4000)); return s; } },
{ 5, [](std::string) { std::string s; AppendFormat(s, "%d;%d", CFuzzChance::GetRandom<USHORT>(0, 0x4000), CFuzzChance::GetRandom<USHORT>(0, 0x4000)); return s; } },
{ 5, [](std::string) { std::string s; AppendFormat(s, "%d", CFuzzChance::GetRandom<USHORT>(0, 0x4000)); return s; } },
{ 45, [](std::string) { std::string s; AppendFormat(s, "8;%d;%d", CFuzzChance::GetRandom<USHORT>(0, 0x4000), CFuzzChance::GetRandom<USHORT>(0, 0x4000)); return s; } },
{ 10, [](std::string) { std::string s; AppendFormat(s, "8;%d;", CFuzzChance::GetRandom<USHORT>(0, 0x4000)); return s; } },
{ 10, [](std::string) { std::string s; AppendFormat(s, "8;;%d", CFuzzChance::GetRandom<USHORT>(0, 0x4000)); return s; } },
};
return GenerateFuzzedToken(FUZZ_MAP(map), tokens, ARRAYSIZE(tokens));
@ -387,27 +381,27 @@ CStringA GenerateResizeToken()
// Osc Window Title String. An Osc followed by a param on [0, SHORT_MAX], followed by a ";", followed by a string,
// and BEL terminated.
CStringA GenerateOscTitleToken()
std::string GenerateOscTitleToken()
{
const LPSTR tokens[] = { "\x7" };
const _fuzz_type_entry<CStringA> map[] =
const _fuzz_type_entry<std::string> map[] =
{
{
100,
[](CStringA) {
CStringA s;
[](std::string) {
std::string s;
SHORT limit = CFuzzChance::GetRandom<SHORT>(0, 10);
// append up to 10 numbers for the param
for(SHORT i = 0; i < limit; i++)
{
s.AppendFormat("%d", CFuzzChance::GetRandom<BYTE>(0, 9));
AppendFormat(s, "%d", CFuzzChance::GetRandom<BYTE>(0, 9));
}
s.Append(";");
s.append(";");
// append some characters for the string
limit = CFuzzChance::GetRandom<SHORT>();
for(SHORT i = 0; i < limit; i++)
{
s.AppendFormat("%c", CFuzzChance::GetRandom<BYTE>());
AppendFormat(s, "%c", CFuzzChance::GetRandom<BYTE>());
}
return s;
}
@ -419,29 +413,29 @@ CStringA GenerateOscTitleToken()
// Osc Window Title String. An Osc followed by a param on [0, SHORT_MAX], followed by a ";", followed by a string,
// and BEL terminated.
CStringA GenerateOscColorTableToken()
std::string GenerateOscColorTableToken()
{
const LPSTR tokens[] = { "\x7", "\x1b\\" };
const _fuzz_type_entry<CStringA> map[] =
const _fuzz_type_entry<std::string> map[] =
{
{
100,
[](CStringA) {
CStringA s;
[](std::string) {
std::string s;
SHORT limit = CFuzzChance::GetRandom<SHORT>(0, 10);
// append up to 10 numbers for the param
for(SHORT i = 0; i < limit; i++)
{
s.AppendFormat("%d", CFuzzChance::GetRandom<BYTE>(0, 9));
AppendFormat(s, "%d", CFuzzChance::GetRandom<BYTE>(0, 9));
}
s.Append(";");
s.append(";");
// Append some random numbers for the index
limit = CFuzzChance::GetRandom<SHORT>(0, 10);
// append up to 10 numbers for the param
for(SHORT i = 0; i < limit; i++)
{
s.AppendFormat("%d", CFuzzChance::GetRandom<BYTE>(0, 9));
AppendFormat(s, "%d", CFuzzChance::GetRandom<BYTE>(0, 9));
}
// Maybe add more text
if (CFuzzChance::GetRandom<BOOL>())
@ -457,20 +451,20 @@ CStringA GenerateOscColorTableToken()
case 4:
case 5:
case 6:
s.AppendFormat("rgb:");
s.append("rgb:");
break;
case 7:
s.AppendFormat("rgbi:");
s.append("rgbi:");
break;
case 8:
s.AppendFormat("cmyk:");
s.append("cmyk:");
break;
default:
// append some characters for the string
limit = CFuzzChance::GetRandom<SHORT>();
for(SHORT i = 0; i < limit; i++)
{
s.AppendFormat("%c", CFuzzChance::GetRandom<BYTE>());
AppendFormat(s, "%c", CFuzzChance::GetRandom<BYTE>());
}
}
@ -485,12 +479,12 @@ CStringA GenerateOscColorTableToken()
// append up to 10 numbers for the param
for(SHORT j = 0; j < limit; j++)
{
s.AppendFormat("%d", CFuzzChance::GetRandom<BYTE>(0, 9));
AppendFormat(s, "%d", CFuzzChance::GetRandom<BYTE>(0, 9));
}
// Sometimes don't add a '/'
if (CFuzzChance::GetRandom<SHORT>(0, 10) != 0)
{
s.AppendFormat("/");
s.append("/");
}
}
@ -522,28 +516,31 @@ int __cdecl wmain(int argc, WCHAR* argv[])
hr = CoCreateGuid(&guid);
if (SUCCEEDED(hr))
{
WCHAR wszName[MAX_PATH] = { 0 };
StringFromGUID2(guid, wszName, ARRAYSIZE(wszName));
std::wstring sGuid(MAX_PATH, L'\0');
const auto len = StringFromGUID2(guid, sGuid.data(), MAX_PATH);
if (len != 0)
sGuid.resize(len - 1);
TrimLeft(sGuid, L'{');
TrimRight(sGuid, L'}');
CStringW sGuid(wszName);
CStringW outputFile(pwszOutputDir);
outputFile.AppendFormat(L"\\%s.bin", sGuid.TrimLeft(L'{').TrimRight(L'}').GetBuffer());
std::wstring outputFile(pwszOutputDir);
outputFile += L"\\" + sGuid + L".bin";
CStringA text;
std::string text;
for (int j = 0; j < CFuzzChance::GetRandom<BYTE>(); j++)
{
text.Append(GenerateToken().GetBuffer());
text.append(GenerateToken());
}
CComPtr<IStream> spStream;
hr = SHCreateStreamOnFileW(outputFile.GetBuffer(), STGM_CREATE | STGM_READWRITE, &spStream);
wil::com_ptr<IStream> spStream;
hr = SHCreateStreamOnFileW(outputFile.c_str(), STGM_CREATE | STGM_READWRITE, &spStream);
if (SUCCEEDED(hr))
{
ULONG cbWritten = 0;
hr = spStream->Write(reinterpret_cast<BYTE*>(text.GetBuffer()), text.GetLength(), &cbWritten);
hr = spStream->Write(text.c_str(), static_cast<ULONG>(text.length()), &cbWritten);
if (SUCCEEDED(hr))
{
wprintf(L"Wrote file (%d bytes): %s\n", cbWritten, outputFile.GetBuffer());
wprintf(L"Wrote file (%d bytes): %s\n", cbWritten, outputFile.c_str());
}
}
}

View file

@ -10,7 +10,9 @@
<ItemGroup>
<ClInclude Include="fuzzing_directed.h" />
<ClInclude Include="fuzzing_logic.h" />
<ClInclude Include="memallocator.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="string_helper.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{96927B31-D6E8-4ABD-B03E-A5088A30BEBE}</ProjectGuid>

View file

@ -32,5 +32,11 @@
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="string_helper.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="memallocator.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View file

@ -21,12 +21,14 @@
#include <vector>
#include <limits>
#include <atlcoll.h>
#include <assert.h>
#include <strsafe.h>
#pragma warning(disable:4505)
#include "memallocator.h"
#ifndef __FUZZING_ALLOCATOR
#define __FUZZING_ALLOCATOR CComAllocator
#define __FUZZING_ALLOCATOR fuzz::CFuzzCRTAllocator
#endif
namespace variadic

View file

@ -12,8 +12,8 @@
#pragma once
#include "fuzzing_directed.h"
#include "string_helper.h"
#ifdef __GENERATE_DIRECTED_FUZZING
#include <atlstr.h>
#include <strsafe.h>
namespace fuzz
@ -241,7 +241,7 @@ namespace fuzz
// that does not require external modules or complex setup. This should
// make fuzzing easier to implement and test, as well as more explicit
// with regard to what fuzzing manipulations are possible.
template <class _Alloc = CComAllocator>
template <class _Alloc = CFuzzCRTAllocator>
class CFuzzLogic
{
public:
@ -467,7 +467,7 @@ namespace fuzz
{ 1, [](DWORD) { return CFuzzChance::GetRandom<DWORD>(0xF); } }
};
CStringA sFuzzed;
std::string sFuzzed;
char *next_token = nullptr;
char *token = strtok_s(psz, " ", &next_token);
while (token)
@ -475,7 +475,8 @@ namespace fuzz
CFuzzType<DWORD> repeat(FUZZ_MAP(repeatMap), 1);
for (DWORD i = 0; i < (DWORD)repeat; i++)
{
sFuzzed.AppendFormat("%s ", token);
sFuzzed += token;
sFuzzed += " ";
}
token = strtok_s(nullptr, " ", &next_token);
@ -484,7 +485,9 @@ namespace fuzz
// If psz has a final trailing space, avoid trimming it away. Otherwise, remove
// the extra added final space appended via the loop above.
size_t cch = strlen(psz);
return CFuzzLogic<>::DuplicateStringA(psz[cch] == ' ' ? sFuzzed.TrimRight() : sFuzzed);
if (psz[cch] == ' ')
TrimRight(sFuzzed, ' ');
return CFuzzLogic<>::DuplicateStringA(sFuzzed.c_str());
}
}
#endif

View file

@ -0,0 +1,32 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#ifndef __MEMALLOCATOR_H__
#define __MEMALLOCATOR_H__
#pragma once
namespace fuzz
{
struct CFuzzCRTAllocator
{
_Ret_maybenull_ _Post_writable_byte_size_(nBytes) static void* Reallocate(
_In_ void* p,
_In_ size_t nBytes) throw()
{
return realloc(p, nBytes);
}
_Ret_maybenull_ _Post_writable_byte_size_(nBytes) static void* Allocate(_In_ size_t nBytes) throw()
{
return malloc(nBytes);
}
static void Free(_In_ void* p) throw()
{
free(p);
}
};
}
#endif

View file

@ -4,5 +4,8 @@
#pragma once
#include <windows.h>
#include <atlstr.h>
#include <shlwapi.h>
#include <stdio.h>
// This includes support libraries from the CRT, STL, WIL, and GSL
#include "LibraryIncludes.h"

View file

@ -0,0 +1,67 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#ifndef __STRING_HELPER_H__
#define __STRING_HELPER_H__
#pragma once
void AppendFormat(
_In_ std::string& to,
_In_z_ _Printf_format_string_ const char* format,
...)
{
THROW_HR_IF_NULL(E_INVALIDARG, format);
va_list args;
va_start(args, format);
const auto currentLength = to.length();
const auto appendLength = _vscprintf(format, args); // _vscprintf The value returned does not include the terminating null character.
THROW_HR_IF(E_FAIL, appendLength < 0);
// sprintf_s guarantees that the buffer will be null-terminated. So allocate one more byte for null character and then remove it.
to.resize(currentLength + appendLength + 1);
const auto len = vsprintf_s(to.data() + currentLength, appendLength + 1, format, args);
THROW_HR_IF(E_FAIL, len < 0);
to.resize(currentLength + appendLength);
va_end(args);
}
template<typename T>
void TrimLeft(_In_ T& str, _In_ const typename T::value_type ch)
{
const auto pos = str.find_first_not_of(ch);
if (pos != T::npos)
{
str.erase(0, pos);
}
else
{
// find_first_not_of returns npos when:
// 1. str is empty.
// 2. str contains only ch. (For example : str = "AAA", ch = 'A')
// So here we should clear the string.
str.clear();
}
}
template<typename T>
void TrimRight(_In_ T& str, _In_ const typename T::value_type ch)
{
const auto pos = str.find_last_not_of(ch);
if (pos != T::npos)
{
str.resize(pos + 1);
}
else
{
str.clear();
}
}
#endif

View file

@ -32,7 +32,7 @@ HRESULT CConsoleTSF::Initialize()
Init_CheckResult();
_fCoInitialized = TRUE;
hr = _spITfThreadMgr.CoCreateInstance(CLSID_TF_ThreadMgr);
hr = ::CoCreateInstance(CLSID_TF_ThreadMgr, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&_spITfThreadMgr));
Init_CheckResult();
hr = _spITfThreadMgr->Activate(&_tid);
@ -52,17 +52,20 @@ HRESULT CConsoleTSF::Initialize()
Init_CheckResult();
// Set the context owner before attaching the context to the doc.
CComQIPtr<ITfSource> spSrcIC(_spITfInputContext);
wil::com_ptr_nothrow<ITfSource> spSrcIC;
hr = _spITfInputContext.query_to(&spSrcIC);
Init_CheckResult();
hr = spSrcIC->AdviseSink(IID_ITfContextOwner, static_cast<ITfContextOwner*>(this), &_dwContextOwnerCookie);
Init_CheckResult();
hr = _spITfDocumentMgr->Push(_spITfInputContext);
hr = _spITfDocumentMgr->Push(_spITfInputContext.get());
Init_CheckResult();
// Collect the active keyboard layout info.
CComPtr<ITfInputProcessorProfileMgr> spITfProfilesMgr;
hr = spITfProfilesMgr.CoCreateInstance(CLSID_TF_InputProcessorProfiles);
wil::com_ptr_nothrow<ITfInputProcessorProfileMgr> spITfProfilesMgr;
hr = ::CoCreateInstance(CLSID_TF_InputProcessorProfiles, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&spITfProfilesMgr));
if (SUCCEEDED(hr))
{
TF_INPUTPROCESSORPROFILE ipp;
@ -77,8 +80,8 @@ HRESULT CConsoleTSF::Initialize()
// Setup some useful Cicero event sinks and callbacks.
CComQIPtr<ITfSource> spSrcTIM(_spITfThreadMgr);
CComQIPtr<ITfSourceSingle> spSrcICS(_spITfInputContext);
wil::com_ptr_nothrow<ITfSource> spSrcTIM(_spITfThreadMgr.try_query<ITfSource>());
wil::com_ptr_nothrow<ITfSourceSingle> spSrcICS(_spITfInputContext.try_query<ITfSourceSingle>());
hr = (spSrcTIM && spSrcIC && spSrcICS) ? S_OK : E_FAIL;
Init_CheckResult();
@ -117,7 +120,7 @@ void CConsoleTSF::Uninitialize()
}
// Detach Cicero event sinks.
CComQIPtr<ITfSourceSingle> spSrcICS(_spITfInputContext);
wil::com_ptr_nothrow<ITfSourceSingle> spSrcICS(_spITfInputContext.try_query<ITfSourceSingle>());
if (spSrcICS)
{
spSrcICS->UnadviseSingleSink(_tid, IID_ITfCleanupContextSink);
@ -125,7 +128,7 @@ void CConsoleTSF::Uninitialize()
// Associate the document\context with the console window.
CComQIPtr<ITfSource> spSrcTIM(_spITfThreadMgr);
wil::com_ptr_nothrow<ITfSource> spSrcTIM(_spITfThreadMgr.try_query<ITfSource>());
if (spSrcTIM)
{
if (_dwUIElementSinkCookie)
@ -140,7 +143,7 @@ void CConsoleTSF::Uninitialize()
_dwUIElementSinkCookie = 0;
_dwActivationSinkCookie = 0;
CComQIPtr<ITfSource> spSrcIC(_spITfInputContext);
wil::com_ptr_nothrow<ITfSource> spSrcIC(_spITfInputContext.try_query<ITfSource>());
if (spSrcIC)
{
if (_dwContextOwnerCookie)
@ -159,7 +162,7 @@ void CConsoleTSF::Uninitialize()
if (_spITfThreadMgr && _spITfDocumentMgr)
{
CComPtr<ITfDocumentMgr> spDocMgr;
wil::com_ptr_nothrow<ITfDocumentMgr> spDocMgr;
_spITfThreadMgr->AssociateFocus(_hwndConsole, NULL, &spDocMgr);
}
@ -170,15 +173,15 @@ void CConsoleTSF::Uninitialize()
_spITfDocumentMgr->Pop(TF_POPF_ALL);
}
_spITfInputContext.Release();
_spITfDocumentMgr.Release();
_spITfInputContext.reset();
_spITfDocumentMgr.reset();
// Deactivate per-thread Cicero and uninitialize COM.
if (_spITfThreadMgr)
{
_spITfThreadMgr->Deactivate();
_spITfThreadMgr.Release();
_spITfThreadMgr.reset();
}
if (_fCoInitialized)
{
@ -268,24 +271,22 @@ STDMETHODIMP CConsoleTSF::OnCleanupContext(TfEditCookie ecWrite, ITfContext* pic
//
// Remove GUID_PROP_COMPOSING
//
CComPtr<ITfProperty> prop;
wil::com_ptr_nothrow<ITfProperty> prop;
if (SUCCEEDED(pic->GetProperty(GUID_PROP_COMPOSING, &prop)))
{
CComPtr<IEnumTfRanges> enumranges;
CComPtr<ITfRange> rangeFull;
if (SUCCEEDED(prop->EnumRanges(ecWrite, &enumranges, rangeFull)))
wil::com_ptr_nothrow<IEnumTfRanges> enumranges;
if (SUCCEEDED(prop->EnumRanges(ecWrite, &enumranges, nullptr)))
{
CComPtr<ITfRange> rangeTmp;
wil::com_ptr_nothrow<ITfRange> rangeTmp;
while (enumranges->Next(1, &rangeTmp, NULL) == S_OK)
{
VARIANT var;
VariantInit(&var);
prop->GetValue(ecWrite, rangeTmp, &var);
prop->GetValue(ecWrite, rangeTmp.get(), &var);
if ((var.vt == VT_I4) && (var.lVal != 0))
{
prop->Clear(ecWrite, rangeTmp);
prop->Clear(ecWrite, rangeTmp.get());
}
rangeTmp.Release();
}
}
}
@ -447,8 +448,8 @@ STDMETHODIMP CConsoleTSF::EndUIElement(DWORD /*dwUIElementId*/)
// Associate the document\context with the console window.
if (!fHadConvArea)
{
CComPtr<ITfDocumentMgr> spPrevDocMgr;
_spITfThreadMgr->AssociateFocus(_hwndConsole, _pConversionArea ? _spITfDocumentMgr : NULL, &spPrevDocMgr);
wil::com_ptr_nothrow<ITfDocumentMgr> spPrevDocMgr;
_spITfThreadMgr->AssociateFocus(_hwndConsole, _pConversionArea ? _spITfDocumentMgr.get() : NULL, &spPrevDocMgr);
}
return _pConversionArea;

View file

@ -131,7 +131,7 @@ public:
public:
CConversionArea* CreateConversionArea();
CConversionArea* GetConversionArea() { return _pConversionArea; }
ITfContext* GetInputContext() { return _spITfInputContext; }
ITfContext* GetInputContext() { return _spITfInputContext.get(); }
HWND GetConsoleHwnd() { return _hwndConsole; }
TfClientId GetTfClientId() { return _tid; }
BOOL IsInComposition() { return (_cCompositions > 0); }
@ -148,7 +148,7 @@ public:
if (!fSet && _cCompositions)
{
// Close (terminate) any open compositions when losing the input focus.
CComQIPtr<ITfContextOwnerCompositionServices> spCompositionServices(_spITfInputContext);
wil::com_ptr_nothrow<ITfContextOwnerCompositionServices> spCompositionServices(_spITfInputContext.try_query<ITfContextOwnerCompositionServices>());
if (spCompositionServices)
{
spCompositionServices->TerminateComposition(NULL);
@ -180,9 +180,9 @@ private:
// Cicero stuff.
TfClientId _tid;
CComPtr<ITfThreadMgrEx> _spITfThreadMgr;
CComPtr<ITfDocumentMgr> _spITfDocumentMgr;
CComPtr<ITfContext> _spITfInputContext;
wil::com_ptr_nothrow<ITfThreadMgrEx> _spITfThreadMgr;
wil::com_ptr_nothrow<ITfDocumentMgr> _spITfDocumentMgr;
wil::com_ptr_nothrow<ITfContext> _spITfInputContext;
// Event sink cookies.
DWORD _dwContextOwnerCookie = 0;

View file

@ -1,230 +0,0 @@
//////////////////////////////////////////////////////////////////////
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
// StructureArray.h
//
// CVoidStructureArray declaration.
// CStructureArray declaration.
//
//////////////////////////////////////////////////////////////////////
#pragma once
class CVoidStructureArray
{
public:
CVoidStructureArray(int iElementSize, int iInitSize = 0)
{
ULONG ulInitSize;
ULONG ulElementSize;
ULONG ulBufferSize;
_cElements = 0;
_pData = NULL;
_iAllocatedSize = 0;
_iElementSize = iElementSize;
if (iInitSize)
{
if (IntToULong(iInitSize, &ulInitSize) != S_OK) {
return;
}
if (IntToULong(_iElementSize, &ulElementSize) != S_OK) {
return;
}
if (ULongMult(ulInitSize, ulElementSize, &ulBufferSize) != S_OK) {
return;
}
_pData = (BYTE *)LocalAlloc(LPTR, ulBufferSize);
if (_pData)
{
_iAllocatedSize = iInitSize;
}
}
}
virtual ~CVoidStructureArray() { LocalFree(_pData); }
//
// CVoidStructureArray::GetAt() won't return invalid address or NULL address.
// This function should used to the same idea of element reference as i = a[...]
//
// Note that,
// CVoidStructureArray::GetAt() function should not _pData NULL check and iIndex validation.
// So caller should check empty element and out of index.
//
inline void* GetAt(int iIndex) const
{
FAIL_FAST_IF(!(iIndex >= 0));
FAIL_FAST_IF(!(iIndex <= _cElements)); // there's code that uses the first invalid offset for loop termination
FAIL_FAST_IF(!(_pData != NULL));
return _pData + (iIndex * _iElementSize);
}
BOOL InsertAt(int iIndex, int cElements = 1)
{
BYTE *pb;
int iSizeNew;
// check integer overflow.
if ((iIndex < 0) ||
(cElements < 0) ||
(iIndex > _cElements) ||
(_cElements > _cElements + cElements))
{
return FALSE;
}
// allocate space if necessary
if (_iAllocatedSize < _cElements + cElements)
{
// allocate 1.5x what we need to avoid future allocs
iSizeNew = max(_cElements + cElements, _cElements + _cElements / 2);
UINT uiAllocSize;
if (FAILED(UIntMult(iSizeNew, _iElementSize, &uiAllocSize)) || ((int)uiAllocSize) < 0)
{
return FALSE;
}
if ((pb = (_pData == NULL) ? (BYTE *)LocalAlloc(LPTR, uiAllocSize) :
(BYTE *)LocalReAlloc(_pData, uiAllocSize, LMEM_MOVEABLE | LMEM_ZEROINIT))
== NULL)
{
return FALSE;
}
_pData = pb;
_iAllocatedSize = iSizeNew;
}
if (iIndex < _cElements)
{
// make room for the new addition
memmove(ElementPointer(iIndex + cElements),
ElementPointer(iIndex),
(_cElements - iIndex)*_iElementSize);
}
_cElements += cElements;
FAIL_FAST_IF(!(_iAllocatedSize >= _cElements));
return TRUE;
}
void RemoveAt(int iIndex, int cElements)
{
int iSizeNew;
// check integer overflow.
if ((iIndex < 0) ||
(cElements < 0) ||
(iIndex > _cElements) ||
(_cElements > _cElements + cElements))
{
return;
}
if (iIndex + cElements < _cElements)
{
// shift following eles left
memmove(ElementPointer(iIndex),
ElementPointer(iIndex + cElements),
(_cElements - iIndex - cElements)*_iElementSize);
}
_cElements -= cElements;
// free mem when array contents uses less than half alloc'd mem
iSizeNew = _iAllocatedSize / 2;
if (iSizeNew > _cElements)
{
CompactSize(iSizeNew);
}
}
int Count() const { return _cElements; }
void *Append(int cElements = 1)
{
return InsertAt(Count(), cElements) ? GetAt(Count()-cElements) : NULL;
}
void Clear()
{
LocalFree(_pData);
_pData = NULL;
_cElements = _iAllocatedSize = 0;
}
private:
void CompactSize(int iSizeNew)
{
BYTE *pb;
ULONG ulSizeNew;
ULONG ulElementSize;
ULONG ulBufferSize;
FAIL_FAST_IF(!(iSizeNew <= _iAllocatedSize));
FAIL_FAST_IF(!(_cElements <= iSizeNew));
if (iSizeNew == _iAllocatedSize) // LocalReAlloc will actually re-alloc! Don't let it.
return;
if (IntToULong(iSizeNew, &ulSizeNew) != S_OK) {
return;
}
if (IntToULong(_iElementSize, &ulElementSize) != S_OK) {
return;
}
if (ULongMult(ulSizeNew, ulElementSize, &ulBufferSize) != S_OK) {
return;
}
if ((pb = (BYTE *)LocalReAlloc(_pData, ulBufferSize, LMEM_MOVEABLE | LMEM_ZEROINIT)) != NULL)
{
_pData = pb;
_iAllocatedSize = iSizeNew;
}
}
BYTE *ElementPointer(int iIndex) const
{
return _pData + (iIndex * _iElementSize);
}
private:
BYTE *_pData; // the actual array of data
int _cElements; // number of elements in the array
int _iAllocatedSize; // maximum allocated size (in void *'s) of the array
int _iElementSize; // size of one element
};
//////////////////////////////////////////////////////////////////////
//
// CStructureArray declaration.
//
//////////////////////////////////////////////////////////////////////
//
// typesafe version
//
template<class T>
class CStructureArray : public CVoidStructureArray
{
public:
CStructureArray(int nInitSize = 0):CVoidStructureArray(sizeof(T), nInitSize) {}
T *GetAt(int iIndex) { return (T *)CVoidStructureArray::GetAt(iIndex); }
T *Append(int cElements = 1)
{
T *ret;
ret = (T *)CVoidStructureArray::Append(cElements);
return ret;
}
};

View file

@ -36,9 +36,6 @@ CicCategoryMgr::CicCategoryMgr()
CicCategoryMgr::~CicCategoryMgr()
{
if (m_pcat) {
m_pcat.Release();
}
}
//+---------------------------------------------------------------------------
@ -65,5 +62,5 @@ HRESULT CicCategoryMgr::InitCategoryInstance( )
//
// Create ITfCategoryMgr instance.
//
return m_pcat.CoCreateInstance(CLSID_TF_CategoryMgr);
return ::CoCreateInstance(CLSID_TF_CategoryMgr, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&m_pcat));
}

View file

@ -33,8 +33,8 @@ public:
[[nodiscard]]
HRESULT InitCategoryInstance();
inline ITfCategoryMgr* GetCategoryMgr() { return m_pcat; }
inline ITfCategoryMgr* GetCategoryMgr() { return m_pcat.get(); }
private:
CComQIPtr<ITfCategoryMgr> m_pcat;
wil::com_ptr_nothrow<ITfCategoryMgr> m_pcat;
};

View file

@ -29,7 +29,7 @@ Notes:
//----------------------------------------------------------------------------
[[nodiscard]]
HRESULT CConversionArea::DrawComposition(const CComBSTR& CompStr,
HRESULT CConversionArea::DrawComposition(const std::wstring_view CompStr,
const std::vector<TF_DISPLAYATTRIBUTE>& DisplayAttributes,
const DWORD CompCursorPos)
{
@ -44,15 +44,13 @@ HRESULT CConversionArea::DrawComposition(const CComBSTR& CompStr,
DEFAULT_COMP_INPUT_ERROR
};
std::wstring_view text(CompStr, CompStr.Length());
const auto encodedAttributes = _DisplayAttributesToEncodedAttributes(DisplayAttributes,
CompCursorPos);
std::basic_string_view<BYTE> attributes(encodedAttributes.data(), encodedAttributes.size());
std::basic_string_view<WORD> colorArray(colors.data(), colors.size());
return ImeComposeData(text, attributes, colorArray);
return ImeComposeData(CompStr, attributes, colorArray);
}
[[nodiscard]]
@ -62,11 +60,9 @@ HRESULT CConversionArea::ClearComposition()
}
[[nodiscard]]
HRESULT CConversionArea::DrawResult(const CComBSTR& ResultStr)
HRESULT CConversionArea::DrawResult(const std::wstring_view ResultStr)
{
std::wstring_view text(ResultStr, ResultStr.Length());
return ImeComposeResult(text);
return ImeComposeResult(ResultStr);
}
[[nodiscard]]

View file

@ -31,7 +31,7 @@ class CConversionArea
{
public:
[[nodiscard]]
HRESULT DrawComposition(const CComBSTR& CompStr,
HRESULT DrawComposition(const std::wstring_view CompStr,
const std::vector<TF_DISPLAYATTRIBUTE>& DisplayAttributes,
const DWORD CompCursorPos = -1);
@ -39,7 +39,7 @@ public:
HRESULT ClearComposition();
[[nodiscard]]
HRESULT DrawResult(const CComBSTR& ResultStr);
HRESULT DrawResult(const std::wstring_view ResultStr);
private:
[[nodiscard]]

View file

@ -21,41 +21,6 @@ Notes:
#pragma once
#include "StructureArray.h"
/////////////////////////////////////////////////////////////////////////////
// CCompString
class CCompString : public CComBSTR
{
public:
CCompString() : CComBSTR() { };
CCompString(__in_ecount(dwLen) LPWSTR lpsz, DWORD dwLen) : CComBSTR(dwLen, lpsz) { };
virtual ~CCompString() { };
};
/////////////////////////////////////////////////////////////////////////////
// CCompAttribute
class CCompAttribute : public CStructureArray<BYTE>
{
public:
CCompAttribute(BYTE* lpAttr=NULL, DWORD dwLen=0) : CStructureArray<BYTE>(dwLen)
{
if (! InsertAt(0, dwLen)) {
return;
}
BYTE* pb = GetAt(0);
if (pb == NULL) {
return;
}
memcpy(pb, lpAttr, dwLen * sizeof(BYTE));
}
virtual ~CCompAttribute() { };
};
/////////////////////////////////////////////////////////////////////////////
// CCompCursorPos
@ -77,30 +42,3 @@ public:
private:
DWORD m_CursorPosition;
};
/////////////////////////////////////////////////////////////////////////////
// CCompTfGuidAtom
class CCompTfGuidAtom : public CStructureArray<TfGuidAtom>
{
public:
CCompTfGuidAtom() { };
virtual ~CCompTfGuidAtom() { };
operator TfGuidAtom* () { return GetAt(0); }
DWORD FillData(const TfGuidAtom& data, DWORD dwLen)
{
TfGuidAtom *psTemp = Append(dwLen);
if (psTemp == NULL) {
return 0;
}
DWORD index = dwLen;
while (index--) {
*psTemp++ = data;
}
return dwLen;
}
};

View file

@ -36,9 +36,6 @@ CicDisplayAttributeMgr::CicDisplayAttributeMgr()
CicDisplayAttributeMgr::~CicDisplayAttributeMgr()
{
if (m_pDAM) {
m_pDAM.Release();
}
}
//+---------------------------------------------------------------------------
@ -52,41 +49,29 @@ HRESULT CicDisplayAttributeMgr::GetDisplayAttributeTrackPropertyRange(TfEditCook
ITfReadOnlyProperty **ppProp, IEnumTfRanges **ppEnum, ULONG *pulNumProp)
{
HRESULT hr = E_FAIL;
ULONG ulNumProp;
ulNumProp = (ULONG) m_DispAttrProp.Count();
if (ulNumProp) {
const GUID **ppguidProp;
//
// TrackProperties wants an array of GUID *'s
//
ppguidProp = (const GUID **) new(std::nothrow) GUID* [ulNumProp];
if (ppguidProp == NULL) {
hr = E_OUTOFMEMORY;
}
else {
for (ULONG i=0; i<ulNumProp; i++) {
ppguidProp[i] = m_DispAttrProp.GetAt(i);
try {
ULONG ulNumProp = static_cast<ULONG>(m_DispAttrProp.size());
if (ulNumProp) {
// TrackProperties wants an array of GUID *'s
auto ppguidProp = std::make_unique<const GUID*[]>(ulNumProp);
for (ULONG i = 0; i < ulNumProp; i++) {
ppguidProp[i] = &m_DispAttrProp.at(i);
}
CComPtr<ITfReadOnlyProperty> pProp;
if (SUCCEEDED(hr = pic->TrackProperties(ppguidProp, ulNumProp, 0, NULL, &pProp))) {
wil::com_ptr<ITfReadOnlyProperty> pProp;
if (SUCCEEDED(hr = pic->TrackProperties(ppguidProp.get(), ulNumProp, 0, NULL, &pProp))) {
hr = pProp->EnumRanges(ec, ppEnum, pRange);
if (SUCCEEDED(hr)) {
*ppProp = pProp;
(*ppProp)->AddRef();
*ppProp = pProp.detach();
}
pProp.Release();
}
delete [] ppguidProp;
if (SUCCEEDED(hr)) {
*pulNumProp = ulNumProp;
}
}
}
CATCH_RETURN();
return hr;
}
@ -106,8 +91,8 @@ HRESULT CicDisplayAttributeMgr::GetDisplayAttributeData(ITfCategoryMgr *pcat, Tf
if (SUCCEEDED(pProp->GetValue(ec, pRange, &var))) {
FAIL_FAST_IF(!(var.vt == VT_UNKNOWN));
CComQIPtr<IEnumTfPropertyValue> pEnumPropertyVal(var.punkVal);
if (pEnumPropertyVal) {
wil::com_ptr_nothrow<IEnumTfPropertyValue> pEnumPropertyVal;
if (wil::try_com_query_to(var.punkVal, &pEnumPropertyVal)) {
TF_PROPERTYVAL tfPropVal;
while (pEnumPropertyVal->Next(1, &tfPropVal, NULL) == S_OK) {
if (tfPropVal.varValue.vt == VT_EMPTY) {
@ -121,7 +106,7 @@ HRESULT CicDisplayAttributeMgr::GetDisplayAttributeData(ITfCategoryMgr *pcat, Tf
GUID guid;
pcat->GetGUID(gaVal, &guid);
CComPtr<ITfDisplayAttributeInfo> pDAI;
wil::com_ptr_nothrow<ITfDisplayAttributeInfo> pDAI;
if (SUCCEEDED(m_pDAM->GetDisplayAttributeInfo(guid, &pDAI, NULL))) {
//
// Issue: for simple apps.
@ -138,7 +123,6 @@ HRESULT CicDisplayAttributeMgr::GetDisplayAttributeData(ITfCategoryMgr *pcat, Tf
*pguid = gaVal;
}
pDAI.Release();
hr = S_OK;
break;
}
@ -163,11 +147,11 @@ HRESULT CicDisplayAttributeMgr::InitDisplayAttributeInstance(ITfCategoryMgr* pca
//
// Create ITfDisplayAttributeMgr instance.
//
if (FAILED(hr = m_pDAM.CoCreateInstance(CLSID_TF_DisplayAttributeMgr))) {
if (FAILED(hr = ::CoCreateInstance(CLSID_TF_DisplayAttributeMgr, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&m_pDAM)))) {
return hr;
}
CComPtr<IEnumGUID> pEnumProp;
wil::com_ptr_nothrow<IEnumGUID> pEnumProp;
pcat->EnumItemsInCategory(GUID_TFCAT_DISPLAYATTRIBUTEPROPERTY, &pEnumProp);
//
@ -176,25 +160,20 @@ HRESULT CicDisplayAttributeMgr::InitDisplayAttributeInstance(ITfCategoryMgr* pca
if (pEnumProp) {
GUID guidProp;
//
// add System Display Attribute first.
// so no other Display Attribute property overwrite it.
//
GUID *pguid;
try {
//
// add System Display Attribute first.
// so no other Display Attribute property overwrite it.
//
m_DispAttrProp.emplace_back(GUID_PROP_ATTRIBUTE);
pguid = m_DispAttrProp.Append();
if (pguid != NULL) {
*pguid = GUID_PROP_ATTRIBUTE;
}
while(pEnumProp->Next(1, &guidProp, NULL) == S_OK) {
if (!IsEqualGUID(guidProp, GUID_PROP_ATTRIBUTE)) {
pguid = m_DispAttrProp.Append();
if (pguid != NULL) {
*pguid = guidProp;
while (pEnumProp->Next(1, &guidProp, NULL) == S_OK) {
if (!IsEqualGUID(guidProp, GUID_PROP_ATTRIBUTE)) {
m_DispAttrProp.emplace_back(guidProp);
}
}
}
CATCH_RETURN();
}
return hr;
}

View file

@ -21,8 +21,6 @@ Notes:
#pragma once
#include "StructureArray.h"
class CicDisplayAttributeMgr
{
public:
@ -48,9 +46,9 @@ public:
[[nodiscard]]
HRESULT InitDisplayAttributeInstance(ITfCategoryMgr* pcat);
inline ITfDisplayAttributeMgr* GetDisplayAttributeMgr() { return m_pDAM; }
inline ITfDisplayAttributeMgr* GetDisplayAttributeMgr() { return m_pDAM.get(); }
private:
CComQIPtr<ITfDisplayAttributeMgr> m_pDAM;
CStructureArray<GUID> m_DispAttrProp;
wil::com_ptr_nothrow<ITfDisplayAttributeMgr> m_pDAM;
std::vector<GUID> m_DispAttrProp;
};

View file

@ -93,7 +93,7 @@ HRESULT CEditSessionObject::GetAllTextRange(TfEditCookie ec, ITfContext* ic, ITf
//
// Create the range that covers all the text.
//
CComPtr<ITfRange> rangeFull;
wil::com_ptr_nothrow<ITfRange> rangeFull;
if (FAILED(hr = ic->GetStart(ec, &rangeFull))) {
return hr;
}
@ -109,8 +109,6 @@ HRESULT CEditSessionObject::GetAllTextRange(TfEditCookie ec, ITfContext* ic, ITf
*lpTextLength = cch;
rangeFull.Release();
return S_OK;
}
@ -171,7 +169,7 @@ HRESULT CEditSessionObject::_GetCursorPosition(TfEditCookie ec, CCompCursorPos&
sel.range = NULL;
if (SUCCEEDED(hr = pic->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &sel, &cFetched))) {
CComPtr<ITfRange> start;
wil::com_ptr_nothrow<ITfRange> start;
LONG ich;
TF_HALTCOND hc;
@ -217,7 +215,7 @@ HRESULT CEditSessionObject::_GetCursorPosition(TfEditCookie ec, CCompCursorPos&
[[nodiscard]]
HRESULT CEditSessionObject::_GetTextAndAttribute(TfEditCookie ec, ITfRange* rangeIn,
CCompString& CompStr, CCompTfGuidAtom& CompGuid, CCompString& ResultStr,
std::wstring& CompStr, std::vector<TfGuidAtom>& CompGuid, std::wstring& ResultStr,
BOOL bInWriteSession,
CicCategoryMgr* pCicCatMgr, CicDisplayAttributeMgr* pCicDispAttr)
{
@ -233,7 +231,7 @@ HRESULT CEditSessionObject::_GetTextAndAttribute(TfEditCookie ec, ITfRange* rang
// Otherwise, result range is the same to input range.
//
LONG result_comp;
CComPtr<ITfRange> no_display_attribute_range;
wil::com_ptr_nothrow<ITfRange> no_display_attribute_range;
if (FAILED(hr = rangeIn->Clone(&no_display_attribute_range))) {
return hr;
}
@ -243,13 +241,13 @@ HRESULT CEditSessionObject::_GetTextAndAttribute(TfEditCookie ec, ITfRange* rang
if (FAILED(hr = _GetNoDisplayAttributeRange(ec, rangeIn,
guids, guid_size,
no_display_attribute_range))) {
no_display_attribute_range.get()))) {
return hr;
}
CComPtr<ITfReadOnlyProperty> propComp;
wil::com_ptr_nothrow<ITfReadOnlyProperty> propComp;
if (FAILED(hr = pic->TrackProperties(guids, guid_size, // system property
NULL, 0, // application property
&propComp))) {
@ -257,21 +255,21 @@ HRESULT CEditSessionObject::_GetTextAndAttribute(TfEditCookie ec, ITfRange* rang
}
CComPtr<IEnumTfRanges> enumComp;
wil::com_ptr_nothrow<IEnumTfRanges> enumComp;
if (FAILED(hr = propComp->EnumRanges(ec, &enumComp, rangeIn))) {
return hr;
}
CComPtr<ITfRange> range;
wil::com_ptr_nothrow<ITfRange> range;
while (enumComp->Next(1, &range, NULL) == S_OK) {
VARIANT var;
BOOL fCompExist = FALSE;
hr = propComp->GetValue(ec, range, &var);
hr = propComp->GetValue(ec, range.get(), &var);
if (S_OK == hr) {
CComQIPtr<IEnumTfPropertyValue> EnumPropVal(var.punkVal);
if (EnumPropVal) {
wil::com_ptr_nothrow<IEnumTfPropertyValue> EnumPropVal;
if (wil::try_com_query_to(var.punkVal, &EnumPropVal)) {
TF_PROPERTYVAL tfPropertyVal;
while (EnumPropVal->Next(1, &tfPropertyVal, NULL) == S_OK) {
@ -297,36 +295,36 @@ HRESULT CEditSessionObject::_GetTextAndAttribute(TfEditCookie ec, ITfRange* rang
ULONG ulNumProp;
CComPtr<IEnumTfRanges> enumProp;
CComPtr<ITfReadOnlyProperty> prop;
if (FAILED(hr = pCicDispAttr->GetDisplayAttributeTrackPropertyRange(ec, pic, range, &prop, &enumProp, &ulNumProp))) {
wil::com_ptr_nothrow<IEnumTfRanges> enumProp;
wil::com_ptr_nothrow<ITfReadOnlyProperty> prop;
if (FAILED(hr = pCicDispAttr->GetDisplayAttributeTrackPropertyRange(ec, pic, range.get(), &prop, &enumProp, &ulNumProp))) {
return hr;
}
// use text range for get text
CComPtr<ITfRange> textRange;
wil::com_ptr_nothrow<ITfRange> textRange;
if (FAILED(hr = range->Clone(&textRange))) {
return hr;
}
// use text range for gap text (no property range).
CComPtr<ITfRange> gap_range;
wil::com_ptr_nothrow<ITfRange> gap_range;
if (FAILED(hr = range->Clone(&gap_range))) {
return hr;
}
CComPtr<ITfRange> pPropRange;
wil::com_ptr_nothrow<ITfRange> pPropRange;
while (enumProp->Next(1, &pPropRange, NULL) == S_OK) {
// pick up the gap up to the next property
gap_range->ShiftEndToRange(ec, pPropRange, TF_ANCHOR_START);
gap_range->ShiftEndToRange(ec, pPropRange.get(), TF_ANCHOR_START);
//
// GAP range
//
no_display_attribute_range->CompareStart(ec, gap_range, TF_ANCHOR_START, &result_comp);
no_display_attribute_range->CompareStart(ec, gap_range.get(), TF_ANCHOR_START, &result_comp);
LOG_IF_FAILED(_GetTextAndAttributeGapRange(ec,
gap_range,
gap_range.get(),
result_comp,
CompStr, CompGuid,
ResultStr));
@ -339,8 +337,8 @@ HRESULT CEditSessionObject::_GetTextAndAttribute(TfEditCookie ec, ITfRange* rang
LOG_IF_FAILED(pCicDispAttr->GetDisplayAttributeData(pCicCatMgr->GetCategoryMgr(),
ec,
prop,
pPropRange,
prop.get(),
pPropRange.get(),
&da,
&guidatom,
ulNumProp));
@ -348,16 +346,16 @@ HRESULT CEditSessionObject::_GetTextAndAttribute(TfEditCookie ec, ITfRange* rang
//
// Property range
//
no_display_attribute_range->CompareStart(ec, pPropRange, TF_ANCHOR_START, &result_comp);
no_display_attribute_range->CompareStart(ec, pPropRange.get(), TF_ANCHOR_START, &result_comp);
// Adjust GAP range's start anchor to the end of proprty range.
gap_range->ShiftStartToRange(ec, pPropRange, TF_ANCHOR_END);
gap_range->ShiftStartToRange(ec, pPropRange.get(), TF_ANCHOR_END);
//
// Get property text
//
LOG_IF_FAILED(_GetTextAndAttributePropertyRange(ec,
pPropRange,
pPropRange.get(),
fCompExist,
result_comp,
bInWriteSession,
@ -367,13 +365,11 @@ HRESULT CEditSessionObject::_GetTextAndAttribute(TfEditCookie ec, ITfRange* rang
CompGuid,
ResultStr));
pPropRange.Release();
} // while
// the last non-attr
textRange->ShiftStartToRange(ec, gap_range, TF_ANCHOR_START);
textRange->ShiftEndToRange(ec, range, TF_ANCHOR_END);
textRange->ShiftStartToRange(ec, gap_range.get(), TF_ANCHOR_START);
textRange->ShiftEndToRange(ec, range.get(), TF_ANCHOR_END);
BOOL fEmpty;
while (textRange->IsEmpty(ec, &fEmpty) == S_OK && !fEmpty) {
@ -387,21 +383,22 @@ HRESULT CEditSessionObject::_GetTextAndAttribute(TfEditCookie ec, ITfRange* rang
TF_DISPLAYATTRIBUTE da;
da.bAttr = TF_ATTR_INPUT;
CompGuid.FillData(guidatom, ulcch0);
CompStr.Append(wstr0, ulcch0);
try {
CompGuid.insert(CompGuid.end(), ulcch0, guidatom);
CompStr.append(wstr0, ulcch0);
}
CATCH_RETURN();
}
textRange->Collapse(ec, TF_ANCHOR_END);
range.Release();
} // out-most while for GUID_PROP_COMPOSING
//
// set GUID_PROP_CONIME_TRACKCOMPOSITION
//
CComPtr<ITfProperty> PropertyTrackComposition;
wil::com_ptr_nothrow<ITfProperty> PropertyTrackComposition;
if (SUCCEEDED(hr = pic->GetProperty(GUID_PROP_CONIME_TRACKCOMPOSITION, &PropertyTrackComposition))) {
VARIANT var;
var.vt = VT_I4;
@ -420,7 +417,7 @@ HRESULT CEditSessionObject::_GetTextAndAttribute(TfEditCookie ec, ITfRange* rang
[[nodiscard]]
HRESULT CEditSessionObject::_GetTextAndAttributeGapRange(TfEditCookie ec, ITfRange* gap_range, LONG result_comp,
CCompString& CompStr, CCompTfGuidAtom& CompGuid, CCompString& ResultStr)
std::wstring& CompStr, std::vector<TfGuidAtom>& CompGuid, std::wstring& ResultStr)
{
TfGuidAtom guidatom;
guidatom = TF_INVALID_GUIDATOM;
@ -433,7 +430,7 @@ HRESULT CEditSessionObject::_GetTextAndAttributeGapRange(TfEditCookie ec, ITfRan
ULONG ulcch0;
while (gap_range->IsEmpty(ec, &fEmpty) == S_OK && !fEmpty) {
CComPtr<ITfRange> backup_range;
wil::com_ptr_nothrow<ITfRange> backup_range;
if (FAILED(gap_range->Clone(&backup_range))) {
return E_FAIL;
}
@ -449,14 +446,17 @@ HRESULT CEditSessionObject::_GetTextAndAttributeGapRange(TfEditCookie ec, ITfRan
return E_FAIL;
}
if (result_comp <= 0) {
CompGuid.FillData(guidatom, ulcch0);
CompStr.Append(wstr0, ulcch0);
}
else {
ResultStr.Append(wstr0, ulcch0);
LOG_IF_FAILED(ClearTextInRange(ec, backup_range));
try {
if (result_comp <= 0) {
CompGuid.insert(CompGuid.end(), ulcch0, guidatom);
CompStr.append(wstr0, ulcch0);
}
else {
ResultStr.append(wstr0, ulcch0);
LOG_IF_FAILED(ClearTextInRange(ec, backup_range.get()));
}
}
CATCH_RETURN();
}
@ -477,16 +477,16 @@ HRESULT CEditSessionObject::_GetTextAndAttributePropertyRange(TfEditCookie ec,
BOOL bInWriteSession,
TF_DISPLAYATTRIBUTE da,
TfGuidAtom guidatom,
CCompString& CompStr,
CCompTfGuidAtom& CompGuid,
CCompString& ResultStr)
std::wstring& CompStr,
std::vector<TfGuidAtom>& CompGuid,
std::wstring& ResultStr)
{
BOOL fEmpty;
WCHAR wstr0[256 + 1];
ULONG ulcch0;
while (pPropRange->IsEmpty(ec, &fEmpty) == S_OK && !fEmpty) {
CComPtr<ITfRange> backup_range;
wil::com_ptr_nothrow<ITfRange> backup_range;
if (FAILED(pPropRange->Clone(&backup_range))) {
return E_FAIL;
}
@ -502,31 +502,34 @@ HRESULT CEditSessionObject::_GetTextAndAttributePropertyRange(TfEditCookie ec,
return E_FAIL;
}
// see if there is a valid disp attribute
if (fCompExist == TRUE && result_comp <= 0) {
if (guidatom == TF_INVALID_GUIDATOM) {
da.bAttr = TF_ATTR_INPUT;
try {
// see if there is a valid disp attribute
if (fCompExist == TRUE && result_comp <= 0) {
if (guidatom == TF_INVALID_GUIDATOM) {
da.bAttr = TF_ATTR_INPUT;
}
CompGuid.insert(CompGuid.end(), ulcch0, guidatom);
CompStr.append(wstr0, ulcch0);
}
CompGuid.FillData(guidatom, ulcch0);
CompStr.Append(wstr0, ulcch0);
}
else if (bInWriteSession) {
// if there's no disp attribute attached, it probably means
// the part of string is finalized.
//
ResultStr.Append(wstr0, ulcch0);
else if (bInWriteSession) {
// if there's no disp attribute attached, it probably means
// the part of string is finalized.
//
ResultStr.append(wstr0, ulcch0);
// it was a 'determined' string
// so the doc has to shrink
//
LOG_IF_FAILED(ClearTextInRange(ec, backup_range));
}
else {
//
// Prevent infinite loop
//
break;
// it was a 'determined' string
// so the doc has to shrink
//
LOG_IF_FAILED(ClearTextInRange(ec, backup_range.get()));
}
else {
//
// Prevent infinite loop
//
break;
}
}
CATCH_RETURN();
}
return S_OK;
@ -546,7 +549,7 @@ HRESULT CEditSessionObject::_GetNoDisplayAttributeRange(TfEditCookie ec, ITfRang
return E_FAIL;
}
CComPtr<ITfReadOnlyProperty> propComp;
wil::com_ptr_nothrow<ITfReadOnlyProperty> propComp;
HRESULT hr = pic->TrackProperties(guids, guid_size, // system property
NULL, 0, // application property
&propComp);
@ -554,23 +557,23 @@ HRESULT CEditSessionObject::_GetNoDisplayAttributeRange(TfEditCookie ec, ITfRang
return hr;
}
CComPtr<IEnumTfRanges> enumComp;
wil::com_ptr_nothrow<IEnumTfRanges> enumComp;
hr = propComp->EnumRanges(ec, &enumComp, rangeIn);
if (FAILED(hr)) {
return hr;
}
CComPtr<ITfRange> pRange;
wil::com_ptr_nothrow<ITfRange> pRange;
while (enumComp->Next(1, &pRange, NULL) == S_OK) {
VARIANT var;
BOOL fCompExist = FALSE;
hr = propComp->GetValue(ec, pRange, &var);
hr = propComp->GetValue(ec, pRange.get(), &var);
if (S_OK == hr) {
CComQIPtr<IEnumTfPropertyValue> EnumPropVal(var.punkVal);
if (EnumPropVal) {
wil::com_ptr_nothrow<IEnumTfPropertyValue> EnumPropVal;
if (wil::try_com_query_to(var.punkVal, &EnumPropVal)) {
TF_PROPERTYVAL tfPropertyVal;
while (EnumPropVal->Next(1, &tfPropertyVal, NULL) == S_OK) {
@ -595,12 +598,10 @@ HRESULT CEditSessionObject::_GetNoDisplayAttributeRange(TfEditCookie ec, ITfRang
if (!fCompExist) {
// Adjust GAP range's start anchor to the end of proprty range.
no_display_attribute_range->ShiftStartToRange(ec, pRange, TF_ANCHOR_START);
no_display_attribute_range->ShiftStartToRange(ec, pRange.get(), TF_ANCHOR_START);
}
VariantClear(&var);
pRange.Release();
}
return S_OK;
@ -619,7 +620,7 @@ HRESULT CEditSessionCompositionComplete::CompComplete(TfEditCookie ec)
RETURN_HR_IF_NULL(E_FAIL, pic);
// Get the whole text, finalize it, and set empty string in TOM
CComPtr<ITfRange> spRange;
wil::com_ptr_nothrow<ITfRange> spRange;
LONG cch;
RETURN_IF_FAILED(GetAllTextRange(ec, pic, &spRange, &cch));
@ -659,8 +660,7 @@ HRESULT CEditSessionCompositionComplete::CompComplete(TfEditCookie ec)
if (SUCCEEDED(spRange->GetText(ec, TF_TF_IGNOREEND, wstr.get(), (ULONG)cch, (ULONG*)&cch)))
{
// Make Result String.
CCompString ResultStr(wstr.get(), cch);
hr = conv_area->DrawResult(ResultStr);
hr = conv_area->DrawResult({ wstr.get(), static_cast<size_t>(cch) });
}
}
CATCH_RETURN();
@ -700,7 +700,7 @@ HRESULT CEditSessionCompositionCleanup::EmptyCompositionRange(TfEditCookie ec)
long cchCompleted = g_pConsoleTSF->GetCompletedRangeLength();
if (cchCompleted != 0)
{
CComPtr<ITfRange> spRange;
wil::com_ptr_nothrow<ITfRange> spRange;
LONG cch;
hr = GetAllTextRange(ec, pic, &spRange, &cch);
if (SUCCEEDED(hr))
@ -710,7 +710,7 @@ HRESULT CEditSessionCompositionCleanup::EmptyCompositionRange(TfEditCookie ec)
{
spRange->ShiftEnd(ec, (cchCompleted - cch), &cch, NULL);
}
hr = ClearTextInRange(ec, spRange);
hr = ClearTextInRange(ec, spRange.get());
g_pConsoleTSF->SetCompletedRangeLength(0); // cleaned up all completed text
}
}
@ -750,13 +750,13 @@ HRESULT CEditSessionUpdateCompositionString::UpdateCompositionString(TfEditCooki
return hr;
}
CComPtr<ITfRange> FullTextRange;
wil::com_ptr_nothrow<ITfRange> FullTextRange;
LONG lTextLength;
if (FAILED(hr = GetAllTextRange(ec, pic, &FullTextRange, &lTextLength))) {
return hr;
}
CComPtr<ITfRange> InterimRange;
wil::com_ptr_nothrow<ITfRange> InterimRange;
BOOL fInterim = FALSE;
if (FAILED(hr = _IsInterimSelection(ec, &InterimRange, &fInterim))) {
return hr;
@ -771,10 +771,10 @@ HRESULT CEditSessionUpdateCompositionString::UpdateCompositionString(TfEditCooki
hr = _CreateCategoryAndDisplayAttributeManager(&pCicCat, &pDispAttr);
if (SUCCEEDED(hr)) {
if (fInterim) {
hr = _MakeInterimString(ec, FullTextRange, InterimRange, lTextLength, bInWriteSession, pCicCat, pDispAttr);
hr = _MakeInterimString(ec, FullTextRange.get(), InterimRange.get(), lTextLength, bInWriteSession, pCicCat, pDispAttr);
}
else {
hr = _MakeCompositionString(ec, FullTextRange, bInWriteSession, pCicCat, pDispAttr);
hr = _MakeCompositionString(ec, FullTextRange.get(), bInWriteSession, pCicCat, pDispAttr);
}
}
@ -838,10 +838,10 @@ HRESULT CEditSessionUpdateCompositionString::_IsInterimSelection(TfEditCookie ec
HRESULT CEditSessionUpdateCompositionString::_MakeCompositionString(TfEditCookie ec, ITfRange* FullTextRange, BOOL bInWriteSession,
CicCategoryMgr* pCicCatMgr, CicDisplayAttributeMgr* pCicDispAttr)
{
CCompString CompStr;
CCompTfGuidAtom CompGuid;
std::wstring CompStr;
std::vector<TfGuidAtom> CompGuid;
CCompCursorPos CompCursorPos;
CCompString ResultStr;
std::wstring ResultStr;
BOOL fIgnorePreviousCompositionResult = FALSE;
RETURN_IF_FAILED(_GetTextAndAttribute(ec, FullTextRange,
@ -874,23 +874,23 @@ HRESULT CEditSessionUpdateCompositionString::_MakeCompositionString(TfEditCookie
CConversionArea* conv_area = g_pConsoleTSF ? g_pConsoleTSF->GetConversionArea() : NULL;
RETURN_HR_IF_NULL(E_FAIL, conv_area);
if (ResultStr && !fIgnorePreviousCompositionResult) {
if (!ResultStr.empty() && !fIgnorePreviousCompositionResult) {
return conv_area->DrawResult(ResultStr);
}
if (CompStr) {
ULONG cchDisplayAttribute = (ULONG)CompGuid.Count();
if (!CompStr.empty()) {
const size_t cchDisplayAttribute = CompGuid.size();
std::vector<TF_DISPLAYATTRIBUTE> DisplayAttributes;
DisplayAttributes.reserve(cchDisplayAttribute);
for (DWORD i = 0; i < cchDisplayAttribute; i++) {
for (size_t i = 0; i < cchDisplayAttribute; i++) {
TF_DISPLAYATTRIBUTE da;
ZeroMemory(&da, sizeof(da));
da.bAttr = TF_ATTR_OTHER;
GUID guid;
if (SUCCEEDED(cat->GetGUID(*CompGuid.GetAt(i), &guid))) {
if (SUCCEEDED(cat->GetGUID(CompGuid.at(i), &guid))) {
CLSID clsid;
CComPtr<ITfDisplayAttributeInfo> dai;
wil::com_ptr_nothrow<ITfDisplayAttributeInfo> dai;
if (SUCCEEDED(dam->GetDisplayAttributeInfo(guid, &dai, &clsid))) {
dai->GetAttributeInfo(&da);
}
@ -933,8 +933,6 @@ HRESULT CEditSessionUpdateCompositionString::_MakeInterimString(TfEditCookie ec,
FullTextRange->CompareEnd(ec, InterimRange, TF_ANCHOR_END, &lEndResult);
RETURN_HR_IF(E_FAIL, lEndResult != 1);
CCompString ResultStr;
if (lStartResult < 0) {
// Make result string.
RETURN_IF_FAILED(FullTextRange->ShiftEndToRange(ec, InterimRange, TF_ANCHOR_START));
@ -961,9 +959,9 @@ HRESULT CEditSessionUpdateCompositionString::_MakeInterimString(TfEditCookie ec,
}
// Make interim character
CCompString CompStr;
CCompTfGuidAtom CompGuid;
CCompString _tempResultStr;
std::wstring CompStr;
std::vector<TfGuidAtom> CompGuid;
std::wstring _tempResultStr;
RETURN_IF_FAILED(_GetTextAndAttribute(ec, InterimRange,
CompStr, CompGuid, _tempResultStr,
@ -986,22 +984,19 @@ HRESULT CEditSessionUpdateCompositionString::_MakeInterimString(TfEditCookie ec,
CConversionArea* conv_area = g_pConsoleTSF ? g_pConsoleTSF->GetConversionArea() : NULL;
RETURN_HR_IF_NULL(E_FAIL, conv_area);
if (ResultStr) {
return conv_area->DrawResult(ResultStr);
}
if (CompStr) {
ULONG cchDisplayAttribute = (ULONG)CompGuid.Count();
if (!CompStr.empty()) {
const size_t cchDisplayAttribute = CompGuid.size();
std::vector<TF_DISPLAYATTRIBUTE> DisplayAttributes;
DisplayAttributes.reserve(cchDisplayAttribute);
for (DWORD i = 0; i < cchDisplayAttribute; i++) {
for (size_t i = 0; i < cchDisplayAttribute; i++) {
TF_DISPLAYATTRIBUTE da;
ZeroMemory(&da, sizeof(da));
da.bAttr = TF_ATTR_OTHER;
GUID guid;
if (SUCCEEDED(cat->GetGUID(*CompGuid.GetAt(i), &guid))) {
if (SUCCEEDED(cat->GetGUID(CompGuid.at(i), &guid))) {
CLSID clsid;
CComPtr<ITfDisplayAttributeInfo> dai;
wil::com_ptr_nothrow<ITfDisplayAttributeInfo> dai;
if (SUCCEEDED(dam->GetDisplayAttributeInfo(guid, &dai, &clsid))) {
dai->GetAttributeInfo(&da);
}

View file

@ -84,11 +84,11 @@ protected:
[[nodiscard]]
HRESULT _GetTextAndAttribute(TfEditCookie ec, ITfRange* range,
CCompString& CompStr, CCompTfGuidAtom CompGuid,
std::wstring& CompStr, std::vector<TfGuidAtom> CompGuid,
BOOL bInWriteSession,
CicCategoryMgr* pCicCatMgr, CicDisplayAttributeMgr* pCicDispAttr)
{
CCompString ResultStr;
std::wstring ResultStr;
return _GetTextAndAttribute(ec, range,
CompStr, CompGuid, ResultStr,
bInWriteSession,
@ -97,14 +97,14 @@ protected:
[[nodiscard]]
HRESULT _GetTextAndAttribute(TfEditCookie ec, ITfRange* range,
CCompString& CompStr, CCompTfGuidAtom& CompGuid, CCompString& ResultStr,
std::wstring& CompStr, std::vector<TfGuidAtom>& CompGuid, std::wstring& ResultStr,
BOOL bInWriteSession,
CicCategoryMgr* pCicCatMgr, CicDisplayAttributeMgr* pCicDispAttr);
[[nodiscard]]
HRESULT _GetTextAndAttributeGapRange(TfEditCookie ec, ITfRange* gap_range, LONG result_comp,
CCompString& CompStr, CCompTfGuidAtom& CompGuid, CCompString& ResultStr);
std::wstring& CompStr, std::vector<TfGuidAtom>& CompGuid, std::wstring& ResultStr);
[[nodiscard]]
HRESULT _GetTextAndAttributePropertyRange(TfEditCookie ec, ITfRange* pPropRange,
@ -113,7 +113,7 @@ protected:
BOOL bInWriteSession,
TF_DISPLAYATTRIBUTE da,
TfGuidAtom guidatom,
CCompString& CompStr, CCompTfGuidAtom& CompGuid, CCompString& ResultStr);
std::wstring& CompStr, std::vector<TfGuidAtom>& CompGuid, std::wstring& ResultStr);
[[nodiscard]]
HRESULT _GetNoDisplayAttributeRange(TfEditCookie ec, ITfRange* range,

View file

@ -44,27 +44,27 @@ BOOL CConsoleTSF::_HasCompositionChanged(ITfContext *pInputContext, TfEditCookie
// Find GUID_PROP_CONIME_TRACKCOMPOSITION property.
//
CComPtr<ITfProperty> Property;
CComPtr<ITfRange> FoundRange;
CComPtr<ITfProperty> PropertyTrackComposition;
wil::com_ptr_nothrow<ITfProperty> Property;
wil::com_ptr_nothrow<ITfRange> FoundRange;
wil::com_ptr_nothrow<ITfProperty> PropertyTrackComposition;
BOOL bFound = FALSE;
if (SUCCEEDED(pInputContext->GetProperty(GUID_PROP_CONIME_TRACKCOMPOSITION, &Property))) {
CComPtr<IEnumTfRanges> EnumFindFirstTrackCompRange;
wil::com_ptr_nothrow<IEnumTfRanges> EnumFindFirstTrackCompRange;
if (SUCCEEDED(Property->EnumRanges(ecReadOnly, &EnumFindFirstTrackCompRange, NULL))) {
HRESULT hr;
CComPtr<ITfRange> range;
wil::com_ptr_nothrow<ITfRange> range;
while ((hr = EnumFindFirstTrackCompRange->Next(1, &range, NULL)) == S_OK) {
VARIANT var;
VariantInit(&var);
hr = Property->GetValue(ecReadOnly, range, &var);
hr = Property->GetValue(ecReadOnly, range.get(), &var);
if (SUCCEEDED(hr)) {
if ((V_VT(&var) == VT_I4 && V_I4(&var) != 0)) {
range->Clone(&FoundRange);
@ -75,8 +75,6 @@ BOOL CConsoleTSF::_HasCompositionChanged(ITfContext *pInputContext, TfEditCookie
VariantClear(&var);
range.Release();
if (bFound) {
break; // FOUND!!
}
@ -99,19 +97,19 @@ BOOL CConsoleTSF::_HasCompositionChanged(ITfContext *pInputContext, TfEditCookie
bFound = FALSE; // RESET bFound flag...
CComPtr<ITfRange> rangeTrackComposition;
wil::com_ptr_nothrow<ITfRange> rangeTrackComposition;
if (SUCCEEDED(FoundRange->Clone(&rangeTrackComposition))) {
//
// get the text range that does not include read only area for
// reconversion.
//
CComPtr<ITfRange> rangeAllText;
wil::com_ptr_nothrow<ITfRange> rangeAllText;
LONG cch;
if (SUCCEEDED(CEditSessionObject::GetAllTextRange(ecReadOnly, pInputContext, &rangeAllText, &cch))) {
LONG lResult;
if (SUCCEEDED(rangeTrackComposition->CompareStart(ecReadOnly, rangeAllText, TF_ANCHOR_START, &lResult))) {
if (SUCCEEDED(rangeTrackComposition->CompareStart(ecReadOnly, rangeAllText.get(), TF_ANCHOR_START, &lResult))) {
//
// if the start position of the track composition range is not
@ -121,7 +119,7 @@ BOOL CConsoleTSF::_HasCompositionChanged(ITfContext *pInputContext, TfEditCookie
if (lResult != 0) {
bFound = TRUE; // FOUND!!
}
else if (SUCCEEDED(rangeTrackComposition->CompareEnd(ecReadOnly, rangeAllText, TF_ANCHOR_END, &lResult))) {
else if (SUCCEEDED(rangeTrackComposition->CompareEnd(ecReadOnly, rangeAllText.get(), TF_ANCHOR_END, &lResult))) {
//
// if the start position of the track composition range is not
@ -135,7 +133,7 @@ BOOL CConsoleTSF::_HasCompositionChanged(ITfContext *pInputContext, TfEditCookie
&GUID_PROP_ATTRIBUTE};
const int guid_size = sizeof(guids) / sizeof(GUID*);
CComPtr<IEnumTfRanges> EnumPropertyChanged;
wil::com_ptr_nothrow<IEnumTfRanges> EnumPropertyChanged;
if (lResult != 0) {
bFound = TRUE; // FOUND!!
@ -143,17 +141,14 @@ BOOL CConsoleTSF::_HasCompositionChanged(ITfContext *pInputContext, TfEditCookie
else if (SUCCEEDED(pEditRecord->GetTextAndPropertyUpdates(TF_GTP_INCL_TEXT, guids, guid_size, &EnumPropertyChanged))) {
HRESULT hr;
CComPtr<ITfRange> range;
wil::com_ptr_nothrow<ITfRange> range;
while ((hr = EnumPropertyChanged->Next(1, &range, NULL)) == S_OK) {
BOOL empty;
if (range->IsEmpty(ecReadOnly, &empty) == S_OK && empty) {
range.Release();
continue;
}
range.Release();
bFound = TRUE; // FOUND!!
break;
}

View file

@ -23,8 +23,6 @@ Notes:
#include <windows.h>
#include <ole2.h>
#include <atlbase.h> // ATL base
extern "C"
{
#include <winuser.h>

View file

@ -18,7 +18,6 @@
<ClInclude Include="debug.h" />
<ClInclude Include="globals.h" />
<ClInclude Include="precomp.h" />
<ClInclude Include="StructureArray.h" />
<ClInclude Include="TfCatUtil.h" />
<ClInclude Include="TfConvArea.h" />
<ClInclude Include="TfCtxtComp.h" />

View file

@ -53,9 +53,6 @@
<ClInclude Include="precomp.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="StructureArray.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TfCatUtil.h">
<Filter>Header Files</Filter>
</ClInclude>