はみ出しRAPTの戯言

- a day after yesterday -

目次

Blog 利用状況

ニュース

書庫

日記カテゴリ

コミュニティ リンク

2009年1月14日 #

IE7 以降で HttpOpenRequest() API が エラーコード 12006 で失敗する件

IE7 以降で HttpOpenRequest() API が エラーコード 12006 で失敗する件

プログラム上からインターネットに接続して直接ファイルをダウンロードしたい場合などに、InternetOpen/InternetConnect/HttpOpenRequest API を使って下記のようなコードを使用すると思うが、このコードは IE6 以前では問題なく動作するが、IE7 以降では失敗する。

HINTERNET hSession = ::InternetOpen( _T( "UserAgent" ), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
HINTERNET hConnect = ::InternetConnect( hSession, _T( "www.example.com" ), 80, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0 );
HINTERNET hRequest = ::HttpOpenRequest( hConnect, _T( "GET" ), _T( "/~user/path/file.txt" ), NULL, _T( "Referrer" ), NULL, INTERNET_FLAG_DONT_CACHE, 0 );
if ( hRequest == NULL ) {
    DWORD dwError = ::GetLastError();
    if ( dwError == ERROR_INTERNET_UNRECOGNIZED_SCHEME /*12006*/ ) {
        ATLTRACE( _T( "スキームが認識できないエラー\n" ) );
    }
}

// (snip)

::InternetCloseHandle( hRequest );
::InternetCloseHandle( hConnect );
::InternetCloseHandle( hSession );

原因は、HttpOpenRequest() でリファラに「Referrer」と記述しているがこの形式が「スキーム:識別子」の形式になっていないことによるものらしい。これをたとえば「myscheme:Referrer」に変更することで上記コードは IE7 以降でも正常に動作する。

なぜ IE7 以降で動作しなくなったかは不明だが、これにはかなりハマったので記事にして残しておくことにした。

posted @ 2:51 | Feedback (1462)

IE8 Beta2 で User-Agent が変更できない問題

IE8 Beta2 で User-Agent が変更できない問題

今更ネタにするものでもないけど、去年の夏に IEβニュースグループに投稿した記事と同じ内容をここにも書いておく。

VC6/VC2003 で Trident コンポーネントを使ったプログラムを作成しているときの話。
プログラム上で User-Agent を変更して接続するために UrlMkSetSessionOption( URLMON_OPTION_USERAGENT ) API を使用しているが、IE8β2 では正常に動作しない。

下記のサンプルコードは IE4 以降の環境では正常に動作するが、IE8 では UrlMkSetSessionOption は正常終了(S_OK) を返すものの効果がない。

void ChangeUserAgentTest()
{
    char lpaUserAgent[ 1024 ] = "test user-agent";
    DWORD dwLength = lstrlenA( lpaUserAgent );
    HRESULT hr = ::UrlMkSetSessionOption( URLMON_OPTION_USERAGENT, lpaUserAgent, dwLength, 0 );
    CString strMsg;
    strMsg.Format( _T( "UrlMkSetSessionOption: 0x%08x" ), hr );
    ::MessageBox( NULL, strMsg, _T( "[debug - 1]" ), MB_OK );
    if ( hr == S_OK ) {
        DWORD dwSize = 1023;
        char lpaString[ 1024 ] = {0};
        hr = ::ObtainUserAgentString( 0, lpaString, &dwSize );
        strMsg.Format( _T( "ObtainUserAgentString: 0x%08x\n%s" ), hr, CString( lpaString ) );
        ::MessageBox( NULL, strMsg, _T( "[debug - 2]" ), MB_OK );
    }
}

最初のメッセージは成功を返す。
---------------------------
[debug - 1]
---------------------------
UrlMkSetSessionOption: 0x00000000
---------------------------
OK
---------------------------

二番目ののメッセージも成功を返す。
---------------------------
[debug - 2]
---------------------------
ObtainUserAgentString: 0x00000000
test user-agent
---------------------------
OK
---------------------------

しかしながら、ウェブサイトにアクセスすると、サーバー変数は下記の値を返す:
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0)

IE8 より前では下記の値を返す:
test user-agent

ひょっとしたら IE8 以降で User-Agent を変更するための手順が変更されたのか、とも思ったがバグの可能性が高い。

この API は、urlmon.dll に含まれているため、一般プログラマからは何もできなさげ。
正式版までに解決してくれていることを願うばかり。

posted @ 2:21 | Feedback (32)