COM out-ptr在客户端保持为null

时间:2016-11-29 20:07:16

标签: c++ windows com

什么会导致IEnumString->Next()调用调用正确的函数但是将客户端的指针保留为空?一切都是64位(Windows 10)。

数据流:我的DLL - > MSSpellCheckingHost - >客户端

In my code (Github link)一切都结束了。分配和复制看起来很好。但是客户端看到一个空指针,但只有通过ISpellCheckProvider->Suggest();来时它才能正常通过ISpellCheckProviderFactory->get_SupportedLanguages()

来自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;
};

如图所示,有很多调试打印,因为将调试器附加到MSSpellCheckingHost是非常烦人的,并且它们产生了预期的输出,例如:

EnumString::Next
    1
    0 0
    CoCopyWString
        i-llu 0000000000000000
        i-llu 000001CC35682AE0
    ~CoCopyWString
    000001CC356A1F50 000001CC35682AE0
~EnumString::Next

...显示正在设置的输出指针和指向的数据是正确的。并且它在调用SupportedLanguages时有效 - 它将正确的值返回给枚举器并使用该值,因此它不能为空。但是,当使用Suggest()时,结果无法通过。

返回通过CoTaskMemAlloc分配的结构的所有其他函数也可以工作,因此整个主机看起来都是可用的,除了那个案例。

1 个答案:

答案 0 :(得分:1)

正如Hans Passant指出的那样,片段

    if (celt > 1) {
        *pceltFetched = i;
    }

应该是

    if (pceltFetched) {
        *pceltFetched = i;
    }