* 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:
parent
68d0c23246
commit
fd2fb07bcf
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
32
src/terminal/parser/ft_fuzzer/memallocator.h
Normal file
32
src/terminal/parser/ft_fuzzer/memallocator.h
Normal 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
|
|
@ -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"
|
||||
|
|
67
src/terminal/parser/ft_fuzzer/string_helper.h
Normal file
67
src/terminal/parser/ft_fuzzer/string_helper.h
Normal 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
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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]]
|
||||
|
|
|
@ -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]]
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -23,8 +23,6 @@ Notes:
|
|||
#include <windows.h>
|
||||
#include <ole2.h>
|
||||
|
||||
#include <atlbase.h> // ATL base
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <winuser.h>
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue