Win32 API 日本語リファレンス
ホームNetworking.WinHttp › WinHttpSendRequest

WinHttpSendRequest

関数
HTTP要求をサーバーへ送信する。
DLLWINHTTP.dll呼出規約winapiSetLastErrorあり対応OSWindows XP 以降

シグネチャ

// WINHTTP.dll
#include <windows.h>

BOOL WinHttpSendRequest(
    void* hRequest,
    LPCWSTR lpszHeaders,   // optional
    DWORD dwHeadersLength,
    void* lpOptional,   // optional
    DWORD dwOptionalLength,
    DWORD dwTotalLength,
    UINT_PTR dwContext
);

パラメーター

名前方向説明
hRequestvoid*inoutWinHttpOpenRequest が返した HINTERNET ハンドルです。
lpszHeadersLPCWSTRinoptionalリクエストに追加するヘッダーを含む文字列へのポインターです。追加するヘッダーがない場合、このパラメーターは WINHTTP_NO_ADDITIONAL_HEADERS を指定できます。
dwHeadersLengthDWORDin追加ヘッダーの長さ(文字数)を含む unsigned long 整数値です。このパラメーターが -1L で、かつ pwszHeadersNULL でない場合、この関数は pwszHeadersnull 終端されているとみなし、長さを計算します。
lpOptionalvoid*inoptional

リクエストヘッダーの直後に送信するオプションデータを含むバッファーへのポインターです。このパラメーターは通常、POST 操作および PUT 操作で使用します。オプションデータには、サーバーにポストするリソースやデータを指定できます。送信するオプションデータがない場合、このパラメーターは WINHTTP_NO_REQUEST_DATA を指定できます。

dwOptionalLength パラメーターが 0 の場合、このパラメーターは無視され、NULL に設定されます。

このバッファーは、リクエストハンドルが閉じられるか、WinHttpReceiveResponse の呼び出しが完了するまで有効である必要があります。

dwOptionalLengthDWORDin

オプションデータの長さ(バイト数)を含む unsigned long 整数値です。送信するオプションデータがない場合、このパラメーターは 0 を指定できます。

lpOptional パラメーターが NULL でない場合、このパラメーターには有効な長さを指定する必要があります。それ以外の場合、lpOptional は無視され、NULL に設定されます。

dwTotalLengthDWORDin

送信される全データの長さ(バイト数)を含む unsigned long 整数値です。このパラメーターは、リクエストの Content-Length ヘッダーを指定します。このパラメーターの値が dwOptionalLength で指定された長さより大きい場合、追加データの送信に WinHttpWriteData を使用できます。

同一のリクエストに対する WinHttpSendRequest の呼び出し間で dwTotalLength を変更してはなりません。dwTotalLength を変更する必要がある場合、呼び出し元は新しいリクエストを作成する必要があります。

dwContextUINT_PTRinアプリケーション定義の値を含む、ポインターサイズの変数へのポインターです。この値は、リクエストハンドルとともに、任意のコールバック関数に渡されます。

戻り値の型: BOOL

公式ドキュメント

指定したリクエストを HTTP サーバーに送信します。(WinHttpSendRequest)

戻り値

成功した場合は TRUE を、それ以外の場合は FALSE を返します。拡張エラー情報を取得するには、 GetLastError を呼び出します。エラーコードは次の表に示します。

エラーコード 説明
ERROR_WINHTTP_CANNOT_CONNECT
サーバーへの接続に失敗した場合に返されます。
ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED
セキュア HTTP サーバーがクライアント証明書を要求しています。アプリケーションは、WinHttpQueryOptionWINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST オプションで呼び出すことにより、証明書発行者の一覧を取得します。

サーバーがクライアント証明書を要求するものの必須としていない場合、アプリケーションは代わりに WinHttpSetOptionWINHTTP_OPTION_CLIENT_CERT_CONTEXT オプションで呼び出すことができます。この場合、アプリケーションは WinHttpSetOptionlpBuffer パラメーターに WINHTTP_NO_CLIENT_CERT_CONTEXT マクロを指定します。詳細については、WINHTTP_OPTION_CLIENT_CERT_CONTEXT オプションを参照してください。Windows Server 2003 with SP1、Windows XP with SP2、Windows 2000: このエラーはサポートされていません。

ERROR_WINHTTP_CONNECTION_ERROR
サーバーとの接続がリセットまたは終了されたか、互換性のない SSL プロトコルが検出されました。たとえば、WinHTTP バージョン 5.1 は、クライアントが明示的に有効化しない限り SSL2 をサポートしません。
ERROR_WINHTTP_INCORRECT_HANDLE_STATE
指定されたハンドルが正しい状態にないため、要求された操作を実行できません。
ERROR_WINHTTP_INCORRECT_HANDLE_TYPE
指定されたハンドルの種類がこの操作に対して正しくありません。
ERROR_WINHTTP_INTERNAL_ERROR
内部エラーが発生しました。
ERROR_WINHTTP_INVALID_URL
URL が無効です。
ERROR_WINHTTP_LOGIN_FAILURE
ログイン試行に失敗しました。このエラーが発生した場合、リクエストハンドルを WinHttpCloseHandle で閉じる必要があります。このエラーが最初に発生した関数を再試行する前に、新しいリクエストハンドルを作成する必要があります。
ERROR_WINHTTP_NAME_NOT_RESOLVED
サーバー名を解決できません。
ERROR_WINHTTP_OPERATION_CANCELLED
操作がキャンセルされました。通常、リクエストが操作していたハンドルが、操作完了前に閉じられたために発生します。
ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW
受信した応答が WinHTTP の内部サイズ制限を超えた場合に返されます。
ERROR_WINHTTP_SECURE_FAILURE
サーバーから送信された Secure Sockets Layer (SSL) 証明書に 1 つ以上のエラーが見つかりました。発生したエラーの種類を特定するには、ステータスコールバック関数内の WINHTTP_CALLBACK_STATUS_SECURE_FAILURE 通知で確認してください。詳細については、 WINHTTP_STATUS_CALLBACK を参照してください。
ERROR_WINHTTP_SHUTDOWN
WinHTTP 関数のサポートがシャットダウンされたか、アンロードされています。
ERROR_WINHTTP_TIMEOUT
リクエストがタイムアウトしました。
ERROR_WINHTTP_UNRECOGNIZED_SCHEME
URL に "http:" または "https:" 以外のスキームが指定されました。
ERROR_NOT_ENOUGH_MEMORY
要求された操作を完了するのに十分なメモリがありませんでした。(Windows エラーコード)

Windows Server 2003、Windows XP、Windows 2000: WINHTTP_OPTION_PORT_RESERVATION オプションで設定した TCP 予約範囲が、このリクエストを送信するのに十分な大きさではありません。

ERROR_INVALID_PARAMETER
dwTotalLength パラメーターで指定されたコンテンツ長が、Content-Length ヘッダーで指定された長さと一致しません。

Transfer-Encoding ヘッダーが存在する場合、lpOptional パラメーターは NULL で、dwOptionalLength パラメーターは 0 でなければなりません。

Transfer-Encoding ヘッダーが存在する場合、Content-Length ヘッダーを存在させることはできません。

ERROR_WINHTTP_RESEND_REQUEST
リダイレクトまたは認証チャレンジのため、アプリケーションは WinHttpSendRequest を再度呼び出す必要があります。

Windows Server 2003 with SP1、Windows XP with SP2、Windows 2000: このエラーはサポートされていません。

解説(Remarks)

WinHTTP が非同期モードで使用されている場合、つまり WinHttpOpenWINHTTP_FLAG_ASYNC が設定されている場合でも、この関数は同期的にも非同期的にも動作できます。いずれの場合も、リクエストが正常に送信されると、完了ステータスが WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE に設定されてアプリケーションがコールバックされます。WINHTTP_CALLBACK_STATUS_REQUEST_ERROR の完了は、操作が非同期で完了したものの失敗したことを示します。WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE ステータスコールバックを受け取った後、アプリケーションは WinHttpReceiveResponse を使用してサーバーからの応答の受信を開始できます。それまでは、他の非同期関数を呼び出すことはできません。呼び出した場合、ERROR_WINHTTP_INCORRECT_HANDLE_STATE が返されます。

アプリケーションは、リクエストハンドルが閉じられるか、WinHttpReceiveResponse の呼び出しが完了するまで、lpOptional が指すバッファーを削除または変更してはなりません。応答の受信中に、オプションデータを必要とする認証チャレンジやリダイレクトが発生する可能性があるためです。WinHttpCloseHandle で操作を中止する必要がある場合、アプリケーションは ERROR_WINHTTP_OPERATION_CANCELLED エラーコードを伴う WINHTTP_CALLBACK_STATUS_REQUEST_ERROR コールバックを受け取るまで、バッファーを有効に保つ必要があります。

WinHTTP が同期的に使用されている場合、つまり WinHttpOpenWINHTP_FLAG_ASYNC が設定されていない場合、コールバック関数が登録されていても、アプリケーションは完了ステータスを伴って呼び出されません。このモードでは、アプリケーションは WinHttpSendRequest が返ったときに WinHttpReceiveResponse を呼び出すことができます。

WinHttpSendRequest 関数は、指定したリクエストを HTTP サーバーに送信し、リクエストとともに送信する追加ヘッダーをクライアントが指定できるようにします。

また、この関数は、リクエストヘッダーの直後に HTTP サーバーへ送信するオプションデータをクライアントが指定できるようにします。この機能は通常、PUT や POST などの書き込み操作で使用されます。

アプリケーションは、同じ HTTP リクエストハンドルを WinHttpSendRequest の複数の呼び出しで使用して同じリクエストを再送信できますが、この関数を再度呼び出す前に、前回の呼び出しで返されたすべてのデータを読み取る必要があります。

この関数で追加されたリクエストヘッダーの名前と値は検証されます。ヘッダーは正しい形式でなければなりません。有効な HTTP ヘッダーの詳細については、 RFC 2616 を参照してください。無効なヘッダーが使用された場合、この関数は失敗し、 GetLastErrorERROR_INVALID_PARAMETER を返します。無効なヘッダーは追加されません。

Windows 2000: 複数のスレッドからリクエストを送信する場合、ネットワークおよび CPU のパフォーマンスが大幅に低下することがあります。

Windows XP および Windows 2000: ランタイム要件を参照してください。

WinHttpSetStatusCallback

WinHttpSetStatusCallback でステータスコールバック関数がインストールされている場合、WinHttpSetStatusCallbackdwNotificationFlags パラメーターに設定された次の通知が、リクエスト送信の進行状況を示します。
注意 Windows 7 および Windows Server 2008 R2 では、次の通知はすべて非推奨です。
サーバーが接続を閉じた場合、WinHttpSetStatusCallbackdwNotificationFlags パラメーターに設定されていれば、次の通知も送信されます。

4 GB を超えるアップロードのサポート

Windows Vista および Windows Server 2008 以降、WinHttp は Content-Length ヘッダーを使用して、LARGE_INTEGER のサイズ (2^64 バイト) までのファイルのアップロードをサポートします。WinHttpSendRequest の呼び出しで指定するペイロード長は、DWORD のサイズ (2^32 バイト) に制限されます。DWORD より大きいデータを URL にアップロードするには、アプリケーションはリクエストの Content-Length ヘッダーで長さを指定する必要があります。この場合、WinHttp クライアントアプリケーションは、dwTotalLength パラメーターを WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH に設定して WinHttpSendRequest を呼び出します。

Content-Length ヘッダーが 2^32 未満の長さを指定する場合、アプリケーションは WinHttpSendRequest の呼び出しでもコンテンツ長を指定する必要があります。dwTotalLength パラメーターが Content-Length ヘッダーで指定された長さと一致しない場合、呼び出しは失敗し、ERROR_INVALID_PARAMETER を返します。

Content-Length ヘッダーは、WinHttpAddRequestHeaders の呼び出しで追加するか、次のコード例に示すように WinHttpSendRequestlpszHeader パラメーターで指定できます。

BOOL fRet = WinHttpSendRequest(
            hReq,
            L"Content-Length: 68719476735\r\n",
            -1L,
            WINHTTP_NO_REQUEST_DATA,
            0,
            WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH,
            pMyContent);

Transfer-Encoding ヘッダー

Windows Vista および Windows Server 2008 以降、WinHttp はアプリケーションがサーバーに送信するデータに対してチャンク転送エンコーディングを実行できるようにします。WinHttp リクエストに Transfer-Encoding ヘッダーが存在する場合、WinHttpSendRequest の呼び出しの dwTotalLength パラメーターは WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH に設定され、アプリケーションは WinHttpWriteData への 1 回以上の呼び出しでエンティティ本文を送信します。WinHttpSendRequestlpOptional パラメーターは NULL でなければならず、dwOptionLength パラメーターは 0 でなければなりません。そうでない場合、ERROR_WINHTTP_INVALID_PARAMETER エラーが返されます。チャンクデータ転送を終了するには、アプリケーションは長さ 0 のチャンクを生成し、最後の WinHttpWriteData の呼び出しで送信します。

次のコード例は、 HINTERNET ハンドルの取得、HTTP セッションのオープン、リクエストヘッダーの作成、およびそのヘッダーのサーバーへの送信を行う方法を示します。

    BOOL  bResults = FALSE;
    HINTERNET hSession = NULL,
              hConnect = NULL,
              hRequest = NULL;

    // Use WinHttpOpen to obtain a session handle.
    hSession = WinHttpOpen(  L"A WinHTTP Example Program/1.0", 
                             WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
                             WINHTTP_NO_PROXY_NAME, 
                             WINHTTP_NO_PROXY_BYPASS, 0);

    // Specify an HTTP server.
    if (hSession)
        hConnect = WinHttpConnect( hSession, L"www.wingtiptoys.com",
                                   INTERNET_DEFAULT_HTTP_PORT, 0);

    // Create an HTTP Request handle.
    if (hConnect)
        hRequest = WinHttpOpenRequest( hConnect, L"PUT", 
                                       L"/writetst.txt", 
                                       NULL, WINHTTP_NO_REFERER, 
                                       WINHTTP_DEFAULT_ACCEPT_TYPES, 
                                       0);

    // Send a Request.
    if (hRequest) 
        bResults = WinHttpSendRequest( hRequest, 
                                       WINHTTP_NO_ADDITIONAL_HEADERS,
                                       0, WINHTTP_NO_REQUEST_DATA, 0, 
                                       0, 0);

    // Place additional code here.


    // Report errors.
    if (!bResults)
        printf("Error %d has occurred.\n",GetLastError());

    // Close open handles.
    if (hRequest) WinHttpCloseHandle(hRequest);
    if (hConnect) WinHttpCloseHandle(hConnect);
    if (hSession) WinHttpCloseHandle(hSession);
出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

各言語での呼び出し定義

// WINHTTP.dll
#include <windows.h>

BOOL WinHttpSendRequest(
    void* hRequest,
    LPCWSTR lpszHeaders,   // optional
    DWORD dwHeadersLength,
    void* lpOptional,   // optional
    DWORD dwOptionalLength,
    DWORD dwTotalLength,
    UINT_PTR dwContext
);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("WINHTTP.dll", SetLastError = true, ExactSpelling = true)]
static extern bool WinHttpSendRequest(
    IntPtr hRequest,   // void* in/out
    [MarshalAs(UnmanagedType.LPWStr)] string lpszHeaders,   // LPCWSTR optional
    uint dwHeadersLength,   // DWORD
    IntPtr lpOptional,   // void* optional
    uint dwOptionalLength,   // DWORD
    uint dwTotalLength,   // DWORD
    UIntPtr dwContext   // UINT_PTR
);
<DllImport("WINHTTP.dll", SetLastError:=True, ExactSpelling:=True)>
Public Shared Function WinHttpSendRequest(
    hRequest As IntPtr,   ' void* in/out
    <MarshalAs(UnmanagedType.LPWStr)> lpszHeaders As String,   ' LPCWSTR optional
    dwHeadersLength As UInteger,   ' DWORD
    lpOptional As IntPtr,   ' void* optional
    dwOptionalLength As UInteger,   ' DWORD
    dwTotalLength As UInteger,   ' DWORD
    dwContext As UIntPtr   ' UINT_PTR
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
' hRequest : void* in/out
' lpszHeaders : LPCWSTR optional
' dwHeadersLength : DWORD
' lpOptional : void* optional
' dwOptionalLength : DWORD
' dwTotalLength : DWORD
' dwContext : UINT_PTR
Declare PtrSafe Function WinHttpSendRequest Lib "winhttp" ( _
    ByVal hRequest As LongPtr, _
    ByVal lpszHeaders As LongPtr, _
    ByVal dwHeadersLength As Long, _
    ByVal lpOptional As LongPtr, _
    ByVal dwOptionalLength As Long, _
    ByVal dwTotalLength As Long, _
    ByVal dwContext As LongPtr) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

WinHttpSendRequest = ctypes.windll.winhttp.WinHttpSendRequest
WinHttpSendRequest.restype = wintypes.BOOL
WinHttpSendRequest.argtypes = [
    ctypes.POINTER(None),  # hRequest : void* in/out
    wintypes.LPCWSTR,  # lpszHeaders : LPCWSTR optional
    wintypes.DWORD,  # dwHeadersLength : DWORD
    ctypes.POINTER(None),  # lpOptional : void* optional
    wintypes.DWORD,  # dwOptionalLength : DWORD
    wintypes.DWORD,  # dwTotalLength : DWORD
    ctypes.c_size_t,  # dwContext : UINT_PTR
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('WINHTTP.dll')
WinHttpSendRequest = Fiddle::Function.new(
  lib['WinHttpSendRequest'],
  [
    Fiddle::TYPE_VOIDP,  # hRequest : void* in/out
    Fiddle::TYPE_VOIDP,  # lpszHeaders : LPCWSTR optional
    -Fiddle::TYPE_INT,  # dwHeadersLength : DWORD
    Fiddle::TYPE_VOIDP,  # lpOptional : void* optional
    -Fiddle::TYPE_INT,  # dwOptionalLength : DWORD
    -Fiddle::TYPE_INT,  # dwTotalLength : DWORD
    Fiddle::TYPE_UINTPTR_T,  # dwContext : UINT_PTR
  ],
  Fiddle::TYPE_INT)
#[link(name = "winhttp")]
extern "system" {
    fn WinHttpSendRequest(
        hRequest: *mut (),  // void* in/out
        lpszHeaders: *const u16,  // LPCWSTR optional
        dwHeadersLength: u32,  // DWORD
        lpOptional: *mut (),  // void* optional
        dwOptionalLength: u32,  // DWORD
        dwTotalLength: u32,  // DWORD
        dwContext: usize  // UINT_PTR
    ) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("WINHTTP.dll", SetLastError = true)]
public static extern bool WinHttpSendRequest(IntPtr hRequest, [MarshalAs(UnmanagedType.LPWStr)] string lpszHeaders, uint dwHeadersLength, IntPtr lpOptional, uint dwOptionalLength, uint dwTotalLength, UIntPtr dwContext);
"@
$api = Add-Type -MemberDefinition $sig -Name 'WINHTTP_WinHttpSendRequest' -Namespace Win32 -PassThru
# $api::WinHttpSendRequest(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext)
#uselib "WINHTTP.dll"
#func global WinHttpSendRequest "WinHttpSendRequest" sptr, sptr, sptr, sptr, sptr, sptr, sptr
; WinHttpSendRequest hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext   ; 戻り値は stat
; hRequest : void* in/out -> "sptr"
; lpszHeaders : LPCWSTR optional -> "sptr"
; dwHeadersLength : DWORD -> "sptr"
; lpOptional : void* optional -> "sptr"
; dwOptionalLength : DWORD -> "sptr"
; dwTotalLength : DWORD -> "sptr"
; dwContext : UINT_PTR -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
#uselib "WINHTTP.dll"
#cfunc global WinHttpSendRequest "WinHttpSendRequest" sptr, wstr, int, sptr, int, int, sptr
; res = WinHttpSendRequest(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext)
; hRequest : void* in/out -> "sptr"
; lpszHeaders : LPCWSTR optional -> "wstr"
; dwHeadersLength : DWORD -> "int"
; lpOptional : void* optional -> "sptr"
; dwOptionalLength : DWORD -> "int"
; dwTotalLength : DWORD -> "int"
; dwContext : UINT_PTR -> "sptr"
; BOOL WinHttpSendRequest(void* hRequest, LPCWSTR lpszHeaders, DWORD dwHeadersLength, void* lpOptional, DWORD dwOptionalLength, DWORD dwTotalLength, UINT_PTR dwContext)
#uselib "WINHTTP.dll"
#cfunc global WinHttpSendRequest "WinHttpSendRequest" intptr, wstr, int, intptr, int, int, intptr
; res = WinHttpSendRequest(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext)
; hRequest : void* in/out -> "intptr"
; lpszHeaders : LPCWSTR optional -> "wstr"
; dwHeadersLength : DWORD -> "int"
; lpOptional : void* optional -> "intptr"
; dwOptionalLength : DWORD -> "int"
; dwTotalLength : DWORD -> "int"
; dwContext : UINT_PTR -> "intptr"
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	winhttp = windows.NewLazySystemDLL("WINHTTP.dll")
	procWinHttpSendRequest = winhttp.NewProc("WinHttpSendRequest")
)

// hRequest (void* in/out), lpszHeaders (LPCWSTR optional), dwHeadersLength (DWORD), lpOptional (void* optional), dwOptionalLength (DWORD), dwTotalLength (DWORD), dwContext (UINT_PTR)
r1, _, err := procWinHttpSendRequest.Call(
	uintptr(hRequest),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpszHeaders))),
	uintptr(dwHeadersLength),
	uintptr(lpOptional),
	uintptr(dwOptionalLength),
	uintptr(dwTotalLength),
	uintptr(dwContext),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // BOOL
function WinHttpSendRequest(
  hRequest: Pointer;   // void* in/out
  lpszHeaders: PWideChar;   // LPCWSTR optional
  dwHeadersLength: DWORD;   // DWORD
  lpOptional: Pointer;   // void* optional
  dwOptionalLength: DWORD;   // DWORD
  dwTotalLength: DWORD;   // DWORD
  dwContext: NativeUInt   // UINT_PTR
): BOOL; stdcall;
  external 'WINHTTP.dll' name 'WinHttpSendRequest';
result := DllCall("WINHTTP\WinHttpSendRequest"
    , "Ptr", hRequest   ; void* in/out
    , "WStr", lpszHeaders   ; LPCWSTR optional
    , "UInt", dwHeadersLength   ; DWORD
    , "Ptr", lpOptional   ; void* optional
    , "UInt", dwOptionalLength   ; DWORD
    , "UInt", dwTotalLength   ; DWORD
    , "UPtr", dwContext   ; UINT_PTR
    , "Int")   ; return: BOOL
●WinHttpSendRequest(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext) = DLL("WINHTTP.dll", "bool WinHttpSendRequest(void*, char*, dword, void*, dword, dword, int)")
# 呼び出し: WinHttpSendRequest(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext)
# hRequest : void* in/out -> "void*"
# lpszHeaders : LPCWSTR optional -> "char*"
# dwHeadersLength : DWORD -> "dword"
# lpOptional : void* optional -> "void*"
# dwOptionalLength : DWORD -> "dword"
# dwTotalLength : DWORD -> "dword"
# dwContext : UINT_PTR -> "int"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
const std = @import("std");

extern "winhttp" fn WinHttpSendRequest(
    hRequest: ?*anyopaque, // void* in/out
    lpszHeaders: [*c]const u16, // LPCWSTR optional
    dwHeadersLength: u32, // DWORD
    lpOptional: ?*anyopaque, // void* optional
    dwOptionalLength: u32, // DWORD
    dwTotalLength: u32, // DWORD
    dwContext: usize // UINT_PTR
) callconv(std.os.windows.WINAPI) i32;
proc WinHttpSendRequest(
    hRequest: pointer,  # void* in/out
    lpszHeaders: WideCString,  # LPCWSTR optional
    dwHeadersLength: uint32,  # DWORD
    lpOptional: pointer,  # void* optional
    dwOptionalLength: uint32,  # DWORD
    dwTotalLength: uint32,  # DWORD
    dwContext: uint  # UINT_PTR
): int32 {.importc: "WinHttpSendRequest", stdcall, dynlib: "WINHTTP.dll".}
pragma(lib, "winhttp");
extern(Windows)
int WinHttpSendRequest(
    void* hRequest,   // void* in/out
    const(wchar)* lpszHeaders,   // LPCWSTR optional
    uint dwHeadersLength,   // DWORD
    void* lpOptional,   // void* optional
    uint dwOptionalLength,   // DWORD
    uint dwTotalLength,   // DWORD
    size_t dwContext   // UINT_PTR
);
ccall((:WinHttpSendRequest, "WINHTTP.dll"), stdcall, Int32,
      (Ptr{Cvoid}, Cwstring, UInt32, Ptr{Cvoid}, UInt32, UInt32, Csize_t),
      hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext)
# hRequest : void* in/out -> Ptr{Cvoid}
# lpszHeaders : LPCWSTR optional -> Cwstring
# dwHeadersLength : DWORD -> UInt32
# lpOptional : void* optional -> Ptr{Cvoid}
# dwOptionalLength : DWORD -> UInt32
# dwTotalLength : DWORD -> UInt32
# dwContext : UINT_PTR -> Csize_t
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
int32_t WinHttpSendRequest(
    void* hRequest,
    const uint16_t* lpszHeaders,
    uint32_t dwHeadersLength,
    void* lpOptional,
    uint32_t dwOptionalLength,
    uint32_t dwTotalLength,
    uintptr_t dwContext);
]]
local winhttp = ffi.load("winhttp")
-- winhttp.WinHttpSendRequest(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext)
-- hRequest : void* in/out
-- lpszHeaders : LPCWSTR optional
-- dwHeadersLength : DWORD
-- lpOptional : void* optional
-- dwOptionalLength : DWORD
-- dwTotalLength : DWORD
-- dwContext : UINT_PTR
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('WINHTTP.dll');
const WinHttpSendRequest = lib.func('__stdcall', 'WinHttpSendRequest', 'int32_t', ['void *', 'str16', 'uint32_t', 'void *', 'uint32_t', 'uint32_t', 'uintptr_t']);
// WinHttpSendRequest(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext)
// hRequest : void* in/out -> 'void *'
// lpszHeaders : LPCWSTR optional -> 'str16'
// dwHeadersLength : DWORD -> 'uint32_t'
// lpOptional : void* optional -> 'void *'
// dwOptionalLength : DWORD -> 'uint32_t'
// dwTotalLength : DWORD -> 'uint32_t'
// dwContext : UINT_PTR -> 'uintptr_t'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("WINHTTP.dll", {
  WinHttpSendRequest: { parameters: ["pointer", "buffer", "u32", "pointer", "u32", "u32", "usize"], result: "i32" },
});
// lib.symbols.WinHttpSendRequest(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext)
// hRequest : void* in/out -> "pointer"
// lpszHeaders : LPCWSTR optional -> "buffer"
// dwHeadersLength : DWORD -> "u32"
// lpOptional : void* optional -> "pointer"
// dwOptionalLength : DWORD -> "u32"
// dwTotalLength : DWORD -> "u32"
// dwContext : UINT_PTR -> "usize"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t WinHttpSendRequest(
    void* hRequest,
    const uint16_t* lpszHeaders,
    uint32_t dwHeadersLength,
    void* lpOptional,
    uint32_t dwOptionalLength,
    uint32_t dwTotalLength,
    size_t dwContext);
C, "WINHTTP.dll");
// $ffi->WinHttpSendRequest(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext);
// hRequest : void* in/out
// lpszHeaders : LPCWSTR optional
// dwHeadersLength : DWORD
// lpOptional : void* optional
// dwOptionalLength : DWORD
// dwTotalLength : DWORD
// dwContext : UINT_PTR
// 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
// WINAPI(stdcall): x64 では呼出規約が統一されるため問題なし。x86 では __stdcall 対応のラッパが必要な場合あり。
import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

public interface Winhttp extends StdCallLibrary {
    Winhttp INSTANCE = Native.load("winhttp", Winhttp.class);
    boolean WinHttpSendRequest(
        Pointer hRequest,   // void* in/out
        WString lpszHeaders,   // LPCWSTR optional
        int dwHeadersLength,   // DWORD
        Pointer lpOptional,   // void* optional
        int dwOptionalLength,   // DWORD
        int dwTotalLength,   // DWORD
        long dwContext   // UINT_PTR
    );
}
@[Link("winhttp")]
lib LibWINHTTP
  fun WinHttpSendRequest = WinHttpSendRequest(
    hRequest : Void*,   # void* in/out
    lpszHeaders : UInt16*,   # LPCWSTR optional
    dwHeadersLength : UInt32,   # DWORD
    lpOptional : Void*,   # void* optional
    dwOptionalLength : UInt32,   # DWORD
    dwTotalLength : UInt32,   # DWORD
    dwContext : LibC::SizeT   # UINT_PTR
  ) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef WinHttpSendRequestNative = Int32 Function(Pointer<Void>, Pointer<Utf16>, Uint32, Pointer<Void>, Uint32, Uint32, UintPtr);
typedef WinHttpSendRequestDart = int Function(Pointer<Void>, Pointer<Utf16>, int, Pointer<Void>, int, int, int);
final WinHttpSendRequest = DynamicLibrary.open('WINHTTP.dll')
    .lookupFunction<WinHttpSendRequestNative, WinHttpSendRequestDart>('WinHttpSendRequest');
// hRequest : void* in/out -> Pointer<Void>
// lpszHeaders : LPCWSTR optional -> Pointer<Utf16>
// dwHeadersLength : DWORD -> Uint32
// lpOptional : void* optional -> Pointer<Void>
// dwOptionalLength : DWORD -> Uint32
// dwTotalLength : DWORD -> Uint32
// dwContext : UINT_PTR -> UintPtr
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function WinHttpSendRequest(
  hRequest: Pointer;   // void* in/out
  lpszHeaders: PWideChar;   // LPCWSTR optional
  dwHeadersLength: DWORD;   // DWORD
  lpOptional: Pointer;   // void* optional
  dwOptionalLength: DWORD;   // DWORD
  dwTotalLength: DWORD;   // DWORD
  dwContext: NativeUInt   // UINT_PTR
): BOOL; stdcall;
  external 'WINHTTP.dll' name 'WinHttpSendRequest';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "WinHttpSendRequest"
  c_WinHttpSendRequest :: Ptr () -> CWString -> Word32 -> Ptr () -> Word32 -> Word32 -> CUIntPtr -> IO CInt
-- hRequest : void* in/out -> Ptr ()
-- lpszHeaders : LPCWSTR optional -> CWString
-- dwHeadersLength : DWORD -> Word32
-- lpOptional : void* optional -> Ptr ()
-- dwOptionalLength : DWORD -> Word32
-- dwTotalLength : DWORD -> Word32
-- dwContext : UINT_PTR -> CUIntPtr
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let winhttpsendrequest =
  foreign "WinHttpSendRequest"
    ((ptr void) @-> (ptr uint16_t) @-> uint32_t @-> (ptr void) @-> uint32_t @-> uint32_t @-> size_t @-> returning int32_t)
(* hRequest : void* in/out -> (ptr void) *)
(* lpszHeaders : LPCWSTR optional -> (ptr uint16_t) *)
(* dwHeadersLength : DWORD -> uint32_t *)
(* lpOptional : void* optional -> (ptr void) *)
(* dwOptionalLength : DWORD -> uint32_t *)
(* dwTotalLength : DWORD -> uint32_t *)
(* dwContext : UINT_PTR -> size_t *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library winhttp (t "WINHTTP.dll"))
(cffi:use-foreign-library winhttp)

(cffi:defcfun ("WinHttpSendRequest" win-http-send-request :convention :stdcall) :int32
  (h-request :pointer)   ; void* in/out
  (lpsz-headers (:string :encoding :utf-16le))   ; LPCWSTR optional
  (dw-headers-length :uint32)   ; DWORD
  (lp-optional :pointer)   ; void* optional
  (dw-optional-length :uint32)   ; DWORD
  (dw-total-length :uint32)   ; DWORD
  (dw-context :uint64))   ; UINT_PTR
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $WinHttpSendRequest = Win32::API::More->new('WINHTTP',
    'BOOL WinHttpSendRequest(LPVOID hRequest, LPCWSTR lpszHeaders, DWORD dwHeadersLength, LPVOID lpOptional, DWORD dwOptionalLength, DWORD dwTotalLength, WPARAM dwContext)');
# my $ret = $WinHttpSendRequest->Call($hRequest, $lpszHeaders, $dwHeadersLength, $lpOptional, $dwOptionalLength, $dwTotalLength, $dwContext);
# hRequest : void* in/out -> LPVOID
# lpszHeaders : LPCWSTR optional -> LPCWSTR
# dwHeadersLength : DWORD -> DWORD
# lpOptional : void* optional -> LPVOID
# dwOptionalLength : DWORD -> DWORD
# dwTotalLength : DWORD -> DWORD
# dwContext : UINT_PTR -> WPARAM
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

公式の関連項目