IDirectPlay8ServerのInitializeniで起こるエラー

[戻る]
color 2007/01/27(土) 00:00:53
開発環境:
xp vs2005 C++

コールバック関数を指定すると下記のようなエラーが出てしまいます。

// 第2引数にコールバック指定。
hr = lpDirectPlay8Server->Initialize( NULL, &myMessageHandler, 0 );

【0x00415084 でハンドルされていない例外が発生しました: 0xC0000005: 場所 
0x00000000 を読み込み中にアクセス違反が発生しました。】

ソースの全文は

BOOL DirectPlayInitialize()
{
    
    // IDirectPlay8Serverインターフェイス取得。
    IDirectPlay8Server *lpDirectPlay8Server;
    HRESULT hr;

    hr = CoCreateInstance( CLSID_DirectPlay8Server,
                            NULL,
                        
    CLSCTX_INPROC_SERVER,
                        
    IID_IDirectPlay8Server,
                            (void**)
&lpDirectPlay8Server);

    // オブジェクトの初期化。
    hr = lpDirectPlay8Server->Initialize( NULL, &myMessageHandler, 0 );

    // IDirectPlay8Addressインターフェイスを得てポート番号などを設定。
    IDirectPlay8Address *prgDeviceInfo;

    hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL, 
CLSCTX_INPROC_SERVER, IID_IDirectPlay8Address, (void**)&prgDeviceInfo);
    hr = prgDeviceInfo->SetSP( &CLSID_DP8SP_TCPIP );

    // ポート6699で待ちうけ。
    DWORD dwPort = 6699;
    hr = prgDeviceInfo->AddComponent( DPNA_KEY_PORT, &dwPort, sizeof
(dwPort), DPNA_DATATYPE_DWORD );

    // サーバーのプレーヤー情報設定。
    DPN_PLAYER_INFO    dpnPlayerInfo;

    dpnPlayerInfo.dwSize        = sizeof(DPN_PLAYER_INFO);
    dpnPlayerInfo.dwInfoFlags    = DPNINFO_NAME;
    dpnPlayerInfo.pwszName        = L"プレーヤーの名前";
    dpnPlayerInfo.pvData        = NULL;
    dpnPlayerInfo.dwDataSize    = 0;
    dpnPlayerInfo.dwPlayerFlags    = 0;

    hr = lpDirectPlay8Server->SetServerInfo( &dpnPlayerInfo, NULL, NULL, 
DPNSETPEERINFO_SYNC);

    // セッション情報を設定し、セッションを開始する。
    // アプリケーションのGUID
    static const GUID myAppGUID = { 0x41898a0d, 0xcb96, 0x4d9c, { 0xa4, 
0x8d, 0x9b, 0xba, 0x82, 0xc4, 0x2c, 0x65 } };

    // DPN_APPLICATION_DESC構造体を初期化する。
    DPN_APPLICATION_DESC    dpnAppDesc;

    // 構造体を0で初期化。
    memset( &dpnAppDesc, 0, sizeof(dpnAppDesc));

    // 各メンバを設定。
    dpnAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
    dpnAppDesc.dwFlags = DPNSESSION_CLIENT_SERVER;
    dpnAppDesc.guidApplication = myAppGUID;
    dpnAppDesc.pwszSessionName = L"セッション名";

    // セッションの作成。
    hr = lpDirectPlay8Server->Host( &dpnAppDesc, &prgDeviceInfo, 1,
                                
    NULL, NULL, NULL,
                                
    DPNHOST_OKTOQUERYFORADDRESSING );

    return true;

}

HRESULT CALLBACK myMessageHandler( PVOID pvUserContext, DWORD dwMessageType, 
PVOID pMessage)
{

    // メッセージ・ハンドラ
    // pvUserContext = Initializeメソッドの第@引数に渡した値。
    // dwMessageType = 届いたメッセージの種類。
    // pMessage      = メッセージに付随するデータ。
    // メッセージの種類ごとに処理を分ける。
    switch( dwMessageType )
    {
        case DPN_MSGID_CREATE_PLAYER:
        {
            // プレイヤーがセッションに参加した。
            // ・・・何らかの処理・・・
            return DPN_OK;
        }

    }

    return DPN_OK;
}

となっております。

デバッガで見た際には
hr = lpDirectPlay8Server->Initialize( NULL, &myMessageHandler, 0 );
と
HRESULT CALLBACK myMessageHandler( PVOID pvUserContext, DWORD dwMessageType, 
PVOID pMessage)
のmyMessageHandlerのアドレスは同じでした。

どのようにしましたら、エラーが出なくなるのでしょうか。
知っている方いらっしゃいましたらご教授お願い致します。

通りすがり 2007/01/27(土) 02:03:15
>【0x00415084 でハンドルされていない例外が発生しました: 0xC0000005: 場所 
>0x00000000 を読み込み中にアクセス違反が発生しました。】
どう見てもNULLポインタアクセスしてるが
CoCreateInstance成功してるの?

超初心者 2007/01/27(土) 12:30:43
面倒だけど全ての戻り値hrに対して
if(FAILED(hr)) return FALSE;
をつけるべきだ。

できれば
if(FAILED(hr))
{
    TRACE("xxに失敗 hr=%x\n",hr);
    return FALSE;
}

厳密には途中まで作成したオブジェクトを自動的に削除してくれる
CComPtr<IDirectPlay8Server> pDirectPlay8Server;
のような記述がお勧め。

とはいうものの俺はCComPtrをよく知らない。
CLSCTX_INPROC_SERVERとか指定できるのかな?

プログラムの最初のほうでCoInitialize呼んでる?

color 2007/01/27(土) 17:01:10
[[解決]]
通りすがりさん
超初心者さん

レスありがとうございます。

超初心者さんのご指摘どおり
CoInitializeを呼んでいなかった為に起きた
アクセスエラーでした。

お手数おかけしました。

古いスレッドには追加発言できません。