WindowsMediaPlayerプラグインの他のプログラマーのソースコードをデバッグしています。このプラグインにより、WMPがクラッシュすることがあり、プラグイン設定ウィンドウを開くのに非常に長い時間がかかることがあります。この問題は、音楽の再生中に設定ウィンドウを開いた場合にのみ発生します。プレイヤーが停止している場合は問題なく開きます。
コードを調べてデバッグしていると、問題の原因と思われるコードの行にたどり着きました。
プロパティページには、次のメンバー変数があります。
CComPtr<IDsp_plugin> m_pDsp_plugin;
初期化時のプロパティページは、COMオブジェクトのget_textメソッドを呼び出します。
unsigned char * txt = NULL;
//m_pDsp_plugin is a valid pointer to IDsp_plugin
HRESULT res = m_pDsp_plugin->get_text(&txt);
現時点では、hresは「0x80010105:サーバーが例外をスローしました」です。Visual Studioのデバッグ出力には、「wmplayer.exeの0x764efbaeでの初回例外:0x80010105:」と表示されます。
get_textメソッドは次のように定義されています。
Dsp_plugin.idlで
interface IDsp_plugin : IUnknown
{
HRESULT get_text([out] unsigned char* *pVal);
...
Dsp_plugin.hで
class ATL_NO_VTABLE CDsp_plugin :
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<CDsp_plugin, &CLSID_Dsp_plugin>,
public IDsp_plugin,
public IMediaObject,
public IWMPPluginEnable,
public ISpecifyPropertyPages
{
STDMETHOD(get_text)(unsigned char* *txt);
...
そして最後に、この例外をスローするメソッド自体:Dsp_plugin.cpp
STDMETHODIMP CDsp_plugin::get_text (unsigned char* *txt)
{
... // some code for copying a valid string from somewhere to char* y
// 11 bytes of memory for y was allocated using malloc(10+1);
// y contains a valid C string here, tested with debugger and passing to OutputDebugStringA
*txt = (unsigned char*)(y); // This line executes normally, but at the end the caller gets "The server threw an exception." and WMP starts behaving weirdly.
// If I comment it out, the caller gets S_OK and there are no any issues with WMP.
return S_OK;
}
COM DLLは、「Unicode文字セットを使用する」設定でコンパイルされます。
私はCOMプログラマーの経験はありませんが、文字列をunsigned char **として渡すことは私には珍しいようです。私は、COMを扱うときに主にBSTRまたはVARIANTを見てきました。
COMの第一人者が説明できるかもしれませんが、なぜこの例外が発生するのか、メソッドをunsigned char ** / malloc/freeの代わりにBSTR*とSysAllocString/SysfreeStringを使用するように変換するだけで修正できるのでしょうか?