Reputation: 2255
What would cause an IEnumString->Next() call to call the correct function but leave the client's pointer null? Everything is 64bit (Windows 10).
Data flow: My DLL -> MSSpellCheckingHost -> Client
In my code (Github link) everything checks out. The allocation and copy look fine. But the client sees a null pointer, but only when coming via ISpellCheckProvider->Suggest(); it works fine via ISpellCheckProviderFactory->get_SupportedLanguages()
Snippet from EnumString.hpp :
template<typename String>
inline void CoCopyWString(const String& in, PWSTR* out) {
debugp p(__FUNCTION__);
p(in, static_cast<void*>(*out));
*out = reinterpret_cast<LPWSTR>(CoTaskMemAlloc(sizeof(wchar_t)*(in.size() + 1)));
std::copy(in.begin(), in.end(), *out);
(*out)[in.size()] = 0;
p(std::wstring(*out), static_cast<void*>(*out));
}
class EnumString : public IEnumString {
public:
...
IFACEMETHODIMP Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched) {
debugp p(__FUNCTION__);
p(celt);
HRESULT hr = S_FALSE;
ULONG i = 0;
for (; i < celt && current < strings.size(); ++i, ++current) {
p(i, current);
CoCopyWString(strings[current], rgelt+i);
p(static_cast<void*>(rgelt + i), static_cast<void*>(rgelt[i]));
}
if (celt > 1) {
*pceltFetched = i;
}
if (i == celt) {
hr = S_OK;
}
return hr;
}
...
private:
std::vector<std::wstring> strings;
ULONG current = 0;
};
As shown, there's lots of debug prints, because attaching a debugger to MSSpellCheckingHost is quite an annoyance, and they yield the expected output of e.g.:
EnumString::Next
1
0 0
CoCopyWString
i-llu 0000000000000000
i-llu 000001CC35682AE0
~CoCopyWString
000001CC356A1F50 000001CC35682AE0
~EnumString::Next
...which shows the output pointer being set and the data pointed to is correct. And it works when SupportedLanguages is called - that returns the correct value to the enumerator and the value is used so it couldn't have been null. But when Suggest() is used, the results don't make it through.
All other functions that return structures allocated via CoTaskMemAlloc
also work, so overall the host appears functional, except in that one case.
Upvotes: 0
Views: 63
Reputation: 2255
As Hans Passant pointed out, the snippet
if (celt > 1) {
*pceltFetched = i;
}
should instead be
if (pceltFetched) {
*pceltFetched = i;
}
Upvotes: 1