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

WSCGetApplicationCategory

関数
アプリケーションのLSPカテゴリ許可を取得する。
DLLWS2_32.dll呼出規約winapi対応OSWindows Vista 以降

シグネチャ

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

INT WSCGetApplicationCategory(
    LPCWSTR Path,
    DWORD PathLength,
    LPCWSTR Extra,   // optional
    DWORD ExtraLength,
    DWORD* pPermittedLspCategories,
    INT* lpErrno
);

パラメーター

名前方向説明
PathLPCWSTRinアプリケーションの実行可能イメージへのロードパスを含む Unicode 文字列へのポインター。この文字列は通常のパス解決規則に従い、埋め込みの環境文字列 (%SystemRoot% など) を含めることができます。
PathLengthDWORDinPath パラメーターの長さ (文字数)。この長さには終端の NULL は含まれません。
ExtraLPCWSTRinoptionalPath パラメーターで指定されたアプリケーションを起動する際に使用されるコマンドライン引数を表す Unicode 文字列へのポインター。Extra パラメーターは、一貫したコマンドラインで起動されたアプリケーションの複数の異なるインスタンスを区別するために使用されます。これは、Svchost.exe や Rundll32.exe の異なるインスタンスに対して異なるアプリケーション分類をサポートするためのものです。Path パラメーターのみで十分であり、アプリケーションのインスタンスをさらに区別するためのコマンドライン引数が不要な場合は、Extra パラメーターを NULL に設定してください。
ExtraLengthDWORDinExtra パラメーターの長さ (文字数)。この長さには終端の NULL は含まれません。
pPermittedLspCategoriesDWORD*outこのアプリケーションのすべてのインスタンスに対して許可される LSP カテゴリを示す DWORD 値へのポインター。アプリケーションは Path パラメーターと Extra パラメーターの値の組み合わせによって識別されます。
lpErrnoINT*out関数が失敗した場合のエラーコードへのポインター。

戻り値の型: INT

公式ドキュメント

アプリケーションに関連付けられた階層化サービスプロバイダー (LSP) のカテゴリを取得します。

戻り値

エラーが発生しなかった場合、WSCGetApplicationCategoryERROR_SUCCESS (ゼロ) を返します。それ以外の場合は SOCKET_ERROR を返し、lpErrno パラメーターに特定のエラーコードが返されます。

エラーコード 意味
WSAEFAULT
引数のうち 1 つ以上が、ユーザーアドレス空間の有効な部分にありません。
WSAEINVAL
引数のうち 1 つ以上が無効です。
WSASERVICE_NOT_FOUND
Path パラメーターと Extra パラメーターに基づいてサービスが見つかりませんでした。

クエリ対象のアプリケーションがレジストリに存在しない場合にも、このエラーが返されることがあります。この場合、エラーはアプリケーションが現在分類されていないことを示します。

WSANO_RECOVERY
回復不能なエラーが発生しました。このエラーは、次を含むいくつかの条件下で返されます。すなわち、ユーザーに Winsock レジストリへのアクセスに必要な管理者権限がない場合、または Winsock カタログエントリやアプリケーション ID エントリを開く際に障害が発生した場合です。

解説(Remarks)

WSCGetApplicationCategory は、アプリケーションインスタンスに関連付けられた LSP カテゴリフラグを取得するために使用されます。アプリケーションは、自身のコンテキスト内でどの LSP の動作が許容されるかを判断できます。したがって、許可される LSP カテゴリを指定することで、アプリケーションは許容可能な動作を実装する階層化サービスプロバイダーのみをロードするように許可できます。

Extra パラメーターは、同一の実行可能ファイル内でホストされるアプリケーションまたはサービスの異なるインスタンスを区別するためにコマンドラインを使用する場合に必要です。各インスタンスは異なるアプリケーション分類の要件を持つ可能性があります。Svchost.exe と Rundll32.exe は、異なるプロセスインスタンスを区別するためにコマンドラインが必要となる 2 つの例です。SvcHost.exe の場合、-k <svcinstance> スイッチがプロセスインスタンスを定義します。

サービスの場合、サービス名を使用するだけでは不十分です。Winsock カタログは特定のプロセスに対してグローバルであり、1 つのプロセスが複数のサービスをホストする可能性があるためです。

Windows ソケットは、最初の WSAStartup 呼び出し時にアプリケーションの ID を判定し、許可される LSP カテゴリを取得します。これがアプリケーションインスタンスの期間を通じて適用される、許可される LSP カテゴリのセットとなります。特定のアプリケーション ID に対する許可される LSP カテゴリの後続の変更は、アプリケーションの次のインスタンスまで反映されません。許可される LSP カテゴリは、アプリケーションインスタンスの存続期間中は変更できません。

Winsock 2 は階層化プロトコルに対応しています。階層化プロトコルとは、より高レベルの通信機能のみを実装し、リモートエンドポイントとの実際のデータ交換については下位のトランスポートスタックに依存するプロトコルです。階層化プロトコルまたは階層化サービスプロバイダーの例としては、認証を実行し相互に合意した暗号化方式を確立するために、接続確立プロセスにプロトコルを追加するセキュリティ層が挙げられます。このようなセキュリティプロトコルは、一般に TCP や SPX などの下位の信頼性のあるトランスポートプロトコルのサービスを必要とします。ベースプロトコルという用語は、リモートエンドポイントとのデータ通信を実行できる TCP や SPX などのプロトコルを指します。階層化プロトコルという用語は、単独では成立しないプロトコルを表すために使用されます。

LSP の初期化中、LSP は多数の Winsock SPI 関数へのポインターを提供する必要があります。これらの関数は、LSP の直上の層 (別の LSP または Ws2_32.DLL) による通常の処理中に呼び出されます。

インストール可能ファイルシステム (IFS) を実装する LSP は、自身が実装する関数へのポインターを提供するか、LSP の直下の層が提供するポインターをそのまま返すかを選択的に選ぶことができます。非 IFS LSP は、独自のハンドルを提供するため、すべての Winsock SPI 関数を実装する必要があります。これは、各 SPI が、LSP が作成したすべてのソケットハンドルを下位プロバイダー (別の LSP またはベースプロトコル) のソケットハンドルにマップすることを要求するためです。

ただし、すべての LSP は、Winsock SPI 関数のサブセットに対してのみ追加処理を行うことで、その固有の作業を実行します。

LSP が実装する SPI 関数のサブセットと、それらの各関数に対して実行される追加処理の性質に基づいて、LSP カテゴリを定義することが可能です。

LSP を分類し、さらに Winsock ソケットを使用するアプリケーションを分類することで、実行時に特定のプロセスに LSP を関与させるべきかどうかを選択的に判断できるようになります。

Windows Vista 以降では、LSP は Windows ソケットの呼び出しおよびデータとどのように相互作用するかに基づいて分類できます。LSP カテゴリは、Winsock SPI 関数のサブセットに対する識別可能な動作のグループです。たとえば、HTTP コンテンツフィルターはデータインスペクター (LSP_INSPECTOR カテゴリ) として分類されます。LSP_INSPECTOR カテゴリは、データ転送 SPI 関数のパラメーターを検査します (ただし変更はしません)。アプリケーションは LSP のカテゴリをクエリし、LSP カテゴリとアプリケーションの許可される LSP カテゴリのセットに基づいて、その LSP をロードしないことを選択できます。

次の表は、LSP を分類できるカテゴリの一覧です。

LSP カテゴリ 説明
**LSP_CRYPTO_COMPRESS** LSP は暗号化またはデータ圧縮プロバイダーです。
**LSP_FIREWALL** LSP はファイアウォールプロバイダーです。
**LSP_LOCAL_CACHE** LSP はローカルキャッシュプロバイダーです。
**LSP_INBOUND_MODIFY** LSP は受信データを変更します。
**LSP_INSPECTOR** LSP はデータを検査またはフィルタリングします。
**LSP_OUTBOUND_MODIFY** LSP は送信データを変更します。
**LSP_PROXY** LSP はプロキシとして動作し、パケットをリダイレクトします。
**LSP_REDIRECTOR** LSP はネットワークリダイレクターです。
**LSP_SYSTEM** LSP はサービスおよびシステムプロセスでの使用が許容されます。

1 つの LSP は複数のカテゴリに属することができます。たとえば、ファイアウォール/セキュリティ LSP は、インスペクター (LSP_INSPECTOR) カテゴリとファイアウォール (LSP_FIREWALL) カテゴリの両方に属することができます。

LSP にカテゴリが設定されていない場合、その LSP は「その他すべて (All Other)」カテゴリに属するとみなされます。この LSP カテゴリは、サービスやシステムプロセス (たとえば lsass、winlogon、および多くの svchost プロセス) ではロードされません。

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

各言語での呼び出し定義

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

INT WSCGetApplicationCategory(
    LPCWSTR Path,
    DWORD PathLength,
    LPCWSTR Extra,   // optional
    DWORD ExtraLength,
    DWORD* pPermittedLspCategories,
    INT* lpErrno
);
[DllImport("WS2_32.dll", ExactSpelling = true)]
static extern int WSCGetApplicationCategory(
    [MarshalAs(UnmanagedType.LPWStr)] string Path,   // LPCWSTR
    uint PathLength,   // DWORD
    [MarshalAs(UnmanagedType.LPWStr)] string Extra,   // LPCWSTR optional
    uint ExtraLength,   // DWORD
    out uint pPermittedLspCategories,   // DWORD* out
    out int lpErrno   // INT* out
);
<DllImport("WS2_32.dll", ExactSpelling:=True)>
Public Shared Function WSCGetApplicationCategory(
    <MarshalAs(UnmanagedType.LPWStr)> Path As String,   ' LPCWSTR
    PathLength As UInteger,   ' DWORD
    <MarshalAs(UnmanagedType.LPWStr)> Extra As String,   ' LPCWSTR optional
    ExtraLength As UInteger,   ' DWORD
    <Out> ByRef pPermittedLspCategories As UInteger,   ' DWORD* out
    <Out> ByRef lpErrno As Integer   ' INT* out
) As Integer
End Function
' Path : LPCWSTR
' PathLength : DWORD
' Extra : LPCWSTR optional
' ExtraLength : DWORD
' pPermittedLspCategories : DWORD* out
' lpErrno : INT* out
Declare PtrSafe Function WSCGetApplicationCategory Lib "ws2_32" ( _
    ByVal Path As LongPtr, _
    ByVal PathLength As Long, _
    ByVal Extra As LongPtr, _
    ByVal ExtraLength As Long, _
    ByRef pPermittedLspCategories As Long, _
    ByRef lpErrno As Long) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

WSCGetApplicationCategory = ctypes.windll.ws2_32.WSCGetApplicationCategory
WSCGetApplicationCategory.restype = ctypes.c_int
WSCGetApplicationCategory.argtypes = [
    wintypes.LPCWSTR,  # Path : LPCWSTR
    wintypes.DWORD,  # PathLength : DWORD
    wintypes.LPCWSTR,  # Extra : LPCWSTR optional
    wintypes.DWORD,  # ExtraLength : DWORD
    ctypes.POINTER(wintypes.DWORD),  # pPermittedLspCategories : DWORD* out
    ctypes.POINTER(ctypes.c_int),  # lpErrno : INT* out
]
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('WS2_32.dll')
WSCGetApplicationCategory = Fiddle::Function.new(
  lib['WSCGetApplicationCategory'],
  [
    Fiddle::TYPE_VOIDP,  # Path : LPCWSTR
    -Fiddle::TYPE_INT,  # PathLength : DWORD
    Fiddle::TYPE_VOIDP,  # Extra : LPCWSTR optional
    -Fiddle::TYPE_INT,  # ExtraLength : DWORD
    Fiddle::TYPE_VOIDP,  # pPermittedLspCategories : DWORD* out
    Fiddle::TYPE_VOIDP,  # lpErrno : INT* out
  ],
  Fiddle::TYPE_INT)
#[link(name = "ws2_32")]
extern "system" {
    fn WSCGetApplicationCategory(
        Path: *const u16,  // LPCWSTR
        PathLength: u32,  // DWORD
        Extra: *const u16,  // LPCWSTR optional
        ExtraLength: u32,  // DWORD
        pPermittedLspCategories: *mut u32,  // DWORD* out
        lpErrno: *mut i32  // INT* out
    ) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[DllImport("WS2_32.dll")]
public static extern int WSCGetApplicationCategory([MarshalAs(UnmanagedType.LPWStr)] string Path, uint PathLength, [MarshalAs(UnmanagedType.LPWStr)] string Extra, uint ExtraLength, out uint pPermittedLspCategories, out int lpErrno);
"@
$api = Add-Type -MemberDefinition $sig -Name 'WS2_32_WSCGetApplicationCategory' -Namespace Win32 -PassThru
# $api::WSCGetApplicationCategory(Path, PathLength, Extra, ExtraLength, pPermittedLspCategories, lpErrno)
#uselib "WS2_32.dll"
#func global WSCGetApplicationCategory "WSCGetApplicationCategory" sptr, sptr, sptr, sptr, sptr, sptr
; WSCGetApplicationCategory Path, PathLength, Extra, ExtraLength, varptr(pPermittedLspCategories), varptr(lpErrno)   ; 戻り値は stat
; Path : LPCWSTR -> "sptr"
; PathLength : DWORD -> "sptr"
; Extra : LPCWSTR optional -> "sptr"
; ExtraLength : DWORD -> "sptr"
; pPermittedLspCategories : DWORD* out -> "sptr"
; lpErrno : INT* out -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "WS2_32.dll"
#cfunc global WSCGetApplicationCategory "WSCGetApplicationCategory" wstr, int, wstr, int, var, var
; res = WSCGetApplicationCategory(Path, PathLength, Extra, ExtraLength, pPermittedLspCategories, lpErrno)
; Path : LPCWSTR -> "wstr"
; PathLength : DWORD -> "int"
; Extra : LPCWSTR optional -> "wstr"
; ExtraLength : DWORD -> "int"
; pPermittedLspCategories : DWORD* out -> "var"
; lpErrno : INT* out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; INT WSCGetApplicationCategory(LPCWSTR Path, DWORD PathLength, LPCWSTR Extra, DWORD ExtraLength, DWORD* pPermittedLspCategories, INT* lpErrno)
#uselib "WS2_32.dll"
#cfunc global WSCGetApplicationCategory "WSCGetApplicationCategory" wstr, int, wstr, int, var, var
; res = WSCGetApplicationCategory(Path, PathLength, Extra, ExtraLength, pPermittedLspCategories, lpErrno)
; Path : LPCWSTR -> "wstr"
; PathLength : DWORD -> "int"
; Extra : LPCWSTR optional -> "wstr"
; ExtraLength : DWORD -> "int"
; pPermittedLspCategories : DWORD* out -> "var"
; lpErrno : INT* out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	ws2_32 = windows.NewLazySystemDLL("WS2_32.dll")
	procWSCGetApplicationCategory = ws2_32.NewProc("WSCGetApplicationCategory")
)

// Path (LPCWSTR), PathLength (DWORD), Extra (LPCWSTR optional), ExtraLength (DWORD), pPermittedLspCategories (DWORD* out), lpErrno (INT* out)
r1, _, err := procWSCGetApplicationCategory.Call(
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(Path))),
	uintptr(PathLength),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(Extra))),
	uintptr(ExtraLength),
	uintptr(pPermittedLspCategories),
	uintptr(lpErrno),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // INT
function WSCGetApplicationCategory(
  Path: PWideChar;   // LPCWSTR
  PathLength: DWORD;   // DWORD
  Extra: PWideChar;   // LPCWSTR optional
  ExtraLength: DWORD;   // DWORD
  pPermittedLspCategories: Pointer;   // DWORD* out
  lpErrno: Pointer   // INT* out
): Integer; stdcall;
  external 'WS2_32.dll' name 'WSCGetApplicationCategory';
result := DllCall("WS2_32\WSCGetApplicationCategory"
    , "WStr", Path   ; LPCWSTR
    , "UInt", PathLength   ; DWORD
    , "WStr", Extra   ; LPCWSTR optional
    , "UInt", ExtraLength   ; DWORD
    , "Ptr", pPermittedLspCategories   ; DWORD* out
    , "Ptr", lpErrno   ; INT* out
    , "Int")   ; return: INT
●WSCGetApplicationCategory(Path, PathLength, Extra, ExtraLength, pPermittedLspCategories, lpErrno) = DLL("WS2_32.dll", "int WSCGetApplicationCategory(char*, dword, char*, dword, void*, void*)")
# 呼び出し: WSCGetApplicationCategory(Path, PathLength, Extra, ExtraLength, pPermittedLspCategories, lpErrno)
# Path : LPCWSTR -> "char*"
# PathLength : DWORD -> "dword"
# Extra : LPCWSTR optional -> "char*"
# ExtraLength : DWORD -> "dword"
# pPermittedLspCategories : DWORD* out -> "void*"
# lpErrno : INT* out -> "void*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
const std = @import("std");

extern "ws2_32" fn WSCGetApplicationCategory(
    Path: [*c]const u16, // LPCWSTR
    PathLength: u32, // DWORD
    Extra: [*c]const u16, // LPCWSTR optional
    ExtraLength: u32, // DWORD
    pPermittedLspCategories: [*c]u32, // DWORD* out
    lpErrno: [*c]i32 // INT* out
) callconv(std.os.windows.WINAPI) i32;
proc WSCGetApplicationCategory(
    Path: WideCString,  # LPCWSTR
    PathLength: uint32,  # DWORD
    Extra: WideCString,  # LPCWSTR optional
    ExtraLength: uint32,  # DWORD
    pPermittedLspCategories: ptr uint32,  # DWORD* out
    lpErrno: ptr int32  # INT* out
): int32 {.importc: "WSCGetApplicationCategory", stdcall, dynlib: "WS2_32.dll".}
pragma(lib, "ws2_32");
extern(Windows)
int WSCGetApplicationCategory(
    const(wchar)* Path,   // LPCWSTR
    uint PathLength,   // DWORD
    const(wchar)* Extra,   // LPCWSTR optional
    uint ExtraLength,   // DWORD
    uint* pPermittedLspCategories,   // DWORD* out
    int* lpErrno   // INT* out
);
ccall((:WSCGetApplicationCategory, "WS2_32.dll"), stdcall, Int32,
      (Cwstring, UInt32, Cwstring, UInt32, Ptr{UInt32}, Ptr{Int32}),
      Path, PathLength, Extra, ExtraLength, pPermittedLspCategories, lpErrno)
# Path : LPCWSTR -> Cwstring
# PathLength : DWORD -> UInt32
# Extra : LPCWSTR optional -> Cwstring
# ExtraLength : DWORD -> UInt32
# pPermittedLspCategories : DWORD* out -> Ptr{UInt32}
# lpErrno : INT* out -> Ptr{Int32}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
int32_t WSCGetApplicationCategory(
    const uint16_t* Path,
    uint32_t PathLength,
    const uint16_t* Extra,
    uint32_t ExtraLength,
    uint32_t* pPermittedLspCategories,
    int32_t* lpErrno);
]]
local ws2_32 = ffi.load("ws2_32")
-- ws2_32.WSCGetApplicationCategory(Path, PathLength, Extra, ExtraLength, pPermittedLspCategories, lpErrno)
-- Path : LPCWSTR
-- PathLength : DWORD
-- Extra : LPCWSTR optional
-- ExtraLength : DWORD
-- pPermittedLspCategories : DWORD* out
-- lpErrno : INT* out
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('WS2_32.dll');
const WSCGetApplicationCategory = lib.func('__stdcall', 'WSCGetApplicationCategory', 'int32_t', ['str16', 'uint32_t', 'str16', 'uint32_t', 'uint32_t *', 'int32_t *']);
// WSCGetApplicationCategory(Path, PathLength, Extra, ExtraLength, pPermittedLspCategories, lpErrno)
// Path : LPCWSTR -> 'str16'
// PathLength : DWORD -> 'uint32_t'
// Extra : LPCWSTR optional -> 'str16'
// ExtraLength : DWORD -> 'uint32_t'
// pPermittedLspCategories : DWORD* out -> 'uint32_t *'
// lpErrno : INT* out -> 'int32_t *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("WS2_32.dll", {
  WSCGetApplicationCategory: { parameters: ["buffer", "u32", "buffer", "u32", "pointer", "pointer"], result: "i32" },
});
// lib.symbols.WSCGetApplicationCategory(Path, PathLength, Extra, ExtraLength, pPermittedLspCategories, lpErrno)
// Path : LPCWSTR -> "buffer"
// PathLength : DWORD -> "u32"
// Extra : LPCWSTR optional -> "buffer"
// ExtraLength : DWORD -> "u32"
// pPermittedLspCategories : DWORD* out -> "pointer"
// lpErrno : INT* out -> "pointer"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t WSCGetApplicationCategory(
    const uint16_t* Path,
    uint32_t PathLength,
    const uint16_t* Extra,
    uint32_t ExtraLength,
    uint32_t* pPermittedLspCategories,
    int32_t* lpErrno);
C, "WS2_32.dll");
// $ffi->WSCGetApplicationCategory(Path, PathLength, Extra, ExtraLength, pPermittedLspCategories, lpErrno);
// Path : LPCWSTR
// PathLength : DWORD
// Extra : LPCWSTR optional
// ExtraLength : DWORD
// pPermittedLspCategories : DWORD* out
// lpErrno : INT* out
// 構造体/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 Ws2_32 extends StdCallLibrary {
    Ws2_32 INSTANCE = Native.load("ws2_32", Ws2_32.class);
    int WSCGetApplicationCategory(
        WString Path,   // LPCWSTR
        int PathLength,   // DWORD
        WString Extra,   // LPCWSTR optional
        int ExtraLength,   // DWORD
        IntByReference pPermittedLspCategories,   // DWORD* out
        IntByReference lpErrno   // INT* out
    );
}
@[Link("ws2_32")]
lib LibWS2_32
  fun WSCGetApplicationCategory = WSCGetApplicationCategory(
    Path : UInt16*,   # LPCWSTR
    PathLength : UInt32,   # DWORD
    Extra : UInt16*,   # LPCWSTR optional
    ExtraLength : UInt32,   # DWORD
    pPermittedLspCategories : UInt32*,   # DWORD* out
    lpErrno : Int32*   # INT* out
  ) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef WSCGetApplicationCategoryNative = Int32 Function(Pointer<Utf16>, Uint32, Pointer<Utf16>, Uint32, Pointer<Uint32>, Pointer<Int32>);
typedef WSCGetApplicationCategoryDart = int Function(Pointer<Utf16>, int, Pointer<Utf16>, int, Pointer<Uint32>, Pointer<Int32>);
final WSCGetApplicationCategory = DynamicLibrary.open('WS2_32.dll')
    .lookupFunction<WSCGetApplicationCategoryNative, WSCGetApplicationCategoryDart>('WSCGetApplicationCategory');
// Path : LPCWSTR -> Pointer<Utf16>
// PathLength : DWORD -> Uint32
// Extra : LPCWSTR optional -> Pointer<Utf16>
// ExtraLength : DWORD -> Uint32
// pPermittedLspCategories : DWORD* out -> Pointer<Uint32>
// lpErrno : INT* out -> Pointer<Int32>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function WSCGetApplicationCategory(
  Path: PWideChar;   // LPCWSTR
  PathLength: DWORD;   // DWORD
  Extra: PWideChar;   // LPCWSTR optional
  ExtraLength: DWORD;   // DWORD
  pPermittedLspCategories: Pointer;   // DWORD* out
  lpErrno: Pointer   // INT* out
): Integer; stdcall;
  external 'WS2_32.dll' name 'WSCGetApplicationCategory';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "WSCGetApplicationCategory"
  c_WSCGetApplicationCategory :: CWString -> Word32 -> CWString -> Word32 -> Ptr Word32 -> Ptr Int32 -> IO Int32
-- Path : LPCWSTR -> CWString
-- PathLength : DWORD -> Word32
-- Extra : LPCWSTR optional -> CWString
-- ExtraLength : DWORD -> Word32
-- pPermittedLspCategories : DWORD* out -> Ptr Word32
-- lpErrno : INT* out -> Ptr Int32
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let wscgetapplicationcategory =
  foreign "WSCGetApplicationCategory"
    ((ptr uint16_t) @-> uint32_t @-> (ptr uint16_t) @-> uint32_t @-> (ptr uint32_t) @-> (ptr int32_t) @-> returning int32_t)
(* Path : LPCWSTR -> (ptr uint16_t) *)
(* PathLength : DWORD -> uint32_t *)
(* Extra : LPCWSTR optional -> (ptr uint16_t) *)
(* ExtraLength : DWORD -> uint32_t *)
(* pPermittedLspCategories : DWORD* out -> (ptr uint32_t) *)
(* lpErrno : INT* out -> (ptr int32_t) *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library ws2_32 (t "WS2_32.dll"))
(cffi:use-foreign-library ws2_32)

(cffi:defcfun ("WSCGetApplicationCategory" wscget-application-category :convention :stdcall) :int32
  (path (:string :encoding :utf-16le))   ; LPCWSTR
  (path-length :uint32)   ; DWORD
  (extra (:string :encoding :utf-16le))   ; LPCWSTR optional
  (extra-length :uint32)   ; DWORD
  (p-permitted-lsp-categories :pointer)   ; DWORD* out
  (lp-errno :pointer))   ; INT* out
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $WSCGetApplicationCategory = Win32::API::More->new('WS2_32',
    'int WSCGetApplicationCategory(LPCWSTR Path, DWORD PathLength, LPCWSTR Extra, DWORD ExtraLength, LPVOID pPermittedLspCategories, LPVOID lpErrno)');
# my $ret = $WSCGetApplicationCategory->Call($Path, $PathLength, $Extra, $ExtraLength, $pPermittedLspCategories, $lpErrno);
# Path : LPCWSTR -> LPCWSTR
# PathLength : DWORD -> DWORD
# Extra : LPCWSTR optional -> LPCWSTR
# ExtraLength : DWORD -> DWORD
# pPermittedLspCategories : DWORD* out -> LPVOID
# lpErrno : INT* out -> LPVOID
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

公式の関連項目