WinINet アプリケーションの Win への移植HTTP

Microsoft Windows HTTP Services (WinHTTP) は、HTTP クライアント スタックへのアクセスを必要とする中間層およびバックエンド サーバー アプリケーションを対象としています。 Microsoft Windows Internet (WinINet) は、クライアント アプリケーション用の HTTP クライアント スタックと、ファイル転送プロトコル (FTP)、SOCKSv4、および Gopher プロトコルへのアクセスを提供します。 この概要は、WinINet アプリケーションを WinHTTP に移植することが有益かどうかを判断するのに役立ちます。 また、特定の変換要件についても説明します。

WinINet アプリケーションを移植する前に考慮すべき事項

アプリケーションで次の利点がある場合は、WinINet アプリケーションを WinHTTP に移植することを検討してください。

  • サーバーセーフな HTTP クライアント スタック。
  • スタックの使用量を最小限に抑えました。
  • サーバー アプリケーションのスケーラビリティ。
  • プラットフォーム関連の API への依存関係が少なくなります。
  • スレッドの偽装のサポート。
  • サービスに優しい HTTP スタック。
  • スクリプト可能な WinHttpRequest オブジェクトへのアクセス。

次の 1 つ以上をサポートする必要がある場合は、WinINet アプリケーションを WinHTTP に移植することを検討しないでください。

  • HTTP スタックからの FTP または Gopher プロトコル。
  • SOCKS プロキシと通信するための SOCKSv4 プロトコルのサポート。
  • 自動ダイヤルアップ サービス。

アプリケーションを WinHTTP に移植する場合は、次のセクションで変換プロセスについて説明します。

WinINet と WinHTTP の両方のサンプル アプリケーションの場合は、WinINet の AsyncDemo サンプルと WinHTTP の AsyncDemo サンプルを比較します。

WinHTTP と WinINet 関数の同等物

次の表に、HTTP クライアント スタックに関連する WinINet 関数と、WinHTTP と同等の関数を示します。

一覧にない WinINet 関数がアプリケーションに必要な場合は、アプリケーションを WinHTTP に移植しないでください。

WinINet 関数 WinHTTP と同等 主な変更点
HttpAddRequestHeaders WinHttpAddRequestHeaders [なし] :
HttpEndRequest WinHttpReceiveResponse コンテキスト値は、 WinHttpSendRequest または WinHttpSetOption で設定されます。 要求オプションは WinHttpOpenRequest で設定されます。 WinHttpReceiveResponse は、要求の送信後に呼び出す必要があります。
HttpOpenRequest WinHttpOpenRequest コンテキスト値は、 WinHttpSendRequest または WinHttpSetOption で設定されます。
HttpQueryInfo WinHttpQueryHeaders [なし] :
HttpSendRequest WinHttpSendRequest コンテキスト値は WinHttpSendRequest で設定できます。
HttpSendRequestEx WinHttpSendRequest バッファーを指定できません。
InternetCanonicalizeUrl 同等の機能がありません これで、 URL が WinHttpOpenRequest に正規形式で配置されるようになりました。
InternetCheckConnection 同等の機能がありません WinHTTP では実装されていません。
InternetCloseHandle WinHttpCloseHandle WinHTTP で親ハンドルを閉じても、子ハンドルは再帰的に閉じません。
InternetCombineUrl 同等の機能がありません URL は、 WinHttpCreateUrl 関数を使用して組み立てることができます。
InternetConfirmZoneCrossing 同等の機能がありません WinHTTP では実装されていません。
InternetConnect WinHttpConnect コンテキスト値は、 WinHttpSendRequest または WinHttpSetOption で設定されます。 要求オプションは WinHttpOpenRequest で設定されます。 ユーザー資格情報は WinHttpSetCredentials で設定されます。
InternetCrackUrl WinHttpCrackUrl ICU_ESCAPE フラグとは逆の動作: InternetCrackUrl では、このフラグによってエスケープ シーケンス (%xx) が文字に変換されますが、 WinHttpCrackUrl では、HTTP 要求で からエスケープする必要がある文字がエスケープ シーケンスに変換されます。
InternetCreateUrl WinHttpCreateUrl [なし] :
InternetErrorDlg 同等の機能がありません WinHTTP はサーバー側アプリケーションを対象としているため、ユーザー インターフェイスは実装されません。
InternetGetCookie 同等の機能がありません WinHTTP はセッション間でデータを保持せず、WinINet Cookie にアクセスできません。
InternetOpen WinHttpOpen [なし] :
InternetOpenUrl WinHttpConnectWinHttpOpenRequestWinHttpSendRequestWinHttpReceiveResponse この機能は、一覧表示されている WinHTTP 関数で使用できます。
InternetQueryDataAvailable WinHttpQueryDataAvailable 予約済みパラメーターはありません。
InternetQueryOption WinHttpQueryOption WinHTTP には、WinINet とは異なるオプション セットが用意されています。 WinHTTP で提供される詳細とオプションについては、「 オプション フラグ」を参照してください。
InternetReadFile WinHttpReadData [なし] :
InternetReadFileEx WinHttpReadData 構造体ではなく、バッファーはポインターでアドレス指定されたメモリの領域です。
InternetSetOption WinHttpSetOption [なし] :
InternetSetStatusCallback WinHttpSetStatusCallback 詳細については、このトピックの「非同期要求の異なる処理」を参照してください。
InternetTimeFromSystemTime WinHttpTimeFromSystemTime [なし] :
InternetTimeToSystemTime WinHttpTimeToSystemTime [なし] :
InternetWriteFile WinHttpWriteData [なし] :

 

非同期要求の異なる処理

WinINet と WinHTTP では、一部の関数で非同期要求を同期的または非同期的に完了できることに注意してください。 アプリケーションでは、どちらの状況も処理する必要があります。 WinINet と WinHTTP がこれらの非同期関数を処理する方法には大きな違いがあります。

Wininet

  • 同期補完: WinINet 関数の非同期呼び出しが同期的に完了する可能性がある場合、関数の OUT パラメーターは操作の結果を返します。 エラーが発生した場合は、WinINet 関数呼び出し後に GetLastError を呼び出してエラー コードを取得します。

  • 非同期補完: 非同期関数呼び出しが非同期的に完了する可能性がある場合、操作の結果とエラーにコールバック関数でアクセスできます。 コールバック関数は、最初の関数呼び出しを行ったスレッドではなく、ワーカー スレッドで実行されます。

つまり、アプリケーションは、関数呼び出し直後とコールバック関数の両方の 2 つの場所でこのような操作の結果を処理するロジックを複製する必要があります。

WinHTTP では、操作が同期的または非同期的に完了したかどうかに関係なく完了通知を受け取るコールバック関数でのみ操作ロジックを実装できるようにすることで、このモデルが簡略化されます。 非同期操作が有効になっている場合、WinHTTP 関数の OUT パラメーターは意味のあるデータを返せず、 NULL に設定する必要があります。

アプリケーションの観点から見ると、WinHTTP の非同期完了と同期補完の唯一の重要な違いは、コールバック関数が実行される場所です。

WinHTTP

  • 同期完了: 操作が同期的に完了すると、元の関数呼び出しと同じスレッドで実行されるコールバック関数で結果が返されます。

  • 非同期完了: 操作が非同期的に完了すると、ワーカー スレッドで実行されるコールバック関数で結果が返されます。

ほとんどのエラーはコールバック関数内で完全に処理することもできますが、GetLastError を呼び出して取得したERROR_INVALID_PARAMETERやその他の同様のエラーが原因で、関数が FALSE を返すように WinHTTP アプリケーションを準備する必要があります。

複数の非同期操作を同時に実行できる WinINet とは異なり、WinHTTP は要求ハンドルごとに 1 つの保留中の非同期操作のポリシーを適用します。 1 つの操作が保留中で、別の WinHTTP 関数が呼び出されると、2 番目の関数は失敗し、 GetLastError は ERROR_INVALID_OPERATIONを返します。

WinHTTP では、操作が同期的または非同期的に完了したかどうかに関係なく完了通知を受け取るコールバック関数でのみ操作ロジックを実装できるようにすることで、このモデルが簡略化されます。 非同期操作が有効になっている場合、WinHTTP 関数の OUT パラメーターは意味のあるデータを返せず、 NULL に設定する必要があります。

WinHTTP コールバック通知の違い

状態コールバック関数は、通知フラグを介して操作の状態に関する更新を受け取ります。 WinHTTP では、WinHttpSetStatusCallback 関数の dwNotificationFlags パラメーターを使用して通知が選択されます。 WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS フラグを使用して、すべての状態更新の通知を受け取ります。

特定の操作が完了したことを示す通知は、完了通知と呼ばれるか、完了と呼ばれます。 WinINet では、コールバック関数が完了を受け取るたびに、 lpvStatusInformation パラメーターに INTERNET_ASYNC_RESULT 構造体が含まれます。 WinHTTP では、この構造はすべての完了で使用できるわけではありません。 通知に関する情報 と、それぞれに必要なデータの種類が含まれるWINHTTP_STATUS_CALLBACKの参照ページを確認することが重要です。

WinHTTP では、1 つの完了 (WINHTTP_CALLBACK_STATUS_REQUEST_ERROR) は、操作が失敗したことを示します。 その他のすべての完了は、正常な操作を示します。

WinINet と WinHTTP の両方で、ユーザー定義のコンテキスト値を使用して、メイン スレッドからステータス コールバック関数に情報を渡します。これは、ワーカー スレッドで実行できます。 WinINet では、状態コールバック関数で使用されるコンテキスト値は、複数の関数のいずれかを呼び出すことによって設定されます。 WinHTTP では、コンテキスト値は WinHttpSendRequest または WinHttpSetOption でのみ設定されます。 このため、WinHTTP では、コンテキスト値が設定される前に通知が発生する可能性があります。 コンテキスト値が設定される前にコールバック関数が通知を受け取る場合は、コールバック関数の dwContext パラメーターで NULL を受け取るアプリケーションを準備する必要があります。

認証の違い

WinINet では、ユーザー資格情報は、次のコード例で示すようなコードを使用して InternetSetOption 関数を呼び出すことによって設定されます。

// Use the WinINet InternetSetOption function to set the 
// user credentials to the user name contained in strUsername 
// and the password to the contents of strPassword.
       
InternetSetOption( hRequest, INTERNET_OPTION_PROXY_USERNAME, 
                   strUsername, strlen(strUsername) + 1 );

InternetSetOption( hRequest, INTERNET_OPTION_PROXY_PASSWORD, 
                   strPassword, strlen(strPassword) + 1 );

互換性のために、 WinHttpSetOption 関数を使用して WinHTTP でユーザー資格情報を同様に設定できますが、セキュリティの脆弱性を引き起こす可能性があるため、これはお勧めしません。

代わりに、アプリケーションが WinHTTP で 401 状態コードを受け取った場合、まず WinHttpQueryAuthSchemes を使用して認証スキームを識別し、次に WinHttpSetCredentials を使用して資格情報を設定することをお勧めします。 次のコード例は、これを行う方法を示しています。

DWORD dwSupportedSchemes;
DWORD dwPrefered;
DWORD dwTarget;

// Obtain the supported and first schemes.
WinHttpQueryAuthSchemes( hRequest, &dwSupportedSchemes, &dwPrefered, &dwTarget );

// Set the credentials before resending the request.
WinHttpSetCredentials( hRequest, dwTarget, dwPrefered, strUsername, strPassword, NULL );

WinHTTP の InternetErrorDlg と同等のものがないため、ユーザー インターフェイスを介して資格情報を取得するアプリケーションは、独自のインターフェイスを提供する必要があります。

WinINet とは異なり、WinHTTP はパスワードをキャッシュしません。 有効なユーザー資格情報は、要求ごとに指定する必要があります。

WinHTTP では、WinINet でサポートされている分散パスワード認証 (DPA) スキームはサポートされていません。 ただし、WinHTTP では Microsoft Passport 1.4 がサポートされます。 WinHTTP での Passport 認証の使用の詳細については、「 WinHTTP でのパスポート認証」を参照してください。

WinHTTP は、自動ログオン ポリシーを決定するためにインターネット エクスプローラー設定に依存しません。 代わりに、自動ログオン ポリシーは WinHttpSetOption で設定されます。 自動ログオン ポリシーなど、WinHTTP での認証の詳細については、「 WinHTTP での認証」を参照してください。

セキュリティで保護された HTTP トランザクションの違い

WinINet で、HttpOpenRequest または InternetConnect を使用してセキュリティで保護されたセッションを開始しますが、WinHTTP では、WINHTTP_FLAG_SECURE フラグを使用して WinHttpOpenRequest を呼び出す必要があります。

セキュリティで保護された HTTP トランザクションでは、サーバー証明書を使用してクライアントに対してサーバーを認証できます。 WinINet では、サーバー証明書にエラーが含まれている場合、 HttpSendRequest は失敗し、証明書エラーの詳細を提供します。

WinHttp では、サーバー証明書エラーは次のようにバージョンに従って処理されます。

  • WinHttp 5.1 以降では、サーバー証明書が失敗した場合、またはエラーが含まれている場合、 WinHttpSendRequest の呼び出しによってコールバック関数の WINHTTP_CALLBACK_STATUS_SECURE_FAILURE が報告されます。 WinHttpSendRequest によって生成されたエラーが無視された場合、後続の WinHttpReceiveResponse の呼び出しは失敗し、ERROR_WINHTTP_OPERATION_CANCELLED エラーが発生します。
  • WinHTTP 5.0 では、既定では、サーバー証明書のエラーによって要求が失敗することはありません。 代わりに、 WINHTTP_CALLBACK_STATUS_SECURE_FAILURE 通知を使用してコールバック関数でエラーが報告されます。

一部の以前のプラットフォームでは、WinINet は Windows XP ではサポートされていませんが、プライベート 通信テクノロジ (PCT) や Fortezza プロトコルをサポートしました。

WinHTTP は、どのプラットフォームでも PCT および Fortezza プロトコルをサポートせず、代わりに Secure Sockets Layer (SSL) 2.0、SSL 3.0、またはトランスポート層セキュリティ (TLS) 1.0 に依存しています。